Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_screen.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_screen.h"2425#include "d3d12_bufmgr.h"26#include "d3d12_compiler.h"27#include "d3d12_context.h"28#include "d3d12_debug.h"29#include "d3d12_fence.h"30#include "d3d12_format.h"31#include "d3d12_resource.h"32#include "d3d12_nir_passes.h"3334#include "pipebuffer/pb_bufmgr.h"35#include "util/debug.h"36#include "util/u_math.h"37#include "util/u_memory.h"38#include "util/u_screen.h"39#include "util/u_dl.h"4041#include "nir.h"42#include "frontend/sw_winsys.h"4344#include <directx/d3d12sdklayers.h>4546#include <dxguids/dxguids.h>47static GUID OpenGLOn12CreatorID = { 0x6bb3cd34, 0x0d19, 0x45ab, 0x97, 0xed, 0xd7, 0x20, 0xba, 0x3d, 0xfc, 0x80 };4849static const struct debug_named_value50d3d12_debug_options[] = {51{ "verbose", D3D12_DEBUG_VERBOSE, NULL },52{ "blit", D3D12_DEBUG_BLIT, "Trace blit and copy resource calls" },53{ "experimental", D3D12_DEBUG_EXPERIMENTAL, "Enable experimental shader models feature" },54{ "dxil", D3D12_DEBUG_DXIL, "Dump DXIL during program compile" },55{ "disass", D3D12_DEBUG_DISASS, "Dump disassambly of created DXIL shader" },56{ "res", D3D12_DEBUG_RESOURCE, "Debug resources" },57{ "debuglayer", D3D12_DEBUG_DEBUG_LAYER, "Enable debug layer" },58{ "gpuvalidator", D3D12_DEBUG_GPU_VALIDATOR, "Enable GPU validator" },59DEBUG_NAMED_VALUE_END60};6162DEBUG_GET_ONCE_FLAGS_OPTION(d3d12_debug, "D3D12_DEBUG", d3d12_debug_options, 0)6364uint32_t65d3d12_debug;6667enum {68HW_VENDOR_AMD = 0x1002,69HW_VENDOR_INTEL = 0x8086,70HW_VENDOR_MICROSOFT = 0x1414,71HW_VENDOR_NVIDIA = 0x10de,72};7374static const char *75d3d12_get_vendor(struct pipe_screen *pscreen)76{77return "Microsoft Corporation";78}7980static const char *81d3d12_get_device_vendor(struct pipe_screen *pscreen)82{83struct d3d12_screen* screen = d3d12_screen(pscreen);8485switch (screen->vendor_id) {86case HW_VENDOR_MICROSOFT:87return "Microsoft";88case HW_VENDOR_AMD:89return "AMD";90case HW_VENDOR_NVIDIA:91return "NVIDIA";92case HW_VENDOR_INTEL:93return "Intel";94default:95return "Unknown";96}97}9899static int100d3d12_get_video_mem(struct pipe_screen *pscreen)101{102struct d3d12_screen* screen = d3d12_screen(pscreen);103104return screen->memory_size_megabytes;105}106107static int108d3d12_get_param(struct pipe_screen *pscreen, enum pipe_cap param)109{110struct d3d12_screen *screen = d3d12_screen(pscreen);111112switch (param) {113case PIPE_CAP_NPOT_TEXTURES:114return 1;115116case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:117/* D3D12 only supports dual-source blending for a single118* render-target. From the D3D11 functional spec (which also defines119* this for D3D12):120*121* "When Dual Source Color Blending is enabled, the Pixel Shader must122* have only a single RenderTarget bound, at slot 0, and must output123* both o0 and o1. Writing to other outputs (o2, o3 etc.) produces124* undefined results for the corresponding RenderTargets, if bound125* illegally."126*127* Source: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#17.6%20Dual%20Source%20Color%20Blending128*/129return 1;130131case PIPE_CAP_ANISOTROPIC_FILTER:132return 1;133134case PIPE_CAP_MAX_RENDER_TARGETS:135if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)136return 8;137else if (screen->max_feature_level == D3D_FEATURE_LEVEL_9_3)138return 4;139return 1;140141case PIPE_CAP_TEXTURE_SWIZZLE:142return 1;143144case PIPE_CAP_MAX_TEXTURE_2D_SIZE:145if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0)146return 16384;147else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)148return 8192;149else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_9_3)150return 4096;151return 2048;152153case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:154if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)155return 11;156return 9;157158case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:159if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0)160return 14;161else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)162return 13;163else if (screen->max_feature_level == D3D_FEATURE_LEVEL_9_3)164return 12;165return 9;166167case PIPE_CAP_PRIMITIVE_RESTART:168case PIPE_CAP_INDEP_BLEND_ENABLE:169case PIPE_CAP_INDEP_BLEND_FUNC:170case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:171case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:172case PIPE_CAP_VERTEX_SHADER_SATURATE:173case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:174case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:175case PIPE_CAP_RGB_OVERRIDE_DST_ALPHA_BLEND:176return 1;177178/* We need to do some lowering that requires a link to the sampler */179case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:180return 1;181182case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:183if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0)184return 1 << 14;185else if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)186return 1 << 13;187return 0;188189case PIPE_CAP_DEPTH_CLIP_DISABLE:190return 1;191192case PIPE_CAP_TGSI_TEXCOORD:193return 0;194195case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:196return 1;197198case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:199return 1;200201case PIPE_CAP_GLSL_FEATURE_LEVEL:202return 330;203case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:204return 140;205206#if 0 /* TODO: Enable me */207case PIPE_CAP_COMPUTE:208return 0;209#endif210211case PIPE_CAP_TEXTURE_MULTISAMPLE:212return 1;213214#if 0 /* TODO: Enable me */215case PIPE_CAP_CUBE_MAP_ARRAY:216return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_1;217#endif218219case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:220return 1;221222case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:223return 0; /* unsure */224225case PIPE_CAP_ENDIANNESS:226return PIPE_ENDIAN_NATIVE; /* unsure */227228case PIPE_CAP_MAX_VIEWPORTS:229return 1; /* probably wrong */230231case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:232return 1;233234#if 0 /* TODO: Enable me. Enables ARB_texture_gather */235case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:236return 4;237#endif238239case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:240case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:241return 1;242243case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:244return 1;245246case PIPE_CAP_ACCELERATED:247return 1;248249case PIPE_CAP_VIDEO_MEMORY:250return d3d12_get_video_mem(pscreen);251252case PIPE_CAP_UMA:253return screen->architecture.UMA;254255case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:256return 2048; /* FIXME: no clue how to query this */257258case PIPE_CAP_TEXTURE_FLOAT_LINEAR:259case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:260return 1;261262#if 0 /* TODO: Enable me. Enables GL_ARB_shader_storage_buffer_object */263case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:264return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0;265#endif266267case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:268return 256;269270case PIPE_CAP_PCI_GROUP:271case PIPE_CAP_PCI_BUS:272case PIPE_CAP_PCI_DEVICE:273case PIPE_CAP_PCI_FUNCTION:274return 0; /* TODO: figure these out */275276case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:277return 0; /* not sure */278279case PIPE_CAP_FLATSHADE:280case PIPE_CAP_ALPHA_TEST:281case PIPE_CAP_TWO_SIDED_COLOR:282case PIPE_CAP_CLIP_PLANES:283return 0;284285case PIPE_CAP_SHADER_STENCIL_EXPORT:286return screen->opts.PSSpecifiedStencilRefSupported;287288case PIPE_CAP_SEAMLESS_CUBE_MAP:289case PIPE_CAP_TEXTURE_QUERY_LOD:290case PIPE_CAP_TGSI_INSTANCEID:291case PIPE_CAP_TGSI_TEX_TXF_LZ:292case PIPE_CAP_OCCLUSION_QUERY:293case PIPE_CAP_POINT_SPRITE:294case PIPE_CAP_VIEWPORT_TRANSFORM_LOWERED:295case PIPE_CAP_PSIZ_CLAMPED:296case PIPE_CAP_BLEND_EQUATION_SEPARATE:297case PIPE_CAP_CONDITIONAL_RENDER:298case PIPE_CAP_QUERY_TIMESTAMP:299case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:300case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:301return 1;302303case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:304return 4;305306case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:307case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:308return 16 * 4;309310/* Geometry shader output. */311case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:312return 256;313case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:314return 256 * 4;315316case PIPE_CAP_MAX_VARYINGS:317return 32;318319case PIPE_CAP_NIR_COMPACT_ARRAYS:320return 1;321322default:323return u_pipe_screen_get_param_defaults(pscreen, param);324}325}326327static float328d3d12_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)329{330struct d3d12_screen *screen = d3d12_screen(pscreen);331332switch (param) {333case PIPE_CAPF_MAX_LINE_WIDTH:334case PIPE_CAPF_MAX_LINE_WIDTH_AA:335return 1.0f; /* no clue */336337case PIPE_CAPF_MAX_POINT_WIDTH:338case PIPE_CAPF_MAX_POINT_WIDTH_AA:339return D3D12_MAX_POINT_SIZE;340341case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:342return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0 ? 16.0f : 2.0f;343344case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:345return 15.99f;346347case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:348case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:349case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:350return 0.0f; /* not implemented */351352default:353unreachable("unknown pipe_capf");354}355356return 0.0;357}358359static int360d3d12_get_shader_param(struct pipe_screen *pscreen,361enum pipe_shader_type shader,362enum pipe_shader_cap param)363{364struct d3d12_screen *screen = d3d12_screen(pscreen);365366switch (param) {367case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:368case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:369case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:370case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:371case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:372if (shader == PIPE_SHADER_VERTEX ||373shader == PIPE_SHADER_FRAGMENT ||374shader == PIPE_SHADER_GEOMETRY)375return INT_MAX;376return 0;377378case PIPE_SHADER_CAP_MAX_INPUTS:379return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_1 ? 32 : 16;380381case PIPE_SHADER_CAP_MAX_OUTPUTS:382if (shader == PIPE_SHADER_FRAGMENT) {383/* same as max MRTs (not sure if this is correct) */384if (screen->max_feature_level >= D3D_FEATURE_LEVEL_10_0)385return 8;386else if (screen->max_feature_level == D3D_FEATURE_LEVEL_9_3)387return 4;388return 1;389}390return screen->max_feature_level >= D3D_FEATURE_LEVEL_10_1 ? 32 : 16;391392case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:393if (screen->opts.ResourceBindingTier == D3D12_RESOURCE_BINDING_TIER_1)394return 16;395return PIPE_MAX_SAMPLERS;396397case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:398return 65536;399400case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:401return 13; /* 15 - 2 for lowered uniforms and state vars*/402403case PIPE_SHADER_CAP_MAX_TEMPS:404return INT_MAX;405406case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:407case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:408case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:409case PIPE_SHADER_CAP_SUBROUTINES:410return 0; /* not implemented */411412case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:413case PIPE_SHADER_CAP_INTEGERS:414return 1;415416case PIPE_SHADER_CAP_INT64_ATOMICS:417case PIPE_SHADER_CAP_FP16:418return 0; /* not implemented */419420case PIPE_SHADER_CAP_PREFERRED_IR:421return PIPE_SHADER_IR_NIR;422423case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:424return 0; /* not implemented */425426case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:427if (screen->opts.ResourceBindingTier == D3D12_RESOURCE_BINDING_TIER_1)428return 128;429return PIPE_MAX_SHADER_SAMPLER_VIEWS;430431case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:432case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:433case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:434return 0; /* not implemented */435436case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:437return 0; /* no idea */438439case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:440return 32; /* arbitrary */441442#if 0443case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:444return 8; /* no clue */445#endif446447case PIPE_SHADER_CAP_SUPPORTED_IRS:448return 1 << PIPE_SHADER_IR_NIR;449450case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:451return 0; /* TODO: enable me */452453case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:454case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:455return 0; /* unsure */456457case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:458case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:459case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:460case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:461return 0; /* not implemented */462463/* should only get here on unhandled cases */464default: return 0;465}466}467468static bool469d3d12_is_format_supported(struct pipe_screen *pscreen,470enum pipe_format format,471enum pipe_texture_target target,472unsigned sample_count,473unsigned storage_sample_count,474unsigned bind)475{476struct d3d12_screen *screen = d3d12_screen(pscreen);477478if (MAX2(1, sample_count) != MAX2(1, storage_sample_count))479return false;480481if (target == PIPE_BUFFER) {482/* Replace emulated vertex element formats for the tests */483format = d3d12_emulated_vtx_format(format);484} else {485/* Allow 3-comp 32 bit formats only for BOs (needed for ARB_tbo_rgb32) */486if ((format == PIPE_FORMAT_R32G32B32_FLOAT ||487format == PIPE_FORMAT_R32G32B32_SINT ||488format == PIPE_FORMAT_R32G32B32_UINT))489return false;490}491492/* Don't advertise alpha/luminance_alpha formats because they can't be used493* for render targets (except A8_UNORM) and can't be emulated by R/RG formats.494* Let the state tracker choose an RGBA format instead. */495if (format != PIPE_FORMAT_A8_UNORM &&496(util_format_is_alpha(format) ||497util_format_is_luminance_alpha(format)))498return false;499500DXGI_FORMAT dxgi_format = d3d12_get_format(format);501if (dxgi_format == DXGI_FORMAT_UNKNOWN)502return false;503504enum D3D12_FORMAT_SUPPORT1 dim_support = D3D12_FORMAT_SUPPORT1_NONE;505switch (target) {506case PIPE_TEXTURE_1D:507case PIPE_TEXTURE_1D_ARRAY:508dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE1D;509break;510case PIPE_TEXTURE_2D:511case PIPE_TEXTURE_RECT:512case PIPE_TEXTURE_2D_ARRAY:513dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE2D;514break;515case PIPE_TEXTURE_3D:516dim_support = D3D12_FORMAT_SUPPORT1_TEXTURE3D;517break;518case PIPE_TEXTURE_CUBE:519case PIPE_TEXTURE_CUBE_ARRAY:520dim_support = D3D12_FORMAT_SUPPORT1_TEXTURECUBE;521break;522case PIPE_BUFFER:523dim_support = D3D12_FORMAT_SUPPORT1_BUFFER;524break;525default:526unreachable("Unknown target");527}528529D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info;530fmt_info.Format = d3d12_get_resource_rt_format(format);531if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,532&fmt_info, sizeof(fmt_info))))533return false;534535if (!(fmt_info.Support1 & dim_support))536return false;537538if (target == PIPE_BUFFER) {539if (bind & PIPE_BIND_VERTEX_BUFFER &&540!(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER))541return false;542543if (bind & PIPE_BIND_INDEX_BUFFER) {544if (format != PIPE_FORMAT_R8_UINT &&545format != PIPE_FORMAT_R16_UINT &&546format != PIPE_FORMAT_R32_UINT)547return false;548}549550if (sample_count > 0)551return false;552} else {553/* all other targets are texture-targets */554if (bind & PIPE_BIND_RENDER_TARGET &&555!(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET))556return false;557558if (bind & PIPE_BIND_BLENDABLE &&559!(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_BLENDABLE))560return false;561562D3D12_FEATURE_DATA_FORMAT_SUPPORT fmt_info_sv;563if (util_format_is_depth_or_stencil(format)) {564fmt_info_sv.Format = d3d12_get_resource_srv_format(format, target);565if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT,566&fmt_info_sv, sizeof(fmt_info_sv))))567return false;568} else569fmt_info_sv = fmt_info;570571if (bind & PIPE_BIND_DISPLAY_TARGET &&572(!(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DISPLAY) ||573// Disable formats that don't support flip model574dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM ||575dxgi_format == DXGI_FORMAT_B5G5R5A1_UNORM ||576dxgi_format == DXGI_FORMAT_B5G6R5_UNORM ||577dxgi_format == DXGI_FORMAT_B4G4R4A4_UNORM))578return false;579580if (bind & PIPE_BIND_DEPTH_STENCIL &&581!(fmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL))582return false;583584if (sample_count > 0) {585if (!(fmt_info_sv.Support1 & D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD))586return false;587588if (!util_is_power_of_two_nonzero(sample_count))589return false;590591D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS ms_info = {};592ms_info.Format = dxgi_format;593ms_info.SampleCount = sample_count;594if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,595&ms_info,596sizeof(ms_info))) ||597!ms_info.NumQualityLevels)598return false;599}600}601return true;602}603604static void605d3d12_destroy_screen(struct pipe_screen *pscreen)606{607struct d3d12_screen *screen = d3d12_screen(pscreen);608slab_destroy_parent(&screen->transfer_pool);609d3d12_descriptor_pool_free(screen->rtv_pool);610d3d12_descriptor_pool_free(screen->dsv_pool);611d3d12_descriptor_pool_free(screen->view_pool);612screen->readback_slab_bufmgr->destroy(screen->readback_slab_bufmgr);613screen->slab_bufmgr->destroy(screen->slab_bufmgr);614screen->cache_bufmgr->destroy(screen->cache_bufmgr);615screen->bufmgr->destroy(screen->bufmgr);616mtx_destroy(&screen->descriptor_pool_mutex);617FREE(screen);618}619620static void621d3d12_flush_frontbuffer(struct pipe_screen * pscreen,622struct pipe_context *pctx,623struct pipe_resource *pres,624unsigned level, unsigned layer,625void *winsys_drawable_handle,626struct pipe_box *sub_box)627{628struct d3d12_screen *screen = d3d12_screen(pscreen);629struct sw_winsys *winsys = screen->winsys;630struct d3d12_resource *res = d3d12_resource(pres);631632if (!winsys || !pctx)633return;634635assert(res->dt);636void *map = winsys->displaytarget_map(winsys, res->dt, 0);637638if (map) {639pipe_transfer *transfer = nullptr;640void *res_map = pipe_texture_map(pctx, pres, level, layer, PIPE_MAP_READ, 0, 0,641u_minify(pres->width0, level),642u_minify(pres->height0, level),643&transfer);644if (res_map) {645util_copy_rect((ubyte*)map, pres->format, res->dt_stride, 0, 0,646transfer->box.width, transfer->box.height,647(const ubyte*)res_map, transfer->stride, 0, 0);648pipe_texture_unmap(pctx, transfer);649}650winsys->displaytarget_unmap(winsys, res->dt);651}652653#ifdef _WIN32654// WindowFromDC is Windows-only, and this method requires an HWND, so only use it on Windows655ID3D12SharingContract *sharing_contract;656if (SUCCEEDED(screen->cmdqueue->QueryInterface(IID_PPV_ARGS(&sharing_contract)))) {657ID3D12Resource *d3d12_res = d3d12_resource_resource(res);658sharing_contract->Present(d3d12_res, 0, WindowFromDC((HDC)winsys_drawable_handle));659}660#endif661662winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box);663}664665static ID3D12Debug *666get_debug_interface()667{668typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory);669PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface;670671util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT);672if (!d3d12_mod) {673debug_printf("D3D12: failed to load D3D12.DLL\n");674return NULL;675}676677D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface");678if (!D3D12GetDebugInterface) {679debug_printf("D3D12: failed to load D3D12GetDebugInterface from D3D12.DLL\n");680return NULL;681}682683ID3D12Debug *debug;684if (FAILED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {685debug_printf("D3D12: D3D12GetDebugInterface failed\n");686return NULL;687}688689return debug;690}691692static void693enable_d3d12_debug_layer()694{695ID3D12Debug *debug = get_debug_interface();696if (debug)697debug->EnableDebugLayer();698}699700static void701enable_gpu_validation()702{703ID3D12Debug *debug = get_debug_interface();704ID3D12Debug3 *debug3;705if (debug &&706SUCCEEDED(debug->QueryInterface(IID_PPV_ARGS(&debug3))))707debug3->SetEnableGPUBasedValidation(true);708}709710static ID3D12Device *711create_device(IUnknown *adapter)712{713typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);714typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID*, void*, UINT*);715PFN_D3D12CREATEDEVICE D3D12CreateDevice;716PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures;717718util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT);719if (!d3d12_mod) {720debug_printf("D3D12: failed to load D3D12.DLL\n");721return NULL;722}723724#ifdef _WIN32725if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)) {726struct d3d12_validation_tools *validation_tools = d3d12_validator_create();727if (!validation_tools) {728debug_printf("D3D12: failed to initialize validator with experimental shader models disabled\n");729return nullptr;730}731d3d12_validator_destroy(validation_tools);732} else733#endif734{735D3D12EnableExperimentalFeatures = (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");736if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) {737debug_printf("D3D12: failed to enable experimental shader models\n");738return nullptr;739}740}741742D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice");743if (!D3D12CreateDevice) {744debug_printf("D3D12: failed to load D3D12CreateDevice from D3D12.DLL\n");745return NULL;746}747748ID3D12Device *dev;749if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,750IID_PPV_ARGS(&dev))))751return dev;752753debug_printf("D3D12: D3D12CreateDevice failed\n");754return NULL;755}756757static bool758can_attribute_at_vertex(struct d3d12_screen *screen)759{760switch (screen->vendor_id) {761case HW_VENDOR_MICROSOFT:762return true;763default:764return screen->opts3.BarycentricsSupported;765}766}767768static void769d3d12_init_null_srvs(struct d3d12_screen *screen)770{771for (unsigned i = 0; i < RESOURCE_DIMENSION_COUNT; ++i) {772D3D12_SHADER_RESOURCE_VIEW_DESC srv = {};773774srv.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;775srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;776switch (i) {777case RESOURCE_DIMENSION_BUFFER:778case RESOURCE_DIMENSION_UNKNOWN:779srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;780srv.Buffer.FirstElement = 0;781srv.Buffer.NumElements = 0;782srv.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;783srv.Buffer.StructureByteStride = 0;784break;785case RESOURCE_DIMENSION_TEXTURE1D:786srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;787srv.Texture1D.MipLevels = 1;788srv.Texture1D.MostDetailedMip = 0;789srv.Texture1D.ResourceMinLODClamp = 0.0f;790break;791case RESOURCE_DIMENSION_TEXTURE1DARRAY:792srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;793srv.Texture1DArray.MipLevels = 1;794srv.Texture1DArray.ArraySize = 1;795srv.Texture1DArray.MostDetailedMip = 0;796srv.Texture1DArray.FirstArraySlice = 0;797srv.Texture1DArray.ResourceMinLODClamp = 0.0f;798break;799case RESOURCE_DIMENSION_TEXTURE2D:800srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;801srv.Texture2D.MipLevels = 1;802srv.Texture2D.MostDetailedMip = 0;803srv.Texture2D.PlaneSlice = 0;804srv.Texture2D.ResourceMinLODClamp = 0.0f;805break;806case RESOURCE_DIMENSION_TEXTURE2DARRAY:807srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;808srv.Texture2DArray.MipLevels = 1;809srv.Texture2DArray.ArraySize = 1;810srv.Texture2DArray.MostDetailedMip = 0;811srv.Texture2DArray.FirstArraySlice = 0;812srv.Texture2DArray.PlaneSlice = 0;813srv.Texture2DArray.ResourceMinLODClamp = 0.0f;814break;815case RESOURCE_DIMENSION_TEXTURE2DMS:816srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;817break;818case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:819srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;820srv.Texture2DMSArray.ArraySize = 1;821srv.Texture2DMSArray.FirstArraySlice = 0;822break;823case RESOURCE_DIMENSION_TEXTURE3D:824srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;825srv.Texture3D.MipLevels = 1;826srv.Texture3D.MostDetailedMip = 0;827srv.Texture3D.ResourceMinLODClamp = 0.0f;828break;829case RESOURCE_DIMENSION_TEXTURECUBE:830srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;831srv.TextureCube.MipLevels = 1;832srv.TextureCube.MostDetailedMip = 0;833srv.TextureCube.ResourceMinLODClamp = 0.0f;834break;835case RESOURCE_DIMENSION_TEXTURECUBEARRAY:836srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;837srv.TextureCubeArray.MipLevels = 1;838srv.TextureCubeArray.NumCubes = 1;839srv.TextureCubeArray.MostDetailedMip = 0;840srv.TextureCubeArray.First2DArrayFace = 0;841srv.TextureCubeArray.ResourceMinLODClamp = 0.0f;842break;843}844845if (srv.ViewDimension != D3D12_SRV_DIMENSION_UNKNOWN)846{847d3d12_descriptor_pool_alloc_handle(screen->view_pool, &screen->null_srvs[i]);848screen->dev->CreateShaderResourceView(NULL, &srv, screen->null_srvs[i].cpu_handle);849}850}851}852853static void854d3d12_init_null_rtv(struct d3d12_screen *screen)855{856D3D12_RENDER_TARGET_VIEW_DESC rtv = {};857rtv.Format = DXGI_FORMAT_R8G8B8A8_UNORM;858rtv.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;859rtv.Texture2D.MipSlice = 0;860rtv.Texture2D.PlaneSlice = 0;861d3d12_descriptor_pool_alloc_handle(screen->rtv_pool, &screen->null_rtv);862screen->dev->CreateRenderTargetView(NULL, &rtv, screen->null_rtv.cpu_handle);863}864865bool866d3d12_init_screen(struct d3d12_screen *screen, struct sw_winsys *winsys, IUnknown *adapter)867{868d3d12_debug = debug_get_option_d3d12_debug();869870screen->winsys = winsys;871mtx_init(&screen->descriptor_pool_mutex, mtx_plain);872873screen->base.get_vendor = d3d12_get_vendor;874screen->base.get_device_vendor = d3d12_get_device_vendor;875screen->base.get_param = d3d12_get_param;876screen->base.get_paramf = d3d12_get_paramf;877screen->base.get_shader_param = d3d12_get_shader_param;878screen->base.is_format_supported = d3d12_is_format_supported;879screen->base.get_compiler_options = d3d12_get_compiler_options;880screen->base.context_create = d3d12_context_create;881screen->base.flush_frontbuffer = d3d12_flush_frontbuffer;882screen->base.destroy = d3d12_destroy_screen;883884#ifndef DEBUG885if (d3d12_debug & D3D12_DEBUG_DEBUG_LAYER)886#endif887enable_d3d12_debug_layer();888889if (d3d12_debug & D3D12_DEBUG_GPU_VALIDATOR)890enable_gpu_validation();891892screen->dev = create_device(adapter);893894if (!screen->dev) {895debug_printf("D3D12: failed to create device\n");896goto failed;897}898899ID3D12InfoQueue *info_queue;900if (SUCCEEDED(screen->dev->QueryInterface(IID_PPV_ARGS(&info_queue)))) {901D3D12_MESSAGE_SEVERITY severities[] = {902D3D12_MESSAGE_SEVERITY_INFO,903D3D12_MESSAGE_SEVERITY_WARNING,904};905906D3D12_MESSAGE_ID msg_ids[] = {907D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,908};909910D3D12_INFO_QUEUE_FILTER NewFilter = {};911NewFilter.DenyList.NumSeverities = ARRAY_SIZE(severities);912NewFilter.DenyList.pSeverityList = severities;913NewFilter.DenyList.NumIDs = ARRAY_SIZE(msg_ids);914NewFilter.DenyList.pIDList = msg_ids;915916info_queue->PushStorageFilter(&NewFilter);917}918919if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS,920&screen->opts,921sizeof(screen->opts)))) {922debug_printf("D3D12: failed to get device options\n");923goto failed;924}925if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS2,926&screen->opts2,927sizeof(screen->opts2)))) {928debug_printf("D3D12: failed to get device options\n");929goto failed;930}931if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3,932&screen->opts3,933sizeof(screen->opts3)))) {934debug_printf("D3D12: failed to get device options\n");935goto failed;936}937if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4,938&screen->opts4,939sizeof(screen->opts4)))) {940debug_printf("D3D12: failed to get device options\n");941goto failed;942}943944screen->architecture.NodeIndex = 0;945if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE,946&screen->architecture,947sizeof(screen->architecture)))) {948debug_printf("D3D12: failed to get device architecture\n");949goto failed;950}951952D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels;953static const D3D_FEATURE_LEVEL levels[] = {954D3D_FEATURE_LEVEL_11_0,955D3D_FEATURE_LEVEL_11_1,956D3D_FEATURE_LEVEL_12_0,957D3D_FEATURE_LEVEL_12_1,958};959feature_levels.NumFeatureLevels = ARRAY_SIZE(levels);960feature_levels.pFeatureLevelsRequested = levels;961if (FAILED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,962&feature_levels,963sizeof(feature_levels)))) {964debug_printf("D3D12: failed to get device feature levels\n");965goto failed;966}967screen->max_feature_level = feature_levels.MaxSupportedFeatureLevel;968969D3D12_COMMAND_QUEUE_DESC queue_desc;970queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;971queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;972queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;973queue_desc.NodeMask = 0;974975ID3D12Device9 *device9;976if (SUCCEEDED(screen->dev->QueryInterface(&device9))) {977if (FAILED(device9->CreateCommandQueue1(&queue_desc, OpenGLOn12CreatorID,978IID_PPV_ARGS(&screen->cmdqueue))))979goto failed;980device9->Release();981} else {982if (FAILED(screen->dev->CreateCommandQueue(&queue_desc,983IID_PPV_ARGS(&screen->cmdqueue))))984goto failed;985}986987UINT64 timestamp_freq;988if (FAILED(screen->cmdqueue->GetTimestampFrequency(×tamp_freq)))989timestamp_freq = 10000000;990screen->timestamp_multiplier = 1000000000.0 / timestamp_freq;991992d3d12_screen_fence_init(&screen->base);993d3d12_screen_resource_init(&screen->base);994slab_create_parent(&screen->transfer_pool, sizeof(struct d3d12_transfer), 16);995996struct pb_desc desc;997desc.alignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;998desc.usage = (pb_usage_flags)(PB_USAGE_CPU_WRITE | PB_USAGE_GPU_READ);9991000screen->bufmgr = d3d12_bufmgr_create(screen);1001screen->cache_bufmgr = pb_cache_manager_create(screen->bufmgr, 0xfffff, 2, 0, 64 * 1024 * 1024);1002screen->slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16, 512,1003D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,1004&desc);1005desc.usage = (pb_usage_flags)(PB_USAGE_CPU_READ_WRITE | PB_USAGE_GPU_WRITE);1006screen->readback_slab_bufmgr = pb_slab_range_manager_create(screen->cache_bufmgr, 16, 512,1007D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,1008&desc);10091010screen->rtv_pool = d3d12_descriptor_pool_new(screen,1011D3D12_DESCRIPTOR_HEAP_TYPE_RTV,101264);1013screen->dsv_pool = d3d12_descriptor_pool_new(screen,1014D3D12_DESCRIPTOR_HEAP_TYPE_DSV,101564);1016screen->view_pool = d3d12_descriptor_pool_new(screen,1017D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,10181024);10191020d3d12_init_null_srvs(screen);1021d3d12_init_null_rtv(screen);10221023screen->have_load_at_vertex = can_attribute_at_vertex(screen);1024return true;10251026failed:1027return false;1028}102910301031