d3d12: Support R16G16B16A16_FLOAT display targets

Since GDI doesn't support this format, we need a fallback path to
get contents on-screen if we're not using DXGI. For that scenario,
we allocate a proxy display target and blit during frontbuffer flush.

Once we have that fallback in place, we can override the sw winsys
format support check for that format.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27512>
This commit is contained in:
Jesse Natalie
2024-02-07 10:59:59 -08:00
committed by Marge Bot
parent 6a60270336
commit 5c85cdd378
3 changed files with 48 additions and 9 deletions

View File

@@ -86,6 +86,8 @@ d3d12_resource_destroy(struct pipe_screen *pscreen,
screen->winsys->displaytarget_destroy(screen->winsys, resource->dt); screen->winsys->displaytarget_destroy(screen->winsys, resource->dt);
} }
if (resource->dt_proxy)
pipe_resource_reference(&resource->dt_proxy, NULL);
threaded_resource_deinit(presource); threaded_resource_deinit(presource);
if (can_map_directly(presource)) if (can_map_directly(presource))
util_range_destroy(&resource->valid_buffer_range); 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)) { if (screen->winsys && (templ->bind & PIPE_BIND_DISPLAY_TARGET)) {
struct sw_winsys *winsys = screen->winsys; struct sw_winsys *winsys = screen->winsys;
res->dt = winsys->displaytarget_create(screen->winsys, if (winsys->is_displaytarget_format_supported(winsys, res->base.b.bind, res->base.b.format)) {
res->base.b.bind, res->dt = winsys->displaytarget_create(screen->winsys,
res->base.b.format, res->base.b.bind,
templ->width0, res->base.b.format,
templ->height0, templ->width0,
64, NULL, templ->height0,
&res->dt_stride); 64, NULL,
res->dt_refcount = 1; &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); res->bo = d3d12_bo_wrap_res(screen, d3d12_res, init_residency);

View File

@@ -48,9 +48,12 @@ struct d3d12_resource {
unsigned int plane_slice; unsigned int plane_slice;
struct pipe_resource* first_plane; struct pipe_resource* first_plane;
unsigned mip_levels; unsigned mip_levels;
struct sw_displaytarget *dt; struct sw_displaytarget *dt;
unsigned dt_refcount; /* For planar resources sharing the dt pointer */ unsigned dt_refcount; /* For planar resources sharing the dt pointer */
unsigned dt_stride; unsigned dt_stride;
struct pipe_resource *dt_proxy;
struct util_range valid_buffer_range; struct util_range valid_buffer_range;
uint32_t bind_counts[PIPE_SHADER_TYPES][D3D12_RESOURCE_BINDING_TYPES]; uint32_t bind_counts[PIPE_SHADER_TYPES][D3D12_RESOURCE_BINDING_TYPES];
unsigned generation_id; unsigned generation_id;

View File

@@ -634,7 +634,8 @@ d3d12_is_format_supported(struct pipe_screen *pscreen,
} }
if (bind & PIPE_BIND_DISPLAY_TARGET) { 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; return false;
} }
@@ -798,6 +799,29 @@ d3d12_flush_frontbuffer(struct pipe_screen * pscreen,
if (!winsys || !pctx) if (!winsys || !pctx)
return; 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); assert(res->dt);
void *map = winsys->displaytarget_map(winsys, res->dt, 0); void *map = winsys->displaytarget_map(winsys, res->dt, 0);