From fee83f4fcc8d95809ebc0fb5e0f351141242b048 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Fri, 22 Aug 2025 14:31:33 -0700 Subject: [PATCH] d3d12: Move logicop descriptor initialization to after all blits The blit code is destructive on the framebuffer state, which means that it can set new render targets. If you have 2 BGRA surfaces bound for logic ops, then after setting up the surface for the first one, the blit for the second will end up destroying + re-creating the surface for the first one. Let's be robust to this by putting the blit in a first pass, and then actually initializing all of the descriptors in a second pass. This is still woefully inefficient but at least it's correct. Part-of: --- src/gallium/drivers/d3d12/d3d12_draw.cpp | 2 +- src/gallium/drivers/d3d12/d3d12_surface.cpp | 18 ++++++++++-------- src/gallium/drivers/d3d12/d3d12_surface.h | 3 ++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp index 3b1668818df..11fa9c66907 100644 --- a/src/gallium/drivers/d3d12/d3d12_draw.cpp +++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp @@ -1160,7 +1160,7 @@ d3d12_draw_vbo(struct pipe_context *pctx, for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { if (ctx->fb_cbufs[i]) { struct d3d12_surface *surface = ctx->fb_cbufs[i]; - render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]); + render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i], d3d12_rtv_format(ctx, i)); d3d12_batch_reference_surface_texture(batch, surface); } else render_targets[i] = screen->null_rtv.cpu_handle; diff --git a/src/gallium/drivers/d3d12/d3d12_surface.cpp b/src/gallium/drivers/d3d12/d3d12_surface.cpp index e8b7912ec2c..9abde8e9696 100644 --- a/src/gallium/drivers/d3d12/d3d12_surface.cpp +++ b/src/gallium/drivers/d3d12/d3d12_surface.cpp @@ -298,7 +298,6 @@ d3d12_surface_update_pre_draw(struct pipe_context *pctx, struct d3d12_surface *surface, DXGI_FORMAT format) { - struct d3d12_screen *screen = d3d12_screen(pctx->screen); struct d3d12_resource *res = d3d12_resource(surface->base.texture); DXGI_FORMAT dxgi_format = d3d12_get_resource_rt_format(surface->base.format); enum d3d12_surface_conversion_mode mode; @@ -315,11 +314,6 @@ d3d12_surface_update_pre_draw(struct pipe_context *pctx, mode = D3D12_SURFACE_CONVERSION_BGRA_UINT; } - if (!d3d12_descriptor_handle_is_allocated(&surface->uint_rtv_handle)) { - initialize_rtv(screen, res, &surface->base, - &surface->uint_rtv_handle, format); - } - return mode; } @@ -334,9 +328,17 @@ d3d12_surface_update_post_draw(struct pipe_context *pctx, D3D12_CPU_DESCRIPTOR_HANDLE d3d12_surface_get_handle(struct d3d12_surface *surface, - enum d3d12_surface_conversion_mode mode) + enum d3d12_surface_conversion_mode mode, + DXGI_FORMAT format) { - if (mode != D3D12_SURFACE_CONVERSION_NONE) + if (mode != D3D12_SURFACE_CONVERSION_NONE) { + struct d3d12_resource *base_res = d3d12_resource(surface->base.texture); + if (!d3d12_descriptor_handle_is_allocated(&surface->uint_rtv_handle)) { + initialize_rtv(surface->screen, + d3d12_resource(d3d12_resource_get_logicop_texture(base_res)), + &surface->base, &surface->uint_rtv_handle, format); + } return surface->uint_rtv_handle.cpu_handle; + } return surface->desc_handle.cpu_handle; } diff --git a/src/gallium/drivers/d3d12/d3d12_surface.h b/src/gallium/drivers/d3d12/d3d12_surface.h index 853914b79ad..19e31d14028 100644 --- a/src/gallium/drivers/d3d12/d3d12_surface.h +++ b/src/gallium/drivers/d3d12/d3d12_surface.h @@ -55,7 +55,8 @@ d3d12_surface_update_post_draw(struct pipe_context *pctx, D3D12_CPU_DESCRIPTOR_HANDLE d3d12_surface_get_handle(struct d3d12_surface *surface, - enum d3d12_surface_conversion_mode mode); + enum d3d12_surface_conversion_mode mode, + DXGI_FORMAT format); struct d3d12_surface * d3d12_create_surface(struct d3d12_screen *screen,