From: Stian Low <wineryyyyy@gmail.com> --- dlls/d3d10core/tests/d3d10core.c | 8 +- dlls/d3d11/device.c | 14 +++ dlls/d3d11/tests/d3d11.c | 6 +- dlls/d3d11/view.c | 36 +++++++- dlls/wined3d/adapter_gl.c | 54 ++++++++++- dlls/wined3d/adapter_vk.c | 52 +++++++++-- dlls/wined3d/swapchain.c | 92 ++++++++++++++++++- dlls/wined3d/view.c | 150 ++++++++++++++++++++++++------- dlls/wined3d/wined3d.spec | 1 + dlls/wined3d/wined3d_gl.h | 15 ++++ dlls/wined3d/wined3d_private.h | 23 +++-- dlls/wined3d/wined3d_vk.h | 15 ++++ include/wine/wined3d.h | 1 + 13 files changed, 413 insertions(+), 54 deletions(-) diff --git a/dlls/d3d10core/tests/d3d10core.c b/dlls/d3d10core/tests/d3d10core.c index fb5482c484c..ff78ac23b9e 100644 --- a/dlls/d3d10core/tests/d3d10core.c +++ b/dlls/d3d10core/tests/d3d10core.c @@ -11048,7 +11048,7 @@ static void test_swapchain_views(void) hr = ID3D10Device_CreateRenderTargetView(device, (ID3D10Resource *)test_context.backbuffer, &rtv_desc, &rtv); flags &= D3D10_FORMAT_SUPPORT_BACK_BUFFER_CAST; flags = (FAILED(hr) && !flags) || (SUCCEEDED(hr) && flags); - todo_wine ok(flags, "Got unexpected for SRGB rtv for UNORM swapchain, hr %#lx.\n", hr); + ok(flags, "Got unexpected for SRGB rtv for UNORM swapchain, hr %#lx.\n", hr); if (SUCCEEDED(hr)) ID3D10RenderTargetView_Release(rtv); @@ -11193,7 +11193,7 @@ static void test_swapchain_flip(void) ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected usage %u.\n", texture_desc.Usage); hr = ID3D10Device_CreateRenderTargetView(device, (ID3D10Resource *)backbuffer_1, NULL, &offscreen_rtv); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected for rtv for swapchain backbuffer_1, hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected for rtv for swapchain backbuffer_1, hr %#lx.\n", hr); if (SUCCEEDED(hr)) ID3D10RenderTargetView_Release(offscreen_rtv); @@ -11245,12 +11245,12 @@ static void test_swapchain_flip(void) hr = ID3D10Device_CreateRenderTargetView(device, (ID3D10Resource *)backbuffer_0, &rtv_desc, &backbuffer_0_rtv_srgb); flags &= D3D10_FORMAT_SUPPORT_BACK_BUFFER_CAST; flags = (FAILED(hr) && !flags) || (SUCCEEDED(hr) && flags); - todo_wine ok(flags, "Got unexpected for SRGB rtv for UNORM swapchain, hr %#lx.\n", hr); + ok(flags, "Got unexpected for SRGB rtv for UNORM swapchain, hr %#lx.\n", hr); if (SUCCEEDED(hr)) { ID3D10Device_ClearRenderTargetView(device, backbuffer_0_rtv_srgb, grey); color = get_texture_color(backbuffer_0, 320, 240); /* red */ - todo_wine ok(compare_color(color, 0x80bcbcbc, 1), "Got unexpected srgb color 0x%08x.\n", color); + ok(compare_color(color, 0x80bcbcbc, 1), "Got unexpected srgb color 0x%08x.\n", color); ID3D10RenderTargetView_Release(backbuffer_0_rtv_srgb); } diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index e1a846698e6..2757010dbe0 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -4703,6 +4703,20 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CheckFormatSupport(ID3D11Device5 * | D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD; } + switch (wined3d_format) + { + case WINED3DFMT_R10G10B10A2_UNORM: + case WINED3DFMT_R10G10B10_XR_BIAS_A2_UNORM: + case WINED3DFMT_R8G8B8A8_UNORM: + case WINED3DFMT_R8G8B8A8_UNORM_SRGB: + case WINED3DFMT_B8G8R8A8_UNORM: + case WINED3DFMT_B8G8R8X8_UNORM_SRGB: + /* d3d10/11 share saem FORMAT_SUPPORT_BACK_BUFFER_CAST flag value*/ + *format_support |= D3D11_FORMAT_SUPPORT_BACK_BUFFER_CAST; + default: + break; + } + return *format_support ? S_OK : E_FAIL; } diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 7b45dafbdb3..5adbf2c977c 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -16143,7 +16143,7 @@ static void test_swapchain_flip(void) ok(texture_desc.Usage == D3D11_USAGE_DEFAULT, "Got unexpected usage %u.\n", texture_desc.Usage); hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)backbuffer_1, NULL, &offscreen_rtv); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected for rtv for swapchain backbuffer_1, hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected for rtv for swapchain backbuffer_1, hr %#lx.\n", hr); if (SUCCEEDED(hr)) ID3D11RenderTargetView_Release(offscreen_rtv); @@ -16195,12 +16195,12 @@ static void test_swapchain_flip(void) hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)backbuffer_0, &rtv_desc, &backbuffer_0_rtv_srgb); flags &= D3D11_FORMAT_SUPPORT_BACK_BUFFER_CAST; flags = (FAILED(hr) && !flags) || (SUCCEEDED(hr) && flags); - todo_wine ok(flags, "Got unexpected for SRGB rtv vs swapchain UNORM, hr %#lx.\n", hr); + ok(flags, "Got unexpected for SRGB rtv vs swapchain UNORM, hr %#lx.\n", hr); if (SUCCEEDED(hr)) { ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_0_rtv_srgb, grey); color = get_texture_color(backbuffer_0, 320, 240); /* grey */ - todo_wine ok(compare_color(color, 0x80bcbcbc, 1), "Got unexpected srgb color 0x%08lx.\n", color); + ok(compare_color(color, 0x80bcbcbc, 1), "Got unexpected srgb color 0x%08lx.\n", color); } ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_0_rtv, red); diff --git a/dlls/d3d11/view.c b/dlls/d3d11/view.c index ec55dba5cf3..5acd410e2bb 100644 --- a/dlls/d3d11/view.c +++ b/dlls/d3d11/view.c @@ -1709,6 +1709,7 @@ static HRESULT d3d_rendertarget_view_init(struct d3d_rendertarget_view *view, st { struct wined3d_resource *wined3d_resource; struct wined3d_view_desc wined3d_desc; + struct wined3d_swapchain *swapchain; HRESULT hr; view->ID3D11RenderTargetView_iface.lpVtbl = &d3d11_rendertarget_view_vtbl; @@ -1732,10 +1733,43 @@ static HRESULT d3d_rendertarget_view_init(struct d3d_rendertarget_view *view, st { wined3d_mutex_unlock(); ERR("Failed to get wined3d resource for d3d11 resource %p.\n", resource); - return E_FAIL; + return E_INVALIDARG; } wined3d_rendertarget_view_desc_from_d3d11(&wined3d_desc, &view->desc); + + if ((swapchain = wined3d_swapchain_from_resource(wined3d_resource))) + { + if (wined3d_swapchain_get_back_buffer(swapchain, 0) != wined3d_texture_from_resource(wined3d_resource)) + { + wined3d_mutex_unlock(); + ERR("RTVs texture does not match swapchain back_buffers[0]\n"); + return E_INVALIDARG; + } + + if (desc) + { + UINT flags; + + if (FAILED(hr = ID3D11Device_CheckFormatSupport((ID3D11Device*)&device->ID3D11Device5_iface, desc->Format, &flags))) + { + wined3d_mutex_unlock(); + ERR("Failed to get format support\n"); + return hr; + } + + flags &= D3D11_FORMAT_SUPPORT_BACK_BUFFER_CAST; + if (!flags) + { + wined3d_mutex_unlock(); + ERR("Casting format for swapchain backbuffer not supported\n"); + return E_INVALIDARG; + } + } + + } + + if (FAILED(hr = wined3d_rendertarget_view_create(&wined3d_desc, wined3d_resource, view, &d3d_render_target_view_wined3d_parent_ops, &view->wined3d_view))) { diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 35f73b64497..1f6c0bc9e61 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4561,19 +4561,29 @@ static HRESULT adapter_gl_create_rendertarget_view(const struct wined3d_view_des struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rendertarget_view **view) { - struct wined3d_rendertarget_view_gl *view_gl; + struct wined3d_swapchain_rendertarget_view_gl *swap_view_gl = NULL; + struct wined3d_rendertarget_view_gl *view_gl = NULL; HRESULT hr; TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n", wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view); - if (!(view_gl = calloc(1, sizeof(*view_gl)))) + if (swapchain_from_resource(resource)) + { + if (!(swap_view_gl = calloc(1, sizeof(*swap_view_gl)))) + return E_OUTOFMEMORY; + view_gl = &swap_view_gl->view_gl; + } + else if (!(view_gl = calloc(1, sizeof(*view_gl)))) return E_OUTOFMEMORY; if (FAILED(hr = wined3d_rendertarget_view_gl_init(view_gl, desc, resource, parent, parent_ops))) { WARN("Failed to initialise view, hr %#lx.\n", hr); - free(view_gl); + if (swap_view_gl) + free(swap_view_gl); + else if (view_gl) + free(view_gl); return hr; } @@ -4649,12 +4659,48 @@ static void wined3d_view_gl_destroy(struct wined3d_device *device, const struct static void adapter_gl_destroy_rendertarget_view(struct wined3d_rendertarget_view *view) { struct wined3d_rendertarget_view_gl *view_gl = wined3d_rendertarget_view_gl(view); + struct wined3d_swapchain_rendertarget_view_gl *swap_view_gl; struct wined3d_resource *resource = view_gl->v.resource; + struct wined3d_swapchain *swapchain; + void *object = view_gl; TRACE("view_gl %p.\n", view_gl); wined3d_rendertarget_view_cleanup(&view_gl->v); - wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, NULL, NULL, view_gl); + + if ((swapchain = wined3d_swapchain_from_resource(resource))) + { + if ((swap_view_gl = wined3d_swapchain_rendertarget_view_gl(view_gl))) + { + unsigned int i, count = swapchain->state.desc.backbuffer_count - 1; + struct wined3d_swapchain_rendertarget_view *view; + GLuint name = view_gl->gl_view.name; + + for (i = 0; i < count; i++) + { + view_gl->gl_view.name = swap_view_gl->gl_swap_views[i]; + wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, NULL, NULL, NULL); + } + view_gl->gl_view.name = name; + object = swap_view_gl; + + LIST_FOR_EACH_ENTRY(view, &swapchain->back_buffer_rendertarget_views, struct wined3d_swapchain_rendertarget_view, entry) + { + if (view->view != &view_gl->v) + continue; + + list_remove(&view->entry); + break; + } + } + else + { + FIXME("Missing wined3d_swapchain_rendertarget_view_gl for view_gl %p which should not occur.\n", view_gl); + object = view_gl; + } + } + + wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, NULL, NULL, object); } static HRESULT adapter_gl_create_shader_resource_view(const struct wined3d_view_desc *desc, diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 79014b4c331..460afb4ecb3 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1393,19 +1393,30 @@ static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_des struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rendertarget_view **view) { - struct wined3d_rendertarget_view_vk *view_vk; + struct wined3d_swapchain_rendertarget_view_vk *swap_view_vk = NULL; + struct wined3d_rendertarget_view_vk *view_vk = NULL; + HRESULT hr; TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n", wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view); - if (!(view_vk = calloc(1, sizeof(*view_vk)))) + if (swapchain_from_resource(resource)) + { + if (!(swap_view_vk = calloc(1, sizeof(*swap_view_vk)))) + return E_OUTOFMEMORY; + view_vk = &swap_view_vk->view_vk; + } + else if (!(view_vk = calloc(1, sizeof(*view_vk)))) return E_OUTOFMEMORY; if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops))) { WARN("Failed to initialise view, hr %#lx.\n", hr); - free(view_vk); + if (swap_view_vk) + free(swap_view_vk); + else if (view_vk) + free(view_vk); return hr; } @@ -1518,13 +1529,44 @@ static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view) { struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view); + struct wined3d_swapchain_rendertarget_view_vk *swap_view_vk; struct wined3d_resource *resource = view_vk->v.resource; + struct wined3d_swapchain *swapchain; + void *object = view_vk; TRACE("view_vk %p.\n", view_vk); wined3d_rendertarget_view_cleanup(&view_vk->v); - wined3d_view_vk_destroy(resource->device, NULL, &view_vk->vk_image_view, - NULL, NULL, NULL, &view_vk->command_buffer_id, view_vk); + + if ((swapchain = wined3d_swapchain_from_resource(resource))) + { + if ((swap_view_vk = wined3d_swapchain_rendertarget_view_vk(view_vk))) + { + unsigned int i, count = swapchain->state.desc.backbuffer_count - 1; + struct wined3d_swapchain_rendertarget_view *view; + for (i = 0; i < count; i++) + { + wined3d_view_vk_destroy(resource->device, NULL, &swap_view_vk->vk_swap_views[i], NULL, NULL, NULL, &view_vk->command_buffer_id, NULL); + } + + LIST_FOR_EACH_ENTRY(view, &swapchain->back_buffer_rendertarget_views, struct wined3d_swapchain_rendertarget_view, entry) + { + if (view->view != &view_vk->v) + continue; + + list_remove(&view->entry); + break; + } + object = swap_view_vk; + } + else + { + WARN("Missing wined3d_swapchain_view_vk for view_vk %p.\n", view_vk); + object = view_vk; + } + } + + wined3d_view_vk_destroy(resource->device, NULL, &view_vk->vk_image_view, NULL, NULL, NULL, &view_vk->command_buffer_id, object); } static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc, diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index c26df770cdb..1173703b764 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -145,6 +145,11 @@ void wined3d_swapchain_vk_cleanup(struct wined3d_swapchain_vk *swapchain_vk) wined3d_swapchain_cleanup(&swapchain_vk->s); } +struct wined3d_swapchain * __cdecl wined3d_swapchain_from_resource(struct wined3d_resource *resource) +{ + return swapchain_from_resource(resource); +} + ULONG CDECL wined3d_swapchain_incref(struct wined3d_swapchain *swapchain) { unsigned int refcount = InterlockedIncrement(&swapchain->ref); @@ -533,16 +538,51 @@ static void swapchain_gl_set_swap_interval(struct wined3d_swapchain *swapchain, } } +static void wined3d_swapchain_rendertarget_view_gl_rotate(struct wined3d_swapchain *swapchain) +{ + struct wined3d_swapchain_rendertarget_view_gl *swap_view_gl; + struct wined3d_swapchain_rendertarget_view *view; + struct wined3d_rendertarget_view_gl *view_gl; + unsigned int i, count; + GLuint name0; + + if (!swapchain || swapchain->state.desc.backbuffer_count < 2) + return; + + count = swapchain->state.desc.backbuffer_count - 2; + + LIST_FOR_EACH_ENTRY(view, &swapchain->back_buffer_rendertarget_views, struct wined3d_swapchain_rendertarget_view, entry) + { + if (!view->view) + continue; + + view_gl = wined3d_rendertarget_view_gl(view->view); + name0 = view_gl->gl_view.name; + if (!name0) + { + FIXME("Skipping rotate for view_gl %p with name 0 which should not occur.\n", view_gl); + continue; + } + + swap_view_gl = wined3d_swapchain_rendertarget_view_gl(view_gl); + view_gl->gl_view.name = swap_view_gl->gl_swap_views[0]; + for (i = 0; i < count; i++) + swap_view_gl->gl_swap_views[i] = swap_view_gl->gl_swap_views[i + 1]; + + swap_view_gl->gl_swap_views[i] = name0; + } +} + /* Context activation is done by the caller. */ static void wined3d_swapchain_gl_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context *context) { + static const DWORD supported_locations = WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_RB_MULTISAMPLE; struct wined3d_texture_sub_resource *sub_resource; struct wined3d_texture_gl *texture, *texture_prev; struct gl_texture tex0; - GLuint rb0; DWORD locations0; unsigned int i; - static const DWORD supported_locations = WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_RB_MULTISAMPLE; + GLuint rb0; if (swapchain->state.desc.backbuffer_count < 2) return; @@ -554,6 +594,7 @@ static void wined3d_swapchain_gl_rotate(struct wined3d_swapchain *swapchain, str rb0 = texture_prev->rb_multisample; locations0 = texture_prev->t.sub_resources[0].locations; + for (i = 1; i < swapchain->state.desc.backbuffer_count; ++i) { texture = wined3d_texture_gl(swapchain->back_buffers[i]); @@ -574,6 +615,8 @@ static void wined3d_swapchain_gl_rotate(struct wined3d_swapchain *swapchain, str texture_prev->texture_rgb = tex0; texture_prev->rb_multisample = rb0; + wined3d_swapchain_rendertarget_view_gl_rotate(swapchain); + wined3d_texture_validate_location(&texture_prev->t, 0, locations0 & supported_locations); wined3d_texture_invalidate_location(&texture_prev->t, 0, ~(locations0 & supported_locations)); @@ -645,6 +688,12 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, wined3d_texture_load_location(back_buffer, 0, context, back_buffer->resource.draw_binding); + if (gl_info->supported[ARB_FRAMEBUFFER_SRGB]) + { + gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB); + context_invalidate_state(context, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); + } + swapchain_blit(swapchain, context, src_rect, dst_rect); if (swapchain->device->context_count > 1) @@ -1195,6 +1244,41 @@ static VkResult wined3d_swapchain_vk_blit(struct wined3d_swapchain_vk *swapchain return vr; } +static void wined3d_swapchain_rendertarget_view_vk_rotate(struct wined3d_swapchain *swapchain) +{ + struct wined3d_swapchain_rendertarget_view_vk *swap_view_vk; + struct wined3d_swapchain_rendertarget_view *view; + struct wined3d_rendertarget_view_vk *view_vk; + VkImageView vk_image_view0; + unsigned int i, count; + + if (!swapchain || swapchain->state.desc.backbuffer_count < 2) + return; + + count = swapchain->state.desc.backbuffer_count - 2; + LIST_FOR_EACH_ENTRY(view, &swapchain->back_buffer_rendertarget_views, struct wined3d_swapchain_rendertarget_view, entry) + { + if (!view->view) + continue; + + view_vk = wined3d_rendertarget_view_vk(view->view); + if (!view_vk->vk_image_view) + { + FIXME("Skipping rotate for view_vk %p with name 0 which should not occur.\n", view_vk); + continue; + } + + swap_view_vk = wined3d_swapchain_rendertarget_view_vk(view_vk); + vk_image_view0 = view_vk->vk_image_view; + view_vk->vk_image_view = swap_view_vk->vk_swap_views[0]; + + for (i = 0; i < count; i++) + swap_view_vk->vk_swap_views[i] = swap_view_vk->vk_swap_views[i + 1]; + + swap_view_vk->vk_swap_views[i] = vk_image_view0; + } +} + static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, struct wined3d_context_vk *context_vk) { struct wined3d_texture_sub_resource *sub_resource; @@ -1244,6 +1328,8 @@ static void wined3d_swapchain_vk_rotate(struct wined3d_swapchain *swapchain, str texture_prev->bind_mask = bind_mask0; texture_prev->default_image_info = vk_info0; + wined3d_swapchain_rendertarget_view_vk_rotate(swapchain); + wined3d_texture_validate_location(&texture_prev->t, 0, locations0 & supported_locations); wined3d_texture_invalidate_location(&texture_prev->t, 0, ~(locations0 & supported_locations)); @@ -1633,6 +1719,8 @@ static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struc displaymode_set = TRUE; } + list_init(&swapchain->back_buffer_rendertarget_views); + if (swapchain->state.desc.backbuffer_count > 0) { if (!(swapchain->back_buffers = calloc(swapchain->state.desc.backbuffer_count, diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index a506b0c6f18..dd2d1f9f822 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -587,48 +587,99 @@ void wined3d_rendertarget_view_get_box(struct wined3d_rendertarget_view *view, static void wined3d_render_target_view_gl_cs_init(void *object) { + struct wined3d_swapchain_rendertarget_view_gl *swap_view_gl; struct wined3d_rendertarget_view_gl *view_gl = object; + struct wined3d_swapchain_rendertarget_view *lview = NULL; struct wined3d_resource *resource = view_gl->v.resource; const struct wined3d_view_desc *desc = &view_gl->v.desc; + struct wined3d_texture_gl *texture_gl; + struct wined3d_swapchain *swapchain; + unsigned int depth_or_layer_count; + GLenum resource_class, view_class; + struct wined3d_context *context; + unsigned int i, count; + GLuint name; TRACE("view_gl %p.\n", view_gl); if (resource->type == WINED3D_RTYPE_BUFFER) { FIXME("Not implemented for resources %s.\n", debug_d3dresourcetype(resource->type)); + return; } + + texture_gl = wined3d_texture_gl(texture_from_resource(resource)); + + if (resource->type == WINED3D_RTYPE_TEXTURE_3D) + depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx); else + depth_or_layer_count = texture_gl->t.layer_count; + + if (resource->format->id == view_gl->v.format->id + && (view_gl->v.layer_count == 1 && view_gl->v.layer_count == depth_or_layer_count)) { - struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture_from_resource(resource)); - unsigned int depth_or_layer_count; + TRACE("Skipping view init because format and layer_count matches underlying texture\n"); + return; + } - if (resource->type == WINED3D_RTYPE_TEXTURE_3D) - depth_or_layer_count = wined3d_texture_get_level_depth(&texture_gl->t, desc->u.texture.level_idx); - else - depth_or_layer_count = texture_gl->t.layer_count; + resource_class = wined3d_format_gl(resource->format)->view_class; + view_class = wined3d_format_gl(view_gl->v.format)->view_class; + if (resource_class != view_class) + { + FIXME("Render target view not supported, resource format %s, view format %s.\n", + debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id)); + return; + } - if (resource->format->id != view_gl->v.format->id - || (view_gl->v.layer_count != 1 && view_gl->v.layer_count != depth_or_layer_count)) - { - GLenum resource_class, view_class; + context = context_acquire(resource->device, NULL, 0); + create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format); + context_release(context); - resource_class = wined3d_format_gl(resource->format)->view_class; - view_class = wined3d_format_gl(view_gl->v.format)->view_class; - if (resource_class != view_class) - { - FIXME("Render target view not supported, resource format %s, view format %s.\n", - debug_d3dformat(resource->format->id), debug_d3dformat(view_gl->v.format->id)); - return; - } - if (texture_gl->t.swapchain && texture_gl->t.swapchain->state.desc.backbuffer_count > 1) - { - FIXME("Swapchain views not supported.\n"); - return; - } + if (!view_gl->gl_view.name) + { + ERR("Failed to create render target view for resource %p\n", resource); + /* TODO: cleanup gl, mem? */ + return; + } + + if (!(swapchain = swapchain_from_resource(resource))) + return; - create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format); + if (!(swap_view_gl = wined3d_swapchain_rendertarget_view_gl(view_gl))) + { + WARN("Missing wined3d_swapchain_rendertarget_view_gl for view_gl %p.\n", view_gl); + return; + } + + context = context_acquire(resource->device, NULL, 0); + count = swapchain->state.desc.backbuffer_count - 1; + name = view_gl->gl_view.name; + for (i = 0; i < count; i++) + { + texture_gl = wined3d_texture_gl(swapchain->back_buffers[i + 1]); + create_texture_view(&view_gl->gl_view, texture_gl->target, desc, texture_gl, view_gl->v.format); + if (view_gl->gl_view.name) + { + swap_view_gl->gl_swap_views[i] = view_gl->gl_view.name; + continue; } + + ERR("Failed to create render target view for swapchain %p backbuffer[%u]\n", swapchain, i); + /* TODO: cleanup gl, mem? */ + context_release(context); + return; + } + view_gl->gl_view.name = name; + context_release(context); + + if (!(lview = calloc(1, sizeof(*lview)))) + { + ERR("Out of memory.\n"); + /* TODO: cleanup gl, mem? */ + return; } + list_add_head(&swapchain->back_buffer_rendertarget_views, &lview->entry); + lview->view = &view_gl->v; } static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view, @@ -896,14 +947,18 @@ static VkImageView wined3d_view_vk_create_vk_image_view(struct wined3d_context_v static void wined3d_render_target_view_vk_cs_init(void *object) { + struct wined3d_swapchain_rendertarget_view_vk *swap_view_vk; + struct wined3d_swapchain_rendertarget_view *lview = NULL; struct wined3d_rendertarget_view_vk *view_vk = object; struct wined3d_view_desc *desc = &view_vk->v.desc; const struct wined3d_format_vk *format_vk; struct wined3d_texture_vk *texture_vk; + struct wined3d_swapchain *swapchain; struct wined3d_resource *resource; struct wined3d_context *context; VkImageUsageFlags vk_usage = 0; uint32_t default_flags = 0; + unsigned int i, count; TRACE("view_vk %p.\n", view_vk); @@ -930,12 +985,6 @@ static void wined3d_render_target_view_vk_cs_init(void *object) return; } - if (texture_vk->t.swapchain && texture_vk->t.swapchain->state.desc.backbuffer_count > 1) - { - FIXME("Swapchain views not supported.\n"); - return; - } - if (resource->bind_flags & WINED3D_BIND_RENDER_TARGET) vk_usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL) @@ -947,8 +996,48 @@ static void wined3d_render_target_view_vk_cs_init(void *object) context_release(context); if (!view_vk->vk_image_view) + { + ERR("Failed to create render target view for resource %p\n", resource); + /* TODO: cleanup gl, mem? */ + return; + } + + if (!(swapchain = swapchain_from_resource(resource))) return; + if (!(swap_view_vk = wined3d_swapchain_rendertarget_view_vk(view_vk))) + { + WARN("Missing wined3d_swapchain_view_vk for view_vk %p.\n", view_vk); + return; + } + + context = context_acquire(resource->device, NULL, 0); + count = swapchain->state.desc.backbuffer_count - 1; + for (i = 0; i < count; i++) + { + texture_vk = wined3d_texture_vk(swapchain->back_buffers[i + 1]); + swap_view_vk->vk_swap_views[i] = wined3d_view_vk_create_vk_image_view(wined3d_context_vk(context), + desc, texture_vk, format_vk, COLOR_FIXUP_IDENTITY, true, vk_usage); + if (view_vk->vk_image_view) + continue; + + ERR("Failed to create render target view for swapchain %p backbuffer[%u]\n", swapchain, i); + context_release(context); + /* TODO: cleanup gl, mem? */ + return; + } + context_release(context); + + if (!(lview = calloc(1, sizeof(*lview)))) + { + ERR("Out of memory.\n"); + /* TODO: cleanup gl, mem? */ + return; + } + + list_add_head(&swapchain->back_buffer_rendertarget_views, &lview->entry); + lview->view = &view_vk->v; + TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(view_vk->vk_image_view)); } @@ -979,6 +1068,7 @@ HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_view_desc *d wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view); adapter_ops = resource->device->adapter->adapter_ops; + return adapter_ops->adapter_create_rendertarget_view(desc, resource, parent, parent_ops, view); } diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index e08dd089521..00438617093 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -306,6 +306,7 @@ @ cdecl wined3d_swapchain_get_parent(ptr) @ cdecl wined3d_swapchain_get_raster_status(ptr ptr) @ cdecl wined3d_swapchain_get_state(ptr) +@ cdecl wined3d_swapchain_from_resource(ptr) @ cdecl wined3d_swapchain_incref(ptr) @ cdecl wined3d_swapchain_present(ptr ptr ptr ptr long long) @ cdecl wined3d_swapchain_resize_buffers(ptr long long long long long long) diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index c9c7118c59e..709b7fafed5 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -1084,6 +1084,21 @@ struct wined3d_rendertarget_view_gl struct wined3d_gl_view gl_view; }; +struct wined3d_swapchain_rendertarget_view_gl +{ + struct wined3d_rendertarget_view_gl view_gl; + GLuint gl_swap_views[29]; /* D3DPRESENT_BACK_BUFFERS_MAX_EX - 1 for view_gl->gl_image_view */ +}; + +static inline struct wined3d_swapchain_rendertarget_view_gl *wined3d_swapchain_rendertarget_view_gl( + struct wined3d_rendertarget_view_gl *view_gl) +{ + if (!view_gl || !wined3d_swapchain_from_resource(view_gl->v.resource)) + return NULL; + + return CONTAINING_RECORD(view_gl, struct wined3d_swapchain_rendertarget_view_gl, view_gl); +} + static inline struct wined3d_rendertarget_view_gl *wined3d_rendertarget_view_gl( struct wined3d_rendertarget_view *view) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index e4e0cf24dc7..d95dc35d3b3 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3563,8 +3563,7 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned struct wined3d_context *context, uint32_t location); void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain); -BOOL wined3d_texture_can_use_pbo(const struct wined3d_texture *texture, const struct wined3d_d3d_info *d3d_info) - ; +BOOL wined3d_texture_can_use_pbo(const struct wined3d_texture *texture, const struct wined3d_d3d_info *d3d_info); void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *texture); void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture, HWND window, RECT *rect); @@ -4094,6 +4093,12 @@ struct wined3d_swapchain_ops void (*swapchain_frontbuffer_updated)(struct wined3d_swapchain *swapchain); }; +struct wined3d_swapchain_rendertarget_view +{ + struct list entry; + struct wined3d_rendertarget_view *view; +}; + struct wined3d_swapchain { LONG ref; @@ -4101,16 +4106,16 @@ struct wined3d_swapchain const struct wined3d_parent_ops *parent_ops; const struct wined3d_swapchain_ops *swapchain_ops; struct wined3d_device *device; - struct wined3d_texture **back_buffers; struct wined3d_texture *front_buffer; + struct list back_buffer_rendertarget_views; + struct wined3d_gamma_ramp orig_gamma; bool reapply_mode; const struct wined3d_format *ds_format; struct wined3d_palette *palette; RECT front_buffer_update; - unsigned int swap_interval; - unsigned int max_frame_latency; + unsigned int swap_interval, max_frame_latency; /* Performance tracking */ LARGE_INTEGER last_present_time; @@ -4121,6 +4126,14 @@ struct wined3d_swapchain HDC dc; }; +static inline struct wined3d_swapchain *swapchain_from_resource(struct wined3d_resource *resource) +{ + if (!resource || resource->type != WINED3D_RTYPE_TEXTURE_2D) + return NULL; + + return texture_from_resource(resource)->swapchain; +} + void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activate); void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain); struct wined3d_output * wined3d_swapchain_get_output(const struct wined3d_swapchain *swapchain); diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index 937a958760c..fafde8c0699 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -1039,6 +1039,21 @@ struct wined3d_rendertarget_view_vk uint64_t command_buffer_id; }; +struct wined3d_swapchain_rendertarget_view_vk +{ + struct wined3d_rendertarget_view_vk view_vk; + VkImageView vk_swap_views[29]; /* D3DPRESENT_BACK_BUFFERS_MAX_EX - 1 for view_vk->vk_image_view */ +}; + +static inline struct wined3d_swapchain_rendertarget_view_vk *wined3d_swapchain_rendertarget_view_vk( + struct wined3d_rendertarget_view_vk *view_vk) +{ + if (!view_vk || !wined3d_swapchain_from_resource(view_vk->v.resource)) + return NULL; + + return CONTAINING_RECORD(view_vk, struct wined3d_swapchain_rendertarget_view_vk, view_vk); +} + static inline struct wined3d_rendertarget_view_vk *wined3d_rendertarget_view_vk( struct wined3d_rendertarget_view *view) { diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 355140043db..a2e60493a22 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2914,6 +2914,7 @@ void __cdecl wined3d_swapchain_get_desc(const struct wined3d_swapchain *swapchai HRESULT __cdecl wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain, struct wined3d_raster_status *raster_status); struct wined3d_swapchain_state * __cdecl wined3d_swapchain_get_state(struct wined3d_swapchain *swapchain); +struct wined3d_swapchain * __cdecl wined3d_swapchain_from_resource(struct wined3d_resource *resource); ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain); HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, uint32_t flags); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10567