yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
698e43372
master
1// metal-device.cpp 2#include "metal-device.h" 3 4#include "../resource-desc-utils.h" 5#include "metal-buffer.h" 6#include "metal-render-pass.h" 7#include "metal-shader-program.h" 8#include "metal-swap-chain.h" 9#include "metal-texture.h" 10#include "metal-util.h" 11#include "metal-vertex-layout.h" 12// #include "metal-command-queue.h" 13#include "metal-fence.h" 14#include "metal-query.h" 15// #include "metal-resource-views.h" 16#include "metal-sampler.h" 17#include "metal-shader-object-layout.h" 18#include "metal-shader-object.h" 19// #include "metal-shader-table.h" 20#include "metal-transient-heap.h" 21// #include "metal-pipeline-dump-layer.h" 22// #include "metal-helper-functions.h" 23 24#include "core/slang-platform.h" 25namespace gfx 26{ 27 28using namespace Slang ; 29 30namespace metal 31{ 32 33static bool shouldDumpPipeline () 34{ 35StringBuilder dumpPipelineSettings ; 36PlatformUtil ::getEnvironmentVariable (toSlice ("SLANG_GFX_DUMP_PIPELINE" ),dumpPipelineSettings ); 37return dumpPipelineSettings .produceString ()== "1" ; 38} 39 40DeviceImpl ::~DeviceImpl () {} 41 42Result DeviceImpl ::getNativeDeviceHandles (InteropHandles * outHandles ) 43{ 44outHandles -> handles [0 ].api = InteropHandleAPI ::Metal ; 45outHandles -> handles [0 ].handleValue = reinterpret_cast < intptr_t > (m_device .get ()); 46return SLANG_OK ; 47} 48 49SlangResult DeviceImpl ::initialize (const Desc & desc ) 50{ 51AUTORELEASEPOOL 52 53// Initialize device info. 54 { 55m_info .apiName = "Metal" ; 56m_info .bindingStyle = BindingStyle ::Metal ; 57m_info .projectionStyle = ProjectionStyle ::Metal ; 58m_info .deviceType = DeviceType ::Metal ; 59m_info .adapterName = "default" ; 60static const float kIdentity []= {1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0 ,1 }; 61 ::memcpy (m_info .identityProjectionMatrix ,kIdentity ,sizeof (kIdentity )); 62 } 63 64m_desc = desc ; 65 66SLANG_RETURN_ON_FAIL (RendererBase ::initialize (desc )); 67SlangResult initDeviceResult = SLANG_OK ; 68 69m_device = NS ::TransferPtr (MTL ::CreateSystemDefaultDevice ()); 70m_commandQueue = NS ::TransferPtr (m_device -> newCommandQueue (64 )); 71m_hasArgumentBufferTier2 = m_device -> argumentBuffersSupport () >=MTL ::ArgumentBuffersTier2 ; 72 73if (m_hasArgumentBufferTier2 ) 74 { 75m_features .add ("argument-buffer-tier-2" ); 76 } 77 78SLANG_RETURN_ON_FAIL (slangContext .initialize ( 79desc .slang , 80desc .extendedDescCount , 81desc .extendedDescs , 82SLANG_METAL_LIB , 83"" , 84makeArray (slang::PreprocessorMacroDesc {"__METAL__" ,"1" }).getView ())); 85 86// TODO: expose via some other means 87if (captureEnabled ()) 88 { 89MTL ::CaptureManager * captureManager = MTL ::CaptureManager ::sharedCaptureManager (); 90MTL ::CaptureDescriptor * d = MTL ::CaptureDescriptor ::alloc ()-> init (); 91MTL ::CaptureDestination captureDest = 92MTL ::CaptureDestination ::CaptureDestinationGPUTraceDocument ; 93if (!captureManager -> supportsDestination (MTL ::CaptureDestinationGPUTraceDocument )) 94 { 95 std::cout <<"Cannot capture MTL calls to document; ensure that Info.plist exists with " 96"'MetalCaptureEnabled' set to 'true'." 97 << std::endl ; 98exit (1 ); 99 } 100d -> setDestination (MTL ::CaptureDestinationGPUTraceDocument ); 101d -> setCaptureObject (m_device .get ()); 102NS ::SharedPtr < NS ::String > path = MetalUtil ::createString ("frame.gputrace" ); 103NS ::SharedPtr < NS ::URL > url = 104NS ::TransferPtr (NS ::URL ::alloc ()-> initFileURLWithPath (path .get ())); 105d -> setOutputURL (url .get ()); 106NS ::Error * errorCode = NS ::Error ::alloc (); 107if (!captureManager -> startCapture (d ,& errorCode )) 108 { 109NS ::String * errorString = errorCode -> description (); 110 std::string estr (errorString -> cString (NS ::UTF8StringEncoding )); 111 std::cout <<"Start capture failure: " <<estr << std::endl ; 112exit (1 ); 113 } 114 } 115return SLANG_OK ; 116} 117 118// void DeviceImpl::waitForGpu() { m_deviceQueue.flushAndWait(); } 119 120 121const DeviceInfo & DeviceImpl ::getDeviceInfo ()const 122{ 123return m_info ; 124} 125 126Result DeviceImpl ::createTransientResourceHeap ( 127const ITransientResourceHeap ::Desc & desc , 128ITransientResourceHeap ** outHeap ) 129{ 130AUTORELEASEPOOL 131 132RefPtr < TransientResourceHeapImpl > result = new TransientResourceHeapImpl (); 133SLANG_RETURN_ON_FAIL (result -> init (desc ,this )); 134returnComPtr (outHeap ,result ); 135return SLANG_OK ; 136} 137 138Result DeviceImpl ::createCommandQueue (const ICommandQueue ::Desc & desc ,ICommandQueue ** outQueue ) 139{ 140AUTORELEASEPOOL 141 142if (m_queueAllocCount != 0 ) 143return SLANG_FAIL ; 144 145RefPtr < CommandQueueImpl > result = new CommandQueueImpl ; 146result -> init (this ,m_commandQueue ); 147returnComPtr (outQueue ,result ); 148m_queueAllocCount ++ ; 149return SLANG_OK ; 150} 151 152Result DeviceImpl ::createSwapchain ( 153const ISwapchain ::Desc & desc , 154WindowHandle window , 155ISwapchain ** outSwapchain ) 156{ 157AUTORELEASEPOOL 158 159RefPtr < SwapchainImpl > swapchainImpl = new SwapchainImpl (); 160SLANG_RETURN_ON_FAIL (swapchainImpl -> init (this ,desc ,window )); 161returnComPtr (outSwapchain ,swapchainImpl ); 162return SLANG_OK ; 163} 164 165Result DeviceImpl ::createFramebufferLayout ( 166const IFramebufferLayout ::Desc & desc , 167IFramebufferLayout ** outLayout ) 168{ 169AUTORELEASEPOOL 170 171RefPtr < FramebufferLayoutImpl > layoutImpl = new FramebufferLayoutImpl ; 172SLANG_RETURN_ON_FAIL (layoutImpl -> init (desc )); 173returnComPtr (outLayout ,layoutImpl ); 174return SLANG_OK ; 175} 176 177Result DeviceImpl ::createRenderPassLayout ( 178const IRenderPassLayout ::Desc & desc , 179IRenderPassLayout ** outRenderPassLayout ) 180{ 181AUTORELEASEPOOL 182 183RefPtr < RenderPassLayoutImpl > renderPassLayoutImpl = new RenderPassLayoutImpl ; 184SLANG_RETURN_ON_FAIL (renderPassLayoutImpl -> init (this ,desc )); 185returnComPtr (outRenderPassLayout ,renderPassLayoutImpl ); 186return SLANG_OK ; 187} 188 189Result DeviceImpl ::createFramebuffer (const IFramebuffer ::Desc & desc ,IFramebuffer ** outFramebuffer ) 190{ 191AUTORELEASEPOOL 192 193RefPtr < FramebufferImpl > framebufferImpl = new FramebufferImpl ; 194SLANG_RETURN_ON_FAIL (framebufferImpl -> init (this ,desc )); 195returnComPtr (outFramebuffer ,framebufferImpl ); 196return SLANG_OK ; 197} 198 199SlangResult DeviceImpl ::readTextureResource ( 200ITextureResource * texture , 201ResourceState state , 202ISlangBlob ** outBlob , 203Size * outRowPitch , 204Size * outPixelSize ) 205{ 206AUTORELEASEPOOL 207 208TextureResourceImpl * textureImpl = static_cast < TextureResourceImpl *> (texture ); 209 210if (textureImpl -> getDesc ()-> sampleDesc .numSamples > 1 ) 211 { 212return SLANG_E_NOT_IMPLEMENTED ; 213 } 214 215NS ::SharedPtr < MTL ::Texture > srcTexture = textureImpl -> m_texture ; 216 217const ITextureResource ::Desc & desc = * textureImpl -> getDesc (); 218Count width = Math ::Max (desc .size .width ,1 ); 219Count height = Math ::Max (desc .size .height ,1 ); 220Count depth = Math ::Max (desc .size .depth ,1 ); 221FormatInfo formatInfo ; 222gfxGetFormatInfo (desc .format ,& formatInfo ); 223Size bytesPerPixel = formatInfo .blockSizeInBytes /formatInfo .pixelsPerBlock ; 224Size bytesPerRow = Size (width )* bytesPerPixel ; 225Size bytesPerSlice = Size (height )* bytesPerRow ; 226Size bufferSize = Size (depth )* bytesPerSlice ; 227if (outRowPitch ) 228* outRowPitch = bytesPerRow ; 229if (outPixelSize ) 230* outPixelSize = bytesPerPixel ; 231 232// create staging buffer 233NS ::SharedPtr < MTL ::Buffer > stagingBuffer = 234NS ::TransferPtr (m_device -> newBuffer (bufferSize ,MTL ::StorageModeShared )); 235if (!stagingBuffer ) 236 { 237return SLANG_FAIL ; 238 } 239 240MTL ::CommandBuffer * commandBuffer = m_commandQueue -> commandBuffer (); 241MTL ::BlitCommandEncoder * encoder = commandBuffer -> blitCommandEncoder (); 242encoder -> copyFromTexture ( 243srcTexture .get (), 2440 , 2450 , 246MTL ::Origin (0 ,0 ,0 ), 247MTL ::Size (width ,height ,depth ), 248stagingBuffer .get (), 2490 , 250bytesPerRow , 251bytesPerSlice ); 252encoder -> endEncoding (); 253commandBuffer -> commit (); 254commandBuffer -> waitUntilCompleted (); 255 256List < uint8_t > blobData ; 257blobData .setCount (bufferSize ); 258 ::memcpy (blobData .getBuffer (),stagingBuffer -> contents (),bufferSize ); 259auto blob = ListBlob ::moveCreate (blobData ); 260 261returnComPtr (outBlob ,blob ); 262return SLANG_OK ; 263} 264 265SlangResult DeviceImpl ::readBufferResource ( 266IBufferResource * buffer , 267Offset offset , 268Size size , 269ISlangBlob ** outBlob ) 270{ 271AUTORELEASEPOOL 272 273// create staging buffer 274NS ::SharedPtr < MTL ::Buffer > stagingBuffer = 275NS ::TransferPtr (m_device -> newBuffer (size ,MTL ::StorageModeShared )); 276if (!stagingBuffer ) 277 { 278return SLANG_FAIL ; 279 } 280 281MTL ::CommandBuffer * commandBuffer = m_commandQueue -> commandBuffer (); 282MTL ::BlitCommandEncoder * blitEncoder = commandBuffer -> blitCommandEncoder (); 283blitEncoder -> copyFromBuffer ( 284static_cast < BufferResourceImpl *> (buffer )-> m_buffer .get (), 285offset , 286stagingBuffer .get (), 2870 , 288size ); 289blitEncoder -> endEncoding (); 290commandBuffer -> commit (); 291commandBuffer -> waitUntilCompleted (); 292 293List < uint8_t > blobData ; 294blobData .setCount (size ); 295 ::memcpy (blobData .getBuffer (),stagingBuffer -> contents (),size ); 296auto blob = ListBlob ::moveCreate (blobData ); 297 298returnComPtr (outBlob ,blob ); 299return SLANG_OK ; 300} 301 302Result DeviceImpl ::getAccelerationStructurePrebuildInfo ( 303const IAccelerationStructure ::BuildInputs & buildInputs , 304IAccelerationStructure ::PrebuildInfo * outPrebuildInfo ) 305{ 306AUTORELEASEPOOL 307 308return SLANG_E_NOT_IMPLEMENTED ; 309} 310 311Result DeviceImpl ::createAccelerationStructure ( 312const IAccelerationStructure ::CreateDesc & desc , 313IAccelerationStructure ** outAS ) 314{ 315AUTORELEASEPOOL 316 317return SLANG_E_NOT_IMPLEMENTED ; 318} 319 320Result DeviceImpl ::getTextureAllocationInfo ( 321const ITextureResource ::Desc & descIn , 322Size * outSize , 323Size * outAlignment ) 324{ 325AUTORELEASEPOOL 326 327auto alignTo = [& ](Size size ,Size alignment )-> Size 328 {return ((size + alignment - 1 ) /alignment )* alignment ; }; 329 330TextureResource ::Desc desc = fixupTextureDesc (descIn ); 331FormatInfo formatInfo ; 332gfxGetFormatInfo (desc .format ,& formatInfo ); 333MTL ::PixelFormat pixelFormat = MetalUtil ::translatePixelFormat (desc .format ); 334bool isCompressed = gfxIsCompressedFormat (desc .format ); 335Size alignment = 336isCompressed ?1 :m_device -> minimumLinearTextureAlignmentForPixelFormat (pixelFormat ); 337Size size = 0 ; 338ITextureResource ::Extents extents = desc .size ; 339extents .width = extents .width ?extents .width :1 ; 340extents .height = extents .height ?extents .height :1 ; 341extents .depth = extents .depth ?extents .depth :1 ; 342 343for (Int i = 0 ;i < desc .numMipLevels ;++ i ) 344 { 345Size rowSize = ((extents .width + formatInfo .blockWidth - 1 ) /formatInfo .blockWidth )* 346formatInfo .blockSizeInBytes ; 347rowSize = alignTo (rowSize ,alignment ); 348Size sliceSize = rowSize * alignTo (extents .height ,formatInfo .blockHeight ); 349size += sliceSize * extents .depth ; 350extents .width = Math ::Max (1 ,extents .width /2 ); 351extents .height = Math ::Max (1 ,extents .height /2 ); 352extents .depth = Math ::Max (1 ,extents .depth /2 ); 353 } 354size *=desc .arraySize ?desc .arraySize :1 ; 355 356* outSize = size ; 357* outAlignment = alignment ; 358 359return SLANG_OK ; 360} 361 362Result DeviceImpl ::getTextureRowAlignment (Size * outAlignment ) 363{ 364AUTORELEASEPOOL 365 366* outAlignment = 1 ; 367return SLANG_E_NOT_IMPLEMENTED ; 368} 369 370Result DeviceImpl ::createTextureResource ( 371const ITextureResource ::Desc & descIn , 372const ITextureResource ::SubresourceData * initData , 373ITextureResource ** outResource ) 374{ 375AUTORELEASEPOOL 376 377TextureResource ::Desc desc = fixupTextureDesc (descIn ); 378 379// Metal doesn't support mip-mapping for 1D textures 380// However, we still need to use the provided mip level count when initializing the texture 381Count initMipLevels = desc .numMipLevels ; 382desc .numMipLevels = desc .type == IResource ::Type ::Texture1D ?1 :desc .numMipLevels ; 383 384const MTL ::PixelFormat pixelFormat = MetalUtil ::translatePixelFormat (desc .format ); 385if (pixelFormat == MTL ::PixelFormat ::PixelFormatInvalid ) 386 { 387assert (!"Unsupported texture format" ); 388return SLANG_FAIL ; 389 } 390 391RefPtr < TextureResourceImpl > textureImpl (new TextureResourceImpl (desc ,this )); 392 393NS ::SharedPtr < MTL ::TextureDescriptor > textureDesc = 394NS ::TransferPtr (MTL ::TextureDescriptor ::alloc ()-> init ()); 395switch (desc .memoryType ) 396 { 397case MemoryType ::DeviceLocal : 398textureDesc -> setStorageMode (MTL ::StorageModePrivate ); 399break ; 400case MemoryType ::Upload : 401textureDesc -> setStorageMode (MTL ::StorageModeShared ); 402textureDesc -> setCpuCacheMode (MTL ::CPUCacheModeWriteCombined ); 403break ; 404case MemoryType ::ReadBack : 405textureDesc -> setStorageMode (MTL ::StorageModeShared ); 406break ; 407 } 408 409bool isArray = desc .arraySize > 0 ; 410 411switch (desc .type ) 412 { 413case IResource ::Type ::Texture1D : 414textureDesc -> setTextureType (isArray ?MTL ::TextureType1DArray :MTL ::TextureType1D ); 415textureDesc -> setWidth (desc .size .width ); 416break ; 417case IResource ::Type ::Texture2D : 418if (desc .sampleDesc .numSamples > 1 ) 419 { 420textureDesc -> setTextureType ( 421isArray ?MTL ::TextureType2DMultisampleArray :MTL ::TextureType2DMultisample ); 422textureDesc -> setSampleCount (desc .sampleDesc .numSamples ); 423 } 424else 425 { 426textureDesc -> setTextureType (isArray ?MTL ::TextureType2DArray :MTL ::TextureType2D ); 427 } 428textureDesc -> setWidth (descIn .size .width ); 429textureDesc -> setHeight (descIn .size .height ); 430break ; 431case IResource ::Type ::TextureCube : 432textureDesc -> setTextureType (isArray ?MTL ::TextureTypeCubeArray :MTL ::TextureTypeCube ); 433textureDesc -> setWidth (descIn .size .width ); 434textureDesc -> setHeight (descIn .size .height ); 435break ; 436case IResource ::Type ::Texture3D : 437textureDesc -> setTextureType (MTL ::TextureType ::TextureType3D ); 438textureDesc -> setWidth (descIn .size .width ); 439textureDesc -> setHeight (descIn .size .height ); 440textureDesc -> setDepth (descIn .size .depth ); 441break ; 442default : 443assert ("!Unsupported texture type" ); 444return SLANG_FAIL ; 445 } 446 447MTL ::TextureUsage textureUsage = MTL ::TextureUsageUnknown ; 448if (desc .allowedStates .contains (ResourceState ::RenderTarget )) 449 { 450textureUsage |=MTL ::TextureUsageRenderTarget ; 451 } 452if (desc .allowedStates .contains (ResourceState ::ShaderResource )) 453 { 454textureUsage |=MTL ::TextureUsageShaderRead ; 455 } 456if (desc .allowedStates .contains (ResourceState ::UnorderedAccess )) 457 { 458textureUsage |=MTL ::TextureUsageShaderRead ; 459textureUsage |=MTL ::TextureUsageShaderWrite ; 460 461// Request atomic access if the format allows it. 462switch (desc .format ) 463 { 464case Format ::R32_UINT : 465case Format ::R32_SINT : 466case Format ::R32G32_UINT : 467case Format ::R32G32_SINT : 468textureUsage |=MTL ::TextureUsageShaderAtomic ; 469break ; 470 } 471 } 472 473textureDesc -> setMipmapLevelCount (desc .numMipLevels ); 474textureDesc -> setArrayLength (isArray ?desc .arraySize :1 ); 475textureDesc -> setPixelFormat (pixelFormat ); 476textureDesc -> setUsage (textureUsage ); 477textureDesc -> setSampleCount (desc .sampleDesc .numSamples ); 478textureDesc -> setAllowGPUOptimizedContents (desc .memoryType == MemoryType ::DeviceLocal ); 479 480textureImpl -> m_texture = NS ::TransferPtr (m_device -> newTexture (textureDesc .get ())); 481if (!textureImpl -> m_texture ) 482 { 483return SLANG_FAIL ; 484 } 485textureImpl -> m_textureType = textureDesc -> textureType (); 486textureImpl -> m_pixelFormat = textureDesc -> pixelFormat (); 487 488// TODO: handle initData 489if (initData ) 490 { 491textureDesc -> setStorageMode (MTL ::StorageModeManaged ); 492textureDesc -> setCpuCacheMode (MTL ::CPUCacheModeDefaultCache ); 493NS ::SharedPtr < MTL ::Texture > stagingTexture = 494NS ::TransferPtr (m_device -> newTexture (textureDesc .get ())); 495 496MTL ::CommandBuffer * commandBuffer = m_commandQueue -> commandBuffer (); 497MTL ::BlitCommandEncoder * encoder = commandBuffer -> blitCommandEncoder (); 498if (!stagingTexture || !commandBuffer || !encoder ) 499 { 500return SLANG_FAIL ; 501 } 502 503Count sliceCount = isArray ?desc .arraySize :1 ; 504if (desc .type == IResource ::Type ::TextureCube ) 505 { 506sliceCount *=6 ; 507 } 508 509for (Index slice = 0 ;slice < sliceCount ;++ slice ) 510 { 511MTL ::Region region ; 512region .origin = MTL ::Origin (0 ,0 ,0 ); 513region .size = MTL ::Size (desc .size .width ,desc .size .height ,desc .size .depth ); 514for (Index level = 0 ;level < initMipLevels ;++ level ) 515 { 516if (level >=desc .numMipLevels ) 517continue ; 518const ITextureResource ::SubresourceData & subresourceData = 519initData [slice * initMipLevels + level ]; 520stagingTexture -> replaceRegion ( 521region , 522level , 523slice , 524subresourceData .data , 525subresourceData .strideY , 526subresourceData .strideZ ); 527encoder -> synchronizeTexture (stagingTexture .get (),slice ,level ); 528region .size .width = 529region .size .width > 0 ?Math ::Max (1ul ,region .size .width >>1 ) :0 ; 530region .size .height = 531region .size .height > 0 ?Math ::Max (1ul ,region .size .height >>1 ) :0 ; 532region .size .depth = 533region .size .depth > 0 ?Math ::Max (1ul ,region .size .depth >>1 ) :0 ; 534 } 535 } 536 537encoder -> copyFromTexture (stagingTexture .get (),textureImpl -> m_texture .get ()); 538encoder -> endEncoding (); 539commandBuffer -> commit (); 540commandBuffer -> waitUntilCompleted (); 541 } 542 543returnComPtr (outResource ,textureImpl ); 544return SLANG_OK ; 545} 546 547Result DeviceImpl ::createBufferResource ( 548const IBufferResource ::Desc & descIn , 549const void * initData , 550IBufferResource ** outResource ) 551{ 552AUTORELEASEPOOL 553 554BufferResource ::Desc desc = fixupBufferDesc (descIn ); 555 556const Size bufferSize = desc .sizeInBytes ; 557 558MTL ::ResourceOptions resourceOptions = MTL ::ResourceOptions (0 ); 559switch (desc .memoryType ) 560 { 561case MemoryType ::DeviceLocal : 562resourceOptions = MTL ::ResourceStorageModePrivate ; 563break ; 564case MemoryType ::Upload : 565resourceOptions = MTL ::ResourceStorageModeShared |MTL ::ResourceCPUCacheModeWriteCombined ; 566break ; 567case MemoryType ::ReadBack : 568resourceOptions = MTL ::ResourceStorageModeShared ; 569break ; 570 } 571resourceOptions |= (desc .memoryType == MemoryType ::DeviceLocal ) 572 ?MTL ::ResourceStorageModePrivate 573 :MTL ::ResourceStorageModeShared ; 574 575RefPtr < BufferResourceImpl > bufferImpl (new BufferResourceImpl (desc ,this )); 576bufferImpl -> m_buffer = NS ::TransferPtr (m_device -> newBuffer (bufferSize ,resourceOptions )); 577if (!bufferImpl -> m_buffer ) 578 { 579return SLANG_FAIL ; 580 } 581 582if (initData ) 583 { 584NS ::SharedPtr < MTL ::Buffer > stagingBuffer = NS ::TransferPtr (m_device -> newBuffer ( 585initData , 586bufferSize , 587MTL ::ResourceStorageModeShared |MTL ::ResourceCPUCacheModeWriteCombined )); 588MTL ::CommandBuffer * commandBuffer = m_commandQueue -> commandBuffer (); 589MTL ::BlitCommandEncoder * encoder = commandBuffer -> blitCommandEncoder (); 590if (!stagingBuffer || !commandBuffer || !encoder ) 591 { 592return SLANG_FAIL ; 593 } 594encoder -> copyFromBuffer (stagingBuffer .get (),0 ,bufferImpl -> m_buffer .get (),0 ,bufferSize ); 595encoder -> endEncoding (); 596commandBuffer -> commit (); 597commandBuffer -> waitUntilCompleted (); 598 } 599 600returnComPtr (outResource ,bufferImpl ); 601return SLANG_OK ; 602} 603 604Result DeviceImpl ::createBufferFromNativeHandle ( 605InteropHandle handle , 606const IBufferResource ::Desc & srcDesc , 607IBufferResource ** outResource ) 608{ 609AUTORELEASEPOOL 610 611return SLANG_E_NOT_IMPLEMENTED ; 612} 613 614Result DeviceImpl ::createSamplerState (ISamplerState ::Desc const & desc ,ISamplerState ** outSampler ) 615{ 616AUTORELEASEPOOL 617 618RefPtr < SamplerStateImpl > samplerImpl = new SamplerStateImpl (); 619SLANG_RETURN_ON_FAIL (samplerImpl -> init (this ,desc )); 620returnComPtr (outSampler ,samplerImpl ); 621return SLANG_OK ; 622} 623 624Result DeviceImpl ::createTextureView ( 625ITextureResource * texture , 626IResourceView ::Desc const & desc , 627IResourceView ** outView ) 628{ 629AUTORELEASEPOOL 630 631auto textureImpl = static_cast < TextureResourceImpl *> (texture ); 632RefPtr < TextureResourceViewImpl > viewImpl = new TextureResourceViewImpl (this ); 633viewImpl -> m_desc = desc ; 634viewImpl -> m_device = this ; 635viewImpl -> m_texture = textureImpl ; 636if (textureImpl == nullptr ) 637 { 638returnComPtr (outView ,viewImpl ); 639return SLANG_OK ; 640 } 641 642const ITextureResource ::Desc & textureDesc = * textureImpl -> getDesc (); 643SubresourceRange sr = desc .subresourceRange ; 644sr .mipLevelCount = 645sr .mipLevelCount == 0 ?textureDesc .numMipLevels - sr .mipLevel :sr .mipLevelCount ; 646sr .layerCount = sr .layerCount == 0 ?textureDesc .arraySize - sr .baseArrayLayer :sr .layerCount ; 647if (sr .mipLevel == 0 && sr .mipLevelCount == textureDesc .numMipLevels && 648sr .baseArrayLayer == 0 && sr .layerCount == textureDesc .arraySize ) 649 { 650viewImpl -> m_textureView = textureImpl -> m_texture ; 651returnComPtr (outView ,viewImpl ); 652return SLANG_OK ; 653 } 654 655MTL ::PixelFormat pixelFormat = desc .format == Format ::Unknown 656 ?textureImpl -> m_pixelFormat 657 :MetalUtil ::translatePixelFormat (desc .format ); 658NS ::Range sliceRange (sr .baseArrayLayer ,sr .layerCount ); 659NS ::Range levelRange (sr .mipLevel ,sr .mipLevelCount ); 660 661viewImpl -> m_textureView = NS ::TransferPtr (textureImpl -> m_texture -> newTextureView ( 662pixelFormat , 663textureImpl -> m_textureType , 664levelRange , 665sliceRange )); 666if (!viewImpl -> m_textureView ) 667 { 668return SLANG_FAIL ; 669 } 670 671returnComPtr (outView ,viewImpl ); 672return SLANG_OK ; 673} 674 675Result DeviceImpl ::getFormatSupportedResourceStates (Format format ,ResourceStateSet * outStates ) 676{ 677AUTORELEASEPOOL 678 679// TODO - add table based on https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf 680ResourceStateSet allowedStates ; 681allowedStates .add (ResourceState ::VertexBuffer ); 682allowedStates .add (ResourceState ::IndexBuffer ); 683allowedStates .add (ResourceState ::ConstantBuffer ); 684allowedStates .add (ResourceState ::ShaderResource ); 685allowedStates .add (ResourceState ::UnorderedAccess ); 686allowedStates .add (ResourceState ::RenderTarget ); 687allowedStates .add (ResourceState ::DepthRead ); 688allowedStates .add (ResourceState ::DepthWrite ); 689allowedStates .add (ResourceState ::Present ); 690allowedStates .add (ResourceState ::IndirectArgument ); 691allowedStates .add (ResourceState ::CopySource ); 692allowedStates .add (ResourceState ::ResolveSource ); 693allowedStates .add (ResourceState ::CopyDestination ); 694allowedStates .add (ResourceState ::ResolveDestination ); 695allowedStates .add (ResourceState ::AccelerationStructure ); 696allowedStates .add (ResourceState ::AccelerationStructureBuildInput ); 697 698* outStates = allowedStates ; 699return SLANG_OK ; 700} 701 702Result DeviceImpl ::createBufferView ( 703IBufferResource * buffer , 704IBufferResource * counterBuffer , 705IResourceView ::Desc const & desc , 706IResourceView ** outView ) 707{ 708AUTORELEASEPOOL 709 710// Counter buffers are not supported on metal. 711if (counterBuffer ) 712 { 713return SLANG_FAIL ; 714 } 715 716if (desc .type != IResourceView ::Type ::UnorderedAccess && 717desc .type != IResourceView ::Type ::ShaderResource ) 718 { 719return SLANG_FAIL ; 720 } 721 722auto bufferImpl = static_cast < BufferResourceImpl *> (buffer ); 723 724RefPtr < BufferResourceViewImpl > viewImpl = new BufferResourceViewImpl (this ); 725viewImpl -> m_desc = desc ; 726viewImpl -> m_buffer = bufferImpl ; 727viewImpl -> m_offset = desc .bufferRange .offset ; 728viewImpl -> m_size = 729desc .bufferRange .size == 0 ?bufferImpl -> getDesc ()-> sizeInBytes :desc .bufferRange .size ; 730returnComPtr (outView ,viewImpl ); 731return SLANG_OK ; 732} 733 734Result DeviceImpl ::createInputLayout (IInputLayout ::Desc const & desc ,IInputLayout ** outLayout ) 735{ 736AUTORELEASEPOOL 737 738RefPtr < InputLayoutImpl > layoutImpl (new InputLayoutImpl ); 739SLANG_RETURN_ON_FAIL (layoutImpl -> init (desc )); 740returnComPtr (outLayout ,layoutImpl ); 741return SLANG_OK ; 742} 743 744Result DeviceImpl ::createProgram ( 745const IShaderProgram ::Desc & desc , 746IShaderProgram ** outProgram , 747ISlangBlob ** outDiagnosticBlob ) 748{ 749AUTORELEASEPOOL 750 751RefPtr < ShaderProgramImpl > shaderProgram = new ShaderProgramImpl (this ); 752shaderProgram -> init (desc ); 753 754RootShaderObjectLayoutImpl ::create ( 755this , 756shaderProgram -> linkedProgram , 757shaderProgram -> linkedProgram -> getLayout (), 758shaderProgram -> m_rootObjectLayout .writeRef ()); 759 760if (!shaderProgram -> isSpecializable ()) 761 { 762SLANG_RETURN_ON_FAIL (shaderProgram -> compileShaders (this )); 763 } 764 765returnComPtr (outProgram ,shaderProgram ); 766return SLANG_OK ; 767} 768 769Result DeviceImpl ::createShaderObjectLayout ( 770 slang::ISession * session , 771 slang::TypeLayoutReflection * typeLayout , 772ShaderObjectLayoutBase ** outLayout ) 773{ 774AUTORELEASEPOOL 775 776RefPtr < ShaderObjectLayoutImpl > layout ; 777SLANG_RETURN_ON_FAIL ( 778ShaderObjectLayoutImpl ::createForElementType (this ,session ,typeLayout ,layout .writeRef ())); 779returnRefPtrMove (outLayout ,layout ); 780return SLANG_OK ; 781} 782 783Result DeviceImpl ::createShaderObject (ShaderObjectLayoutBase * layout ,IShaderObject ** outObject ) 784{ 785AUTORELEASEPOOL 786 787RefPtr < ShaderObjectImpl > shaderObject ; 788SLANG_RETURN_ON_FAIL (ShaderObjectImpl ::create ( 789this , 790static_cast < ShaderObjectLayoutImpl *> (layout ), 791shaderObject .writeRef ())); 792returnComPtr (outObject ,shaderObject ); 793return SLANG_OK ; 794} 795 796Result DeviceImpl ::createMutableShaderObject ( 797ShaderObjectLayoutBase * layout , 798IShaderObject ** outObject ) 799{ 800AUTORELEASEPOOL 801 802return SLANG_E_NOT_IMPLEMENTED ; 803} 804 805Result DeviceImpl ::createMutableRootShaderObject (IShaderProgram * program ,IShaderObject ** outObject ) 806{ 807AUTORELEASEPOOL 808 809return SLANG_E_NOT_IMPLEMENTED ; 810} 811 812Result DeviceImpl ::createShaderTable (const IShaderTable ::Desc & desc ,IShaderTable ** outShaderTable ) 813{ 814AUTORELEASEPOOL 815 816return SLANG_E_NOT_IMPLEMENTED ; 817} 818 819Result DeviceImpl ::createGraphicsPipelineState ( 820const GraphicsPipelineStateDesc & desc , 821IPipelineState ** outState ) 822{ 823AUTORELEASEPOOL 824 825RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (this ); 826pipelineStateImpl -> init (desc ); 827returnComPtr (outState ,pipelineStateImpl ); 828return SLANG_OK ; 829} 830 831Result DeviceImpl ::createComputePipelineState ( 832const ComputePipelineStateDesc & desc , 833IPipelineState ** outState ) 834{ 835AUTORELEASEPOOL 836 837RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (this ); 838pipelineStateImpl -> init (desc ); 839m_deviceObjectsWithPotentialBackReferences .add (pipelineStateImpl ); 840returnComPtr (outState ,pipelineStateImpl ); 841return SLANG_OK ; 842} 843 844Result DeviceImpl ::createRayTracingPipelineState ( 845const RayTracingPipelineStateDesc & desc , 846IPipelineState ** outState ) 847{ 848AUTORELEASEPOOL 849 850return SLANG_E_NOT_IMPLEMENTED ; 851} 852 853Result DeviceImpl ::createQueryPool (const IQueryPool ::Desc & desc ,IQueryPool ** outPool ) 854{ 855AUTORELEASEPOOL 856 857RefPtr < QueryPoolImpl > poolImpl = new QueryPoolImpl (); 858SLANG_RETURN_ON_FAIL (poolImpl -> init (this ,desc )); 859returnComPtr (outPool ,poolImpl ); 860return SLANG_OK ; 861} 862 863Result DeviceImpl ::createFence (const IFence ::Desc & desc ,IFence ** outFence ) 864{ 865AUTORELEASEPOOL 866 867RefPtr < FenceImpl > fenceImpl = new FenceImpl (); 868SLANG_RETURN_ON_FAIL (fenceImpl -> init (this ,desc )); 869returnComPtr (outFence ,fenceImpl ); 870return SLANG_OK ; 871} 872 873Result DeviceImpl ::waitForFences ( 874GfxCount fenceCount , 875IFence ** fences , 876uint64_t * fenceValues , 877bool waitForAll , 878uint64_t timeout ) 879{ 880// return SLANG_E_NOT_IMPLEMENTED; 881for (GfxCount i = 0 ;i < fenceCount ;++ i ) 882 { 883FenceImpl * fenceImpl = static_cast < FenceImpl *> (fences [i ]); 884if (!fenceImpl -> waitForFence (fenceValues [i ],timeout )) 885 { 886return SLANG_FAIL ; 887 } 888 } 889return SLANG_OK ; 890} 891 892}// namespace metal 893}// namespace gfx