yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
28006e36d
master
1// d3d11-device.cpp 2#define _CRT_SECURE_NO_WARNINGS 3#include "d3d11-device.h" 4 5#include "d3d11-buffer.h" 6#include "d3d11-helper-functions.h" 7#include "d3d11-query.h" 8#include "d3d11-resource-views.h" 9#include "d3d11-sampler.h" 10#include "d3d11-scopeNVAPI.h" 11#include "d3d11-shader-object-layout.h" 12#include "d3d11-shader-object.h" 13#include "d3d11-shader-program.h" 14#include "d3d11-swap-chain.h" 15#include "d3d11-texture.h" 16#include "d3d11-vertex-layout.h" 17 18#ifdef GFX_NV_AFTERMATH 19#include "GFSDK_Aftermath.h" 20#include "GFSDK_Aftermath_Defines.h" 21#include "GFSDK_Aftermath_GpuCrashDump.h" 22#endif 23 24namespace gfx 25{ 26 27using namespace Slang ; 28 29namespace d3d11 30{ 31 32SlangResult DeviceImpl ::initialize (const Desc & desc ) 33{ 34SLANG_RETURN_ON_FAIL (slangContext .initialize ( 35desc .slang , 36desc .extendedDescCount , 37desc .extendedDescs , 38SLANG_DXBC , 39"sm_5_0" , 40makeArray (slang::PreprocessorMacroDesc {"__D3D11__" ,"1" }).getView ())); 41 42SLANG_RETURN_ON_FAIL (RendererBase ::initialize (desc )); 43 44// Initialize DeviceInfo 45 { 46m_info .deviceType = DeviceType ::DirectX11 ; 47m_info .bindingStyle = BindingStyle ::DirectX ; 48m_info .projectionStyle = ProjectionStyle ::DirectX ; 49m_info .apiName = "Direct3D 11" ; 50static const float kIdentity []= {1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,1 }; 51 ::memcpy (m_info .identityProjectionMatrix ,kIdentity ,sizeof (kIdentity )); 52 } 53 54m_desc = desc ; 55 56// Rather than statically link against D3D, we load it dynamically. 57SharedLibrary ::Handle d3dModule ; 58const char * libName = SLANG_ENABLE_DXVK ?"dxvk_d3d11" :"d3d11" ; 59if (SLANG_FAILED (SharedLibrary ::load (libName ,d3dModule ))) 60 { 61fprintf (stderr ,"error: failed to load '%s'\n" ,libName ); 62return SLANG_FAIL ; 63 } 64 65PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN D3D11CreateDeviceAndSwapChain_ = 66 (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN )SharedLibrary ::findSymbolAddressByName ( 67d3dModule , 68"D3D11CreateDeviceAndSwapChain" ); 69if (!D3D11CreateDeviceAndSwapChain_ ) 70 { 71fprintf (stderr ,"error: failed load symbol 'D3D11CreateDeviceAndSwapChain'\n" ); 72return SLANG_FAIL ; 73 } 74 75PFN_D3D11_CREATE_DEVICE D3D11CreateDevice_ = (PFN_D3D11_CREATE_DEVICE ) 76SharedLibrary ::findSymbolAddressByName (d3dModule ,"D3D11CreateDevice" ); 77if (!D3D11CreateDevice_ ) 78 { 79fprintf (stderr ,"error: failed load symbol 'D3D11CreateDevice'\n" ); 80return SLANG_FAIL ; 81 } 82 83// We will ask for the highest feature level that can be supported. 84const D3D_FEATURE_LEVEL featureLevels []= { 85D3D_FEATURE_LEVEL_11_1 , 86D3D_FEATURE_LEVEL_11_0 , 87D3D_FEATURE_LEVEL_10_1 , 88D3D_FEATURE_LEVEL_10_0 , 89D3D_FEATURE_LEVEL_9_3 , 90D3D_FEATURE_LEVEL_9_2 , 91D3D_FEATURE_LEVEL_9_1 , 92 }; 93D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_9_1 ; 94const int totalNumFeatureLevels = SLANG_COUNT_OF (featureLevels ); 95 96 { 97// On a machine that does not have an up-to-date version of D3D installed, 98// the `D3D11CreateDeviceAndSwapChain` call will fail with `E_INVALIDARG` 99// if you ask for feature level 11_1 (DeviceCheckFlag::UseFullFeatureLevel). 100// The workaround is to call `D3D11CreateDeviceAndSwapChain` the first time 101// with 11_1 and then back off to 11_0 if that fails. 102 103FlagCombiner combiner ; 104// TODO: we should probably provide a command-line option 105// to override UseDebug of default rather than leave it 106// up to each back-end to specify. 107 108#if _DEBUG 109combiner .add ( 110DeviceCheckFlag ::UseDebug , 111ChangeType ::OnOff );///< First try debug then non debug 112#else 113combiner .add (DeviceCheckFlag ::UseDebug ,ChangeType ::Off );///< Don't bother with debug 114#endif 115combiner .add ( 116DeviceCheckFlag ::UseHardwareDevice , 117ChangeType ::OnOff );///< First try hardware, then reference 118combiner .add ( 119DeviceCheckFlag ::UseFullFeatureLevel , 120ChangeType ::OnOff );///< First try fully featured, then degrade features 121 122 123const int numCombinations = combiner .getNumCombinations (); 124Result res = SLANG_FAIL ; 125for (int i = 0 ;i < numCombinations ;++ i ) 126 { 127const auto deviceCheckFlags = combiner .getCombination (i ); 128D3DUtil ::createFactory (deviceCheckFlags ,m_dxgiFactory ); 129 130// If we have an adapter set on the desc, look it up. 131ComPtr < IDXGIAdapter > adapter ; 132if (desc .adapterLUID ) 133 { 134List < ComPtr < IDXGIAdapter >> dxgiAdapters ; 135D3DUtil ::findAdapters ( 136deviceCheckFlags , 137desc .adapterLUID , 138m_dxgiFactory , 139dxgiAdapters ); 140if (dxgiAdapters .getCount ()== 0 ) 141 { 142continue ; 143 } 144adapter = dxgiAdapters [0 ]; 145 } 146 147// The adapter can be nullptr - that just means 'default', but when so we need to select 148// the driver type 149D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_UNKNOWN ; 150if (adapter == nullptr ) 151 { 152// If we don't have an adapter, select directly 153driverType = (deviceCheckFlags & DeviceCheckFlag ::UseHardwareDevice ) 154 ?D3D_DRIVER_TYPE_HARDWARE 155 :D3D_DRIVER_TYPE_REFERENCE ; 156 } 157 158const int startFeatureIndex = 159 (deviceCheckFlags & DeviceCheckFlag ::UseFullFeatureLevel ) ?0 :1 ; 160const UINT deviceFlags = 161 (deviceCheckFlags & DeviceCheckFlag ::UseDebug ) ?D3D11_CREATE_DEVICE_DEBUG :0 ; 162 163res = D3D11CreateDevice_ ( 164adapter , 165driverType , 166nullptr , 167deviceFlags , 168& featureLevels [startFeatureIndex ], 169totalNumFeatureLevels - startFeatureIndex , 170D3D11_SDK_VERSION , 171m_device .writeRef (), 172& featureLevel , 173m_immediateContext .writeRef ()); 174 175#ifdef GFX_NV_AFTERMATH 176if (SLANG_SUCCEEDED (res )) 177 { 178if (deviceCheckFlags & DeviceCheckFlag ::UseDebug ) 179 { 180// Initialize Nsight Aftermath for this device. 181// This combination of flags is not necessarily appropriate for real world usage 182const uint32_t aftermathFlags = 183GFSDK_Aftermath_FeatureFlags_EnableMarkers |// Enable event marker 184// tracking. 185GFSDK_Aftermath_FeatureFlags_CallStackCapturing |// Enable automatic call 186// stack event markers. 187GFSDK_Aftermath_FeatureFlags_EnableResourceTracking |// Enable tracking of 188// resources. 189GFSDK_Aftermath_FeatureFlags_GenerateShaderDebugInfo |// Generate debug 190// information for 191// shaders. 192GFSDK_Aftermath_FeatureFlags_EnableShaderErrorReporting ;// Enable 193// additional 194// runtime shader 195// error reporting. 196 197auto initResult = GFSDK_Aftermath_DX11_Initialize ( 198GFSDK_Aftermath_Version_API , 199aftermathFlags , 200m_device ); 201 202if (initResult != GFSDK_Aftermath_Result_Success ) 203 { 204SLANG_ASSERT_FAILURE ("Unable to initialize aftermath" ); 205// Unable to initialize aftermath 206return SLANG_FAIL ; 207 } 208 } 209 } 210#endif 211 212// Check if successfully constructed - if so we are done. 213if (SLANG_SUCCEEDED (res )) 214 { 215break ; 216 } 217 } 218// If res is failure, means all styles have have failed, and so initialization fails. 219if (SLANG_FAILED (res )) 220 { 221return res ; 222 } 223// Check we have a swap chain, context and device 224SLANG_ASSERT (m_immediateContext && m_device ); 225 226ComPtr < IDXGIDevice > dxgiDevice ; 227if (m_device -> QueryInterface (dxgiDevice .writeRef ())== 0 ) 228 { 229ComPtr < IDXGIAdapter > dxgiAdapter ; 230dxgiDevice -> GetAdapter (dxgiAdapter .writeRef ()); 231DXGI_ADAPTER_DESC adapterDesc ; 232dxgiAdapter -> GetDesc (& adapterDesc ); 233m_adapterName = String ::fromWString (adapterDesc .Description ); 234m_info .adapterName = m_adapterName .begin (); 235 } 236 } 237 238// NVAPI 239if (desc .nvapiExtnSlot >=0 ) 240 { 241if (SLANG_FAILED (NVAPIUtil ::initialize ())) 242 { 243return SLANG_E_NOT_AVAILABLE ; 244 } 245 246#ifdef GFX_NVAPI 247if (NvAPI_D3D11_SetNvShaderExtnSlot (m_device ,NvU32 (desc .nvapiExtnSlot ))!= NVAPI_OK ) 248 { 249return SLANG_E_NOT_AVAILABLE ; 250 } 251 252if (isSupportedNVAPIOp (m_device ,NV_EXTN_OP_UINT64_ATOMIC )) 253 { 254m_features .add ("atomic-int64" ); 255 } 256if (isSupportedNVAPIOp (m_device ,NV_EXTN_OP_FP32_ATOMIC )) 257 { 258m_features .add ("atomic-float" ); 259 } 260 261// If we have NVAPI well assume we have realtime clock 262 { 263m_features .add ("realtime-clock" ); 264 } 265 266m_nvapi = true; 267#endif 268 } 269 270// Check double precision support 271 { 272D3D11_FEATURE_DATA_DOUBLES doublePrecisionFeature = {}; 273if (SUCCEEDED (m_device -> CheckFeatureSupport ( 274D3D11_FEATURE_DOUBLES , 275& doublePrecisionFeature , 276sizeof (doublePrecisionFeature )))&& 277doublePrecisionFeature .DoublePrecisionFloatShaderOps ) 278 { 279m_features .add ("double" ); 280 } 281 } 282 283 { 284// Create a TIMESTAMP_DISJOINT query object to query/update frequency info. 285D3D11_QUERY_DESC disjointQueryDesc = {}; 286disjointQueryDesc .Query = D3D11_QUERY_TIMESTAMP_DISJOINT ; 287SLANG_RETURN_ON_FAIL (m_device -> CreateQuery (& disjointQueryDesc ,m_disjointQuery .writeRef ())); 288m_immediateContext -> Begin (m_disjointQuery ); 289m_immediateContext -> End (m_disjointQuery ); 290D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData = {}; 291m_immediateContext -> GetData (m_disjointQuery ,& disjointData ,sizeof (disjointData ),0 ); 292m_info .timestampFrequency = disjointData .Frequency ; 293 } 294 295// Get device limits. 296 { 297uint32_t maxTextureDimensionUV = 2048 ; 298if (featureLevel >=D3D_FEATURE_LEVEL_9_3 ) 299maxTextureDimensionUV = 4096 ; 300if (featureLevel >=D3D_FEATURE_LEVEL_10_0 ) 301maxTextureDimensionUV = 8192 ; 302if (featureLevel >=D3D_FEATURE_LEVEL_11_0 ) 303maxTextureDimensionUV = 16384 ; 304 305uint32_t maxTextureDimensionW = 256 ; 306if (featureLevel >=D3D_FEATURE_LEVEL_10_0 ) 307maxTextureDimensionW = 2048 ; 308 309uint32_t maxTextureDimensionCube = 512 ; 310if (featureLevel >=D3D_FEATURE_LEVEL_9_3 ) 311maxTextureDimensionCube = maxTextureDimensionUV ; 312 313uint32_t maxInputElements = 16 ; 314if (featureLevel >=D3D_FEATURE_LEVEL_10_1 ) 315maxInputElements = 32 ; 316 317uint32_t maxColorAttachments = 4 ; 318if (featureLevel >=D3D_FEATURE_LEVEL_10_1 ) 319maxColorAttachments = 8 ; 320 321uint32_t maxComputeThreadGroupSizeXY = 0 ; 322uint32_t maxComputeThreadGroupSizeZ = 0 ; 323uint32_t maxComputeDispatchThreadGroupsZ = 0 ; 324if (featureLevel >=D3D_FEATURE_LEVEL_10_0 ) 325 { 326maxComputeThreadGroupSizeXY = D3D11_CS_4_X_THREAD_GROUP_MAX_X ; 327maxComputeThreadGroupSizeZ = 1 ; 328maxComputeDispatchThreadGroupsZ = 1 ; 329 } 330if (featureLevel >=D3D_FEATURE_LEVEL_11_0 ) 331 { 332maxComputeThreadGroupSizeXY = D3D11_CS_THREAD_GROUP_MAX_X ; 333maxComputeThreadGroupSizeZ = D3D11_CS_THREAD_GROUP_MAX_Z ; 334maxComputeDispatchThreadGroupsZ = D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION ; 335 } 336 337DeviceLimits limits = {}; 338limits .maxTextureDimension1D = maxTextureDimensionUV ; 339limits .maxTextureDimension2D = maxTextureDimensionUV ; 340limits .maxTextureDimension3D = maxTextureDimensionW ; 341limits .maxTextureDimensionCube = maxTextureDimensionCube ; 342limits .maxTextureArrayLayers = maxTextureDimensionCube ; 343 344limits .maxVertexInputElements = maxInputElements ; 345limits .maxVertexInputElementOffset = 256 ;// TODO 346limits .maxVertexStreams = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT ; 347limits .maxVertexStreamStride = D3D11_REQ_MULTI_ELEMENT_STRUCTURE_SIZE_IN_BYTES ; 348 349limits .maxComputeThreadsPerGroup = D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP ; 350limits .maxComputeThreadGroupSize [0 ]= maxComputeThreadGroupSizeXY ; 351limits .maxComputeThreadGroupSize [1 ]= maxComputeThreadGroupSizeXY ; 352limits .maxComputeThreadGroupSize [2 ]= maxComputeThreadGroupSizeZ ; 353limits .maxComputeDispatchThreadGroups [0 ]= 354D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION ; 355limits .maxComputeDispatchThreadGroups [1 ]= 356D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION ; 357limits .maxComputeDispatchThreadGroups [2 ]= maxComputeDispatchThreadGroupsZ ; 358 359limits .maxViewports = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE ; 360limits .maxViewportDimensions [0 ]= D3D11_VIEWPORT_BOUNDS_MAX ; 361limits .maxViewportDimensions [1 ]= D3D11_VIEWPORT_BOUNDS_MAX ; 362limits .maxFramebufferDimensions [0 ]= 4096 ;// TODO 363limits .maxFramebufferDimensions [1 ]= 4096 ;// TODO 364limits .maxFramebufferDimensions [2 ]= 1 ; 365 366limits .maxShaderVisibleSamplers = D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT ; 367 368m_info .limits = limits ; 369 } 370 371return SLANG_OK ; 372} 373 374void DeviceImpl ::clearFrame (uint32_t colorBufferMask ,bool clearDepth ,bool clearStencil ) 375{ 376uint32_t mask = 1 ; 377for (auto rtv :m_currentFramebuffer -> renderTargetViews ) 378 { 379if (colorBufferMask & mask ) 380m_immediateContext -> ClearRenderTargetView (rtv -> m_rtv ,rtv -> m_clearValue ); 381mask <<=1 ; 382 } 383 384if (m_currentFramebuffer -> depthStencilView ) 385 { 386UINT clearFlags = 0 ; 387if (clearDepth ) 388clearFlags = D3D11_CLEAR_DEPTH ; 389if (clearStencil ) 390clearFlags |=D3D11_CLEAR_STENCIL ; 391if (clearFlags ) 392 { 393m_immediateContext -> ClearDepthStencilView ( 394m_currentFramebuffer -> depthStencilView -> m_dsv , 395clearFlags , 396m_currentFramebuffer -> depthStencilView -> m_clearValue .depth , 397m_currentFramebuffer -> depthStencilView -> m_clearValue .stencil ); 398 } 399 } 400} 401 402Result DeviceImpl ::createSwapchain ( 403const ISwapchain ::Desc & desc , 404WindowHandle window , 405ISwapchain ** outSwapchain ) 406{ 407RefPtr < SwapchainImpl > swapchain = new SwapchainImpl (); 408SLANG_RETURN_ON_FAIL (swapchain -> init (this ,desc ,window )); 409returnComPtr (outSwapchain ,swapchain ); 410return SLANG_OK ; 411} 412 413Result DeviceImpl ::createFramebufferLayout ( 414const IFramebufferLayout ::Desc & desc , 415IFramebufferLayout ** outLayout ) 416{ 417RefPtr < FramebufferLayoutImpl > layout = new FramebufferLayoutImpl (); 418layout -> m_renderTargets .setCount (desc .renderTargetCount ); 419for (GfxIndex i = 0 ;i < desc .renderTargetCount ;i ++ ) 420 { 421layout -> m_renderTargets [i ]= desc .renderTargets [i ]; 422 } 423 424if (desc .depthStencil ) 425 { 426layout -> m_hasDepthStencil = true; 427layout -> m_depthStencil = * desc .depthStencil ; 428 } 429else 430 { 431layout -> m_hasDepthStencil = false; 432 } 433returnComPtr (outLayout ,layout ); 434return SLANG_OK ; 435} 436 437Result DeviceImpl ::createFramebuffer (const IFramebuffer ::Desc & desc ,IFramebuffer ** outFramebuffer ) 438{ 439RefPtr < FramebufferImpl > framebuffer = new FramebufferImpl (); 440framebuffer -> renderTargetViews .setCount (desc .renderTargetCount ); 441framebuffer -> d3dRenderTargetViews .setCount (desc .renderTargetCount ); 442for (GfxIndex i = 0 ;i < desc .renderTargetCount ;i ++ ) 443 { 444framebuffer -> renderTargetViews [i ]= 445static_cast < RenderTargetViewImpl *> (desc .renderTargetViews [i ]); 446framebuffer -> d3dRenderTargetViews [i ]= framebuffer -> renderTargetViews [i ]-> m_rtv ; 447 } 448framebuffer -> depthStencilView = static_cast < DepthStencilViewImpl *> (desc .depthStencilView ); 449framebuffer -> d3dDepthStencilView = 450framebuffer -> depthStencilView ?framebuffer -> depthStencilView -> m_dsv :nullptr ; 451returnComPtr (outFramebuffer ,framebuffer ); 452return SLANG_OK ; 453} 454 455void DeviceImpl ::setFramebuffer (IFramebuffer * frameBuffer ) 456{ 457// Note: the framebuffer state will be flushed to the pipeline as part 458// of binding the root shader object. 459// 460// TODO: alternatively we could call `OMSetRenderTargets` here and then 461// call `OMSetRenderTargetsAndUnorderedAccessViews` later with the option 462// that preserves the existing RTV/DSV bindings. 463// 464m_currentFramebuffer = static_cast < FramebufferImpl *> (frameBuffer ); 465} 466 467void DeviceImpl ::setStencilReference (uint32_t referenceValue ) 468{ 469m_stencilRef = referenceValue ; 470m_depthStencilStateDirty = true; 471} 472 473SlangResult DeviceImpl ::readTextureResource ( 474ITextureResource * resource , 475ResourceState state , 476ISlangBlob ** outBlob , 477size_t * outRowPitch , 478size_t * outPixelSize ) 479{ 480SLANG_UNUSED (state ); 481 482auto texture = static_cast < TextureResourceImpl *> (resource ); 483// Don't bother supporting MSAA for right now 484if (texture -> getDesc ()-> sampleDesc .numSamples > 1 ) 485 { 486fprintf (stderr ,"ERROR: cannot capture multi-sample texture\n" ); 487return E_INVALIDARG ; 488 } 489 490FormatInfo sizeInfo ; 491gfxGetFormatInfo (texture -> getDesc ()-> format ,& sizeInfo ); 492size_t bytesPerPixel = sizeInfo .blockSizeInBytes /sizeInfo .pixelsPerBlock ; 493size_t rowPitch = int (texture -> getDesc ()-> size .width )* bytesPerPixel ; 494size_t bufferSize = rowPitch * int (texture -> getDesc ()-> size .height ); 495if (outRowPitch ) 496* outRowPitch = rowPitch ; 497if (outPixelSize ) 498* outPixelSize = bytesPerPixel ; 499 500D3D11_TEXTURE2D_DESC textureDesc ; 501auto d3d11Texture = ((ID3D11Texture2D * )texture -> m_resource .get ()); 502d3d11Texture -> GetDesc (& textureDesc ); 503 504HRESULT hr = S_OK ; 505ComPtr < ID3D11Texture2D > stagingTexture ; 506 507if (textureDesc .Usage == D3D11_USAGE_STAGING && 508 (textureDesc .CPUAccessFlags & D3D11_CPU_ACCESS_READ )) 509 { 510stagingTexture = d3d11Texture ; 511 } 512else 513 { 514// Modify the descriptor to give us a staging texture 515textureDesc .BindFlags = 0 ; 516textureDesc .MiscFlags &= ~D3D11_RESOURCE_MISC_TEXTURECUBE ; 517textureDesc .CPUAccessFlags = D3D11_CPU_ACCESS_READ ; 518textureDesc .Usage = D3D11_USAGE_STAGING ; 519 520hr = m_device -> CreateTexture2D (& textureDesc ,0 ,stagingTexture .writeRef ()); 521if (FAILED (hr )) 522 { 523fprintf (stderr ,"ERROR: failed to create staging texture\n" ); 524return hr ; 525 } 526 527m_immediateContext -> CopyResource (stagingTexture ,d3d11Texture ); 528 } 529 530// Now just read back texels from the staging textures 531 { 532D3D11_MAPPED_SUBRESOURCE mappedResource ; 533SLANG_RETURN_ON_FAIL ( 534m_immediateContext -> Map (stagingTexture ,0 ,D3D11_MAP_READ ,0 ,& mappedResource )); 535 536List < uint8_t > data ; 537 538data .setCount (bufferSize ); 539char * buffer = (char * )data .begin (); 540for (size_t y = 0 ;y < textureDesc .Height ;y ++ ) 541 { 542memcpy ( 543 (char * )buffer + y * (* outRowPitch ), 544 (char * )mappedResource .pData + y * mappedResource .RowPitch , 545* outRowPitch ); 546 } 547// Make sure to unmap 548m_immediateContext -> Unmap (stagingTexture ,0 ); 549 550ComPtr < ISlangBlob > blob = ListBlob ::moveCreate (data ); 551 552returnComPtr (outBlob ,blob ); 553return SLANG_OK ; 554 } 555} 556 557Result DeviceImpl ::createTextureResource ( 558const ITextureResource ::Desc & descIn , 559const ITextureResource ::SubresourceData * initData , 560ITextureResource ** outResource ) 561{ 562TextureResource ::Desc srcDesc = fixupTextureDesc (descIn ); 563 564const int effectiveArraySize = calcEffectiveArraySize (srcDesc ); 565 566const DXGI_FORMAT format = D3DUtil ::getMapFormat (srcDesc .format ); 567if (format == DXGI_FORMAT_UNKNOWN ) 568 { 569return SLANG_FAIL ; 570 } 571 572const int bindFlags = _calcResourceBindFlags (srcDesc .allowedStates ); 573 574// Set up the initialize data 575List < D3D11_SUBRESOURCE_DATA > subRes ; 576D3D11_SUBRESOURCE_DATA * subResourcesPtr = nullptr ; 577if (initData ) 578 { 579subRes .setCount (srcDesc .numMipLevels * effectiveArraySize ); 580 { 581int subResourceIndex = 0 ; 582for (int i = 0 ;i < effectiveArraySize ;i ++ ) 583 { 584for (int j = 0 ;j < srcDesc .numMipLevels ;j ++ ) 585 { 586const int mipHeight = calcMipSize (srcDesc .size .height ,j ); 587 588D3D11_SUBRESOURCE_DATA & data = subRes [subResourceIndex ]; 589auto & srcData = initData [subResourceIndex ]; 590 591data .pSysMem = srcData .data ; 592data .SysMemPitch = UINT (srcData .strideY ); 593data .SysMemSlicePitch = UINT (srcData .strideZ ); 594 595subResourceIndex ++ ; 596 } 597 } 598 } 599subResourcesPtr = subRes .getBuffer (); 600 } 601 602const int accessFlags = _calcResourceAccessFlags (srcDesc .memoryType ); 603 604RefPtr < TextureResourceImpl > texture (new TextureResourceImpl (srcDesc )); 605 606switch (srcDesc .type ) 607 { 608case IResource ::Type ::Texture1D : 609 { 610D3D11_TEXTURE1D_DESC desc = {0 }; 611desc .BindFlags = bindFlags ; 612desc .CPUAccessFlags = accessFlags ; 613desc .Format = format ; 614desc .MiscFlags = 0 ; 615desc .MipLevels = srcDesc .numMipLevels ; 616desc .ArraySize = effectiveArraySize ; 617desc .Width = srcDesc .size .width ; 618desc .Usage = D3D11_USAGE_DEFAULT ; 619 620ComPtr < ID3D11Texture1D > texture1D ; 621SLANG_RETURN_ON_FAIL ( 622m_device -> CreateTexture1D (& desc ,subResourcesPtr ,texture1D .writeRef ())); 623 624texture -> m_resource = texture1D ; 625break ; 626 } 627case IResource ::Type ::TextureCube : 628case IResource ::Type ::Texture2D : 629 { 630D3D11_TEXTURE2D_DESC desc = {0 }; 631desc .BindFlags = bindFlags ; 632desc .CPUAccessFlags = accessFlags ; 633desc .Format = format ; 634desc .MiscFlags = 0 ; 635desc .MipLevels = srcDesc .numMipLevels ; 636desc .ArraySize = effectiveArraySize ; 637 638desc .Width = srcDesc .size .width ; 639desc .Height = srcDesc .size .height ; 640desc .Usage = D3D11_USAGE_DEFAULT ; 641desc .SampleDesc .Count = srcDesc .sampleDesc .numSamples ; 642desc .SampleDesc .Quality = srcDesc .sampleDesc .quality ; 643 644if (srcDesc .type == IResource ::Type ::TextureCube ) 645 { 646desc .MiscFlags |=D3D11_RESOURCE_MISC_TEXTURECUBE ; 647 } 648 649ComPtr < ID3D11Texture2D > texture2D ; 650SLANG_RETURN_ON_FAIL ( 651m_device -> CreateTexture2D (& desc ,subResourcesPtr ,texture2D .writeRef ())); 652 653texture -> m_resource = texture2D ; 654break ; 655 } 656case IResource ::Type ::Texture3D : 657 { 658D3D11_TEXTURE3D_DESC desc = {0 }; 659desc .BindFlags = bindFlags ; 660desc .CPUAccessFlags = accessFlags ; 661desc .Format = format ; 662desc .MiscFlags = 0 ; 663desc .MipLevels = srcDesc .numMipLevels ; 664desc .Width = srcDesc .size .width ; 665desc .Height = srcDesc .size .height ; 666desc .Depth = srcDesc .size .depth ; 667desc .Usage = D3D11_USAGE_DEFAULT ; 668 669ComPtr < ID3D11Texture3D > texture3D ; 670SLANG_RETURN_ON_FAIL ( 671m_device -> CreateTexture3D (& desc ,subResourcesPtr ,texture3D .writeRef ())); 672 673texture -> m_resource = texture3D ; 674break ; 675 } 676default : 677return SLANG_FAIL ; 678 } 679 680returnComPtr (outResource ,texture ); 681return SLANG_OK ; 682} 683 684Result DeviceImpl ::createBufferResource ( 685const IBufferResource ::Desc & descIn , 686const void * initData , 687IBufferResource ** outResource ) 688{ 689IBufferResource ::Desc srcDesc = fixupBufferDesc (descIn ); 690 691auto d3dBindFlags = _calcResourceBindFlags (srcDesc .allowedStates ); 692 693size_t alignedSizeInBytes = srcDesc .sizeInBytes ; 694 695if (d3dBindFlags & D3D11_BIND_CONSTANT_BUFFER ) 696 { 697// Make aligned to 256 bytes... not sure why, but if you remove this the tests do fail. 698alignedSizeInBytes = D3DUtil ::calcAligned (alignedSizeInBytes ,256 ); 699 } 700 701// Hack to make the initialization never read from out of bounds memory, by copying into a 702// buffer 703List < uint8_t > initDataBuffer ; 704if (initData && alignedSizeInBytes > srcDesc .sizeInBytes ) 705 { 706initDataBuffer .setCount (alignedSizeInBytes ); 707 ::memcpy (initDataBuffer .getBuffer (),initData ,srcDesc .sizeInBytes ); 708initData = initDataBuffer .getBuffer (); 709 } 710 711D3D11_BUFFER_DESC bufferDesc = {0 }; 712bufferDesc .ByteWidth = UINT (alignedSizeInBytes ); 713bufferDesc .BindFlags = d3dBindFlags ; 714// For read we'll need to do some staging 715bufferDesc .CPUAccessFlags = _calcResourceAccessFlags (descIn .memoryType ); 716bufferDesc .Usage = D3D11_USAGE_DEFAULT ; 717 718// If written by CPU, make it dynamic 719if (descIn .memoryType == MemoryType ::Upload && 720 !descIn .allowedStates .contains (ResourceState ::UnorderedAccess )) 721 { 722bufferDesc .Usage = D3D11_USAGE_DYNAMIC ; 723 } 724 725if (srcDesc .memoryType == MemoryType ::ReadBack ) 726 { 727bufferDesc .CPUAccessFlags |=D3D11_CPU_ACCESS_READ ; 728bufferDesc .Usage = D3D11_USAGE_STAGING ; 729 } 730 731switch (descIn .defaultState ) 732 { 733case ResourceState ::ConstantBuffer : 734 { 735// We'll just assume ConstantBuffers are dynamic for now 736bufferDesc .Usage = D3D11_USAGE_DYNAMIC ; 737break ; 738 } 739default : 740break ; 741 } 742 743if (bufferDesc .BindFlags & (D3D11_BIND_UNORDERED_ACCESS |D3D11_BIND_SHADER_RESOURCE )) 744 { 745// desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; 746if (srcDesc .elementSize != 0 ) 747 { 748bufferDesc .StructureByteStride = (UINT )srcDesc .elementSize ; 749bufferDesc .MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED ; 750 } 751else 752 { 753bufferDesc .MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS ; 754 } 755 } 756 757if (srcDesc .memoryType == MemoryType ::Upload ) 758 { 759bufferDesc .CPUAccessFlags |=D3D11_CPU_ACCESS_WRITE ; 760 } 761 762D3D11_SUBRESOURCE_DATA subResourceData = {0 }; 763subResourceData .pSysMem = initData ; 764 765RefPtr < BufferResourceImpl > buffer (new BufferResourceImpl (srcDesc )); 766 767SLANG_RETURN_ON_FAIL (m_device -> CreateBuffer ( 768& bufferDesc , 769initData ?& subResourceData :nullptr , 770buffer -> m_buffer .writeRef ())); 771buffer -> m_d3dUsage = bufferDesc .Usage ; 772 773if (srcDesc .memoryType == MemoryType ::ReadBack || bufferDesc .Usage != D3D11_USAGE_DYNAMIC ) 774 { 775D3D11_BUFFER_DESC bufDesc = {}; 776bufDesc .BindFlags = 0 ; 777bufDesc .ByteWidth = (UINT )alignedSizeInBytes ; 778bufDesc .CPUAccessFlags = D3D11_CPU_ACCESS_READ ; 779bufDesc .Usage = D3D11_USAGE_STAGING ; 780 781SLANG_RETURN_ON_FAIL ( 782m_device -> CreateBuffer (& bufDesc ,nullptr ,buffer -> m_staging .writeRef ())); 783 } 784returnComPtr (outResource ,buffer ); 785return SLANG_OK ; 786} 787 788Result DeviceImpl ::createSamplerState (ISamplerState ::Desc const & desc ,ISamplerState ** outSampler ) 789{ 790D3D11_FILTER_REDUCTION_TYPE dxReduction = translateFilterReduction (desc .reductionOp ); 791D3D11_FILTER dxFilter ; 792if (desc .maxAnisotropy > 1 ) 793 { 794dxFilter = D3D11_ENCODE_ANISOTROPIC_FILTER (dxReduction ); 795 } 796else 797 { 798D3D11_FILTER_TYPE dxMin = translateFilterMode (desc .minFilter ); 799D3D11_FILTER_TYPE dxMag = translateFilterMode (desc .magFilter ); 800D3D11_FILTER_TYPE dxMip = translateFilterMode (desc .mipFilter ); 801 802dxFilter = D3D11_ENCODE_BASIC_FILTER (dxMin ,dxMag ,dxMip ,dxReduction ); 803 } 804 805D3D11_SAMPLER_DESC dxDesc = {}; 806dxDesc .Filter = dxFilter ; 807dxDesc .AddressU = translateAddressingMode (desc .addressU ); 808dxDesc .AddressV = translateAddressingMode (desc .addressV ); 809dxDesc .AddressW = translateAddressingMode (desc .addressW ); 810dxDesc .MipLODBias = desc .mipLODBias ; 811dxDesc .MaxAnisotropy = desc .maxAnisotropy ; 812dxDesc .ComparisonFunc = translateComparisonFunc (desc .comparisonFunc ); 813for (int ii = 0 ;ii < 4 ;++ ii ) 814dxDesc .BorderColor [ii ]= desc .borderColor [ii ]; 815dxDesc .MinLOD = desc .minLOD ; 816dxDesc .MaxLOD = desc .maxLOD ; 817 818ComPtr < ID3D11SamplerState > sampler ; 819SLANG_RETURN_ON_FAIL (m_device -> CreateSamplerState (& dxDesc ,sampler .writeRef ())); 820 821RefPtr < SamplerStateImpl > samplerImpl = new SamplerStateImpl (); 822samplerImpl -> m_sampler = sampler ; 823returnComPtr (outSampler ,samplerImpl ); 824return SLANG_OK ; 825} 826 827Result DeviceImpl ::createTextureView ( 828ITextureResource * texture , 829IResourceView ::Desc const & desc , 830IResourceView ** outView ) 831{ 832auto resourceImpl = (TextureResourceImpl * )texture ; 833 834switch (desc .type ) 835 { 836default : 837return SLANG_FAIL ; 838 839case IResourceView ::Type ::RenderTarget : 840 { 841ComPtr < ID3D11RenderTargetView > rtv ; 842SLANG_RETURN_ON_FAIL (m_device -> CreateRenderTargetView ( 843resourceImpl -> m_resource , 844nullptr , 845rtv .writeRef ())); 846 847RefPtr < RenderTargetViewImpl > viewImpl = new RenderTargetViewImpl (); 848viewImpl -> m_type = ResourceViewImpl ::Type ::RTV ; 849viewImpl -> m_rtv = rtv ; 850viewImpl -> m_desc = desc ; 851if (resourceImpl -> getDesc ()-> optimalClearValue ) 852 { 853memcpy ( 854viewImpl -> m_clearValue , 855& resourceImpl -> getDesc ()-> optimalClearValue -> color , 856sizeof (float )* 4 ); 857 } 858returnComPtr (outView ,viewImpl ); 859return SLANG_OK ; 860 } 861break ; 862 863case IResourceView ::Type ::DepthStencil : 864 { 865ComPtr < ID3D11DepthStencilView > dsv ; 866SLANG_RETURN_ON_FAIL (m_device -> CreateDepthStencilView ( 867resourceImpl -> m_resource , 868nullptr , 869dsv .writeRef ())); 870 871RefPtr < DepthStencilViewImpl > viewImpl = new DepthStencilViewImpl (); 872viewImpl -> m_type = ResourceViewImpl ::Type ::DSV ; 873viewImpl -> m_dsv = dsv ; 874if (resourceImpl -> getDesc ()-> optimalClearValue ) 875viewImpl -> m_clearValue = resourceImpl -> getDesc ()-> optimalClearValue -> depthStencil ; 876viewImpl -> m_desc = desc ; 877 878returnComPtr (outView ,viewImpl ); 879return SLANG_OK ; 880 } 881break ; 882 883case IResourceView ::Type ::UnorderedAccess : 884 { 885ComPtr < ID3D11UnorderedAccessView > uav ; 886SLANG_RETURN_ON_FAIL (m_device -> CreateUnorderedAccessView ( 887resourceImpl -> m_resource , 888nullptr , 889uav .writeRef ())); 890 891RefPtr < UnorderedAccessViewImpl > viewImpl = new UnorderedAccessViewImpl (); 892viewImpl -> m_type = ResourceViewImpl ::Type ::UAV ; 893viewImpl -> m_uav = uav ; 894viewImpl -> m_desc = desc ; 895 896returnComPtr (outView ,viewImpl ); 897return SLANG_OK ; 898 } 899break ; 900 901case IResourceView ::Type ::ShaderResource : 902 { 903D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc ; 904initSrvDesc ( 905resourceImpl -> getType (), 906* resourceImpl -> getDesc (), 907D3DUtil ::getMapFormat (desc .format ), 908srvDesc ); 909 910ComPtr < ID3D11ShaderResourceView > srv ; 911SLANG_RETURN_ON_FAIL (m_device -> CreateShaderResourceView ( 912resourceImpl -> m_resource , 913& srvDesc , 914srv .writeRef ())); 915 916RefPtr < ShaderResourceViewImpl > viewImpl = new ShaderResourceViewImpl (); 917viewImpl -> m_type = ResourceViewImpl ::Type ::SRV ; 918viewImpl -> m_srv = srv ; 919viewImpl -> m_desc = desc ; 920 921returnComPtr (outView ,viewImpl ); 922return SLANG_OK ; 923 } 924break ; 925 } 926} 927 928Result DeviceImpl ::createBufferView ( 929IBufferResource * buffer , 930IBufferResource * counterBuffer , 931IResourceView ::Desc const & desc , 932IResourceView ** outView ) 933{ 934auto resourceImpl = (BufferResourceImpl * )buffer ; 935auto resourceDesc = * resourceImpl -> getDesc (); 936 937switch (desc .type ) 938 { 939default : 940return SLANG_FAIL ; 941 942case IResourceView ::Type ::UnorderedAccess : 943 { 944D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; 945uavDesc .ViewDimension = D3D11_UAV_DIMENSION_BUFFER ; 946uavDesc .Format = D3DUtil ::getMapFormat (desc .format ); 947uavDesc .Buffer .FirstElement = 0 ; 948 949if (resourceDesc .elementSize ) 950 { 951uavDesc .Buffer .NumElements = 952UINT (resourceDesc .sizeInBytes /resourceDesc .elementSize ); 953 } 954else if (desc .format == Format ::Unknown ) 955 { 956uavDesc .Buffer .Flags |=D3D11_BUFFER_UAV_FLAG_RAW ; 957uavDesc .Format = DXGI_FORMAT_R32_TYPELESS ; 958uavDesc .Buffer .NumElements = UINT (resourceDesc .sizeInBytes /4 ); 959 } 960else 961 { 962FormatInfo sizeInfo ; 963gfxGetFormatInfo (desc .format ,& sizeInfo ); 964uavDesc .Buffer .NumElements = UINT ( 965resourceDesc .sizeInBytes / 966 (sizeInfo .blockSizeInBytes /sizeInfo .pixelsPerBlock )); 967 } 968 969ComPtr < ID3D11UnorderedAccessView > uav ; 970SLANG_RETURN_ON_FAIL (m_device -> CreateUnorderedAccessView ( 971resourceImpl -> m_buffer , 972& uavDesc , 973uav .writeRef ())); 974 975RefPtr < UnorderedAccessViewImpl > viewImpl = new UnorderedAccessViewImpl (); 976viewImpl -> m_type = ResourceViewImpl ::Type ::UAV ; 977viewImpl -> m_uav = uav ; 978viewImpl -> m_desc = desc ; 979 980returnComPtr (outView ,viewImpl ); 981return SLANG_OK ; 982 } 983break ; 984 985case IResourceView ::Type ::ShaderResource : 986 { 987D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; 988srvDesc .ViewDimension = D3D11_SRV_DIMENSION_BUFFER ; 989srvDesc .Format = D3DUtil ::getMapFormat (desc .format ); 990srvDesc .Buffer .FirstElement = 0 ; 991 992if (resourceDesc .elementSize ) 993 { 994srvDesc .Buffer .NumElements = 995UINT (resourceDesc .sizeInBytes /resourceDesc .elementSize ); 996 } 997else if (desc .format == Format ::Unknown ) 998 { 999// We need to switch to a different member of the `union`, 1000// so that we can set the `BufferEx.Flags` member. 1001// 1002srvDesc .ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX ; 1003 1004// Because we've switched, we need to re-set the `FirstElement` 1005// field to be valid, since we can't count on all compilers 1006// to respect that `Buffer.FirstElement` and `BufferEx.FirstElement` 1007// alias in memory. 1008// 1009srvDesc .BufferEx .FirstElement = 0 ; 1010 1011srvDesc .BufferEx .Flags = D3D11_BUFFEREX_SRV_FLAG_RAW ; 1012srvDesc .Format = DXGI_FORMAT_R32_TYPELESS ; 1013srvDesc .BufferEx .NumElements = UINT (resourceDesc .sizeInBytes /4 ); 1014 } 1015else 1016 { 1017FormatInfo sizeInfo ; 1018gfxGetFormatInfo (desc .format ,& sizeInfo ); 1019srvDesc .Buffer .NumElements = UINT ( 1020resourceDesc .sizeInBytes / 1021 (sizeInfo .blockSizeInBytes /sizeInfo .pixelsPerBlock )); 1022 } 1023 1024ComPtr < ID3D11ShaderResourceView > srv ; 1025SLANG_RETURN_ON_FAIL (m_device -> CreateShaderResourceView ( 1026resourceImpl -> m_buffer , 1027& srvDesc , 1028srv .writeRef ())); 1029 1030RefPtr < ShaderResourceViewImpl > viewImpl = new ShaderResourceViewImpl (); 1031viewImpl -> m_type = ResourceViewImpl ::Type ::SRV ; 1032viewImpl -> m_srv = srv ; 1033viewImpl -> m_desc = desc ; 1034returnComPtr (outView ,viewImpl ); 1035return SLANG_OK ; 1036 } 1037break ; 1038 } 1039} 1040 1041Result DeviceImpl ::createInputLayout (IInputLayout ::Desc const & desc ,IInputLayout ** outLayout ) 1042{ 1043D3D11_INPUT_ELEMENT_DESC inputElements [16 ]= {}; 1044 1045char hlslBuffer [1024 ]; 1046char * hlslCursor = & hlslBuffer [0 ]; 1047 1048hlslCursor += sprintf (hlslCursor ,"float4 main(\n" ); 1049 1050auto inputElementCount = desc .inputElementCount ; 1051auto inputElementsIn = desc .inputElements ; 1052for (Int ii = 0 ;ii < inputElementCount ;++ ii ) 1053 { 1054auto vertexStreamIndex = inputElementsIn [ii ].bufferSlotIndex ; 1055auto & vertexStream = desc .vertexStreams [vertexStreamIndex ]; 1056 1057inputElements [ii ].SemanticName = inputElementsIn [ii ].semanticName ; 1058inputElements [ii ].SemanticIndex = (UINT )inputElementsIn [ii ].semanticIndex ; 1059inputElements [ii ].Format = D3DUtil ::getMapFormat (inputElementsIn [ii ].format ); 1060inputElements [ii ].InputSlot = (UINT )vertexStreamIndex ; 1061inputElements [ii ].AlignedByteOffset = (UINT )inputElementsIn [ii ].offset ; 1062inputElements [ii ].InputSlotClass = (vertexStream .slotClass == InputSlotClass ::PerInstance ) 1063 ?D3D11_INPUT_PER_INSTANCE_DATA 1064 :D3D11_INPUT_PER_VERTEX_DATA ; 1065inputElements [ii ].InstanceDataStepRate = (UINT )vertexStream .instanceDataStepRate ; 1066 1067if (ii != 0 ) 1068 { 1069hlslCursor += sprintf (hlslCursor ,",\n" ); 1070 } 1071 1072char const * typeName = "Unknown" ; 1073switch (inputElementsIn [ii ].format ) 1074 { 1075case Format ::R32G32B32A32_FLOAT : 1076case Format ::R8G8B8A8_UNORM : 1077typeName = "float4" ; 1078break ; 1079case Format ::R32G32B32_FLOAT : 1080typeName = "float3" ; 1081break ; 1082case Format ::R32G32_FLOAT : 1083typeName = "float2" ; 1084break ; 1085case Format ::R32_FLOAT : 1086typeName = "float" ; 1087break ; 1088default : 1089return SLANG_FAIL ; 1090 } 1091 1092hlslCursor += sprintf ( 1093hlslCursor , 1094"%s a%d : %s%d" , 1095typeName , 1096 (int )ii , 1097inputElementsIn [ii ].semanticName , 1098 (int )inputElementsIn [ii ].semanticIndex ); 1099 } 1100 1101hlslCursor += sprintf (hlslCursor ,"\n) : SV_Position { return 0; }" ); 1102 1103ComPtr < ID3DBlob > vertexShaderBlob ; 1104SLANG_RETURN_ON_FAIL ( 1105D3DUtil ::compileHLSLShader ("inputLayout" ,hlslBuffer ,"main" ,"vs_5_0" ,vertexShaderBlob )); 1106 1107ComPtr < ID3D11InputLayout > inputLayout ; 1108SLANG_RETURN_ON_FAIL (m_device -> CreateInputLayout ( 1109& inputElements [0 ], 1110 (UINT )inputElementCount , 1111vertexShaderBlob -> GetBufferPointer (), 1112vertexShaderBlob -> GetBufferSize (), 1113inputLayout .writeRef ())); 1114 1115RefPtr < InputLayoutImpl > impl = new InputLayoutImpl ; 1116impl -> m_layout .swap (inputLayout ); 1117 1118auto vertexStreamCount = desc .vertexStreamCount ; 1119impl -> m_vertexStreamStrides .setCount (vertexStreamCount ); 1120for (Int i = 0 ;i < vertexStreamCount ;++ i ) 1121 { 1122impl -> m_vertexStreamStrides [i ]= (UINT )desc .vertexStreams [i ].stride ; 1123 } 1124 1125returnComPtr (outLayout ,impl ); 1126return SLANG_OK ; 1127} 1128 1129Result DeviceImpl ::createQueryPool (const IQueryPool ::Desc & desc ,IQueryPool ** outPool ) 1130{ 1131RefPtr < QueryPoolImpl > result = new QueryPoolImpl (); 1132SLANG_RETURN_ON_FAIL (result -> init (desc ,this )); 1133returnComPtr (outPool ,result ); 1134return SLANG_OK ; 1135} 1136 1137void * DeviceImpl ::map (IBufferResource * bufferIn ,MapFlavor flavor ) 1138{ 1139BufferResourceImpl * bufferResource = static_cast < BufferResourceImpl *> (bufferIn ); 1140 1141D3D11_MAP mapType ; 1142ID3D11Buffer * buffer = bufferResource -> m_buffer ; 1143 1144switch (flavor ) 1145 { 1146case MapFlavor ::WriteDiscard : 1147mapType = D3D11_MAP_WRITE_DISCARD ; 1148break ; 1149case MapFlavor ::HostWrite : 1150mapType = D3D11_MAP_WRITE_NO_OVERWRITE ; 1151break ; 1152case MapFlavor ::HostRead : 1153mapType = D3D11_MAP_READ ; 1154break ; 1155default : 1156return nullptr ; 1157 } 1158 1159bufferResource -> m_mapFlavor = flavor ; 1160 1161switch (flavor ) 1162 { 1163case MapFlavor ::WriteDiscard : 1164case MapFlavor ::HostWrite : 1165// If buffer is not dynamic, we need to use staging buffer. 1166if (bufferResource -> m_d3dUsage != D3D11_USAGE_DYNAMIC ) 1167 { 1168bufferResource -> m_uploadStagingBuffer .setCount (bufferResource -> getDesc ()-> sizeInBytes ); 1169return bufferResource -> m_uploadStagingBuffer .getBuffer (); 1170 } 1171break ; 1172case MapFlavor ::HostRead : 1173buffer = bufferResource -> m_staging ; 1174if (!buffer ) 1175 { 1176return nullptr ; 1177 } 1178 1179// Okay copy the data over 1180m_immediateContext -> CopyResource (buffer ,bufferResource -> m_buffer ); 1181 } 1182 1183// We update our constant buffer per-frame, just for the purposes 1184// of the example, but we don't actually load different data 1185// per-frame (we always use an identity projection). 1186D3D11_MAPPED_SUBRESOURCE mappedSub ; 1187SLANG_RETURN_NULL_ON_FAIL (m_immediateContext -> Map (buffer ,0 ,mapType ,0 ,& mappedSub )); 1188 1189return mappedSub .pData ; 1190} 1191 1192void DeviceImpl ::unmap (IBufferResource * bufferIn ,size_t offsetWritten ,size_t sizeWritten ) 1193{ 1194BufferResourceImpl * bufferResource = static_cast < BufferResourceImpl *> (bufferIn ); 1195switch (bufferResource -> m_mapFlavor ) 1196 { 1197case MapFlavor ::WriteDiscard : 1198case MapFlavor ::HostWrite : 1199// If buffer is not dynamic, the CPU has already written to the staging buffer, 1200// and we need to copy the content over to the GPU buffer. 1201if (bufferResource -> m_d3dUsage != D3D11_USAGE_DYNAMIC && sizeWritten != 0 ) 1202 { 1203D3D11_BOX dstBox = {}; 1204dstBox .left = (UINT )offsetWritten ; 1205dstBox .right = (UINT )(offsetWritten + sizeWritten ); 1206dstBox .back = 1 ; 1207dstBox .bottom = 1 ; 1208m_immediateContext -> UpdateSubresource ( 1209bufferResource -> m_buffer , 12100 , 1211& dstBox , 1212bufferResource -> m_uploadStagingBuffer .getBuffer ()+ offsetWritten , 12130 , 12140 ); 1215return ; 1216 } 1217 } 1218m_immediateContext -> Unmap ( 1219bufferResource -> m_mapFlavor == MapFlavor ::HostRead ?bufferResource -> m_staging 1220 :bufferResource -> m_buffer , 12210 ); 1222} 1223 1224#if 0 1225void D3D11Device ::setInputLayout (InputLayout * inputLayoutIn ) 1226{ 1227auto inputLayout = static_cast < InputLayoutImpl *> (inputLayoutIn ); 1228m_immediateContext -> IASetInputLayout (inputLayout -> m_layout ); 1229} 1230#endif 1231 1232void DeviceImpl ::setPrimitiveTopology (PrimitiveTopology topology ) 1233{ 1234m_immediateContext -> IASetPrimitiveTopology (D3DUtil ::getPrimitiveTopology (topology )); 1235} 1236 1237void DeviceImpl ::setVertexBuffers ( 1238GfxIndex startSlot , 1239GfxCount slotCount , 1240IBufferResource * const * buffersIn , 1241const Offset * offsetsIn ) 1242{ 1243static const int kMaxVertexBuffers = 16 ; 1244assert (slotCount <=kMaxVertexBuffers ); 1245assert (m_currentPipelineState );// The pipeline state should be created before setting vertex 1246// buffers. 1247 1248UINT vertexStrides [kMaxVertexBuffers ]; 1249UINT vertexOffsets [kMaxVertexBuffers ]; 1250ID3D11Buffer * dxBuffers [kMaxVertexBuffers ]; 1251 1252auto buffers = (BufferResourceImpl * const * )buffersIn ; 1253 1254for (GfxIndex ii = 0 ;ii < slotCount ;++ ii ) 1255 { 1256auto inputLayout = (InputLayoutImpl * )m_currentPipelineState -> inputLayout .Ptr (); 1257vertexStrides [ii ]= inputLayout -> m_vertexStreamStrides [startSlot + ii ]; 1258vertexOffsets [ii ]= (UINT )offsetsIn [ii ]; 1259dxBuffers [ii ]= buffers [ii ]-> m_buffer ; 1260 } 1261 1262m_immediateContext -> IASetVertexBuffers ( 1263 (UINT )startSlot , 1264 (UINT )slotCount , 1265dxBuffers , 1266& vertexStrides [0 ], 1267& vertexOffsets [0 ]); 1268} 1269 1270void DeviceImpl ::setIndexBuffer (IBufferResource * buffer ,Format indexFormat ,Offset offset ) 1271{ 1272DXGI_FORMAT dxFormat = D3DUtil ::getMapFormat (indexFormat ); 1273m_immediateContext -> IASetIndexBuffer ( 1274 ((BufferResourceImpl * )buffer )-> m_buffer , 1275dxFormat , 1276UINT (offset )); 1277} 1278 1279void DeviceImpl ::setViewports (GfxCount count ,Viewport const * viewports ) 1280{ 1281static const int kMaxViewports = D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX + 1 ; 1282assert (count <=kMaxViewports ); 1283 1284D3D11_VIEWPORT dxViewports [kMaxViewports ]; 1285for (GfxIndex ii = 0 ;ii < count ;++ ii ) 1286 { 1287auto & inViewport = viewports [ii ]; 1288auto & dxViewport = dxViewports [ii ]; 1289 1290dxViewport .TopLeftX = inViewport .originX ; 1291dxViewport .TopLeftY = inViewport .originY ; 1292dxViewport .Width = inViewport .extentX ; 1293dxViewport .Height = inViewport .extentY ; 1294dxViewport .MinDepth = inViewport .minZ ; 1295dxViewport .MaxDepth = inViewport .maxZ ; 1296 } 1297 1298m_immediateContext -> RSSetViewports (UINT (count ),dxViewports ); 1299} 1300 1301void DeviceImpl ::setScissorRects (GfxCount count ,ScissorRect const * rects ) 1302{ 1303static const int kMaxScissorRects = D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX + 1 ; 1304assert (count <=kMaxScissorRects ); 1305 1306D3D11_RECT dxRects [kMaxScissorRects ]; 1307for (GfxIndex ii = 0 ;ii < count ;++ ii ) 1308 { 1309auto & inRect = rects [ii ]; 1310auto & dxRect = dxRects [ii ]; 1311 1312dxRect .left = LONG (inRect .minX ); 1313dxRect .top = LONG (inRect .minY ); 1314dxRect .right = LONG (inRect .maxX ); 1315dxRect .bottom = LONG (inRect .maxY ); 1316 } 1317 1318m_immediateContext -> RSSetScissorRects (UINT (count ),dxRects ); 1319} 1320 1321 1322void DeviceImpl ::setPipelineState (IPipelineState * state ) 1323{ 1324auto pipelineType = static_cast < PipelineStateBase *> (state )-> desc .type ; 1325 1326switch (pipelineType ) 1327 { 1328default : 1329break ; 1330 1331case PipelineType ::Graphics : 1332 { 1333auto stateImpl = (GraphicsPipelineStateImpl * )state ; 1334auto programImpl = static_cast < ShaderProgramImpl *> (stateImpl -> m_program .Ptr ()); 1335 1336// TODO: We could conceivably do some lightweight state 1337// differencing here (e.g., check if `programImpl` is the 1338// same as the program that is currently bound). 1339// 1340// It isn't clear how much that would pay off given that 1341// the D3D11 runtime seems to do its own state diffing. 1342 1343// IA 1344 1345m_immediateContext -> IASetInputLayout (stateImpl -> m_inputLayout -> m_layout ); 1346 1347// VS 1348 1349// TODO(tfoley): Why the conditional here? If somebody is trying to disable the VS or 1350// PS, shouldn't we respect that? 1351if (programImpl -> m_vertexShader ) 1352m_immediateContext -> VSSetShader (programImpl -> m_vertexShader ,nullptr ,0 ); 1353 1354// HS 1355 1356// DS 1357 1358// GS 1359 1360// RS 1361 1362m_immediateContext -> RSSetState (stateImpl -> m_rasterizerState ); 1363 1364// PS 1365if (programImpl -> m_pixelShader ) 1366m_immediateContext -> PSSetShader (programImpl -> m_pixelShader ,nullptr ,0 ); 1367 1368// OM 1369 1370m_immediateContext -> OMSetBlendState ( 1371stateImpl -> m_blendState , 1372stateImpl -> m_blendColor , 1373stateImpl -> m_sampleMask ); 1374 1375m_currentPipelineState = stateImpl ; 1376 1377m_depthStencilStateDirty = true; 1378 } 1379break ; 1380 1381case PipelineType ::Compute : 1382 { 1383auto stateImpl = (ComputePipelineStateImpl * )state ; 1384auto programImpl = static_cast < ShaderProgramImpl *> (stateImpl -> m_program .Ptr ()); 1385 1386// CS 1387 1388m_immediateContext -> CSSetShader (programImpl -> m_computeShader ,nullptr ,0 ); 1389m_currentPipelineState = stateImpl ; 1390 } 1391break ; 1392 } 1393 1394/// ... 1395} 1396 1397void DeviceImpl ::draw (GfxCount vertexCount ,GfxIndex startVertex ) 1398{ 1399_flushGraphicsState (); 1400m_immediateContext -> Draw (vertexCount ,startVertex ); 1401} 1402 1403void DeviceImpl ::drawIndexed (GfxCount indexCount ,GfxIndex startIndex ,GfxIndex baseVertex ) 1404{ 1405_flushGraphicsState (); 1406m_immediateContext -> DrawIndexed (indexCount ,startIndex ,baseVertex ); 1407} 1408 1409void DeviceImpl ::drawInstanced ( 1410GfxCount vertexCount , 1411GfxCount instanceCount , 1412GfxIndex startVertex , 1413GfxIndex startInstanceLocation ) 1414{ 1415_flushGraphicsState (); 1416m_immediateContext 1417-> DrawInstanced (vertexCount ,instanceCount ,startVertex ,startInstanceLocation ); 1418} 1419 1420void DeviceImpl ::drawIndexedInstanced ( 1421GfxCount indexCount , 1422GfxCount instanceCount , 1423GfxIndex startIndexLocation , 1424GfxIndex baseVertexLocation , 1425GfxIndex startInstanceLocation ) 1426{ 1427_flushGraphicsState (); 1428m_immediateContext -> DrawIndexedInstanced ( 1429indexCount , 1430instanceCount , 1431startIndexLocation , 1432baseVertexLocation , 1433startInstanceLocation ); 1434} 1435 1436Result DeviceImpl ::createProgram ( 1437const IShaderProgram ::Desc & desc , 1438IShaderProgram ** outProgram , 1439ISlangBlob ** outDiagnosticBlob ) 1440{ 1441SLANG_ASSERT (desc .slangGlobalScope ); 1442 1443if (desc .slangGlobalScope -> getSpecializationParamCount ()!= 0 ) 1444 { 1445// For a specializable program, we don't invoke any actual slang compilation yet. 1446RefPtr < ShaderProgramImpl > shaderProgram = new ShaderProgramImpl (); 1447shaderProgram -> init (desc ); 1448returnComPtr (outProgram ,shaderProgram ); 1449return SLANG_OK ; 1450 } 1451 1452// If the program is already specialized, compile and create shader kernels now. 1453SlangInt targetIndex = 0 ; 1454auto slangGlobalScope = desc .slangGlobalScope ; 1455auto programLayout = slangGlobalScope -> getLayout (targetIndex ); 1456if (!programLayout ) 1457return SLANG_FAIL ; 1458SlangUInt entryPointCount = programLayout -> getEntryPointCount (); 1459if (entryPointCount == 0 ) 1460return SLANG_FAIL ; 1461 1462RefPtr < ShaderProgramImpl > shaderProgram = new ShaderProgramImpl (); 1463shaderProgram -> slangGlobalScope = desc .slangGlobalScope ; 1464 1465ScopeNVAPI scopeNVAPI ; 1466SLANG_RETURN_ON_FAIL (scopeNVAPI .init (this ,0 )); 1467for (SlangUInt i = 0 ;i < entryPointCount ;i ++ ) 1468 { 1469ComPtr < ISlangBlob > kernelCode ; 1470ComPtr < ISlangBlob > diagnostics ; 1471 1472auto compileResult = getEntryPointCodeFromShaderCache ( 1473slangGlobalScope , 1474 (SlangInt )i , 14750 , 1476kernelCode .writeRef (), 1477diagnostics .writeRef ()); 1478 1479if (diagnostics ) 1480 { 1481DebugMessageType msgType = DebugMessageType ::Warning ; 1482if (compileResult != SLANG_OK ) 1483msgType = DebugMessageType ::Error ; 1484getDebugCallback ()-> handleMessage ( 1485msgType , 1486DebugMessageSource ::Slang , 1487 (char * )diagnostics -> getBufferPointer ()); 1488if (outDiagnosticBlob ) 1489returnComPtr (outDiagnosticBlob ,diagnostics ); 1490 } 1491 1492SLANG_RETURN_ON_FAIL (compileResult ); 1493 1494auto entryPoint = programLayout -> getEntryPointByIndex (i ); 1495switch (entryPoint -> getStage ()) 1496 { 1497case SLANG_STAGE_COMPUTE : 1498SLANG_ASSERT (entryPointCount == 1 ); 1499SLANG_RETURN_ON_FAIL (m_device -> CreateComputeShader ( 1500kernelCode -> getBufferPointer (), 1501kernelCode -> getBufferSize (), 1502nullptr , 1503shaderProgram -> m_computeShader .writeRef ())); 1504break ; 1505case SLANG_STAGE_VERTEX : 1506SLANG_RETURN_ON_FAIL (m_device -> CreateVertexShader ( 1507kernelCode -> getBufferPointer (), 1508kernelCode -> getBufferSize (), 1509nullptr , 1510shaderProgram -> m_vertexShader .writeRef ())); 1511break ; 1512case SLANG_STAGE_FRAGMENT : 1513SLANG_RETURN_ON_FAIL (m_device -> CreatePixelShader ( 1514kernelCode -> getBufferPointer (), 1515kernelCode -> getBufferSize (), 1516nullptr , 1517shaderProgram -> m_pixelShader .writeRef ())); 1518break ; 1519default : 1520SLANG_ASSERT (!"pipeline stage not implemented" ); 1521 } 1522 } 1523returnComPtr (outProgram ,shaderProgram ); 1524return SLANG_OK ; 1525} 1526 1527Result DeviceImpl ::createShaderObjectLayout ( 1528 slang::ISession * session , 1529 slang::TypeLayoutReflection * typeLayout , 1530ShaderObjectLayoutBase ** outLayout ) 1531{ 1532RefPtr < ShaderObjectLayoutImpl > layout ; 1533SLANG_RETURN_ON_FAIL ( 1534ShaderObjectLayoutImpl ::createForElementType (this ,session ,typeLayout ,layout .writeRef ())); 1535returnRefPtrMove (outLayout ,layout ); 1536return SLANG_OK ; 1537} 1538 1539Result DeviceImpl ::createShaderObject (ShaderObjectLayoutBase * layout ,IShaderObject ** outObject ) 1540{ 1541RefPtr < ShaderObjectImpl > shaderObject ; 1542SLANG_RETURN_ON_FAIL (ShaderObjectImpl ::create ( 1543this , 1544static_cast < ShaderObjectLayoutImpl *> (layout ), 1545shaderObject .writeRef ())); 1546returnComPtr (outObject ,shaderObject ); 1547return SLANG_OK ; 1548} 1549 1550Result DeviceImpl ::createMutableShaderObject ( 1551ShaderObjectLayoutBase * layout , 1552IShaderObject ** outObject ) 1553{ 1554auto layoutImpl = static_cast < ShaderObjectLayoutImpl *> (layout ); 1555 1556RefPtr < MutableShaderObjectImpl > result = new MutableShaderObjectImpl (); 1557SLANG_RETURN_ON_FAIL (result -> init (this ,layoutImpl )); 1558returnComPtr (outObject ,result ); 1559 1560return SLANG_OK ; 1561} 1562 1563Result DeviceImpl ::createRootShaderObject (IShaderProgram * program ,ShaderObjectBase ** outObject ) 1564{ 1565auto programImpl = static_cast < ShaderProgramImpl *> (program ); 1566RefPtr < RootShaderObjectImpl > shaderObject ; 1567RefPtr < RootShaderObjectLayoutImpl > rootLayout ; 1568SLANG_RETURN_ON_FAIL (RootShaderObjectLayoutImpl ::create ( 1569this , 1570programImpl -> slangGlobalScope , 1571programImpl -> slangGlobalScope -> getLayout (), 1572rootLayout .writeRef ())); 1573SLANG_RETURN_ON_FAIL ( 1574RootShaderObjectImpl ::create (this ,rootLayout .Ptr (),shaderObject .writeRef ())); 1575returnRefPtrMove (outObject ,shaderObject ); 1576return SLANG_OK ; 1577} 1578 1579void DeviceImpl ::bindRootShaderObject (IShaderObject * shaderObject ) 1580{ 1581RootShaderObjectImpl * rootShaderObjectImpl = static_cast < RootShaderObjectImpl *> (shaderObject ); 1582RefPtr < PipelineStateBase > specializedPipeline ; 1583// TODO: Do something less crappy than just asserting on failure here 1584SLANG_ASSERT_VOID_ON_FAIL ( 1585maybeSpecializePipeline (m_currentPipelineState ,rootShaderObjectImpl ,specializedPipeline )); 1586maybeSpecializePipeline (m_currentPipelineState ,rootShaderObjectImpl ,specializedPipeline ); 1587PipelineStateImpl * specializedPipelineImpl = 1588static_cast < PipelineStateImpl *> (specializedPipeline .Ptr ()); 1589setPipelineState (specializedPipelineImpl ); 1590 1591// In order to bind the root object we must compute its specialized layout. 1592// 1593// TODO: This is in most ways redundant with `maybeSpecializePipeline` above, 1594// and the two operations should really be one. 1595// 1596RefPtr < ShaderObjectLayoutImpl > specializedRootLayout ; 1597rootShaderObjectImpl -> _getSpecializedLayout (specializedRootLayout .writeRef ()); 1598RootShaderObjectLayoutImpl * specializedRootLayoutImpl = 1599static_cast < RootShaderObjectLayoutImpl *> (specializedRootLayout .Ptr ()); 1600 1601// Depending on whether we are binding a compute or a graphics/rasterization 1602// pipeline, we will need to bind any SRVs/UAVs/CBs/samplers using different 1603// D3D11 calls. We deal with that distinction here by instantiating an 1604// appropriate subtype of `BindingContext` based on the pipeline type. 1605// 1606switch (m_currentPipelineState -> desc .type ) 1607 { 1608case PipelineType ::Compute : 1609 { 1610ComputeBindingContext context (this ,m_immediateContext ); 1611rootShaderObjectImpl -> bindAsRoot (& context ,specializedRootLayoutImpl ); 1612 1613// Because D3D11 requires all UAVs to be set at once, we did *not* issue 1614// actual binding calls during the `bindAsRoot` step, and instead we 1615// batch them up and set them here. 1616// 1617m_immediateContext 1618-> CSSetUnorderedAccessViews (0 ,context .uavCount ,context .uavs ,nullptr ); 1619 } 1620break ; 1621default : 1622 { 1623GraphicsBindingContext context (this ,m_immediateContext ); 1624rootShaderObjectImpl -> bindAsRoot (& context ,specializedRootLayoutImpl ); 1625 1626// Similar to the compute case above, the rasteirzation case needs to 1627// set the UAVs after the call to `bindAsRoot()` completes, but we 1628// also have a few extra wrinkles here that are specific to the D3D 11.0 1629// rasterization pipeline. 1630// 1631// In D3D 11.0, the RTV and UAV binding slots alias, so that a shader 1632// that binds an RTV for `SV_Target0` cannot also bind a UAV for `u0`. 1633// The Slang layout algorithm already accounts for this rule, and assigns 1634// all UAVs to slots taht won't alias the RTVs it knows about. 1635// 1636// In order to account for the aliasing, we need to consider how many 1637// RTVs are bound as part of the active framebuffer, and then adjust 1638// the UAVs that we bind accordingly. 1639// 1640auto rtvCount = (UINT )m_currentFramebuffer -> renderTargetViews .getCount (); 1641// 1642// The `context` we are using will have computed the number of UAV registers 1643// that might need to be bound, as a range from 0 to `context.uavCount`. 1644// However we need to skip over the first `rtvCount` of those, so the 1645// actual number of UAVs we wnat to bind is smaller: 1646// 1647// Note: As a result we expect that either there were no UAVs bound, 1648// *or* the number of UAV slots bound is higher than the number of 1649// RTVs so that there is something left to actually bind. 1650// 1651SLANG_ASSERT ((context .uavCount == 0 )|| (context .uavCount >=rtvCount )); 1652auto bindableUAVCount = context .uavCount - rtvCount ; 1653// 1654// Similarly, the actual UAVs we intend to bind will come after the first 1655// `rtvCount` in the array. 1656// 1657auto bindableUAVs = context .uavs + rtvCount ; 1658 1659// Once the offsetting is accounted for, we set all of the RTVs, DSV, 1660// and UAVs with one call. 1661// 1662// TODO: We may want to use the capability for `OMSetRenderTargetsAnd...` 1663// to only set the UAVs and leave the RTVs/UAVs alone, so that we don't 1664// needlessly re-bind RTVs during a pass. 1665// 1666m_immediateContext -> OMSetRenderTargetsAndUnorderedAccessViews ( 1667rtvCount , 1668m_currentFramebuffer -> d3dRenderTargetViews .getArrayView ().getBuffer (), 1669m_currentFramebuffer -> d3dDepthStencilView , 1670rtvCount , 1671bindableUAVCount , 1672bindableUAVs , 1673nullptr ); 1674 } 1675break ; 1676 } 1677} 1678 1679Result DeviceImpl ::createGraphicsPipelineState ( 1680const GraphicsPipelineStateDesc & inDesc , 1681IPipelineState ** outState ) 1682{ 1683GraphicsPipelineStateDesc desc = inDesc ; 1684 1685auto programImpl = (ShaderProgramImpl * )desc .program ; 1686 1687ComPtr < ID3D11DepthStencilState > depthStencilState ; 1688 { 1689D3D11_DEPTH_STENCIL_DESC dsDesc ; 1690dsDesc .DepthEnable = desc .depthStencil .depthTestEnable ; 1691dsDesc .DepthWriteMask = desc .depthStencil .depthWriteEnable ?D3D11_DEPTH_WRITE_MASK_ALL 1692 :D3D11_DEPTH_WRITE_MASK_ZERO ; 1693dsDesc .DepthFunc = translateComparisonFunc (desc .depthStencil .depthFunc ); 1694dsDesc .StencilEnable = desc .depthStencil .stencilEnable ; 1695dsDesc .StencilReadMask = desc .depthStencil .stencilReadMask ; 1696dsDesc .StencilWriteMask = desc .depthStencil .stencilWriteMask ; 1697 1698#define FACE (DST ,SRC ) \ 1699 dsDesc.DST.StencilFailOp = translateStencilOp(desc.depthStencil.SRC.stencilFailOp); \ 1700 dsDesc.DST.StencilDepthFailOp = translateStencilOp(desc.depthStencil.SRC.stencilDepthFailOp); \ 1701 dsDesc.DST.StencilPassOp = translateStencilOp(desc.depthStencil.SRC.stencilPassOp); \ 1702 dsDesc.DST.StencilFunc = translateComparisonFunc(desc.depthStencil.SRC.stencilFunc); \ 1703/* end */ 1704 1705FACE (FrontFace ,frontFace ); 1706FACE (BackFace ,backFace ); 1707 1708SLANG_RETURN_ON_FAIL ( 1709m_device -> CreateDepthStencilState (& dsDesc ,depthStencilState .writeRef ())); 1710 } 1711 1712ComPtr < ID3D11RasterizerState > rasterizerState ; 1713 { 1714D3D11_RASTERIZER_DESC rsDesc ; 1715rsDesc .FillMode = translateFillMode (desc .rasterizer .fillMode ); 1716rsDesc .CullMode = translateCullMode (desc .rasterizer .cullMode ); 1717rsDesc .FrontCounterClockwise = desc .rasterizer .frontFace == FrontFaceMode ::Clockwise ; 1718rsDesc .DepthBias = desc .rasterizer .depthBias ; 1719rsDesc .DepthBiasClamp = desc .rasterizer .depthBiasClamp ; 1720rsDesc .SlopeScaledDepthBias = desc .rasterizer .slopeScaledDepthBias ; 1721rsDesc .DepthClipEnable = desc .rasterizer .depthClipEnable ; 1722rsDesc .ScissorEnable = desc .rasterizer .scissorEnable ; 1723rsDesc .MultisampleEnable = desc .rasterizer .multisampleEnable ; 1724rsDesc .AntialiasedLineEnable = desc .rasterizer .antialiasedLineEnable ; 1725 1726SLANG_RETURN_ON_FAIL (m_device -> CreateRasterizerState (& rsDesc ,rasterizerState .writeRef ())); 1727 } 1728 1729ComPtr < ID3D11BlendState > blendState ; 1730 { 1731auto & srcDesc = desc .blend ; 1732D3D11_BLEND_DESC dstDesc = {}; 1733 1734TargetBlendDesc defaultTargetBlendDesc ; 1735 1736static const UInt kMaxTargets = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT ; 1737if (srcDesc .targetCount > kMaxTargets ) 1738return SLANG_FAIL ; 1739 1740for (GfxIndex ii = 0 ;ii < kMaxTargets ;++ ii ) 1741 { 1742TargetBlendDesc const * srcTargetBlendDescPtr = nullptr ; 1743if (ii < srcDesc .targetCount ) 1744 { 1745srcTargetBlendDescPtr = & srcDesc .targets [ii ]; 1746 } 1747else if (srcDesc .targetCount == 0 ) 1748 { 1749srcTargetBlendDescPtr = & defaultTargetBlendDesc ; 1750 } 1751else 1752 { 1753srcTargetBlendDescPtr = & srcDesc .targets [srcDesc .targetCount - 1 ]; 1754 } 1755 1756auto & srcTargetBlendDesc = * srcTargetBlendDescPtr ; 1757auto & dstTargetBlendDesc = dstDesc .RenderTarget [ii ]; 1758 1759if (isBlendDisabled (srcTargetBlendDesc )) 1760 { 1761dstTargetBlendDesc .BlendEnable = false; 1762dstTargetBlendDesc .BlendOp = D3D11_BLEND_OP_ADD ; 1763dstTargetBlendDesc .BlendOpAlpha = D3D11_BLEND_OP_ADD ; 1764dstTargetBlendDesc .SrcBlend = D3D11_BLEND_ONE ; 1765dstTargetBlendDesc .SrcBlendAlpha = D3D11_BLEND_ONE ; 1766dstTargetBlendDesc .DestBlend = D3D11_BLEND_ZERO ; 1767dstTargetBlendDesc .DestBlendAlpha = D3D11_BLEND_ZERO ; 1768 } 1769else 1770 { 1771dstTargetBlendDesc .BlendEnable = true; 1772dstTargetBlendDesc .BlendOp = translateBlendOp (srcTargetBlendDesc .color .op ); 1773dstTargetBlendDesc .BlendOpAlpha = translateBlendOp (srcTargetBlendDesc .alpha .op ); 1774dstTargetBlendDesc .SrcBlend = 1775translateBlendFactor (srcTargetBlendDesc .color .srcFactor ); 1776dstTargetBlendDesc .SrcBlendAlpha = 1777translateBlendFactor (srcTargetBlendDesc .alpha .srcFactor ); 1778dstTargetBlendDesc .DestBlend = 1779translateBlendFactor (srcTargetBlendDesc .color .dstFactor ); 1780dstTargetBlendDesc .DestBlendAlpha = 1781translateBlendFactor (srcTargetBlendDesc .alpha .dstFactor ); 1782 } 1783 1784dstTargetBlendDesc .RenderTargetWriteMask = 1785translateRenderTargetWriteMask (srcTargetBlendDesc .writeMask ); 1786 } 1787 1788dstDesc .IndependentBlendEnable = srcDesc .targetCount > 1 ; 1789dstDesc .AlphaToCoverageEnable = srcDesc .alphaToCoverageEnable ; 1790 1791SLANG_RETURN_ON_FAIL (m_device -> CreateBlendState (& dstDesc ,blendState .writeRef ())); 1792 } 1793 1794RefPtr < GraphicsPipelineStateImpl > state = new GraphicsPipelineStateImpl (); 1795state -> m_depthStencilState = depthStencilState ; 1796state -> m_rasterizerState = rasterizerState ; 1797state -> m_blendState = blendState ; 1798state -> m_inputLayout = static_cast < InputLayoutImpl *> (desc .inputLayout ); 1799state -> m_rtvCount = (UINT )static_cast < FramebufferLayoutImpl *> (desc .framebufferLayout ) 1800-> m_renderTargets .getCount (); 1801state -> m_blendColor [0 ]= 0 ; 1802state -> m_blendColor [1 ]= 0 ; 1803state -> m_blendColor [2 ]= 0 ; 1804state -> m_blendColor [3 ]= 0 ; 1805state -> m_sampleMask = 0xFFFFFFFF ; 1806state -> init (desc ); 1807returnComPtr (outState ,state ); 1808return SLANG_OK ; 1809} 1810 1811Result DeviceImpl ::createComputePipelineState ( 1812const ComputePipelineStateDesc & inDesc , 1813IPipelineState ** outState ) 1814{ 1815ComputePipelineStateDesc desc = inDesc ; 1816 1817RefPtr < ComputePipelineStateImpl > state = new ComputePipelineStateImpl (); 1818state -> init (desc ); 1819returnComPtr (outState ,state ); 1820return SLANG_OK ; 1821} 1822 1823void DeviceImpl ::copyBuffer ( 1824IBufferResource * dst , 1825Offset dstOffset , 1826IBufferResource * src , 1827Offset srcOffset , 1828Size size ) 1829{ 1830auto dstImpl = static_cast < BufferResourceImpl *> (dst ); 1831auto srcImpl = static_cast < BufferResourceImpl *> (src ); 1832D3D11_BOX srcBox = {}; 1833srcBox .left = (UINT )srcOffset ; 1834srcBox .right = (UINT )(srcOffset + size ); 1835srcBox .bottom = srcBox .back = 1 ; 1836m_immediateContext -> CopySubresourceRegion ( 1837dstImpl -> m_buffer , 18380 , 1839 (UINT )dstOffset , 18400 , 18410 , 1842srcImpl -> m_buffer , 18430 , 1844& srcBox ); 1845} 1846 1847void DeviceImpl ::dispatchCompute (int x ,int y ,int z ) 1848{ 1849m_immediateContext -> Dispatch (x ,y ,z ); 1850} 1851 1852void DeviceImpl ::_flushGraphicsState () 1853{ 1854if (m_depthStencilStateDirty ) 1855 { 1856m_depthStencilStateDirty = false; 1857auto pipelineState = static_cast < GraphicsPipelineStateImpl *> (m_currentPipelineState .Ptr ()); 1858m_immediateContext -> OMSetDepthStencilState ( 1859pipelineState -> m_depthStencilState , 1860m_stencilRef ); 1861 } 1862} 1863 1864void DeviceImpl ::beginCommandBuffer (const CommandBufferInfo & info ) 1865{ 1866if (info .hasWriteTimestamps ) 1867 { 1868m_immediateContext -> Begin (m_disjointQuery ); 1869 } 1870} 1871 1872void DeviceImpl ::endCommandBuffer (const CommandBufferInfo & info ) 1873{ 1874if (info .hasWriteTimestamps ) 1875 { 1876m_immediateContext -> End (m_disjointQuery ); 1877 } 1878} 1879 1880void DeviceImpl ::writeTimestamp (IQueryPool * pool ,GfxIndex index ) 1881{ 1882auto poolImpl = static_cast < QueryPoolImpl *> (pool ); 1883m_immediateContext -> End (poolImpl -> getQuery (index )); 1884} 1885}// namespace d3d11 1886}// namespace gfx