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);
|
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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user