diff --git a/src/gallium/drivers/d3d12/d3d12_resource.cpp b/src/gallium/drivers/d3d12/d3d12_resource.cpp index fefaad24264..3ca838f7088 100644 --- a/src/gallium/drivers/d3d12/d3d12_resource.cpp +++ b/src/gallium/drivers/d3d12/d3d12_resource.cpp @@ -86,6 +86,8 @@ d3d12_resource_destroy(struct pipe_screen *pscreen, screen->winsys->displaytarget_destroy(screen->winsys, resource->dt); } + if (resource->dt_proxy) + pipe_resource_reference(&resource->dt_proxy, NULL); threaded_resource_deinit(presource); if (can_map_directly(presource)) util_range_destroy(&resource->valid_buffer_range); @@ -369,14 +371,24 @@ init_texture(struct d3d12_screen *screen, if (screen->winsys && (templ->bind & PIPE_BIND_DISPLAY_TARGET)) { struct sw_winsys *winsys = screen->winsys; - res->dt = winsys->displaytarget_create(screen->winsys, - res->base.b.bind, - res->base.b.format, - templ->width0, - templ->height0, - 64, NULL, - &res->dt_stride); - res->dt_refcount = 1; + if (winsys->is_displaytarget_format_supported(winsys, res->base.b.bind, res->base.b.format)) { + res->dt = winsys->displaytarget_create(screen->winsys, + res->base.b.bind, + res->base.b.format, + templ->width0, + templ->height0, + 64, NULL, + &res->dt_stride); + res->dt_refcount = 1; + } else { + assert(res->base.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT); /* The only format we proxy right now */ + struct pipe_resource proxy_templ = *templ; + proxy_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; + res->dt_proxy = screen->base.resource_create(&screen->base, &proxy_templ); + if (!res->dt_proxy) + return false; + assert(d3d12_resource(res->dt_proxy)->dt); + } } res->bo = d3d12_bo_wrap_res(screen, d3d12_res, init_residency); diff --git a/src/gallium/drivers/d3d12/d3d12_resource.h b/src/gallium/drivers/d3d12/d3d12_resource.h index c17eba00aa7..9667991cdef 100644 --- a/src/gallium/drivers/d3d12/d3d12_resource.h +++ b/src/gallium/drivers/d3d12/d3d12_resource.h @@ -48,9 +48,12 @@ struct d3d12_resource { unsigned int plane_slice; struct pipe_resource* first_plane; unsigned mip_levels; + struct sw_displaytarget *dt; unsigned dt_refcount; /* For planar resources sharing the dt pointer */ unsigned dt_stride; + struct pipe_resource *dt_proxy; + struct util_range valid_buffer_range; uint32_t bind_counts[PIPE_SHADER_TYPES][D3D12_RESOURCE_BINDING_TYPES]; unsigned generation_id; diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp index 7d6a1aa1699..57e1d348480 100644 --- a/src/gallium/drivers/d3d12/d3d12_screen.cpp +++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp @@ -634,7 +634,8 @@ d3d12_is_format_supported(struct pipe_screen *pscreen, } if (bind & PIPE_BIND_DISPLAY_TARGET) { - if (!screen->winsys->is_displaytarget_format_supported(screen->winsys, bind, format)) + enum pipe_format dt_format = format == PIPE_FORMAT_R16G16B16A16_FLOAT ? PIPE_FORMAT_R8G8B8A8_UNORM : format; + if (!screen->winsys->is_displaytarget_format_supported(screen->winsys, bind, dt_format)) return false; } @@ -798,6 +799,29 @@ d3d12_flush_frontbuffer(struct pipe_screen * pscreen, if (!winsys || !pctx) return; + assert(res->dt || res->dt_proxy); + if (res->dt_proxy) { + struct pipe_blit_info blit; + + memset(&blit, 0, sizeof(blit)); + blit.dst.resource = res->dt_proxy; + blit.dst.box.width = blit.dst.resource->width0; + blit.dst.box.height = blit.dst.resource->height0; + blit.dst.box.depth = 1; + blit.dst.format = blit.dst.resource->format; + blit.src.resource = pres; + blit.src.box.width = blit.src.resource->width0; + blit.src.box.height = blit.src.resource->height0; + blit.src.box.depth = 1; + blit.src.format = blit.src.resource->format; + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + pctx->blit(pctx, &blit); + pres = res->dt_proxy; + res = d3d12_resource(pres); + } + assert(res->dt); void *map = winsys->displaytarget_map(winsys, res->dt, 0);