yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
debdc7251
master
1// d3d12-device.cpp 2#include "d3d12-device.h" 3 4#include "../nvapi/nvapi-util.h" 5#include "d3d12-buffer.h" 6#include "d3d12-fence.h" 7#include "d3d12-framebuffer.h" 8#include "d3d12-helper-functions.h" 9#include "d3d12-pipeline-state.h" 10#include "d3d12-query.h" 11#include "d3d12-render-pass.h" 12#include "d3d12-resource-views.h" 13#include "d3d12-sampler.h" 14#include "d3d12-shader-object.h" 15#include "d3d12-shader-program.h" 16#include "d3d12-shader-table.h" 17#include "d3d12-swap-chain.h" 18#include "d3d12-vertex-layout.h" 19 20#ifdef GFX_NVAPI 21#include "../nvapi/nvapi-include.h" 22#endif 23 24#ifdef GFX_NV_AFTERMATH 25#include "GFSDK_Aftermath.h" 26#include "GFSDK_Aftermath_Defines.h" 27#include "GFSDK_Aftermath_GpuCrashDump.h" 28#endif 29 30namespace gfx 31{ 32namespace d3d12 33{ 34 35using namespace Slang ; 36 37static const uint32_t D3D_FEATURE_LEVEL_12_2 = 0xc200 ; 38 39 40#if GFX_NV_AFTERMATH 41/* static */ const bool DeviceImpl ::g_isAftermathEnabled = true; 42#else 43/* static */ const bool DeviceImpl ::g_isAftermathEnabled = false; 44#endif 45 46struct ShaderModelInfo 47{ 48D3D_SHADER_MODEL shaderModel ; 49SlangCompileTarget compileTarget ; 50const char * profileName ; 51}; 52// List of shader models. Do not change oldest to newest order. 53static ShaderModelInfo kKnownShaderModels []= { 54#define SHADER_MODEL_INFO_DXBC (major ,minor ) \ 55 { \ 56D3D_SHADER_MODEL_ ##major ##_##minor, SLANG_DXBC, "sm_" #major "_" #minor \ 57 } 58SHADER_MODEL_INFO_DXBC (5 ,1 ), 59#undef SHADER_MODEL_INFO_DXBC 60#define SHADER_MODEL_INFO_DXIL (major ,minor ) \ 61 { \ 62 (D3D_SHADER_MODEL)0x##major##minor, SLANG_DXIL, "sm_" #major "_" #minor \ 63 } 64SHADER_MODEL_INFO_DXIL (6 ,0 ), 65SHADER_MODEL_INFO_DXIL (6 ,1 ), 66SHADER_MODEL_INFO_DXIL (6 ,2 ), 67SHADER_MODEL_INFO_DXIL (6 ,3 ), 68SHADER_MODEL_INFO_DXIL (6 ,4 ), 69SHADER_MODEL_INFO_DXIL (6 ,5 ), 70SHADER_MODEL_INFO_DXIL (6 ,6 ), 71SHADER_MODEL_INFO_DXIL (6 ,7 ), 72SHADER_MODEL_INFO_DXIL (6 ,8 ), 73SHADER_MODEL_INFO_DXIL (6 ,9 ) 74#undef SHADER_MODEL_INFO_DXIL 75}; 76 77Result DeviceImpl ::createBuffer ( 78const D3D12_RESOURCE_DESC & resourceDesc , 79const void * srcData , 80Size srcDataSize , 81D3D12_RESOURCE_STATES finalState , 82D3D12Resource & resourceOut , 83bool isShared , 84MemoryType memoryType ) 85{ 86const Size bufferSize = Size (resourceDesc .Width ); 87 88D3D12_HEAP_PROPERTIES heapProps ; 89heapProps .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN ; 90heapProps .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN ; 91heapProps .CreationNodeMask = 1 ; 92heapProps .VisibleNodeMask = 1 ; 93 94D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ; 95if (isShared ) 96flags |=D3D12_HEAP_FLAG_SHARED ; 97 98D3D12_RESOURCE_DESC desc = resourceDesc ; 99 100D3D12_RESOURCE_STATES initialState = finalState ; 101 102 103switch (memoryType ) 104 { 105case MemoryType ::ReadBack : 106assert (!srcData ); 107 108heapProps .Type = D3D12_HEAP_TYPE_READBACK ; 109desc .Flags = D3D12_RESOURCE_FLAG_NONE ; 110initialState |=D3D12_RESOURCE_STATE_COPY_DEST ; 111break ; 112case MemoryType ::Upload : 113 114heapProps .Type = D3D12_HEAP_TYPE_UPLOAD ; 115desc .Flags = D3D12_RESOURCE_FLAG_NONE ; 116initialState |=D3D12_RESOURCE_STATE_GENERIC_READ ; 117break ; 118case MemoryType ::DeviceLocal : 119heapProps .Type = D3D12_HEAP_TYPE_DEFAULT ; 120if (initialState != D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE ) 121initialState = D3D12_RESOURCE_STATE_COMMON ; 122break ; 123default : 124return SLANG_FAIL ; 125 } 126 127// Create the resource. 128SLANG_RETURN_ON_FAIL ( 129resourceOut .initCommitted (m_device ,heapProps ,flags ,desc ,initialState ,nullptr )); 130 131if (srcData ) 132 { 133D3D12Resource uploadResource ; 134 135if (memoryType == MemoryType ::DeviceLocal ) 136 { 137// If the buffer is on the default heap, create upload buffer. 138D3D12_RESOURCE_DESC uploadDesc (resourceDesc ); 139uploadDesc .Flags = D3D12_RESOURCE_FLAG_NONE ; 140heapProps .Type = D3D12_HEAP_TYPE_UPLOAD ; 141 142SLANG_RETURN_ON_FAIL (uploadResource .initCommitted ( 143m_device , 144heapProps , 145D3D12_HEAP_FLAG_NONE , 146uploadDesc , 147D3D12_RESOURCE_STATE_GENERIC_READ , 148nullptr )); 149 } 150 151// Be careful not to actually copy a resource here. 152D3D12Resource & uploadResourceRef = 153 (memoryType == MemoryType ::DeviceLocal ) ?uploadResource :resourceOut ; 154 155// Copy data to the intermediate upload heap and then schedule a copy 156// from the upload heap to the vertex buffer. 157UINT8 * dstData ; 158D3D12_RANGE readRange = {};// We do not intend to read from this resource on the CPU. 159 160ID3D12Resource * dxUploadResource = uploadResourceRef .getResource (); 161 162SLANG_RETURN_ON_FAIL ( 163dxUploadResource -> Map (0 ,& readRange ,reinterpret_cast < void **> (& dstData ))); 164 ::memcpy (dstData ,srcData ,srcDataSize ); 165dxUploadResource -> Unmap (0 ,nullptr ); 166 167if (memoryType == MemoryType ::DeviceLocal ) 168 { 169auto encodeInfo = encodeResourceCommands (); 170encodeInfo .d3dCommandList 171-> CopyBufferRegion (resourceOut ,0 ,uploadResourceRef ,0 ,bufferSize ); 172submitResourceCommandsAndWait (encodeInfo ); 173 } 174 } 175 176return SLANG_OK ; 177} 178 179Result DeviceImpl ::captureTextureToSurface ( 180TextureResourceImpl * resourceImpl , 181ResourceState state , 182ISlangBlob ** outBlob , 183Size * outRowPitch , 184Size * outPixelSize ) 185{ 186auto & resource = resourceImpl -> m_resource ; 187 188const D3D12_RESOURCE_STATES initialState = D3DUtil ::getResourceState (state ); 189 190const ITextureResource ::Desc & gfxDesc = * resourceImpl -> getDesc (); 191const D3D12_RESOURCE_DESC desc = resource .getResource ()-> GetDesc (); 192 193// Don't bother supporting MSAA for right now 194if (desc .SampleDesc .Count > 1 ) 195 { 196fprintf (stderr ,"ERROR: cannot capture multi-sample texture\n" ); 197return SLANG_FAIL ; 198 } 199 200FormatInfo formatInfo ; 201gfxGetFormatInfo (gfxDesc .format ,& formatInfo ); 202Size bytesPerPixel = formatInfo .blockSizeInBytes /formatInfo .pixelsPerBlock ; 203Size rowPitch = int (desc .Width )* bytesPerPixel ; 204static const Size align = 256 ;// D3D requires minimum 256 byte alignment for texture data. 205rowPitch = (rowPitch + align - 1 )& ~(align - 1 );// Bit trick for rounding up 206Size bufferSize = rowPitch * int (desc .Height )* int (desc .DepthOrArraySize ); 207if (outRowPitch ) 208* outRowPitch = rowPitch ; 209if (outPixelSize ) 210* outPixelSize = bytesPerPixel ; 211 212D3D12Resource stagingResource ; 213 { 214D3D12_RESOURCE_DESC stagingDesc ; 215initBufferResourceDesc (bufferSize ,stagingDesc ); 216 217D3D12_HEAP_PROPERTIES heapProps ; 218heapProps .Type = D3D12_HEAP_TYPE_READBACK ; 219heapProps .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN ; 220heapProps .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN ; 221heapProps .CreationNodeMask = 1 ; 222heapProps .VisibleNodeMask = 1 ; 223 224SLANG_RETURN_ON_FAIL (stagingResource .initCommitted ( 225m_device , 226heapProps , 227D3D12_HEAP_FLAG_NONE , 228stagingDesc , 229D3D12_RESOURCE_STATE_COPY_DEST , 230nullptr )); 231 } 232 233auto encodeInfo = encodeResourceCommands (); 234auto currentState = D3DUtil ::getResourceState (state ); 235 236 { 237D3D12BarrierSubmitter submitter (encodeInfo .d3dCommandList ); 238resource .transition (currentState ,D3D12_RESOURCE_STATE_COPY_SOURCE ,submitter ); 239 } 240 241// Do the copy 242 { 243D3D12_TEXTURE_COPY_LOCATION srcLoc ; 244srcLoc .pResource = resource ; 245srcLoc .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX ; 246srcLoc .SubresourceIndex = 0 ; 247 248D3D12_TEXTURE_COPY_LOCATION dstLoc ; 249dstLoc .pResource = stagingResource ; 250dstLoc .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT ; 251dstLoc .PlacedFootprint .Offset = 0 ; 252dstLoc .PlacedFootprint .Footprint .Format = desc .Format ; 253dstLoc .PlacedFootprint .Footprint .Width = UINT (desc .Width ); 254dstLoc .PlacedFootprint .Footprint .Height = UINT (desc .Height ); 255dstLoc .PlacedFootprint .Footprint .Depth = UINT (desc .DepthOrArraySize ); 256dstLoc .PlacedFootprint .Footprint .RowPitch = UINT (rowPitch ); 257 258encodeInfo .d3dCommandList -> CopyTextureRegion (& dstLoc ,0 ,0 ,0 ,& srcLoc ,nullptr ); 259 } 260 261 { 262D3D12BarrierSubmitter submitter (encodeInfo .d3dCommandList ); 263resource .transition (D3D12_RESOURCE_STATE_COPY_SOURCE ,currentState ,submitter ); 264 } 265 266// Submit the copy, and wait for copy to complete 267submitResourceCommandsAndWait (encodeInfo ); 268 269 { 270ID3D12Resource * dxResource = stagingResource ; 271 272UINT8 * data ; 273D3D12_RANGE readRange = {0 ,bufferSize }; 274 275SLANG_RETURN_ON_FAIL (dxResource -> Map (0 ,& readRange ,reinterpret_cast < void **> (& data ))); 276 277List < uint8_t > blobData ; 278 279blobData .setCount (bufferSize ); 280memcpy (blobData .getBuffer (),data ,bufferSize ); 281dxResource -> Unmap (0 ,nullptr ); 282 283auto resultBlob = Slang ::ListBlob ::moveCreate (blobData ); 284 285returnComPtr (outBlob ,resultBlob ); 286return SLANG_OK ; 287 } 288} 289 290Result DeviceImpl ::getNativeDeviceHandles (InteropHandles * outHandles ) 291{ 292outHandles -> handles [0 ].handleValue = (uint64_t )m_device ; 293outHandles -> handles [0 ].api = InteropHandleAPI ::D3D12 ; 294return SLANG_OK ; 295} 296 297Result DeviceImpl ::_createDevice ( 298DeviceCheckFlags deviceCheckFlags , 299const AdapterLUID * adapterLUID , 300D3D_FEATURE_LEVEL featureLevel , 301D3D12DeviceInfo & outDeviceInfo ) 302{ 303if (m_dxDebug && (deviceCheckFlags & DeviceCheckFlag ::UseDebug )&& !g_isAftermathEnabled ) 304 { 305m_dxDebug -> EnableDebugLayer (); 306 } 307 308outDeviceInfo .clear (); 309 310ComPtr < IDXGIFactory > dxgiFactory ; 311SLANG_RETURN_ON_FAIL (D3DUtil ::createFactory (deviceCheckFlags ,dxgiFactory )); 312 313List < ComPtr < IDXGIAdapter >> dxgiAdapters ; 314SLANG_RETURN_ON_FAIL ( 315D3DUtil ::findAdapters (deviceCheckFlags ,adapterLUID ,dxgiFactory ,dxgiAdapters )); 316 317ComPtr < ID3D12Device > device ; 318ComPtr < IDXGIAdapter > adapter ; 319 320for (Index i = 0 ;i < dxgiAdapters .getCount ();++ i ) 321 { 322IDXGIAdapter * dxgiAdapter = dxgiAdapters [i ]; 323if (SLANG_SUCCEEDED ( 324m_D3D12CreateDevice (dxgiAdapter ,featureLevel ,IID_PPV_ARGS (device .writeRef ())))) 325 { 326adapter = dxgiAdapter ; 327break ; 328 } 329 } 330 331if (!device ) 332 { 333return SLANG_FAIL ; 334 } 335 336if (m_dxDebug && (deviceCheckFlags & DeviceCheckFlag ::UseDebug )&& !g_isAftermathEnabled ) 337 { 338ComPtr < ID3D12InfoQueue > infoQueue ; 339if (SLANG_SUCCEEDED (device -> QueryInterface (infoQueue .writeRef ()))) 340 { 341// Make break 342infoQueue -> SetBreakOnSeverity (D3D12_MESSAGE_SEVERITY_CORRUPTION , true); 343if (m_extendedDesc .debugBreakOnD3D12Error ) 344 { 345infoQueue -> SetBreakOnSeverity (D3D12_MESSAGE_SEVERITY_ERROR , true); 346 } 347D3D12_MESSAGE_ID hideMessages []= { 348D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE , 349D3D12_MESSAGE_ID_CLEARDEPTHSTENCILVIEW_MISMATCHINGCLEARVALUE , 350 }; 351D3D12_INFO_QUEUE_FILTER f = {}; 352f .DenyList .NumIDs = (UINT )SLANG_COUNT_OF (hideMessages ); 353f .DenyList .pIDList = hideMessages ; 354infoQueue -> AddStorageFilterEntries (& f ); 355 356// Apparently there is a problem with sm 6.3 with spurious errors, with debug layer 357// enabled 358D3D12_FEATURE_DATA_SHADER_MODEL featureShaderModel ; 359featureShaderModel .HighestShaderModel = D3D_SHADER_MODEL_6_3 ; 360SLANG_SUCCEEDED (device -> CheckFeatureSupport ( 361D3D12_FEATURE_SHADER_MODEL , 362& featureShaderModel , 363sizeof (featureShaderModel ))); 364 365if (featureShaderModel .HighestShaderModel >=D3D_SHADER_MODEL_6_3 ) 366 { 367// Filter out any messages that cause issues 368// TODO: Remove this when the debug layers work properly 369D3D12_MESSAGE_ID messageIds []= { 370// When the debug layer is enabled this error is triggered sometimes after a 371// CopyDescriptorsSimple call The failed check validates that the source and 372// destination ranges of the copy do not overlap. The check assumes descriptor 373// handles are pointers to memory, but this is not always the case and the check 374// fails (even though everything is okay). 375D3D12_MESSAGE_ID_COPY_DESCRIPTORS_INVALID_RANGES , 376 }; 377 378// We filter INFO messages because they are way too many 379D3D12_MESSAGE_SEVERITY severities []= {D3D12_MESSAGE_SEVERITY_INFO }; 380 381D3D12_INFO_QUEUE_FILTER infoQueueFilter = {}; 382infoQueueFilter .DenyList .NumSeverities = SLANG_COUNT_OF (severities ); 383infoQueueFilter .DenyList .pSeverityList = severities ; 384infoQueueFilter .DenyList .NumIDs = SLANG_COUNT_OF (messageIds ); 385infoQueueFilter .DenyList .pIDList = messageIds ; 386 387infoQueue -> PushStorageFilter (& infoQueueFilter ); 388 } 389 } 390 } 391 392 393#ifdef GFX_NV_AFTERMATH 394 { 395if ((deviceCheckFlags & DeviceCheckFlag ::UseDebug )&& g_isAftermathEnabled ) 396 { 397// Initialize Nsight Aftermath for this device. 398// This combination of flags is not necessarily appropraite for real world usage 399const uint32_t aftermathFlags = 400GFSDK_Aftermath_FeatureFlags_EnableMarkers |// Enable event marker tracking. 401GFSDK_Aftermath_FeatureFlags_CallStackCapturing |// Enable automatic call stack 402// event markers. 403GFSDK_Aftermath_FeatureFlags_EnableResourceTracking |// Enable tracking of 404// resources. 405GFSDK_Aftermath_FeatureFlags_GenerateShaderDebugInfo |// Generate debug information 406// for shaders. 407GFSDK_Aftermath_FeatureFlags_EnableShaderErrorReporting ;// Enable additional 408// runtime shader error 409// reporting. 410 411auto initResult = GFSDK_Aftermath_DX12_Initialize ( 412GFSDK_Aftermath_Version_API , 413aftermathFlags , 414device ); 415 416if (initResult != GFSDK_Aftermath_Result_Success ) 417 { 418SLANG_ASSERT_FAILURE ("Unable to initialize aftermath" ); 419// Unable to initialize 420return SLANG_FAIL ; 421 } 422 } 423 } 424#endif 425 426// Get the descs 427 { 428adapter -> GetDesc (& outDeviceInfo .m_desc ); 429 430// Look up GetDesc1 info 431ComPtr < IDXGIAdapter1 > adapter1 ; 432if (SLANG_SUCCEEDED (adapter -> QueryInterface (adapter1 .writeRef ()))) 433 { 434adapter1 -> GetDesc1 (& outDeviceInfo .m_desc1 ); 435 } 436 } 437 438// Save other info 439outDeviceInfo .m_device = device ; 440outDeviceInfo .m_dxgiFactory = dxgiFactory ; 441outDeviceInfo .m_adapter = adapter ; 442outDeviceInfo .m_isWarp = D3DUtil ::isWarp (dxgiFactory ,adapter ); 443const UINT kMicrosoftVendorId = 5140 ; 444outDeviceInfo .m_isSoftware = 445outDeviceInfo .m_isWarp || 446 ((outDeviceInfo .m_desc1 .Flags & DXGI_ADAPTER_FLAG_SOFTWARE )!= 0 )|| 447outDeviceInfo .m_desc .VendorId == kMicrosoftVendorId ; 448 449return SLANG_OK ; 450} 451 452Result DeviceImpl ::initialize (const Desc & desc ) 453{ 454SLANG_RETURN_ON_FAIL (RendererBase ::initialize (desc )); 455 456// Rather than statically link against D3D, we load it dynamically. 457 458SharedLibrary ::Handle d3dModule ; 459#if SLANG_WINDOWS_FAMILY 460const char * libName = "d3d12" ; 461#else 462const char * libName = "vkd3d-proton-d3d12" ; 463#endif 464if (SLANG_FAILED (SharedLibrary ::load (libName ,d3dModule ))) 465 { 466getDebugCallback ()-> handleMessage ( 467DebugMessageType ::Error , 468DebugMessageSource ::Layer , 469"error: failed load 'd3d12.dll'\n" ); 470return SLANG_FAIL ; 471 } 472 473// Find extended desc. 474for (GfxIndex i = 0 ;i < desc .extendedDescCount ;i ++ ) 475 { 476StructType stype ; 477memcpy (& stype ,desc .extendedDescs [i ],sizeof (stype )); 478switch (stype ) 479 { 480case StructType ::D3D12DeviceExtendedDesc : 481memcpy (& m_extendedDesc ,desc .extendedDescs [i ],sizeof (m_extendedDesc )); 482break ; 483case StructType ::D3D12ExperimentalFeaturesDesc : 484processExperimentalFeaturesDesc (d3dModule ,desc .extendedDescs [i ]); 485break ; 486 } 487 } 488 489// Initialize queue index allocator. 490// Support max 32 queues. 491m_queueIndexAllocator .initPool (32 ); 492 493// Initialize DeviceInfo 494 { 495m_info .deviceType = DeviceType ::DirectX12 ; 496m_info .bindingStyle = BindingStyle ::DirectX ; 497m_info .projectionStyle = ProjectionStyle ::DirectX ; 498m_info .apiName = "Direct3D 12" ; 499static const float kIdentity []= {1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,1 }; 500 ::memcpy (m_info .identityProjectionMatrix ,kIdentity ,sizeof (kIdentity )); 501 } 502 503// Get all the dll entry points 504m_D3D12SerializeRootSignature = 505 (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE )loadProc (d3dModule ,"D3D12SerializeRootSignature" ); 506if (!m_D3D12SerializeRootSignature ) 507 { 508return SLANG_FAIL ; 509 } 510 511m_D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE )loadProc ( 512d3dModule , 513"D3D12SerializeVersionedRootSignature" ); 514if (!m_D3D12SerializeVersionedRootSignature ) 515 { 516return SLANG_FAIL ; 517 } 518 519#if SLANG_ENABLE_PIX 520HMODULE pixModule = LoadLibraryW (L"WinPixEventRuntime.dll" ); 521if (pixModule ) 522 { 523m_BeginEventOnCommandList = 524 (PFN_BeginEventOnCommandList )GetProcAddress (pixModule ,"PIXBeginEventOnCommandList" ); 525m_EndEventOnCommandList = 526 (PFN_EndEventOnCommandList )GetProcAddress (pixModule ,"PIXEndEventOnCommandList" ); 527 } 528#endif 529 530 531// If Aftermath is enabled, we can't enable the D3D12 debug layer as well 532if (isGfxDebugLayerEnabled ()&& !g_isAftermathEnabled ) 533 { 534m_D3D12GetDebugInterface = 535 (PFN_D3D12_GET_DEBUG_INTERFACE )loadProc (d3dModule ,"D3D12GetDebugInterface" ); 536if (m_D3D12GetDebugInterface ) 537 { 538if (SLANG_SUCCEEDED (m_D3D12GetDebugInterface (IID_PPV_ARGS (m_dxDebug .writeRef ())))) 539 { 540#if 0 541// Can enable for extra validation. NOTE! That d3d12 warns if you do.... 542// D3D12 MESSAGE : Device Debug Layer Startup Options : GPU - Based Validation is enabled(disabled by default). 543// This results in new validation not possible during API calls on the CPU, by creating patched shaders that have validation 544// added directly to the shader. However, it can slow things down a lot, especially for applications with numerous 545// PSOs.Time to see the first render frame may take several minutes. 546// [INITIALIZATION MESSAGE #1016: CREATEDEVICE_DEBUG_LAYER_STARTUP_OPTIONS] 547 548ComPtr < ID3D12Debug1 > debug1 ; 549if (SLANG_SUCCEEDED (m_dxDebug -> QueryInterface (debug1 .writeRef ()))) 550 { 551debug1 -> SetEnableGPUBasedValidation (true); 552 } 553#endif 554 } 555 } 556 } 557 558m_D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE )loadProc (d3dModule ,"D3D12CreateDevice" ); 559if (!m_D3D12CreateDevice ) 560 { 561return SLANG_FAIL ; 562 } 563 564if (desc .existingDeviceHandles .handles [0 ].handleValue == 0 ) 565 { 566FlagCombiner combiner ; 567if (isGfxDebugLayerEnabled ()) 568 { 569combiner .add ( 570DeviceCheckFlag ::UseDebug , 571ChangeType ::OnOff );///< First try debug then non debug 572 } 573else 574 { 575combiner .add (DeviceCheckFlag ::UseDebug ,ChangeType ::Off );///< Don't bother with debug 576 } 577combiner .add ( 578DeviceCheckFlag ::UseHardwareDevice , 579ChangeType ::OnOff );///< First try hardware, then reference 580 581 582const D3D_FEATURE_LEVEL featureLevels []= { 583 (D3D_FEATURE_LEVEL )D3D_FEATURE_LEVEL_12_2 , 584D3D_FEATURE_LEVEL_12_1 , 585D3D_FEATURE_LEVEL_12_0 , 586D3D_FEATURE_LEVEL_11_1 , 587D3D_FEATURE_LEVEL_11_0 , 588D3D_FEATURE_LEVEL_10_1 , 589D3D_FEATURE_LEVEL_10_0 , 590D3D_FEATURE_LEVEL_9_3 , 591D3D_FEATURE_LEVEL_9_2 , 592D3D_FEATURE_LEVEL_9_1 }; 593for (auto featureLevel :featureLevels ) 594 { 595const int numCombinations = combiner .getNumCombinations (); 596for (int i = 0 ;i < numCombinations ;++ i ) 597 { 598if (SLANG_SUCCEEDED (_createDevice ( 599combiner .getCombination (i ), 600desc .adapterLUID , 601featureLevel , 602m_deviceInfo ))) 603 { 604 gotosucc ; 605 } 606 } 607 } 608succ : 609if (!m_deviceInfo .m_adapter ) 610 { 611// Couldn't find an adapter 612return SLANG_FAIL ; 613 } 614 } 615else 616 { 617// Store the existing device handle in desc in m_deviceInfo 618m_deviceInfo .m_device = (ID3D12Device * )desc .existingDeviceHandles .handles [0 ].handleValue ; 619 } 620 621// Set the device 622m_device = m_deviceInfo .m_device ; 623 624if (m_deviceInfo .m_isSoftware ) 625 { 626m_features .add ("software-device" ); 627 } 628else 629 { 630m_features .add ("hardware-device" ); 631 } 632 633// NVAPI 634if (desc .nvapiExtnSlot >=0 ) 635 { 636if (SLANG_FAILED (NVAPIUtil ::initialize ())) 637 { 638return SLANG_E_NOT_AVAILABLE ; 639 } 640 641#ifdef GFX_NVAPI 642// From DOCS: Applications are expected to bind null UAV to this slot. 643// NOTE! We don't currently do this, but doesn't seem to be a problem. 644 645const NvAPI_Status status = 646NvAPI_D3D12_SetNvShaderExtnSlotSpace (m_device ,NvU32 (desc .nvapiExtnSlot ),NvU32 (0 )); 647 648if (status != NVAPI_OK ) 649 { 650return SLANG_E_NOT_AVAILABLE ; 651 } 652 653if (isSupportedNVAPIOp (m_device ,NV_EXTN_OP_UINT64_ATOMIC )) 654 { 655m_features .add ("atomic-int64" ); 656 } 657if (isSupportedNVAPIOp (m_device ,NV_EXTN_OP_FP32_ATOMIC )) 658 { 659m_features .add ("atomic-float" ); 660 } 661 662// If we have NVAPI well assume we have realtime clock 663 { 664m_features .add ("realtime-clock" ); 665 } 666 667m_nvapi = true; 668#endif 669 } 670 671D3D12_FEATURE_DATA_SHADER_MODEL shaderModelData = {}; 672 673// Find what features are supported 674 { 675// Check this is how this is laid out... 676SLANG_COMPILE_TIME_ASSERT (D3D_SHADER_MODEL_6_0 == 0x60 ); 677 678 { 679// CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL) can fail if the runtime/driver does 680// not yet know the specified highest shader model. Therefore we assemble a list of 681// shader models to check and walk it from highest to lowest to find the supported 682// shader model. 683Slang ::ShortList < D3D_SHADER_MODEL > shaderModels ; 684if (m_extendedDesc .highestShaderModel != 0 ) 685shaderModels .add ((D3D_SHADER_MODEL )m_extendedDesc .highestShaderModel ); 686for (int i = SLANG_COUNT_OF (kKnownShaderModels )- 1 ;i >=0 ;-- i ) 687shaderModels .add (kKnownShaderModels [i ].shaderModel ); 688for (D3D_SHADER_MODEL shaderModel :shaderModels ) 689 { 690shaderModelData .HighestShaderModel = shaderModel ; 691if (SLANG_SUCCEEDED (m_device -> CheckFeatureSupport ( 692D3D12_FEATURE_SHADER_MODEL , 693& shaderModelData , 694sizeof (shaderModelData )))) 695break ; 696 } 697 698// TODO: Currently warp causes a crash when using half, so disable for now 699if (m_deviceInfo .m_isWarp == false&& 700shaderModelData .HighestShaderModel >=D3D_SHADER_MODEL_6_2 ) 701 { 702// With sm_6_2 we have half 703m_features .add ("half" ); 704 } 705 } 706 { 707D3D12_FEATURE_DATA_D3D12_OPTIONS options ; 708if (SLANG_SUCCEEDED (m_device -> CheckFeatureSupport ( 709D3D12_FEATURE_D3D12_OPTIONS , 710& options , 711sizeof (options )))) 712 { 713// Check double precision support 714if (options .DoublePrecisionFloatShaderOps ) 715m_features .add ("double" ); 716 717// Check conservative-rasterization support 718auto conservativeRasterTier = options .ConservativeRasterizationTier ; 719if (conservativeRasterTier == D3D12_CONSERVATIVE_RASTERIZATION_TIER_3 ) 720 { 721m_features .add ("conservative-rasterization-3" ); 722m_features .add ("conservative-rasterization-2" ); 723m_features .add ("conservative-rasterization-1" ); 724 } 725else if (conservativeRasterTier == D3D12_CONSERVATIVE_RASTERIZATION_TIER_2 ) 726 { 727m_features .add ("conservative-rasterization-2" ); 728m_features .add ("conservative-rasterization-1" ); 729 } 730else if (conservativeRasterTier == D3D12_CONSERVATIVE_RASTERIZATION_TIER_1 ) 731 { 732m_features .add ("conservative-rasterization-1" ); 733 } 734 735// Check rasterizer ordered views support 736if (options .ROVsSupported ) 737 { 738m_features .add ("rasterizer-ordered-views" ); 739 } 740 } 741 } 742 { 743D3D12_FEATURE_DATA_D3D12_OPTIONS1 options ; 744if (SLANG_SUCCEEDED (m_device -> CheckFeatureSupport ( 745D3D12_FEATURE_D3D12_OPTIONS1 , 746& options , 747sizeof (options )))) 748 { 749// Check wave operations support 750if (options .WaveOps ) 751m_features .add ("wave-ops" ); 752 } 753 } 754 { 755D3D12_FEATURE_DATA_D3D12_OPTIONS2 options ; 756if (SLANG_SUCCEEDED (m_device -> CheckFeatureSupport ( 757D3D12_FEATURE_D3D12_OPTIONS2 , 758& options , 759sizeof (options )))) 760 { 761// Check programmable sample positions support 762switch (options .ProgrammableSamplePositionsTier ) 763 { 764case D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_2 : 765m_features .add ("programmable-sample-positions-2" ); 766m_features .add ("programmable-sample-positions-1" ); 767break ; 768case D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_1 : 769m_features .add ("programmable-sample-positions-1" ); 770break ; 771default : 772break ; 773 } 774 } 775 } 776 { 777D3D12_FEATURE_DATA_D3D12_OPTIONS3 options ; 778if (SLANG_SUCCEEDED (m_device -> CheckFeatureSupport ( 779D3D12_FEATURE_D3D12_OPTIONS3 , 780& options , 781sizeof (options )))) 782 { 783// Check barycentrics support 784if (options .BarycentricsSupported ) 785 { 786m_features .add ("barycentrics" ); 787 } 788 } 789 } 790// Check ray tracing support 791 { 792D3D12_FEATURE_DATA_D3D12_OPTIONS5 options ; 793if (SLANG_SUCCEEDED (m_device -> CheckFeatureSupport ( 794D3D12_FEATURE_D3D12_OPTIONS5 , 795& options , 796sizeof (options )))) 797 { 798if (options .RaytracingTier != D3D12_RAYTRACING_TIER_NOT_SUPPORTED ) 799 { 800m_features .add ("ray-tracing" ); 801 } 802if (options .RaytracingTier >=D3D12_RAYTRACING_TIER_1_1 ) 803 { 804m_features .add ("ray-query" ); 805 } 806 } 807 } 808// Check mesh shader support 809 { 810D3D12_FEATURE_DATA_D3D12_OPTIONS7 options ; 811if (SLANG_SUCCEEDED (m_device -> CheckFeatureSupport ( 812D3D12_FEATURE_D3D12_OPTIONS7 , 813& options , 814sizeof (options )))) 815 { 816if (options .MeshShaderTier >=D3D12_MESH_SHADER_TIER_1 ) 817 { 818m_features .add ("mesh-shader" ); 819 } 820 } 821 } 822 } 823 824m_desc = desc ; 825 826// Create a command queue for internal resource transfer operations. 827SLANG_RETURN_ON_FAIL (createCommandQueueImpl (m_resourceCommandQueue .writeRef ())); 828// `CommandQueueImpl` holds a back reference to `D3D12Device`, make it a weak reference here 829// since this object is already owned by `D3D12Device`. 830m_resourceCommandQueue -> breakStrongReferenceToDevice (); 831// Retrieve timestamp frequency. 832m_resourceCommandQueue -> m_d3dQueue -> GetTimestampFrequency (& m_info .timestampFrequency ); 833 834// Get device limits. 835 { 836DeviceLimits limits = {}; 837limits .maxTextureDimension1D = D3D12_REQ_TEXTURE1D_U_DIMENSION ; 838limits .maxTextureDimension2D = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION ; 839limits .maxTextureDimension3D = D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ; 840limits .maxTextureDimensionCube = D3D12_REQ_TEXTURECUBE_DIMENSION ; 841limits .maxTextureArrayLayers = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION ; 842 843limits .maxVertexInputElements = D3D12_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT ; 844limits .maxVertexInputElementOffset = 256 ;// TODO 845limits .maxVertexStreams = D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT ; 846limits .maxVertexStreamStride = D3D12_REQ_MULTI_ELEMENT_STRUCTURE_SIZE_IN_BYTES ; 847 848limits .maxComputeThreadsPerGroup = D3D12_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP ; 849limits .maxComputeThreadGroupSize [0 ]= D3D12_CS_THREAD_GROUP_MAX_X ; 850limits .maxComputeThreadGroupSize [1 ]= D3D12_CS_THREAD_GROUP_MAX_Y ; 851limits .maxComputeThreadGroupSize [2 ]= D3D12_CS_THREAD_GROUP_MAX_Z ; 852limits .maxComputeDispatchThreadGroups [0 ]= 853D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION ; 854limits .maxComputeDispatchThreadGroups [1 ]= 855D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION ; 856limits .maxComputeDispatchThreadGroups [2 ]= 857D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION ; 858 859limits .maxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE ; 860limits .maxViewportDimensions [0 ]= D3D12_VIEWPORT_BOUNDS_MAX ; 861limits .maxViewportDimensions [1 ]= D3D12_VIEWPORT_BOUNDS_MAX ; 862limits .maxFramebufferDimensions [0 ]= D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION ; 863limits .maxFramebufferDimensions [1 ]= D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION ; 864limits .maxFramebufferDimensions [2 ]= 1 ; 865 866limits .maxShaderVisibleSamplers = D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE ; 867 868m_info .limits = limits ; 869 } 870 871SLANG_RETURN_ON_FAIL (createTransientResourceHeapImpl ( 872ITransientResourceHeap ::Flags ::AllowResizing , 8730 , 8748 , 8754 , 876m_resourceCommandTransientHeap .writeRef ())); 877// `TransientResourceHeap` holds a back reference to `D3D12Device`, make it a weak reference 878// here since this object is already owned by `D3D12Device`. 879m_resourceCommandTransientHeap -> breakStrongReferenceToDevice (); 880 881m_cpuViewHeap = new D3D12GeneralExpandingDescriptorHeap (); 882SLANG_RETURN_ON_FAIL (m_cpuViewHeap -> init ( 883m_device , 8841024 * 1024 , 885D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV , 886D3D12_DESCRIPTOR_HEAP_FLAG_NONE )); 887m_cpuSamplerHeap = new D3D12GeneralExpandingDescriptorHeap (); 888SLANG_RETURN_ON_FAIL (m_cpuSamplerHeap -> init ( 889m_device , 8902048 , 891D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER , 892D3D12_DESCRIPTOR_HEAP_FLAG_NONE )); 893 894m_rtvAllocator = new D3D12GeneralExpandingDescriptorHeap (); 895SLANG_RETURN_ON_FAIL (m_rtvAllocator -> init ( 896m_device , 89716 * 1024 , 898D3D12_DESCRIPTOR_HEAP_TYPE_RTV , 899D3D12_DESCRIPTOR_HEAP_FLAG_NONE )); 900m_dsvAllocator = new D3D12GeneralExpandingDescriptorHeap (); 901SLANG_RETURN_ON_FAIL (m_dsvAllocator -> init ( 902m_device , 9031024 , 904D3D12_DESCRIPTOR_HEAP_TYPE_DSV , 905D3D12_DESCRIPTOR_HEAP_FLAG_NONE )); 906 907ComPtr < IDXGIDevice > dxgiDevice ; 908if (m_deviceInfo .m_adapter ) 909 { 910DXGI_ADAPTER_DESC adapterDesc ; 911m_deviceInfo .m_adapter -> GetDesc (& adapterDesc ); 912m_adapterName = String ::fromWString (adapterDesc .Description ); 913m_info .adapterName = m_adapterName .begin (); 914 } 915 916// Initialize DXR interface. 917#if SLANG_GFX_HAS_DXR_SUPPORT 918m_device -> QueryInterface < ID3D12Device5 > (m_deviceInfo .m_device5 .writeRef ()); 919m_device5 = m_deviceInfo .m_device5 .get (); 920#endif 921// Check shader model version. 922SlangCompileTarget compileTarget = SLANG_DXBC ; 923const char * profileName = "sm_5_1" ; 924for (auto & sm :kKnownShaderModels ) 925 { 926if (sm .shaderModel <=shaderModelData .HighestShaderModel ) 927 { 928m_features .add (sm .profileName ); 929profileName = sm .profileName ; 930compileTarget = sm .compileTarget ; 931 } 932else 933 { 934break ; 935 } 936 } 937// If user specified a higher shader model than what the system supports, return failure. 938int userSpecifiedShaderModel = D3DUtil ::getShaderModelFromProfileName (desc .slang .targetProfile ); 939if (userSpecifiedShaderModel > shaderModelData .HighestShaderModel ) 940 { 941getDebugCallback ()-> handleMessage ( 942 gfx::DebugMessageType ::Error , 943 gfx::DebugMessageSource ::Layer , 944"The requested shader model is not supported by the system." ); 945return SLANG_E_NOT_AVAILABLE ; 946 } 947SLANG_RETURN_ON_FAIL (slangContext .initialize ( 948desc .slang , 949desc .extendedDescCount , 950desc .extendedDescs , 951compileTarget , 952profileName , 953makeArray (slang::PreprocessorMacroDesc {"__D3D12__" ,"1" }).getView ())); 954 955// Allocate a D3D12 "command signature" object that matches the behavior 956// of a D3D11-style `DrawInstancedIndirect` operation. 957 { 958D3D12_INDIRECT_ARGUMENT_DESC args ; 959args .Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW ; 960 961D3D12_COMMAND_SIGNATURE_DESC desc ; 962desc .ByteStride = sizeof (D3D12_DRAW_ARGUMENTS ); 963desc .NumArgumentDescs = 1 ; 964desc .pArgumentDescs = & args ; 965desc .NodeMask = 0 ; 966 967SLANG_RETURN_ON_FAIL (m_device -> CreateCommandSignature ( 968& desc , 969nullptr , 970IID_PPV_ARGS (drawIndirectCmdSignature .writeRef ()))); 971 } 972 973// Allocate a D3D12 "command signature" object that matches the behavior 974// of a D3D11-style `DrawIndexedInstancedIndirect` operation. 975 { 976D3D12_INDIRECT_ARGUMENT_DESC args ; 977args .Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED ; 978 979D3D12_COMMAND_SIGNATURE_DESC desc ; 980desc .ByteStride = sizeof (D3D12_DRAW_INDEXED_ARGUMENTS ); 981desc .NumArgumentDescs = 1 ; 982desc .pArgumentDescs = & args ; 983desc .NodeMask = 0 ; 984 985SLANG_RETURN_ON_FAIL (m_device -> CreateCommandSignature ( 986& desc , 987nullptr , 988IID_PPV_ARGS (drawIndexedIndirectCmdSignature .writeRef ()))); 989 } 990 991// Allocate a D3D12 "command signature" object that matches the behavior 992// of a D3D11-style `Dispatch` operation. 993 { 994D3D12_INDIRECT_ARGUMENT_DESC args ; 995args .Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH ; 996 997D3D12_COMMAND_SIGNATURE_DESC desc ; 998desc .ByteStride = sizeof (D3D12_DISPATCH_ARGUMENTS ); 999desc .NumArgumentDescs = 1 ; 1000desc .pArgumentDescs = & args ; 1001desc .NodeMask = 0 ; 1002 1003SLANG_RETURN_ON_FAIL (m_device -> CreateCommandSignature ( 1004& desc , 1005nullptr , 1006IID_PPV_ARGS (dispatchIndirectCmdSignature .writeRef ()))); 1007 } 1008m_isInitialized = true; 1009return SLANG_OK ; 1010} 1011 1012Result DeviceImpl ::createTransientResourceHeap ( 1013const ITransientResourceHeap ::Desc & desc , 1014ITransientResourceHeap ** outHeap ) 1015{ 1016RefPtr < TransientResourceHeapImpl > heap ; 1017SLANG_RETURN_ON_FAIL (createTransientResourceHeapImpl ( 1018desc .flags , 1019desc .constantBufferSize , 1020getViewDescriptorCount (desc ), 1021Math ::Max (1024 ,desc .samplerDescriptorCount ), 1022heap .writeRef ())); 1023returnComPtr (outHeap ,heap ); 1024return SLANG_OK ; 1025} 1026 1027Result DeviceImpl ::createCommandQueue (const ICommandQueue ::Desc & desc ,ICommandQueue ** outQueue ) 1028{ 1029RefPtr < CommandQueueImpl > queue ; 1030SLANG_RETURN_ON_FAIL (createCommandQueueImpl (queue .writeRef ())); 1031returnComPtr (outQueue ,queue ); 1032return SLANG_OK ; 1033} 1034 1035Result DeviceImpl ::createSwapchain ( 1036const ISwapchain ::Desc & desc , 1037WindowHandle window , 1038ISwapchain ** outSwapchain ) 1039{ 1040RefPtr < SwapchainImpl > swapchain = new SwapchainImpl (); 1041SLANG_RETURN_ON_FAIL (swapchain -> init (this ,desc ,window )); 1042returnComPtr (outSwapchain ,swapchain ); 1043return SLANG_OK ; 1044} 1045 1046SlangResult DeviceImpl ::readTextureResource ( 1047ITextureResource * resource , 1048ResourceState state , 1049ISlangBlob ** outBlob , 1050Size * outRowPitch , 1051Size * outPixelSize ) 1052{ 1053return captureTextureToSurface ( 1054static_cast < TextureResourceImpl *> (resource ), 1055state , 1056outBlob , 1057outRowPitch , 1058outPixelSize ); 1059} 1060 1061Result DeviceImpl ::getTextureAllocationInfo ( 1062const ITextureResource ::Desc & desc , 1063Size * outSize , 1064Size * outAlignment ) 1065{ 1066TextureResource ::Desc srcDesc = fixupTextureDesc (desc ); 1067D3D12_RESOURCE_DESC resourceDesc = {}; 1068initTextureResourceDesc (resourceDesc ,srcDesc ); 1069auto allocInfo = m_device -> GetResourceAllocationInfo (0 ,1 ,& resourceDesc ); 1070* outSize = (Size )allocInfo .SizeInBytes ; 1071* outAlignment = (Size )allocInfo .Alignment ; 1072return SLANG_OK ; 1073} 1074 1075Result DeviceImpl ::getTextureRowAlignment (Size * outAlignment ) 1076{ 1077* outAlignment = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT ; 1078return SLANG_OK ; 1079} 1080 1081Result DeviceImpl ::createTextureResource ( 1082const ITextureResource ::Desc & descIn , 1083const ITextureResource ::SubresourceData * initData , 1084ITextureResource ** outResource ) 1085{ 1086// Description of uploading on Dx12 1087// https://msdn.microsoft.com/en-us/library/windows/desktop/dn899215%28v=vs.85%29.aspx 1088 1089TextureResource ::Desc srcDesc = fixupTextureDesc (descIn ); 1090 1091D3D12_RESOURCE_DESC resourceDesc = {}; 1092initTextureResourceDesc (resourceDesc ,srcDesc ); 1093const int arraySize = calcEffectiveArraySize (srcDesc ); 1094const int numMipMaps = srcDesc .numMipLevels ; 1095 1096RefPtr < TextureResourceImpl > texture (new TextureResourceImpl (srcDesc )); 1097 1098// Create the target resource 1099 { 1100D3D12_HEAP_PROPERTIES heapProps ; 1101 1102heapProps .Type = D3D12_HEAP_TYPE_DEFAULT ; 1103heapProps .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN ; 1104heapProps .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN ; 1105heapProps .CreationNodeMask = 1 ; 1106heapProps .VisibleNodeMask = 1 ; 1107 1108D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE ; 1109if (descIn .isShared ) 1110flags |=D3D12_HEAP_FLAG_SHARED ; 1111 1112D3D12_CLEAR_VALUE clearValue ; 1113D3D12_CLEAR_VALUE * clearValuePtr = nullptr ; 1114clearValue .Format = resourceDesc .Format ; 1115if (descIn .optimalClearValue ) 1116 { 1117memcpy (clearValue .Color ,& descIn .optimalClearValue -> color ,sizeof (clearValue .Color )); 1118clearValue .DepthStencil .Depth = descIn .optimalClearValue -> depthStencil .depth ; 1119clearValue .DepthStencil .Stencil = descIn .optimalClearValue -> depthStencil .stencil ; 1120clearValuePtr = & clearValue ; 1121 } 1122if ((resourceDesc .Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | 1123D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL ))== 0 ) 1124 { 1125clearValuePtr = nullptr ; 1126 } 1127if (isTypelessDepthFormat (resourceDesc .Format )) 1128 { 1129clearValuePtr = nullptr ; 1130 } 1131SLANG_RETURN_ON_FAIL (texture -> m_resource .initCommitted ( 1132m_device , 1133heapProps , 1134flags , 1135resourceDesc , 1136D3D12_RESOURCE_STATE_COPY_DEST , 1137clearValuePtr )); 1138 1139texture -> m_resource .setDebugName (L"Texture" ); 1140 } 1141 1142// Calculate the layout 1143List < D3D12_PLACED_SUBRESOURCE_FOOTPRINT > layouts ; 1144layouts .setCount (numMipMaps ); 1145List < UInt64 > mipRowSizeInBytes ; 1146mipRowSizeInBytes .setCount (srcDesc .numMipLevels ); 1147List < UInt32 > mipNumRows ; 1148mipNumRows .setCount (numMipMaps ); 1149 1150// NOTE! This is just the size for one array upload -> not for the whole texture 1151UInt64 requiredSize = 0 ; 1152m_device -> GetCopyableFootprints ( 1153& resourceDesc , 11540 , 1155srcDesc .numMipLevels , 11560 , 1157layouts .begin (), 1158mipNumRows .begin (), 1159mipRowSizeInBytes .begin (), 1160& requiredSize ); 1161 1162// Sub resource indexing 1163// https://msdn.microsoft.com/en-us/library/windows/desktop/dn705766(v=vs.85).aspx#subresource_indexing 1164if (initData ) 1165 { 1166// Create the upload texture 1167D3D12Resource uploadTexture ; 1168 1169 { 1170D3D12_HEAP_PROPERTIES heapProps ; 1171 1172heapProps .Type = D3D12_HEAP_TYPE_UPLOAD ; 1173heapProps .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN ; 1174heapProps .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN ; 1175heapProps .CreationNodeMask = 1 ; 1176heapProps .VisibleNodeMask = 1 ; 1177 1178D3D12_RESOURCE_DESC uploadResourceDesc ; 1179 1180uploadResourceDesc .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER ; 1181uploadResourceDesc .Format = DXGI_FORMAT_UNKNOWN ; 1182uploadResourceDesc .Width = requiredSize ; 1183uploadResourceDesc .Height = 1 ; 1184uploadResourceDesc .DepthOrArraySize = 1 ; 1185uploadResourceDesc .MipLevels = 1 ; 1186uploadResourceDesc .SampleDesc .Count = 1 ; 1187uploadResourceDesc .SampleDesc .Quality = 0 ; 1188uploadResourceDesc .Flags = D3D12_RESOURCE_FLAG_NONE ; 1189uploadResourceDesc .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR ; 1190uploadResourceDesc .Alignment = 0 ; 1191 1192SLANG_RETURN_ON_FAIL (uploadTexture .initCommitted ( 1193m_device , 1194heapProps , 1195D3D12_HEAP_FLAG_NONE , 1196uploadResourceDesc , 1197D3D12_RESOURCE_STATE_GENERIC_READ , 1198nullptr )); 1199 1200uploadTexture .setDebugName (L"TextureUpload" ); 1201 } 1202// Get the pointer to the upload resource 1203ID3D12Resource * uploadResource = uploadTexture ; 1204 1205int subResourceIndex = 0 ; 1206for (int arrayIndex = 0 ;arrayIndex < arraySize ;arrayIndex ++ ) 1207 { 1208uint8_t * p ; 1209uploadResource -> Map (0 ,nullptr ,reinterpret_cast < void **> (& p )); 1210 1211for (int j = 0 ;j < numMipMaps ;++ j ) 1212 { 1213auto srcSubresource = initData [subResourceIndex + j ]; 1214 1215const D3D12_PLACED_SUBRESOURCE_FOOTPRINT & layout = layouts [j ]; 1216const D3D12_SUBRESOURCE_FOOTPRINT & footprint = layout .Footprint ; 1217 1218TextureResource ::Extents mipSize = calcMipSize (srcDesc .size ,j ); 1219if (gfxIsCompressedFormat (descIn .format )) 1220 { 1221mipSize .width = int (D3DUtil ::calcAligned (mipSize .width ,4 )); 1222mipSize .height = int (D3DUtil ::calcAligned (mipSize .height ,4 )); 1223 } 1224 1225assert ( 1226footprint .Width == mipSize .width && footprint .Height == mipSize .height && 1227footprint .Depth == mipSize .depth ); 1228 1229auto mipRowSize = mipRowSizeInBytes [j ]; 1230 1231const ptrdiff_t dstMipRowPitch = ptrdiff_t (footprint .RowPitch ); 1232const ptrdiff_t srcMipRowPitch = ptrdiff_t (srcSubresource .strideY ); 1233 1234const ptrdiff_t dstMipLayerPitch = ptrdiff_t (footprint .RowPitch * footprint .Height ); 1235const ptrdiff_t srcMipLayerPitch = ptrdiff_t (srcSubresource .strideZ ); 1236 1237// Our outer loop will copy the depth layers one at a time. 1238// 1239const uint8_t * srcLayer = (const uint8_t * )srcSubresource .data ; 1240uint8_t * dstLayer = p + layouts [j ].Offset ; 1241for (int l = 0 ;l < mipSize .depth ;l ++ ) 1242 { 1243// Our inner loop will copy the rows one at a time. 1244// 1245const uint8_t * srcRow = srcLayer ; 1246uint8_t * dstRow = dstLayer ; 1247int j = gfxIsCompressedFormat (descIn .format ) 1248 ?4 1249 :1 ;// BC compressed formats are organized into 4x4 blocks 1250for (int k = 0 ;k < mipSize .height ;k += j ) 1251 { 1252 ::memcpy (dstRow ,srcRow , (Size )mipRowSize ); 1253 1254srcRow += srcMipRowPitch ; 1255dstRow += dstMipRowPitch ; 1256 } 1257 1258srcLayer += srcMipLayerPitch ; 1259dstLayer += dstMipLayerPitch ; 1260 } 1261 1262// assert(srcRow == (const uint8_t*)(srcMip.getBuffer() + srcMip.getCount())); 1263 } 1264uploadResource -> Unmap (0 ,nullptr ); 1265 1266auto encodeInfo = encodeResourceCommands (); 1267for (int mipIndex = 0 ;mipIndex < numMipMaps ;++ mipIndex ) 1268 { 1269// https://msdn.microsoft.com/en-us/library/windows/desktop/dn903862(v=vs.85).aspx 1270 1271D3D12_TEXTURE_COPY_LOCATION src ; 1272src .pResource = uploadTexture ; 1273src .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT ; 1274src .PlacedFootprint = layouts [mipIndex ]; 1275 1276D3D12_TEXTURE_COPY_LOCATION dst ; 1277dst .pResource = texture -> m_resource ; 1278dst .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX ; 1279dst .SubresourceIndex = subResourceIndex ; 1280encodeInfo .d3dCommandList -> CopyTextureRegion (& dst ,0 ,0 ,0 ,& src ,nullptr ); 1281 1282subResourceIndex ++ ; 1283 } 1284 1285// Block - waiting for copy to complete (so can drop upload texture) 1286submitResourceCommandsAndWait (encodeInfo ); 1287 } 1288 } 1289 { 1290auto encodeInfo = encodeResourceCommands (); 1291 { 1292D3D12BarrierSubmitter submitter (encodeInfo .d3dCommandList ); 1293texture -> m_resource .transition ( 1294D3D12_RESOURCE_STATE_COPY_DEST , 1295texture -> m_defaultState , 1296submitter ); 1297 } 1298submitResourceCommandsAndWait (encodeInfo ); 1299 } 1300 1301returnComPtr (outResource ,texture ); 1302return SLANG_OK ; 1303} 1304 1305Result DeviceImpl ::createTextureFromNativeHandle ( 1306InteropHandle handle , 1307const ITextureResource ::Desc & srcDesc , 1308ITextureResource ** outResource ) 1309{ 1310RefPtr < TextureResourceImpl > texture (new TextureResourceImpl (srcDesc )); 1311 1312if (handle .api == InteropHandleAPI ::D3D12 ) 1313 { 1314texture -> m_resource .setResource ((ID3D12Resource * )handle .handleValue ); 1315 } 1316else 1317 { 1318return SLANG_FAIL ; 1319 } 1320 1321returnComPtr (outResource ,texture ); 1322return SLANG_OK ; 1323} 1324 1325Result DeviceImpl ::createBufferResource ( 1326const IBufferResource ::Desc & descIn , 1327const void * initData , 1328IBufferResource ** outResource ) 1329{ 1330BufferResource ::Desc srcDesc = fixupBufferDesc (descIn ); 1331 1332RefPtr < BufferResourceImpl > buffer (new BufferResourceImpl (srcDesc )); 1333 1334D3D12_RESOURCE_DESC bufferDesc ; 1335initBufferResourceDesc (descIn .sizeInBytes ,bufferDesc ); 1336 1337bufferDesc .Flags |=calcResourceFlags (srcDesc .allowedStates ); 1338 1339const D3D12_RESOURCE_STATES initialState = buffer -> m_defaultState ; 1340SLANG_RETURN_ON_FAIL (createBuffer ( 1341bufferDesc , 1342initData , 1343srcDesc .sizeInBytes , 1344initialState , 1345buffer -> m_resource , 1346descIn .isShared , 1347descIn .memoryType )); 1348 1349returnComPtr (outResource ,buffer ); 1350return SLANG_OK ; 1351} 1352 1353Result DeviceImpl ::createBufferFromNativeHandle ( 1354InteropHandle handle , 1355const IBufferResource ::Desc & srcDesc , 1356IBufferResource ** outResource ) 1357{ 1358RefPtr < BufferResourceImpl > buffer (new BufferResourceImpl (srcDesc )); 1359 1360if (handle .api == InteropHandleAPI ::D3D12 ) 1361 { 1362buffer -> m_resource .setResource ((ID3D12Resource * )handle .handleValue ); 1363 } 1364else 1365 { 1366return SLANG_FAIL ; 1367 } 1368 1369returnComPtr (outResource ,buffer ); 1370return SLANG_OK ; 1371} 1372 1373Result DeviceImpl ::createSamplerState (ISamplerState ::Desc const & desc ,ISamplerState ** outSampler ) 1374{ 1375D3D12_FILTER_REDUCTION_TYPE dxReduction = translateFilterReduction (desc .reductionOp ); 1376D3D12_FILTER dxFilter ; 1377if (desc .maxAnisotropy > 1 ) 1378 { 1379dxFilter = D3D12_ENCODE_ANISOTROPIC_FILTER (dxReduction ); 1380 } 1381else 1382 { 1383D3D12_FILTER_TYPE dxMin = translateFilterMode (desc .minFilter ); 1384D3D12_FILTER_TYPE dxMag = translateFilterMode (desc .magFilter ); 1385D3D12_FILTER_TYPE dxMip = translateFilterMode (desc .mipFilter ); 1386 1387dxFilter = D3D12_ENCODE_BASIC_FILTER (dxMin ,dxMag ,dxMip ,dxReduction ); 1388 } 1389 1390D3D12_SAMPLER_DESC dxDesc = {}; 1391dxDesc .Filter = dxFilter ; 1392dxDesc .AddressU = translateAddressingMode (desc .addressU ); 1393dxDesc .AddressV = translateAddressingMode (desc .addressV ); 1394dxDesc .AddressW = translateAddressingMode (desc .addressW ); 1395dxDesc .MipLODBias = desc .mipLODBias ; 1396dxDesc .MaxAnisotropy = desc .maxAnisotropy ; 1397dxDesc .ComparisonFunc = translateComparisonFunc (desc .comparisonFunc ); 1398for (int ii = 0 ;ii < 4 ;++ ii ) 1399dxDesc .BorderColor [ii ]= desc .borderColor [ii ]; 1400dxDesc .MinLOD = desc .minLOD ; 1401dxDesc .MaxLOD = desc .maxLOD ; 1402 1403auto & samplerHeap = m_cpuSamplerHeap ; 1404 1405D3D12Descriptor cpuDescriptor ; 1406samplerHeap -> allocate (& cpuDescriptor ); 1407m_device -> CreateSampler (& dxDesc ,cpuDescriptor .cpuHandle ); 1408 1409// TODO: We really ought to have a free-list of sampler-heap 1410// entries that we check before we go to the heap, and then 1411// when we are done with a sampler we simply add it to the free list. 1412// 1413RefPtr < SamplerStateImpl > samplerImpl = new SamplerStateImpl (); 1414samplerImpl -> m_allocator = samplerHeap ; 1415samplerImpl -> m_descriptor = cpuDescriptor ; 1416returnComPtr (outSampler ,samplerImpl ); 1417return SLANG_OK ; 1418} 1419 1420Result DeviceImpl ::createTextureView ( 1421ITextureResource * texture , 1422IResourceView ::Desc const & desc , 1423IResourceView ** outView ) 1424{ 1425auto resourceImpl = (TextureResourceImpl * )texture ; 1426 1427RefPtr < ResourceViewImpl > viewImpl = new ResourceViewImpl (); 1428viewImpl -> m_resource = resourceImpl ; 1429viewImpl -> m_desc = desc ; 1430bool isArray = resourceImpl ?resourceImpl -> getDesc ()-> arraySize > 1 : false; 1431bool isMultiSample = resourceImpl ?resourceImpl -> getDesc ()-> sampleDesc .numSamples > 1 : false; 1432switch (desc .type ) 1433 { 1434default : 1435return SLANG_FAIL ; 1436 1437case IResourceView ::Type ::RenderTarget : 1438 { 1439SLANG_RETURN_ON_FAIL (m_rtvAllocator -> allocate (& viewImpl -> m_descriptor )); 1440viewImpl -> m_allocator = m_rtvAllocator ; 1441D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; 1442rtvDesc .Format = D3DUtil ::getMapFormat (desc .format ); 1443switch (desc .renderTarget .shape ) 1444 { 1445case IResource ::Type ::Texture1D : 1446rtvDesc .ViewDimension = 1447isArray ?D3D12_RTV_DIMENSION_TEXTURE1DARRAY :D3D12_RTV_DIMENSION_TEXTURE1D ; 1448if (isArray ) 1449 { 1450rtvDesc .Texture1DArray .MipSlice = desc .subresourceRange .mipLevel ; 1451rtvDesc .Texture1DArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1452rtvDesc .Texture1DArray .ArraySize = desc .subresourceRange .layerCount ; 1453 } 1454else 1455 { 1456rtvDesc .Texture1D .MipSlice = desc .subresourceRange .mipLevel ; 1457 } 1458 1459break ; 1460case IResource ::Type ::Texture2D : 1461if (isMultiSample ) 1462 { 1463rtvDesc .ViewDimension = isArray ?D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY 1464 :D3D12_RTV_DIMENSION_TEXTURE2DMS ; 1465rtvDesc .Texture2DMSArray .ArraySize = desc .subresourceRange .layerCount ; 1466rtvDesc .Texture2DMSArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1467 } 1468else 1469 { 1470rtvDesc .ViewDimension = isArray ?D3D12_RTV_DIMENSION_TEXTURE2DARRAY 1471 :D3D12_RTV_DIMENSION_TEXTURE2D ; 1472if (isArray ) 1473 { 1474rtvDesc .Texture2DArray .MipSlice = desc .subresourceRange .mipLevel ; 1475rtvDesc .Texture2DArray .ArraySize = desc .subresourceRange .layerCount ; 1476rtvDesc .Texture2DArray .FirstArraySlice = 1477desc .subresourceRange .baseArrayLayer ; 1478rtvDesc .Texture2DArray .PlaneSlice = 1479resourceImpl 1480 ?D3DUtil ::getPlaneSlice ( 1481D3DUtil ::getMapFormat (resourceImpl -> getDesc ()-> format ), 1482desc .subresourceRange .aspectMask ) 1483 :0 ; 1484 } 1485else 1486 { 1487rtvDesc .Texture2D .MipSlice = desc .subresourceRange .mipLevel ; 1488rtvDesc .Texture2D .PlaneSlice = 1489resourceImpl 1490 ?D3DUtil ::getPlaneSlice ( 1491D3DUtil ::getMapFormat (resourceImpl -> getDesc ()-> format ), 1492desc .subresourceRange .aspectMask ) 1493 :0 ; 1494 } 1495 } 1496break ; 1497case IResource ::Type ::TextureCube : 1498rtvDesc .ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY ; 1499rtvDesc .Texture2DArray .MipSlice = desc .subresourceRange .mipLevel ; 1500rtvDesc .Texture2DArray .ArraySize = desc .subresourceRange .layerCount ; 1501rtvDesc .Texture2DArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1502rtvDesc .Texture2DArray .PlaneSlice = 1503resourceImpl ?D3DUtil ::getPlaneSlice ( 1504D3DUtil ::getMapFormat (resourceImpl -> getDesc ()-> format ), 1505desc .subresourceRange .aspectMask ) 1506 :0 ; 1507break ; 1508case IResource ::Type ::Texture3D : 1509rtvDesc .ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D ; 1510rtvDesc .Texture3D .MipSlice = desc .subresourceRange .mipLevel ; 1511rtvDesc .Texture3D .FirstWSlice = desc .subresourceRange .baseArrayLayer ; 1512rtvDesc .Texture3D .WSize = 1513 (desc .subresourceRange .layerCount == 0 ) ?-1 :desc .subresourceRange .layerCount ; 1514break ; 1515case IResource ::Type ::Buffer : 1516rtvDesc .ViewDimension = D3D12_RTV_DIMENSION_BUFFER ; 1517break ; 1518default : 1519return SLANG_FAIL ; 1520 } 1521m_device -> CreateRenderTargetView ( 1522resourceImpl ?resourceImpl -> m_resource .getResource () :nullptr , 1523& rtvDesc , 1524viewImpl -> m_descriptor .cpuHandle ); 1525 } 1526break ; 1527 1528case IResourceView ::Type ::DepthStencil : 1529 { 1530SLANG_RETURN_ON_FAIL (m_dsvAllocator -> allocate (& viewImpl -> m_descriptor )); 1531viewImpl -> m_allocator = m_dsvAllocator ; 1532D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; 1533dsvDesc .Format = D3DUtil ::getMapFormat (desc .format ); 1534switch (desc .renderTarget .shape ) 1535 { 1536case IResource ::Type ::Texture1D : 1537dsvDesc .ViewDimension = D3D12_DSV_DIMENSION_TEXTURE1D ; 1538dsvDesc .Texture1D .MipSlice = desc .subresourceRange .mipLevel ; 1539break ; 1540case IResource ::Type ::Texture2D : 1541if (isMultiSample ) 1542 { 1543dsvDesc .ViewDimension = isArray ?D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY 1544 :D3D12_DSV_DIMENSION_TEXTURE2DMS ; 1545dsvDesc .Texture2DMSArray .ArraySize = desc .subresourceRange .layerCount ; 1546dsvDesc .Texture2DMSArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1547 } 1548else 1549 { 1550dsvDesc .ViewDimension = isArray ?D3D12_DSV_DIMENSION_TEXTURE2DARRAY 1551 :D3D12_DSV_DIMENSION_TEXTURE2D ; 1552dsvDesc .Texture2DArray .MipSlice = desc .subresourceRange .mipLevel ; 1553dsvDesc .Texture2DArray .ArraySize = desc .subresourceRange .layerCount ; 1554dsvDesc .Texture2DArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1555 } 1556break ; 1557case IResource ::Type ::TextureCube : 1558dsvDesc .ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY ; 1559dsvDesc .Texture2DArray .MipSlice = desc .subresourceRange .mipLevel ; 1560dsvDesc .Texture2DArray .ArraySize = desc .subresourceRange .layerCount ; 1561dsvDesc .Texture2DArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1562break ; 1563default : 1564return SLANG_FAIL ; 1565 } 1566m_device -> CreateDepthStencilView ( 1567resourceImpl ?resourceImpl -> m_resource .getResource () :nullptr , 1568& dsvDesc , 1569viewImpl -> m_descriptor .cpuHandle ); 1570 } 1571break ; 1572 1573case IResourceView ::Type ::UnorderedAccess : 1574 { 1575// TODO: need to support the separate "counter resource" for the case 1576// of append/consume buffers with attached counters. 1577 1578SLANG_RETURN_ON_FAIL (m_cpuViewHeap -> allocate (& viewImpl -> m_descriptor )); 1579viewImpl -> m_allocator = m_cpuViewHeap ; 1580D3D12_UNORDERED_ACCESS_VIEW_DESC d3d12desc = {}; 1581auto & resourceDesc = * resourceImpl -> getDesc (); 1582d3d12desc .Format = gfxIsTypelessFormat (texture -> getDesc ()-> format ) 1583 ?D3DUtil ::getMapFormat (desc .format ) 1584 :D3DUtil ::getMapFormat (texture -> getDesc ()-> format ); 1585switch (resourceImpl -> getDesc ()-> type ) 1586 { 1587case IResource ::Type ::Texture1D : 1588d3d12desc .ViewDimension = 1589isArray ?D3D12_UAV_DIMENSION_TEXTURE1DARRAY :D3D12_UAV_DIMENSION_TEXTURE1D ; 1590if (isArray ) 1591 { 1592d3d12desc .Texture1DArray .MipSlice = desc .subresourceRange .mipLevel ; 1593d3d12desc .Texture1DArray .ArraySize = desc .subresourceRange .layerCount == 0 1594 ?resourceDesc .arraySize 1595 :desc .subresourceRange .layerCount ; 1596d3d12desc .Texture1DArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1597 } 1598else 1599 { 1600d3d12desc .Texture1D .MipSlice = desc .subresourceRange .mipLevel ; 1601 } 1602break ; 1603case IResource ::Type ::Texture2D : 1604d3d12desc .ViewDimension = 1605isArray ?D3D12_UAV_DIMENSION_TEXTURE2DARRAY :D3D12_UAV_DIMENSION_TEXTURE2D ; 1606if (isArray ) 1607 { 1608d3d12desc .Texture2DArray .MipSlice = desc .subresourceRange .mipLevel ; 1609d3d12desc .Texture2DArray .ArraySize = desc .subresourceRange .layerCount == 0 1610 ?resourceDesc .arraySize 1611 :desc .subresourceRange .layerCount ; 1612d3d12desc .Texture2DArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1613d3d12desc .Texture2DArray .PlaneSlice = 1614D3DUtil ::getPlaneSlice (d3d12desc .Format ,desc .subresourceRange .aspectMask ); 1615 } 1616else 1617 { 1618d3d12desc .Texture2D .MipSlice = desc .subresourceRange .mipLevel ; 1619d3d12desc .Texture2D .PlaneSlice = 1620D3DUtil ::getPlaneSlice (d3d12desc .Format ,desc .subresourceRange .aspectMask ); 1621 } 1622break ; 1623case IResource ::Type ::TextureCube : 1624d3d12desc .ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY ; 1625d3d12desc .Texture2DArray .MipSlice = desc .subresourceRange .mipLevel ; 1626d3d12desc .Texture2DArray .ArraySize = desc .subresourceRange .layerCount == 0 1627 ?resourceDesc .arraySize 1628 :desc .subresourceRange .layerCount ; 1629d3d12desc .Texture2DArray .FirstArraySlice = desc .subresourceRange .baseArrayLayer ; 1630d3d12desc .Texture2DArray .PlaneSlice = 1631D3DUtil ::getPlaneSlice (d3d12desc .Format ,desc .subresourceRange .aspectMask ); 1632break ; 1633case IResource ::Type ::Texture3D : 1634d3d12desc .ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D ; 1635d3d12desc .Texture3D .MipSlice = desc .subresourceRange .mipLevel ; 1636d3d12desc .Texture3D .FirstWSlice = desc .subresourceRange .baseArrayLayer ; 1637d3d12desc .Texture3D .WSize = 1638resourceDesc .size .depth >>desc .subresourceRange .mipLevel ; 1639break ; 1640default : 1641return SLANG_FAIL ; 1642 } 1643m_device -> CreateUnorderedAccessView ( 1644resourceImpl -> m_resource , 1645nullptr , 1646& d3d12desc , 1647viewImpl -> m_descriptor .cpuHandle ); 1648 } 1649break ; 1650 1651case IResourceView ::Type ::ShaderResource : 1652 { 1653SLANG_RETURN_ON_FAIL (m_cpuViewHeap -> allocate (& viewImpl -> m_descriptor )); 1654viewImpl -> m_allocator = m_cpuViewHeap ; 1655 1656// Need to construct the D3D12_SHADER_RESOURCE_VIEW_DESC because otherwise TextureCube 1657// is not accessed appropriately (rather than just passing nullptr to 1658// CreateShaderResourceView) 1659const D3D12_RESOURCE_DESC resourceDesc = 1660resourceImpl -> m_resource .getResource ()-> GetDesc (); 1661const DXGI_FORMAT pixelFormat = desc .format == Format ::Unknown 1662 ?resourceDesc .Format 1663 :D3DUtil ::getMapFormat (desc .format ); 1664 1665D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc ; 1666initSrvDesc ( 1667resourceImpl -> getType (), 1668* resourceImpl -> getDesc (), 1669resourceDesc , 1670pixelFormat , 1671desc .subresourceRange , 1672srvDesc ); 1673 1674m_device -> CreateShaderResourceView ( 1675resourceImpl -> m_resource , 1676& srvDesc , 1677viewImpl -> m_descriptor .cpuHandle ); 1678 } 1679break ; 1680 } 1681 1682returnComPtr (outView ,viewImpl ); 1683return SLANG_OK ; 1684} 1685 1686Result DeviceImpl ::getFormatSupportedResourceStates (Format format ,ResourceStateSet * outStates ) 1687{ 1688D3D12_FEATURE_DATA_FORMAT_SUPPORT support ; 1689support .Format = D3DUtil ::getMapFormat (format ); 1690SLANG_RETURN_ON_FAIL ( 1691m_device -> CheckFeatureSupport (D3D12_FEATURE_FORMAT_SUPPORT ,& support ,sizeof (support ))); 1692 1693ResourceStateSet allowedStates ; 1694 1695auto dxgi1 = support .Support1 ; 1696if (dxgi1 & D3D12_FORMAT_SUPPORT1_BUFFER ) 1697allowedStates .add (ResourceState ::ConstantBuffer ); 1698if (dxgi1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER ) 1699allowedStates .add (ResourceState ::VertexBuffer ); 1700if (dxgi1 & D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER ) 1701allowedStates .add (ResourceState ::IndexBuffer ); 1702if (dxgi1 & D3D12_FORMAT_SUPPORT1_SO_BUFFER ) 1703allowedStates .add (ResourceState ::StreamOutput ); 1704if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURE1D ) 1705allowedStates .add (ResourceState ::ShaderResource ); 1706if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D ) 1707allowedStates .add (ResourceState ::ShaderResource ); 1708if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURE3D ) 1709allowedStates .add (ResourceState ::ShaderResource ); 1710if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURECUBE ) 1711allowedStates .add (ResourceState ::ShaderResource ); 1712if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD ) 1713allowedStates .add (ResourceState ::ShaderResource ); 1714if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE ) 1715allowedStates .add (ResourceState ::ShaderResource ); 1716if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_COMPARISON ) 1717allowedStates .add (ResourceState ::ShaderResource ); 1718if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_GATHER ) 1719allowedStates .add (ResourceState ::ShaderResource ); 1720if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_GATHER_COMPARISON ) 1721allowedStates .add (ResourceState ::ShaderResource ); 1722if (dxgi1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET ) 1723allowedStates .add (ResourceState ::RenderTarget ); 1724if (dxgi1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL ) 1725allowedStates .add (ResourceState ::DepthWrite ); 1726if (dxgi1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW ) 1727allowedStates .add (ResourceState ::UnorderedAccess ); 1728 1729* outStates = allowedStates ; 1730return SLANG_OK ; 1731} 1732 1733Result DeviceImpl ::createBufferView ( 1734IBufferResource * buffer , 1735IBufferResource * counterBuffer , 1736IResourceView ::Desc const & desc , 1737IResourceView ** outView ) 1738{ 1739auto resourceImpl = (BufferResourceImpl * )buffer ; 1740auto resourceDesc = * resourceImpl -> getDesc (); 1741const auto counterResourceImpl = static_cast < BufferResourceImpl *> (counterBuffer ); 1742 1743RefPtr < ResourceViewImpl > viewImpl = new ResourceViewImpl (); 1744viewImpl -> m_resource = resourceImpl ; 1745viewImpl -> m_counterResource = counterResourceImpl ; 1746viewImpl -> m_desc = desc ; 1747 1748// Buffer view descriptors are created on demand. 1749viewImpl -> m_descriptor = {0 }; 1750viewImpl -> m_allocator = m_cpuViewHeap .get (); 1751 1752returnComPtr (outView ,viewImpl ); 1753return SLANG_OK ; 1754} 1755 1756Result DeviceImpl ::createFramebuffer (IFramebuffer ::Desc const & desc ,IFramebuffer ** outFb ) 1757{ 1758RefPtr < FramebufferImpl > framebuffer = new FramebufferImpl (); 1759framebuffer -> renderTargetViews .setCount (desc .renderTargetCount ); 1760framebuffer -> renderTargetDescriptors .setCount (desc .renderTargetCount ); 1761framebuffer -> renderTargetClearValues .setCount (desc .renderTargetCount ); 1762for (GfxIndex i = 0 ;i < desc .renderTargetCount ;i ++ ) 1763 { 1764framebuffer -> renderTargetViews [i ]= 1765static_cast < ResourceViewImpl *> (desc .renderTargetViews [i ]); 1766framebuffer -> renderTargetDescriptors [i ]= 1767framebuffer -> renderTargetViews [i ]-> m_descriptor .cpuHandle ; 1768if (static_cast < ResourceViewImpl *> (desc .renderTargetViews [i ])-> m_resource .Ptr ()) 1769 { 1770auto clearValue = 1771static_cast < TextureResourceImpl *> ( 1772static_cast < ResourceViewImpl *> (desc .renderTargetViews [i ])-> m_resource .Ptr ()) 1773-> getDesc () 1774-> optimalClearValue ; 1775if (clearValue ) 1776 { 1777memcpy ( 1778& framebuffer -> renderTargetClearValues [i ], 1779& clearValue -> color , 1780sizeof (ColorClearValue )); 1781 } 1782 } 1783else 1784 { 1785memset (& framebuffer -> renderTargetClearValues [i ],0 ,sizeof (ColorClearValue )); 1786 } 1787 } 1788framebuffer -> depthStencilView = static_cast < ResourceViewImpl *> (desc .depthStencilView ); 1789if (desc .depthStencilView ) 1790 { 1791auto clearValue = 1792static_cast < TextureResourceImpl *> ( 1793static_cast < ResourceViewImpl *> (desc .depthStencilView )-> m_resource .Ptr ()) 1794-> getDesc () 1795-> optimalClearValue ; 1796 1797if (clearValue ) 1798 { 1799framebuffer -> depthStencilClearValue = clearValue -> depthStencil ; 1800 } 1801framebuffer -> depthStencilDescriptor = 1802static_cast < ResourceViewImpl *> (desc .depthStencilView )-> m_descriptor .cpuHandle ; 1803 } 1804else 1805 { 1806framebuffer -> depthStencilDescriptor .ptr = 0 ; 1807 } 1808returnComPtr (outFb ,framebuffer ); 1809return SLANG_OK ; 1810} 1811 1812Result DeviceImpl ::createFramebufferLayout ( 1813IFramebufferLayout ::Desc const & desc , 1814IFramebufferLayout ** outLayout ) 1815{ 1816RefPtr < FramebufferLayoutImpl > layout = new FramebufferLayoutImpl (); 1817layout -> m_renderTargets .setCount (desc .renderTargetCount ); 1818for (GfxIndex i = 0 ;i < desc .renderTargetCount ;i ++ ) 1819 { 1820layout -> m_renderTargets [i ]= desc .renderTargets [i ]; 1821 } 1822 1823if (desc .depthStencil ) 1824 { 1825layout -> m_hasDepthStencil = true; 1826layout -> m_depthStencil = * desc .depthStencil ; 1827 } 1828else 1829 { 1830layout -> m_hasDepthStencil = false; 1831 } 1832returnComPtr (outLayout ,layout ); 1833return SLANG_OK ; 1834} 1835 1836Result DeviceImpl ::createRenderPassLayout ( 1837const IRenderPassLayout ::Desc & desc , 1838IRenderPassLayout ** outRenderPassLayout ) 1839{ 1840RefPtr < RenderPassLayoutImpl > result = new RenderPassLayoutImpl (); 1841result -> init (desc ); 1842returnComPtr (outRenderPassLayout ,result ); 1843return SLANG_OK ; 1844} 1845 1846Result DeviceImpl ::createInputLayout (IInputLayout ::Desc const & desc ,IInputLayout ** outLayout ) 1847{ 1848RefPtr < InputLayoutImpl > layout (new InputLayoutImpl ); 1849 1850// Work out a buffer size to hold all text 1851Size textSize = 0 ; 1852auto inputElementCount = desc .inputElementCount ; 1853auto inputElements = desc .inputElements ; 1854auto vertexStreamCount = desc .vertexStreamCount ; 1855auto vertexStreams = desc .vertexStreams ; 1856for (int i = 0 ;i < Int (inputElementCount );++ i ) 1857 { 1858const char * text = inputElements [i ].semanticName ; 1859textSize += text ? (::strlen (text )+ 1 ) :0 ; 1860 } 1861layout -> m_text .setCount (textSize ); 1862char * textPos = layout -> m_text .getBuffer (); 1863 1864List < D3D12_INPUT_ELEMENT_DESC >& elements = layout -> m_elements ; 1865SLANG_ASSERT (inputElementCount > 0 ); 1866elements .setCount (inputElementCount ); 1867 1868for (Int i = 0 ;i < inputElementCount ;++ i ) 1869 { 1870const InputElementDesc & srcEle = inputElements [i ]; 1871const auto & srcStream = vertexStreams [srcEle .bufferSlotIndex ]; 1872D3D12_INPUT_ELEMENT_DESC & dstEle = elements [i ]; 1873 1874// Add text to the buffer 1875const char * semanticName = srcEle .semanticName ; 1876if (semanticName ) 1877 { 1878const int len = int (::strlen (semanticName )); 1879 ::memcpy (textPos ,semanticName ,len + 1 ); 1880semanticName = textPos ; 1881textPos += len + 1 ; 1882 } 1883 1884dstEle .SemanticName = semanticName ; 1885dstEle .SemanticIndex = (UINT )srcEle .semanticIndex ; 1886dstEle .Format = D3DUtil ::getMapFormat (srcEle .format ); 1887dstEle .InputSlot = (UINT )srcEle .bufferSlotIndex ; 1888dstEle .AlignedByteOffset = (UINT )srcEle .offset ; 1889dstEle .InputSlotClass = D3DUtil ::getInputSlotClass (srcStream .slotClass ); 1890dstEle .InstanceDataStepRate = (UINT )srcStream .instanceDataStepRate ; 1891 } 1892 1893auto & vertexStreamStrides = layout -> m_vertexStreamStrides ; 1894vertexStreamStrides .setCount (vertexStreamCount ); 1895for (GfxIndex i = 0 ;i < vertexStreamCount ;++ i ) 1896 { 1897vertexStreamStrides [i ]= (UINT )vertexStreams [i ].stride ; 1898 } 1899 1900returnComPtr (outLayout ,layout ); 1901return SLANG_OK ; 1902} 1903 1904const gfx::DeviceInfo & DeviceImpl ::getDeviceInfo ()const 1905{ 1906return m_info ; 1907} 1908 1909Result DeviceImpl ::readBufferResource ( 1910IBufferResource * bufferIn , 1911Offset offset , 1912Size size , 1913ISlangBlob ** outBlob ) 1914{ 1915 1916BufferResourceImpl * buffer = static_cast < BufferResourceImpl *> (bufferIn ); 1917 1918const Size bufferSize = buffer -> getDesc ()-> sizeInBytes ; 1919 1920// This will be slow!!! - it blocks CPU on GPU completion 1921D3D12Resource & resource = buffer -> m_resource ; 1922 1923D3D12Resource stageBuf ; 1924if (buffer -> getDesc ()-> memoryType != MemoryType ::ReadBack ) 1925 { 1926auto encodeInfo = encodeResourceCommands (); 1927 1928// Readback heap 1929D3D12_HEAP_PROPERTIES heapProps ; 1930heapProps .Type = D3D12_HEAP_TYPE_READBACK ; 1931heapProps .CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN ; 1932heapProps .MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN ; 1933heapProps .CreationNodeMask = 1 ; 1934heapProps .VisibleNodeMask = 1 ; 1935 1936// Resource to readback to 1937D3D12_RESOURCE_DESC stagingDesc ; 1938initBufferResourceDesc (size ,stagingDesc ); 1939 1940SLANG_RETURN_ON_FAIL (stageBuf .initCommitted ( 1941m_device , 1942heapProps , 1943D3D12_HEAP_FLAG_NONE , 1944stagingDesc , 1945D3D12_RESOURCE_STATE_COPY_DEST , 1946nullptr )); 1947 1948// Do the copy 1949encodeInfo .d3dCommandList -> CopyBufferRegion (stageBuf ,0 ,resource ,offset ,size ); 1950 1951// Wait until complete 1952submitResourceCommandsAndWait (encodeInfo ); 1953 } 1954 1955D3D12Resource & stageBufRef = 1956buffer -> getDesc ()-> memoryType != MemoryType ::ReadBack ?stageBuf :resource ; 1957 1958// Map and copy 1959List < uint8_t > blobData ; 1960 { 1961UINT8 * data ; 1962D3D12_RANGE readRange = {0 ,size }; 1963 1964SLANG_RETURN_ON_FAIL ( 1965stageBufRef .getResource ()-> Map (0 ,& readRange ,reinterpret_cast < void **> (& data ))); 1966 1967// Copy to memory buffer 1968blobData .setCount (size ); 1969 ::memcpy (blobData .getBuffer (),data ,size ); 1970 1971stageBufRef .getResource ()-> Unmap (0 ,nullptr ); 1972 } 1973auto blob = ListBlob ::moveCreate (blobData ); 1974returnComPtr (outBlob ,blob ); 1975return SLANG_OK ; 1976} 1977 1978Result DeviceImpl ::createProgram ( 1979const IShaderProgram ::Desc & desc , 1980IShaderProgram ** outProgram , 1981ISlangBlob ** outDiagnosticBlob ) 1982{ 1983RefPtr < ShaderProgramImpl > shaderProgram = new ShaderProgramImpl (); 1984shaderProgram -> init (desc ); 1985ComPtr < ID3DBlob > d3dDiagnosticBlob ; 1986auto rootShaderLayoutResult = RootShaderObjectLayoutImpl ::create ( 1987this , 1988shaderProgram -> linkedProgram , 1989shaderProgram -> linkedProgram -> getLayout (), 1990shaderProgram -> m_rootObjectLayout .writeRef (), 1991d3dDiagnosticBlob .writeRef ()); 1992if (!SLANG_SUCCEEDED (rootShaderLayoutResult )) 1993 { 1994if (outDiagnosticBlob && d3dDiagnosticBlob ) 1995 { 1996String diagnostic ((const char * )d3dDiagnosticBlob -> GetBufferPointer ()); 1997auto diagnosticBlob = StringBlob ::create (diagnostic ); 1998 1999returnComPtr (outDiagnosticBlob ,diagnosticBlob ); 2000 } 2001return rootShaderLayoutResult ; 2002 } 2003 2004if (!shaderProgram -> isSpecializable ()) 2005 { 2006SLANG_RETURN_ON_FAIL (shaderProgram -> compileShaders (this )); 2007 } 2008 2009returnComPtr (outProgram ,shaderProgram ); 2010return SLANG_OK ; 2011} 2012 2013Result DeviceImpl ::createShaderObjectLayout ( 2014 slang::ISession * session , 2015 slang::TypeLayoutReflection * typeLayout , 2016ShaderObjectLayoutBase ** outLayout ) 2017{ 2018RefPtr < ShaderObjectLayoutImpl > layout ; 2019SLANG_RETURN_ON_FAIL ( 2020ShaderObjectLayoutImpl ::createForElementType (this ,session ,typeLayout ,layout .writeRef ())); 2021returnRefPtrMove (outLayout ,layout ); 2022return SLANG_OK ; 2023} 2024 2025Result DeviceImpl ::createShaderObject (ShaderObjectLayoutBase * layout ,IShaderObject ** outObject ) 2026{ 2027RefPtr < ShaderObjectImpl > shaderObject ; 2028SLANG_RETURN_ON_FAIL (ShaderObjectImpl ::create ( 2029this , 2030reinterpret_cast < ShaderObjectLayoutImpl *> (layout ), 2031shaderObject .writeRef ())); 2032returnComPtr (outObject ,shaderObject ); 2033return SLANG_OK ; 2034} 2035 2036Result DeviceImpl ::createMutableShaderObject ( 2037ShaderObjectLayoutBase * layout , 2038IShaderObject ** outObject ) 2039{ 2040auto result = createShaderObject (layout ,outObject ); 2041SLANG_RETURN_ON_FAIL (result ); 2042static_cast < ShaderObjectImpl *> (* outObject )-> m_isMutable = true; 2043return result ; 2044} 2045 2046Result DeviceImpl ::createMutableRootShaderObject (IShaderProgram * program ,IShaderObject ** outObject ) 2047{ 2048RefPtr < MutableRootShaderObjectImpl > result = new MutableRootShaderObjectImpl (); 2049result -> init (this ); 2050auto programImpl = static_cast < ShaderProgramImpl *> (program ); 2051result -> resetImpl ( 2052this , 2053programImpl -> m_rootObjectLayout , 2054m_cpuViewHeap .Ptr (), 2055m_cpuSamplerHeap .Ptr (), 2056 true); 2057returnComPtr (outObject ,result ); 2058return SLANG_OK ; 2059} 2060 2061Result DeviceImpl ::createShaderTable (const IShaderTable ::Desc & desc ,IShaderTable ** outShaderTable ) 2062{ 2063RefPtr < ShaderTableImpl > result = new ShaderTableImpl (); 2064result -> m_device = this ; 2065result -> init (desc ); 2066returnComPtr (outShaderTable ,result ); 2067return SLANG_OK ; 2068} 2069 2070Result DeviceImpl ::createGraphicsPipelineState ( 2071const GraphicsPipelineStateDesc & desc , 2072IPipelineState ** outState ) 2073{ 2074RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (this ); 2075pipelineStateImpl -> init (desc ); 2076returnComPtr (outState ,pipelineStateImpl ); 2077return SLANG_OK ; 2078} 2079 2080Result DeviceImpl ::createComputePipelineState ( 2081const ComputePipelineStateDesc & desc , 2082IPipelineState ** outState ) 2083{ 2084RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (this ); 2085pipelineStateImpl -> init (desc ); 2086returnComPtr (outState ,pipelineStateImpl ); 2087return SLANG_OK ; 2088} 2089 2090DeviceImpl ::ResourceCommandRecordInfo DeviceImpl ::encodeResourceCommands () 2091{ 2092ResourceCommandRecordInfo info ; 2093m_resourceCommandTransientHeap -> createCommandBuffer (info .commandBuffer .writeRef ()); 2094info .d3dCommandList = static_cast < CommandBufferImpl *> (info .commandBuffer .get ())-> m_cmdList ; 2095return info ; 2096} 2097 2098void DeviceImpl ::submitResourceCommandsAndWait (const DeviceImpl ::ResourceCommandRecordInfo & info ) 2099{ 2100info .commandBuffer -> close (); 2101m_resourceCommandQueue -> executeCommandBuffer (info .commandBuffer ); 2102m_resourceCommandTransientHeap -> finish (); 2103m_resourceCommandTransientHeap -> synchronizeAndReset (); 2104} 2105 2106void DeviceImpl ::processExperimentalFeaturesDesc (SharedLibrary ::Handle d3dModule ,void * inDesc ) 2107{ 2108typedef HRESULT (WINAPI * PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES )( 2109UINT NumFeatures , 2110const IID * pIIDs , 2111void * pConfigurationStructs , 2112UINT * pConfigurationStructSizes ); 2113 2114D3D12ExperimentalFeaturesDesc desc = {}; 2115memcpy (& desc ,inDesc ,sizeof (desc )); 2116auto enableExperimentalFeaturesFunc = (PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES )loadProc ( 2117d3dModule , 2118"D3D12EnableExperimentalFeatures" ); 2119if (!enableExperimentalFeaturesFunc ) 2120 { 2121getDebugCallback ()-> handleMessage ( 2122 gfx::DebugMessageType ::Warning , 2123 gfx::DebugMessageSource ::Layer , 2124"cannot enable D3D12 experimental features, 'D3D12EnableExperimentalFeatures' function " 2125"not found." ); 2126return ; 2127 } 2128if (!SLANG_SUCCEEDED (enableExperimentalFeaturesFunc ( 2129desc .numFeatures , 2130 (IID * )desc .featureIIDs , 2131desc .configurationStructs , 2132desc .configurationStructSizes ))) 2133 { 2134getDebugCallback ()-> handleMessage ( 2135 gfx::DebugMessageType ::Warning , 2136 gfx::DebugMessageSource ::Layer , 2137"cannot enable D3D12 experimental features, 'D3D12EnableExperimentalFeatures' call " 2138"failed." ); 2139return ; 2140 } 2141} 2142 2143Result DeviceImpl ::createQueryPool (const IQueryPool ::Desc & desc ,IQueryPool ** outState ) 2144{ 2145switch (desc .type ) 2146 { 2147case QueryType ::AccelerationStructureCompactedSize : 2148case QueryType ::AccelerationStructureSerializedSize : 2149case QueryType ::AccelerationStructureCurrentSize : 2150 { 2151RefPtr < PlainBufferProxyQueryPoolImpl > queryPoolImpl = 2152new PlainBufferProxyQueryPoolImpl (); 2153uint32_t stride = 8 ; 2154if (desc .type == QueryType ::AccelerationStructureSerializedSize ) 2155stride = 16 ; 2156SLANG_RETURN_ON_FAIL (queryPoolImpl -> init (desc ,this ,stride )); 2157returnComPtr (outState ,queryPoolImpl ); 2158return SLANG_OK ; 2159 } 2160default : 2161 { 2162RefPtr < QueryPoolImpl > queryPoolImpl = new QueryPoolImpl (); 2163SLANG_RETURN_ON_FAIL (queryPoolImpl -> init (desc ,this )); 2164returnComPtr (outState ,queryPoolImpl ); 2165return SLANG_OK ; 2166 } 2167 } 2168} 2169 2170Result DeviceImpl ::createFence (const IFence ::Desc & desc ,IFence ** outFence ) 2171{ 2172RefPtr < FenceImpl > fence = new FenceImpl (); 2173SLANG_RETURN_ON_FAIL (fence -> init (this ,desc )); 2174returnComPtr (outFence ,fence ); 2175return SLANG_OK ; 2176} 2177 2178Result DeviceImpl ::waitForFences ( 2179GfxCount fenceCount , 2180IFence ** fences , 2181uint64_t * fenceValues , 2182bool waitForAll , 2183uint64_t timeout ) 2184{ 2185ShortList < HANDLE > waitHandles ; 2186for (GfxCount i = 0 ;i < fenceCount ;++ i ) 2187 { 2188auto fenceImpl = static_cast < FenceImpl *> (fences [i ]); 2189waitHandles .add (fenceImpl -> getWaitEvent ()); 2190SLANG_RETURN_ON_FAIL ( 2191fenceImpl -> m_fence -> SetEventOnCompletion (fenceValues [i ],fenceImpl -> getWaitEvent ())); 2192 } 2193auto result = WaitForMultipleObjects ( 2194fenceCount , 2195waitHandles .getArrayView ().getBuffer (), 2196waitForAll ? TRUE : FALSE, 2197timeout == kTimeoutInfinite ?INFINITE : (DWORD )(timeout /1000000 )); 2198if (result == WAIT_TIMEOUT ) 2199return SLANG_E_TIME_OUT ; 2200return result == WAIT_FAILED ?SLANG_FAIL :SLANG_OK ; 2201} 2202 2203Result DeviceImpl ::getAccelerationStructurePrebuildInfo ( 2204const IAccelerationStructure ::BuildInputs & buildInputs , 2205IAccelerationStructure ::PrebuildInfo * outPrebuildInfo ) 2206{ 2207if (!m_device5 ) 2208return SLANG_E_NOT_AVAILABLE ; 2209 2210D3DAccelerationStructureInputsBuilder inputsBuilder ; 2211SLANG_RETURN_ON_FAIL (inputsBuilder .build (buildInputs ,getDebugCallback ())); 2212 2213D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO prebuildInfo ; 2214m_device5 -> GetRaytracingAccelerationStructurePrebuildInfo (& inputsBuilder .desc ,& prebuildInfo ); 2215 2216outPrebuildInfo -> resultDataMaxSize = (Size )prebuildInfo .ResultDataMaxSizeInBytes ; 2217outPrebuildInfo -> scratchDataSize = (Size )prebuildInfo .ScratchDataSizeInBytes ; 2218outPrebuildInfo -> updateScratchDataSize = (Size )prebuildInfo .UpdateScratchDataSizeInBytes ; 2219return SLANG_OK ; 2220} 2221 2222Result DeviceImpl ::createAccelerationStructure ( 2223const IAccelerationStructure ::CreateDesc & desc , 2224IAccelerationStructure ** outAS ) 2225{ 2226#if SLANG_GFX_HAS_DXR_SUPPORT 2227assert (desc .buffer != nullptr ); 2228RefPtr < AccelerationStructureImpl > result = new AccelerationStructureImpl (); 2229result -> m_device5 = m_device5 ; 2230result -> m_buffer = static_cast < BufferResourceImpl *> (desc .buffer ); 2231result -> m_size = desc .size ; 2232result -> m_offset = desc .offset ; 2233result -> m_allocator = m_cpuViewHeap ; 2234result -> m_desc .type = IResourceView ::Type ::AccelerationStructure ; 2235SLANG_RETURN_ON_FAIL (m_cpuViewHeap -> allocate (& result -> m_descriptor )); 2236D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc ; 2237srvDesc .Format = DXGI_FORMAT_UNKNOWN ; 2238srvDesc .ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE ; 2239srvDesc .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING ; 2240srvDesc .RaytracingAccelerationStructure .Location = 2241result -> m_buffer -> getDeviceAddress ()+ desc .offset ; 2242m_device -> CreateShaderResourceView (nullptr ,& srvDesc ,result -> m_descriptor .cpuHandle ); 2243returnComPtr (outAS ,result ); 2244return SLANG_OK ; 2245#else 2246* outAS = nullptr ; 2247return SLANG_FAIL ; 2248#endif 2249} 2250 2251Result DeviceImpl ::createRayTracingPipelineState ( 2252const RayTracingPipelineStateDesc & inDesc , 2253IPipelineState ** outState ) 2254{ 2255if (!m_device5 ) 2256 { 2257return SLANG_E_NOT_AVAILABLE ; 2258 } 2259 2260RefPtr < RayTracingPipelineStateImpl > pipelineStateImpl = new RayTracingPipelineStateImpl (this ); 2261pipelineStateImpl -> init (inDesc ); 2262returnComPtr (outState ,pipelineStateImpl ); 2263return SLANG_OK ; 2264} 2265 2266Result DeviceImpl ::createTransientResourceHeapImpl ( 2267ITransientResourceHeap ::Flags ::Enum flags , 2268Size constantBufferSize , 2269uint32_t viewDescriptors , 2270uint32_t samplerDescriptors , 2271TransientResourceHeapImpl ** outHeap ) 2272{ 2273RefPtr < TransientResourceHeapImpl > result = new TransientResourceHeapImpl (); 2274ITransientResourceHeap ::Desc desc = {}; 2275desc .flags = flags ; 2276desc .samplerDescriptorCount = samplerDescriptors ; 2277desc .constantBufferSize = constantBufferSize ; 2278desc .constantBufferDescriptorCount = viewDescriptors ; 2279desc .accelerationStructureDescriptorCount = viewDescriptors ; 2280desc .srvDescriptorCount = viewDescriptors ; 2281desc .uavDescriptorCount = viewDescriptors ; 2282SLANG_RETURN_ON_FAIL (result -> init (desc ,this ,viewDescriptors ,samplerDescriptors )); 2283returnRefPtrMove (outHeap ,result ); 2284return SLANG_OK ; 2285} 2286 2287Result DeviceImpl ::createCommandQueueImpl (CommandQueueImpl ** outQueue ) 2288{ 2289int queueIndex = m_queueIndexAllocator .alloc (1 ); 2290// If we run out of queue index space, then the user is requesting too many queues. 2291if (queueIndex == -1 ) 2292return SLANG_FAIL ; 2293 2294RefPtr < CommandQueueImpl > queue = new CommandQueueImpl (); 2295SLANG_RETURN_ON_FAIL (queue -> init (this , (uint32_t )queueIndex )); 2296returnRefPtrMove (outQueue ,queue ); 2297return SLANG_OK ; 2298} 2299 2300void * DeviceImpl ::loadProc (SharedLibrary ::Handle module ,char const * name ) 2301{ 2302void * proc = SharedLibrary ::findSymbolAddressByName (module ,name ); 2303if (!proc ) 2304 { 2305fprintf (stderr ,"error: failed load symbol '%s'\n" ,name ); 2306return nullptr ; 2307 } 2308return proc ; 2309} 2310 2311DeviceImpl ::~DeviceImpl () 2312{ 2313m_shaderObjectLayoutCache = decltype(m_shaderObjectLayoutCache )(); 2314} 2315 2316 2317}// namespace d3d12 2318}// namespace gfx