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:
@@ -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,6 +371,7 @@ init_texture(struct d3d12_screen *screen,
|
||||
|
||||
if (screen->winsys && (templ->bind & PIPE_BIND_DISPLAY_TARGET)) {
|
||||
struct sw_winsys *winsys = screen->winsys;
|
||||
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,
|
||||
@@ -377,6 +380,15 @@ init_texture(struct d3d12_screen *screen,
|
||||
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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user