Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_surface.cpp
4570 views
/*1* Copyright © Microsoft Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "d3d12_context.h"24#include "d3d12_format.h"25#include "d3d12_resource.h"26#include "d3d12_screen.h"27#include "d3d12_surface.h"2829#include "util/format/u_format.h"30#include "util/u_inlines.h"31#include "util/u_memory.h"3233static D3D12_DSV_DIMENSION34view_dsv_dimension(enum pipe_texture_target target, unsigned samples)35{36switch (target) {37case PIPE_TEXTURE_1D: return D3D12_DSV_DIMENSION_TEXTURE1D;38case PIPE_TEXTURE_1D_ARRAY: return D3D12_DSV_DIMENSION_TEXTURE1DARRAY;3940case PIPE_TEXTURE_2D:41case PIPE_TEXTURE_RECT:42return samples > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS :43D3D12_DSV_DIMENSION_TEXTURE2D;4445case PIPE_TEXTURE_2D_ARRAY:46case PIPE_TEXTURE_CUBE:47return samples > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY :48D3D12_DSV_DIMENSION_TEXTURE2DARRAY;4950default:51unreachable("unexpected target");52}53}5455static D3D12_RTV_DIMENSION56view_rtv_dimension(enum pipe_texture_target target, unsigned samples)57{58switch (target) {59case PIPE_BUFFER: return D3D12_RTV_DIMENSION_BUFFER;60case PIPE_TEXTURE_1D: return D3D12_RTV_DIMENSION_TEXTURE1D;61case PIPE_TEXTURE_1D_ARRAY: return D3D12_RTV_DIMENSION_TEXTURE1DARRAY;6263case PIPE_TEXTURE_2D:64case PIPE_TEXTURE_RECT:65return samples > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS :66D3D12_RTV_DIMENSION_TEXTURE2D;6768case PIPE_TEXTURE_2D_ARRAY:69case PIPE_TEXTURE_CUBE:70return samples > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY :71D3D12_RTV_DIMENSION_TEXTURE2DARRAY;7273case PIPE_TEXTURE_3D: return D3D12_RTV_DIMENSION_TEXTURE3D;7475default:76unreachable("unexpected target");77}78}7980static void81initialize_dsv(struct pipe_context *pctx,82struct pipe_resource *pres,83const struct pipe_surface *tpl,84struct d3d12_descriptor_handle *handle,85DXGI_FORMAT dxgi_format)86{87struct d3d12_resource *res = d3d12_resource(pres);88struct d3d12_screen *screen = d3d12_screen(pctx->screen);8990D3D12_DEPTH_STENCIL_VIEW_DESC desc;91desc.Format = dxgi_format;92desc.Flags = D3D12_DSV_FLAG_NONE;9394desc.ViewDimension = view_dsv_dimension(pres->target, pres->nr_samples);95switch (desc.ViewDimension) {96case D3D12_DSV_DIMENSION_TEXTURE1D:97if (tpl->u.tex.first_layer > 0)98debug_printf("D3D12: can't create 1D DSV from layer %d\n",99tpl->u.tex.first_layer);100101desc.Texture1D.MipSlice = tpl->u.tex.level;102break;103104case D3D12_DSV_DIMENSION_TEXTURE1DARRAY:105desc.Texture1DArray.MipSlice = tpl->u.tex.level;106desc.Texture1DArray.FirstArraySlice = tpl->u.tex.first_layer;107desc.Texture1DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;108break;109110case D3D12_DSV_DIMENSION_TEXTURE2DMS:111if (tpl->u.tex.first_layer > 0)112debug_printf("D3D12: can't create 2DMS DSV from layer %d\n",113tpl->u.tex.first_layer);114115break;116117case D3D12_DSV_DIMENSION_TEXTURE2D:118if (tpl->u.tex.first_layer > 0)119debug_printf("D3D12: can't create 2D DSV from layer %d\n",120tpl->u.tex.first_layer);121122desc.Texture2D.MipSlice = tpl->u.tex.level;123break;124125case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:126desc.Texture2DMSArray.FirstArraySlice = tpl->u.tex.first_layer;127desc.Texture2DMSArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;128break;129130case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:131desc.Texture2DArray.MipSlice = tpl->u.tex.level;132desc.Texture2DArray.FirstArraySlice = tpl->u.tex.first_layer;133desc.Texture2DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;134break;135136default:137unreachable("Unhandled DSV dimension");138}139140mtx_lock(&screen->descriptor_pool_mutex);141d3d12_descriptor_pool_alloc_handle(screen->dsv_pool, handle);142mtx_unlock(&screen->descriptor_pool_mutex);143144screen->dev->CreateDepthStencilView(d3d12_resource_resource(res), &desc,145handle->cpu_handle);146}147148static void149initialize_rtv(struct pipe_context *pctx,150struct pipe_resource *pres,151const struct pipe_surface *tpl,152struct d3d12_descriptor_handle *handle,153DXGI_FORMAT dxgi_format)154{155struct d3d12_resource *res = d3d12_resource(pres);156struct d3d12_screen *screen = d3d12_screen(pctx->screen);157158D3D12_RENDER_TARGET_VIEW_DESC desc;159desc.Format = dxgi_format;160161desc.ViewDimension = view_rtv_dimension(pres->target, pres->nr_samples);162switch (desc.ViewDimension) {163case D3D12_RTV_DIMENSION_BUFFER:164desc.Buffer.FirstElement = 0;165desc.Buffer.NumElements = pres->width0 / util_format_get_blocksize(tpl->format);166break;167168case D3D12_RTV_DIMENSION_TEXTURE1D:169if (tpl->u.tex.first_layer > 0)170debug_printf("D3D12: can't create 1D RTV from layer %d\n",171tpl->u.tex.first_layer);172173desc.Texture1D.MipSlice = tpl->u.tex.level;174break;175176case D3D12_RTV_DIMENSION_TEXTURE1DARRAY:177desc.Texture1DArray.MipSlice = tpl->u.tex.level;178desc.Texture1DArray.FirstArraySlice = tpl->u.tex.first_layer;179desc.Texture1DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;180break;181182case D3D12_RTV_DIMENSION_TEXTURE2DMS:183if (tpl->u.tex.first_layer > 0)184debug_printf("D3D12: can't create 2DMS RTV from layer %d\n",185tpl->u.tex.first_layer);186break;187188case D3D12_RTV_DIMENSION_TEXTURE2D:189if (tpl->u.tex.first_layer > 0)190debug_printf("D3D12: can't create 2D RTV from layer %d\n",191tpl->u.tex.first_layer);192193desc.Texture2D.MipSlice = tpl->u.tex.level;194desc.Texture2D.PlaneSlice = 0;195break;196197case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:198desc.Texture2DMSArray.FirstArraySlice = tpl->u.tex.first_layer;199desc.Texture2DMSArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;200break;201202case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:203desc.Texture2DArray.MipSlice = tpl->u.tex.level;204desc.Texture2DArray.FirstArraySlice = tpl->u.tex.first_layer;205desc.Texture2DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;206desc.Texture2DArray.PlaneSlice = 0;207break;208209case D3D12_RTV_DIMENSION_TEXTURE3D:210desc.Texture3D.MipSlice = tpl->u.tex.level;211desc.Texture3D.FirstWSlice = tpl->u.tex.first_layer;212desc.Texture3D.WSize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;213break;214215default:216unreachable("Unhandled RTV dimension");217}218219mtx_lock(&screen->descriptor_pool_mutex);220d3d12_descriptor_pool_alloc_handle(screen->rtv_pool, handle);221mtx_unlock(&screen->descriptor_pool_mutex);222223screen->dev->CreateRenderTargetView(d3d12_resource_resource(res), &desc,224handle->cpu_handle);225}226227static struct pipe_surface *228d3d12_create_surface(struct pipe_context *pctx,229struct pipe_resource *pres,230const struct pipe_surface *tpl)231{232bool is_depth_or_stencil = util_format_is_depth_or_stencil(tpl->format);233unsigned bind = is_depth_or_stencil ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET;234235/* Don't bother if we don't support the requested format as RT or DS */236if (!pctx->screen->is_format_supported(pctx->screen, tpl->format, PIPE_TEXTURE_2D,237tpl->nr_samples, tpl->nr_samples,bind))238return NULL;239240struct d3d12_surface *surface = CALLOC_STRUCT(d3d12_surface);241if (!surface)242return NULL;243244pipe_resource_reference(&surface->base.texture, pres);245pipe_reference_init(&surface->base.reference, 1);246surface->base.context = pctx;247surface->base.format = tpl->format;248surface->base.width = u_minify(pres->width0, tpl->u.tex.level);249surface->base.height = u_minify(pres->height0, tpl->u.tex.level);250surface->base.u.tex.level = tpl->u.tex.level;251surface->base.u.tex.first_layer = tpl->u.tex.first_layer;252surface->base.u.tex.last_layer = tpl->u.tex.last_layer;253254DXGI_FORMAT dxgi_format = d3d12_get_resource_rt_format(tpl->format);255if (is_depth_or_stencil)256initialize_dsv(pctx, pres, tpl, &surface->desc_handle, dxgi_format);257else258initialize_rtv(pctx, pres, tpl, &surface->desc_handle, dxgi_format);259260return &surface->base;261}262263static void264d3d12_surface_destroy(struct pipe_context *pctx,265struct pipe_surface *psurf)266{267struct d3d12_surface *surface = (struct d3d12_surface*) psurf;268struct d3d12_screen *screen = d3d12_screen(pctx->screen);269270mtx_lock(&screen->descriptor_pool_mutex);271d3d12_descriptor_handle_free(&surface->desc_handle);272if (d3d12_descriptor_handle_is_allocated(&surface->uint_rtv_handle))273d3d12_descriptor_handle_free(&surface->uint_rtv_handle);274mtx_unlock(&screen->descriptor_pool_mutex);275276pipe_resource_reference(&psurf->texture, NULL);277pipe_resource_reference(&surface->rgba_texture, NULL);278FREE(surface);279}280281static void282blit_surface(struct d3d12_surface *surface, bool pre)283{284struct pipe_blit_info info = {};285286info.src.resource = pre ? surface->base.texture : surface->rgba_texture;287info.dst.resource = pre ? surface->rgba_texture : surface->base.texture;288info.src.format = pre ? surface->base.texture->format : PIPE_FORMAT_R8G8B8A8_UNORM;289info.dst.format = pre ? PIPE_FORMAT_R8G8B8A8_UNORM : surface->base.texture->format;290info.src.level = info.dst.level = 0;291info.src.box.x = info.dst.box.x = 0;292info.src.box.y = info.dst.box.y = 0;293info.src.box.z = info.dst.box.z = 0;294info.src.box.width = info.dst.box.width = surface->base.width;295info.src.box.height = info.dst.box.height = surface->base.height;296info.src.box.depth = info.dst.box.depth = 0;297info.mask = PIPE_MASK_RGBA;298299d3d12_blit(surface->base.context, &info);300}301302enum d3d12_surface_conversion_mode303d3d12_surface_update_pre_draw(struct d3d12_surface *surface,304DXGI_FORMAT format)305{306struct d3d12_screen *screen = d3d12_screen(surface->base.context->screen);307struct d3d12_resource *res = d3d12_resource(surface->base.texture);308DXGI_FORMAT dxgi_format = d3d12_get_resource_rt_format(surface->base.format);309enum d3d12_surface_conversion_mode mode;310311if (dxgi_format == format)312return D3D12_SURFACE_CONVERSION_NONE;313314if (dxgi_format == DXGI_FORMAT_B8G8R8A8_UNORM ||315dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM)316mode = D3D12_SURFACE_CONVERSION_BGRA_UINT;317else318mode = D3D12_SURFACE_CONVERSION_RGBA_UINT;319320if (mode == D3D12_SURFACE_CONVERSION_BGRA_UINT) {321if (!surface->rgba_texture) {322struct pipe_resource templ = {{0}};323struct pipe_resource *src = surface->base.texture;324325templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;326templ.width0 = src->width0;327templ.height0 = src->height0;328templ.depth0 = src->depth0;329templ.array_size = src->array_size;330templ.nr_samples = src->nr_samples;331templ.nr_storage_samples = src->nr_storage_samples;332templ.usage = PIPE_USAGE_DEFAULT | PIPE_USAGE_STAGING;333templ.bind = src->bind;334templ.target = src->target;335336surface->rgba_texture = screen->base.resource_create(&screen->base, &templ);337}338339blit_surface(surface, true);340res = d3d12_resource(surface->rgba_texture);341}342343if (!d3d12_descriptor_handle_is_allocated(&surface->uint_rtv_handle)) {344initialize_rtv(surface->base.context, &res->base, &surface->base,345&surface->uint_rtv_handle, DXGI_FORMAT_R8G8B8A8_UINT);346}347348return mode;349}350351void352d3d12_surface_update_post_draw(struct d3d12_surface *surface,353enum d3d12_surface_conversion_mode mode)354{355if (mode == D3D12_SURFACE_CONVERSION_BGRA_UINT)356blit_surface(surface, false);357}358359D3D12_CPU_DESCRIPTOR_HANDLE360d3d12_surface_get_handle(struct d3d12_surface *surface,361enum d3d12_surface_conversion_mode mode)362{363if (mode != D3D12_SURFACE_CONVERSION_NONE)364return surface->uint_rtv_handle.cpu_handle;365return surface->desc_handle.cpu_handle;366}367368void369d3d12_context_surface_init(struct pipe_context *context)370{371context->create_surface = d3d12_create_surface;372context->surface_destroy = d3d12_surface_destroy;373}374375376