yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
2ad1f8138
master
1// vk-command-encoder.cpp 2#include "vk-command-encoder.h" 3 4#include "vk-buffer.h" 5#include "vk-command-buffer.h" 6#include "vk-helper-functions.h" 7#include "vk-query.h" 8#include "vk-render-pass.h" 9#include "vk-resource-views.h" 10#include "vk-shader-object.h" 11#include "vk-shader-program.h" 12#include "vk-shader-table.h" 13#include "vk-texture.h" 14#include "vk-transient-heap.h" 15 16namespace gfx 17{ 18 19using namespace Slang ; 20 21namespace vk 22{ 23 24int PipelineCommandEncoder ::getBindPointIndex (VkPipelineBindPoint bindPoint ) 25{ 26switch (bindPoint ) 27 { 28case VK_PIPELINE_BIND_POINT_GRAPHICS : 29return 0 ; 30case VK_PIPELINE_BIND_POINT_COMPUTE : 31return 1 ; 32case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR : 33return 2 ; 34default : 35assert (!"unknown pipeline type." ); 36return -1 ; 37 } 38} 39 40void PipelineCommandEncoder ::init (CommandBufferImpl * commandBuffer ) 41{ 42m_commandBuffer = commandBuffer ; 43m_device = commandBuffer -> m_renderer ; 44m_vkCommandBuffer = m_commandBuffer -> m_commandBuffer ; 45m_api = & m_commandBuffer -> m_renderer -> m_api ; 46} 47 48void PipelineCommandEncoder ::endEncodingImpl () 49{ 50for (auto & pipeline :m_boundPipelines ) 51pipeline = VK_NULL_HANDLE ; 52} 53 54void PipelineCommandEncoder ::_uploadBufferData ( 55VkCommandBuffer commandBuffer , 56TransientResourceHeapImpl * transientHeap , 57BufferResourceImpl * buffer , 58Offset offset , 59Size size , 60void * data ) 61{ 62auto & api = buffer -> m_renderer -> m_api ; 63IBufferResource * stagingBuffer = nullptr ; 64Offset stagingBufferOffset = 0 ; 65transientHeap 66-> allocateStagingBuffer (size ,stagingBuffer ,stagingBufferOffset ,MemoryType ::Upload ); 67 68BufferResourceImpl * stagingBufferImpl = static_cast < BufferResourceImpl *> (stagingBuffer ); 69 70void * mappedData = nullptr ; 71SLANG_VK_CHECK (api .vkMapMemory ( 72api .m_device , 73stagingBufferImpl -> m_buffer .m_memory , 740 , 75stagingBufferOffset + size , 760 , 77& mappedData )); 78memcpy ((char * )mappedData + stagingBufferOffset ,data ,size ); 79api .vkUnmapMemory (api .m_device ,stagingBufferImpl -> m_buffer .m_memory ); 80 81// Copy from staging buffer to real buffer 82VkBufferCopy copyInfo = {}; 83copyInfo .size = size ; 84copyInfo .dstOffset = offset ; 85copyInfo .srcOffset = stagingBufferOffset ; 86api .vkCmdCopyBuffer ( 87commandBuffer , 88stagingBufferImpl -> m_buffer .m_buffer , 89buffer -> m_buffer .m_buffer , 901 , 91& copyInfo ); 92} 93 94void PipelineCommandEncoder ::uploadBufferDataImpl ( 95IBufferResource * buffer , 96Offset offset , 97Size size , 98void * data ) 99{ 100m_vkPreCommandBuffer = m_commandBuffer -> getPreCommandBuffer (); 101_uploadBufferData ( 102m_vkPreCommandBuffer , 103m_commandBuffer -> m_transientHeap .get (), 104static_cast < BufferResourceImpl *> (buffer ), 105offset , 106size , 107data ); 108} 109 110Result PipelineCommandEncoder ::bindRootShaderObjectImpl ( 111RootShaderObjectImpl * rootShaderObject , 112VkPipelineBindPoint bindPoint ) 113{ 114// Obtain specialized root layout. 115auto specializedLayout = rootShaderObject -> getSpecializedLayout (); 116if (!specializedLayout ) 117return SLANG_FAIL ; 118 119// We will set up the context required when binding shader objects 120// to the pipeline. Note that this is mostly just being packaged 121// together to minimize the number of parameters that have to 122// be dealt with in the complex recursive call chains. 123// 124RootBindingContext context ; 125context .pipelineLayout = specializedLayout -> m_pipelineLayout ; 126context .device = m_device ; 127context .descriptorSetAllocator = & m_commandBuffer -> m_transientHeap -> m_descSetAllocator ; 128context .pushConstantRanges = specializedLayout -> getAllPushConstantRanges ().getArrayView (); 129 130// The context includes storage for the descriptor sets we will bind, 131// and the number of sets we need to make space for is determined 132// by the specialized program layout. 133// 134List < VkDescriptorSet > descriptorSetsStorage ; 135 136context .descriptorSets = & descriptorSetsStorage ; 137 138// We kick off recursive binding of shader objects to the pipeline (plus 139// the state in `context`). 140// 141// Note: this logic will directly write any push-constant ranges needed, 142// and will also fill in any descriptor sets. Currently it does not 143// *bind* the descriptor sets it fills in. 144// 145// TODO: It could probably bind the descriptor sets as well. 146// 147rootShaderObject -> bindAsRoot (this ,context ,specializedLayout ); 148 149// Once we've filled in all the descriptor sets, we bind them 150// to the pipeline at once. 151// 152if (descriptorSetsStorage .getCount ()> 0 ) 153 { 154m_device -> m_api .vkCmdBindDescriptorSets ( 155m_commandBuffer -> m_commandBuffer , 156bindPoint , 157specializedLayout -> m_pipelineLayout , 1580 , 159 (uint32_t )descriptorSetsStorage .getCount (), 160descriptorSetsStorage .getBuffer (), 1610 , 162nullptr ); 163 } 164 165return SLANG_OK ; 166} 167 168Result PipelineCommandEncoder ::setPipelineStateImpl ( 169IPipelineState * state , 170IShaderObject ** outRootObject ) 171{ 172m_currentPipeline = static_cast < PipelineStateImpl *> (state ); 173m_commandBuffer -> m_mutableRootShaderObject = nullptr ; 174SLANG_RETURN_ON_FAIL (m_commandBuffer -> m_rootObject .init ( 175m_commandBuffer -> m_renderer , 176m_currentPipeline -> getProgram < ShaderProgramImpl > ()-> m_rootObjectLayout )); 177* outRootObject = & m_commandBuffer -> m_rootObject ; 178return SLANG_OK ; 179} 180 181Result PipelineCommandEncoder ::setPipelineStateWithRootObjectImpl ( 182IPipelineState * state , 183IShaderObject * rootObject ) 184{ 185m_currentPipeline = static_cast < PipelineStateImpl *> (state ); 186m_commandBuffer -> m_mutableRootShaderObject = 187static_cast < MutableRootShaderObjectImpl *> (rootObject ); 188return SLANG_OK ; 189} 190 191Result PipelineCommandEncoder ::bindRenderState (VkPipelineBindPoint pipelineBindPoint ) 192{ 193auto & api = * m_api ; 194 195// Get specialized pipeline state and bind it. 196// 197RootShaderObjectImpl * rootObjectImpl = m_commandBuffer -> m_mutableRootShaderObject 198 ?m_commandBuffer -> m_mutableRootShaderObject .Ptr () 199 :& m_commandBuffer -> m_rootObject ; 200RefPtr < PipelineStateBase > newPipeline ; 201SLANG_RETURN_ON_FAIL ( 202m_device -> maybeSpecializePipeline (m_currentPipeline ,rootObjectImpl ,newPipeline )); 203PipelineStateImpl * newPipelineImpl = static_cast < PipelineStateImpl *> (newPipeline .Ptr ()); 204 205SLANG_RETURN_ON_FAIL (newPipelineImpl -> ensureAPIPipelineStateCreated ()); 206m_currentPipeline = newPipelineImpl ; 207 208bindRootShaderObjectImpl (rootObjectImpl ,pipelineBindPoint ); 209 210auto pipelineBindPointId = getBindPointIndex (pipelineBindPoint ); 211if (m_boundPipelines [pipelineBindPointId ]!= newPipelineImpl -> m_pipeline ) 212 { 213api .vkCmdBindPipeline (m_vkCommandBuffer ,pipelineBindPoint ,newPipelineImpl -> m_pipeline ); 214m_boundPipelines [pipelineBindPointId ]= newPipelineImpl -> m_pipeline ; 215 } 216 217return SLANG_OK ; 218} 219 220void ResourceCommandEncoder ::copyBuffer ( 221IBufferResource * dst , 222Offset dstOffset , 223IBufferResource * src , 224Offset srcOffset , 225Size size ) 226{ 227auto & vkAPI = m_commandBuffer -> m_renderer -> m_api ; 228 229auto dstBuffer = static_cast < BufferResourceImpl *> (dst ); 230auto srcBuffer = static_cast < BufferResourceImpl *> (src ); 231 232VkBufferCopy copyRegion ; 233copyRegion .dstOffset = dstOffset ; 234copyRegion .srcOffset = srcOffset ; 235copyRegion .size = size ; 236 237// Note: Vulkan puts the source buffer first in the copy 238// command, going against the dominant tradition for copy 239// operations in C/C++. 240// 241vkAPI .vkCmdCopyBuffer ( 242m_commandBuffer -> m_commandBuffer , 243srcBuffer -> m_buffer .m_buffer , 244dstBuffer -> m_buffer .m_buffer , 245/* regionCount: */ 1 , 246& copyRegion ); 247} 248 249void ResourceCommandEncoder ::uploadBufferData ( 250IBufferResource * buffer , 251Offset offset , 252Size size , 253void * data ) 254{ 255PipelineCommandEncoder ::_uploadBufferData ( 256m_commandBuffer -> m_commandBuffer , 257m_commandBuffer -> m_transientHeap .get (), 258static_cast < BufferResourceImpl *> (buffer ), 259offset , 260size , 261data ); 262} 263 264void ResourceCommandEncoder ::textureBarrier ( 265GfxCount count , 266ITextureResource * const * textures , 267ResourceState src , 268ResourceState dst ) 269{ 270ShortList < VkImageMemoryBarrier ,16 > barriers ; 271 272for (GfxIndex i = 0 ;i < count ;i ++ ) 273 { 274auto image = static_cast < TextureResourceImpl *> (textures [i ]); 275auto desc = image -> getDesc (); 276 277VkImageMemoryBarrier barrier = {}; 278barrier .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER ; 279barrier .image = image -> m_image ; 280barrier .oldLayout = translateImageLayout (src ); 281barrier .newLayout = translateImageLayout (dst ); 282barrier .subresourceRange .aspectMask = 283getAspectMaskFromFormat (VulkanUtil ::getVkFormat (desc -> format )); 284barrier .subresourceRange .baseArrayLayer = 0 ; 285barrier .subresourceRange .baseMipLevel = 0 ; 286barrier .subresourceRange .layerCount = VK_REMAINING_ARRAY_LAYERS ; 287barrier .subresourceRange .levelCount = VK_REMAINING_MIP_LEVELS ; 288barrier .srcAccessMask = calcAccessFlags (src ); 289barrier .dstAccessMask = calcAccessFlags (dst ); 290barriers .add (barrier ); 291 } 292 293VkPipelineStageFlagBits srcStage = calcPipelineStageFlags (src , true); 294VkPipelineStageFlagBits dstStage = calcPipelineStageFlags (dst , false); 295 296auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 297vkApi .vkCmdPipelineBarrier ( 298m_commandBuffer -> m_commandBuffer , 299srcStage , 300dstStage , 3010 , 3020 , 303nullptr , 3040 , 305nullptr , 306 (uint32_t )count , 307barriers .getArrayView ().getBuffer ()); 308} 309 310// TODO: Change size_t to Count? 311void ResourceCommandEncoder ::bufferBarrier ( 312GfxCount count , 313IBufferResource * const * buffers , 314ResourceState src , 315ResourceState dst ) 316{ 317List < VkBufferMemoryBarrier > barriers ; 318barriers .reserve (count ); 319 320for (GfxIndex i = 0 ;i < count ;i ++ ) 321 { 322auto bufferImpl = static_cast < BufferResourceImpl *> (buffers [i ]); 323 324VkBufferMemoryBarrier barrier = {}; 325barrier .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER ; 326barrier .srcAccessMask = calcAccessFlags (src ); 327barrier .dstAccessMask = calcAccessFlags (dst ); 328barrier .buffer = bufferImpl -> m_buffer .m_buffer ; 329barrier .offset = 0 ; 330barrier .size = bufferImpl -> getDesc ()-> sizeInBytes ; 331 332barriers .add (barrier ); 333 } 334 335VkPipelineStageFlagBits srcStage = calcPipelineStageFlags (src , true); 336VkPipelineStageFlagBits dstStage = calcPipelineStageFlags (dst , false); 337 338auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 339vkApi .vkCmdPipelineBarrier ( 340m_commandBuffer -> m_commandBuffer , 341srcStage , 342dstStage , 3430 , 3440 , 345nullptr , 346 (uint32_t )count , 347barriers .getBuffer (), 3480 , 349nullptr ); 350} 351 352void ResourceCommandEncoder ::endEncoding () 353{ 354// Insert memory barrier to ensure transfers are visible to the GPU. 355auto & vkAPI = m_commandBuffer -> m_renderer -> m_api ; 356 357VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER }; 358memBarrier .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT ; 359memBarrier .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT ; 360vkAPI .vkCmdPipelineBarrier ( 361m_commandBuffer -> m_commandBuffer , 362VK_PIPELINE_STAGE_TRANSFER_BIT , 363VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT , 3640 , 3651 , 366& memBarrier , 3670 , 368nullptr , 3690 , 370nullptr ); 371} 372 373void ResourceCommandEncoder ::writeTimestamp (IQueryPool * queryPool ,GfxIndex index ) 374{ 375_writeTimestamp ( 376& m_commandBuffer -> m_renderer -> m_api , 377m_commandBuffer -> m_commandBuffer , 378queryPool , 379index ); 380} 381 382void ResourceCommandEncoder ::copyTexture ( 383ITextureResource * dst , 384ResourceState dstState , 385SubresourceRange dstSubresource , 386ITextureResource ::Offset3D dstOffset , 387ITextureResource * src , 388ResourceState srcState , 389SubresourceRange srcSubresource , 390ITextureResource ::Offset3D srcOffset , 391ITextureResource ::Extents extent ) 392{ 393auto srcImage = static_cast < TextureResourceImpl *> (src ); 394auto srcDesc = srcImage -> getDesc (); 395auto srcImageLayout = VulkanUtil ::getImageLayoutFromState (srcState ); 396auto dstImage = static_cast < TextureResourceImpl *> (dst ); 397auto dstDesc = dstImage -> getDesc (); 398auto dstImageLayout = VulkanUtil ::getImageLayoutFromState (dstState ); 399if (dstSubresource .layerCount == 0 && dstSubresource .mipLevelCount == 0 ) 400 { 401extent = dstDesc -> size ; 402dstSubresource .layerCount = dstDesc -> arraySize ; 403if (dstSubresource .layerCount == 0 ) 404dstSubresource .layerCount = 1 ; 405dstSubresource .mipLevelCount = dstDesc -> numMipLevels ; 406 } 407if (srcSubresource .layerCount == 0 && srcSubresource .mipLevelCount == 0 ) 408 { 409extent = srcDesc -> size ; 410srcSubresource .layerCount = srcDesc -> arraySize ; 411if (srcSubresource .layerCount == 0 ) 412srcSubresource .layerCount = 1 ; 413srcSubresource .mipLevelCount = dstDesc -> numMipLevels ; 414 } 415VkImageCopy region = {}; 416region .srcSubresource .aspectMask = 417VulkanUtil ::getAspectMask (srcSubresource .aspectMask ,srcImage -> m_vkformat ); 418region .srcSubresource .baseArrayLayer = srcSubresource .baseArrayLayer ; 419region .srcSubresource .mipLevel = srcSubresource .mipLevel ; 420region .srcSubresource .layerCount = srcSubresource .layerCount ; 421region .srcOffset = {(int32_t )srcOffset .x , (int32_t )srcOffset .y , (int32_t )srcOffset .z }; 422region .dstSubresource .aspectMask = 423VulkanUtil ::getAspectMask (dstSubresource .aspectMask ,dstImage -> m_vkformat ); 424region .dstSubresource .baseArrayLayer = dstSubresource .baseArrayLayer ; 425region .dstSubresource .mipLevel = dstSubresource .mipLevel ; 426region .dstSubresource .layerCount = dstSubresource .layerCount ; 427region .dstOffset = {(int32_t )dstOffset .x , (int32_t )dstOffset .y , (int32_t )dstOffset .z }; 428region .extent = {(uint32_t )extent .width , (uint32_t )extent .height , (uint32_t )extent .depth }; 429 430auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 431vkApi .vkCmdCopyImage ( 432m_commandBuffer -> m_commandBuffer , 433srcImage -> m_image , 434srcImageLayout , 435dstImage -> m_image , 436dstImageLayout , 4371 , 438& region ); 439} 440 441void ResourceCommandEncoder ::uploadTextureData ( 442ITextureResource * dst , 443SubresourceRange subResourceRange , 444ITextureResource ::Offset3D offset , 445ITextureResource ::Extents extend , 446ITextureResource ::SubresourceData * subResourceData , 447GfxCount subResourceDataCount ) 448{ 449// VALIDATION: dst must be in TransferDst state. 450 451auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 452auto dstImpl = static_cast < TextureResourceImpl *> (dst ); 453List < TextureResource ::Extents > mipSizes ; 454 455VkCommandBuffer commandBuffer = m_commandBuffer -> m_commandBuffer ; 456auto & desc = * dstImpl -> getDesc (); 457// Calculate how large the buffer has to be 458Size bufferSize = 0 ; 459// Calculate how large an array entry is 460for (GfxIndex j = subResourceRange .mipLevel ; 461j < subResourceRange .mipLevel + subResourceRange .mipLevelCount ; 462++ j ) 463 { 464const TextureResource ::Extents mipSize = calcMipSize (desc .size ,j ); 465 466auto rowSizeInBytes = calcRowSize (desc .format ,mipSize .width ); 467auto numRows = calcNumRows (desc .format ,mipSize .height ); 468 469mipSizes .add (mipSize ); 470 471bufferSize += (rowSizeInBytes * numRows )* mipSize .depth ; 472 } 473 474// Calculate the total size taking into account the array 475bufferSize *=subResourceRange .layerCount ; 476 477IBufferResource * uploadBuffer = nullptr ; 478Offset uploadBufferOffset = 0 ; 479m_commandBuffer -> m_transientHeap 480-> allocateStagingBuffer (bufferSize ,uploadBuffer ,uploadBufferOffset ,MemoryType ::Upload ); 481 482// Copy into upload buffer 483 { 484int subResourceCounter = 0 ; 485 486uint8_t * dstData ; 487uploadBuffer -> map (nullptr , (void ** )& dstData ); 488dstData += uploadBufferOffset ; 489uint8_t * dstDataStart ; 490dstDataStart = dstData ; 491 492Offset dstSubresourceOffset = 0 ; 493for (GfxIndex i = 0 ;i < subResourceRange .layerCount ;++ i ) 494 { 495for (GfxIndex j = 0 ;j < (GfxCount )mipSizes .getCount ();++ j ) 496 { 497const auto & mipSize = mipSizes [j ]; 498 499int subResourceIndex = subResourceCounter ++ ; 500auto initSubresource = subResourceData [subResourceIndex ]; 501 502const ptrdiff_t srcRowStride = (ptrdiff_t )initSubresource .strideY ; 503const ptrdiff_t srcLayerStride = (ptrdiff_t )initSubresource .strideZ ; 504 505auto dstRowSizeInBytes = calcRowSize (desc .format ,mipSize .width ); 506auto numRows = calcNumRows (desc .format ,mipSize .height ); 507auto dstLayerSizeInBytes = dstRowSizeInBytes * numRows ; 508 509const uint8_t * srcLayer = (const uint8_t * )initSubresource .data ; 510uint8_t * dstLayer = dstData + dstSubresourceOffset ; 511 512for (int k = 0 ;k < mipSize .depth ;k ++ ) 513 { 514const uint8_t * srcRow = srcLayer ; 515uint8_t * dstRow = dstLayer ; 516 517for (GfxCount l = 0 ;l < numRows ;l ++ ) 518 { 519 ::memcpy (dstRow ,srcRow ,dstRowSizeInBytes ); 520 521dstRow += dstRowSizeInBytes ; 522srcRow += srcRowStride ; 523 } 524 525dstLayer += dstLayerSizeInBytes ; 526srcLayer += srcLayerStride ; 527 } 528 529dstSubresourceOffset += dstLayerSizeInBytes * mipSize .depth ; 530 } 531 } 532uploadBuffer -> unmap (nullptr ); 533 } 534 { 535Offset srcOffset = uploadBufferOffset ; 536for (GfxIndex i = 0 ;i < subResourceRange .layerCount ;++ i ) 537 { 538for (GfxIndex j = 0 ;j < (GfxCount )mipSizes .getCount ();++ j ) 539 { 540const auto & mipSize = mipSizes [j ]; 541 542auto rowSizeInBytes = calcRowSize (desc .format ,mipSize .width ); 543auto numRows = calcNumRows (desc .format ,mipSize .height ); 544 545// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkBufferImageCopy.html 546// bufferRowLength and bufferImageHeight specify the data in buffer 547// memory as a subregion of a larger two- or three-dimensional image, 548// and control the addressing calculations of data in buffer memory. If 549// either of these values is zero, that aspect of the buffer memory is 550// considered to be tightly packed according to the imageExtent. 551 552VkBufferImageCopy region = {}; 553 554region .bufferOffset = srcOffset ; 555region .bufferRowLength = 0 ;// rowSizeInBytes; 556region .bufferImageHeight = 0 ; 557 558region .imageSubresource .aspectMask = getAspectMaskFromFormat (dstImpl -> m_vkformat ); 559region .imageSubresource .mipLevel = subResourceRange .mipLevel + uint32_t (j ); 560region .imageSubresource .baseArrayLayer = subResourceRange .baseArrayLayer + i ; 561region .imageSubresource .layerCount = 1 ; 562region .imageOffset = {0 ,0 ,0 }; 563region .imageExtent = { 564uint32_t (mipSize .width ), 565uint32_t (mipSize .height ), 566uint32_t (mipSize .depth )}; 567 568// Do the copy (do all depths in a single go) 569vkApi .vkCmdCopyBufferToImage ( 570commandBuffer , 571static_cast < BufferResourceImpl *> (uploadBuffer )-> m_buffer .m_buffer , 572dstImpl -> m_image , 573VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 5741 , 575& region ); 576 577// Next 578srcOffset += rowSizeInBytes * numRows * mipSize .depth ; 579 } 580 } 581 } 582} 583 584void ResourceCommandEncoder ::_clearColorImage ( 585TextureResourceViewImpl * viewImpl , 586ClearValue * clearValue ) 587{ 588auto & api = m_commandBuffer -> m_renderer -> m_api ; 589auto layout = viewImpl -> m_layout ; 590if (layout != VK_IMAGE_LAYOUT_GENERAL && layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ) 591 { 592layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ; 593m_commandBuffer -> m_renderer -> _transitionImageLayout ( 594m_commandBuffer -> m_commandBuffer , 595viewImpl -> m_texture -> m_image , 596viewImpl -> m_texture -> m_vkformat , 597* viewImpl -> m_texture -> getDesc (), 598viewImpl -> m_layout , 599layout ); 600 } 601 602VkImageSubresourceRange subresourceRange = {}; 603subresourceRange .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ; 604subresourceRange .baseArrayLayer = viewImpl -> m_desc .subresourceRange .baseArrayLayer ; 605subresourceRange .baseMipLevel = viewImpl -> m_desc .subresourceRange .mipLevel ; 606subresourceRange .layerCount = viewImpl -> m_desc .subresourceRange .layerCount ; 607subresourceRange .levelCount = 1 ; 608 609VkClearColorValue vkClearColor = {}; 610memcpy (vkClearColor .float32 ,clearValue -> color .floatValues ,sizeof (float )* 4 ); 611 612api .vkCmdClearColorImage ( 613m_commandBuffer -> m_commandBuffer , 614viewImpl -> m_texture -> m_image , 615layout , 616& vkClearColor , 6171 , 618& subresourceRange ); 619 620if (layout != viewImpl -> m_layout ) 621 { 622m_commandBuffer -> m_renderer -> _transitionImageLayout ( 623m_commandBuffer -> m_commandBuffer , 624viewImpl -> m_texture -> m_image , 625viewImpl -> m_texture -> m_vkformat , 626* viewImpl -> m_texture -> getDesc (), 627layout , 628viewImpl -> m_layout ); 629 } 630} 631 632void ResourceCommandEncoder ::_clearDepthImage ( 633TextureResourceViewImpl * viewImpl , 634ClearValue * clearValue , 635ClearResourceViewFlags ::Enum flags ) 636{ 637auto & api = m_commandBuffer -> m_renderer -> m_api ; 638auto layout = viewImpl -> m_layout ; 639if (layout != VK_IMAGE_LAYOUT_GENERAL && layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ) 640 { 641layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ; 642m_commandBuffer -> m_renderer -> _transitionImageLayout ( 643m_commandBuffer -> m_commandBuffer , 644viewImpl -> m_texture -> m_image , 645viewImpl -> m_texture -> m_vkformat , 646* viewImpl -> m_texture -> getDesc (), 647viewImpl -> m_layout , 648layout ); 649 } 650 651VkImageSubresourceRange subresourceRange = {}; 652if (flags & ClearResourceViewFlags ::ClearDepth ) 653 { 654if (VulkanUtil ::isDepthFormat (viewImpl -> m_texture -> m_vkformat )) 655 { 656subresourceRange .aspectMask |=VK_IMAGE_ASPECT_DEPTH_BIT ; 657 } 658 } 659if (flags & ClearResourceViewFlags ::ClearStencil ) 660 { 661if (VulkanUtil ::isStencilFormat (viewImpl -> m_texture -> m_vkformat )) 662 { 663subresourceRange .aspectMask |=VK_IMAGE_ASPECT_STENCIL_BIT ; 664 } 665 } 666subresourceRange .baseArrayLayer = viewImpl -> m_desc .subresourceRange .baseArrayLayer ; 667subresourceRange .baseMipLevel = viewImpl -> m_desc .subresourceRange .mipLevel ; 668subresourceRange .layerCount = viewImpl -> m_desc .subresourceRange .layerCount ; 669subresourceRange .levelCount = 1 ; 670 671VkClearDepthStencilValue vkClearValue = {}; 672vkClearValue .depth = clearValue -> depthStencil .depth ; 673vkClearValue .stencil = clearValue -> depthStencil .stencil ; 674 675api .vkCmdClearDepthStencilImage ( 676m_commandBuffer -> m_commandBuffer , 677viewImpl -> m_texture -> m_image , 678layout , 679& vkClearValue , 6801 , 681& subresourceRange ); 682 683if (layout != viewImpl -> m_layout ) 684 { 685m_commandBuffer -> m_renderer -> _transitionImageLayout ( 686m_commandBuffer -> m_commandBuffer , 687viewImpl -> m_texture -> m_image , 688viewImpl -> m_texture -> m_vkformat , 689* viewImpl -> m_texture -> getDesc (), 690layout , 691viewImpl -> m_layout ); 692 } 693} 694 695void ResourceCommandEncoder ::_clearBuffer ( 696VkBuffer buffer , 697uint64_t bufferSize , 698const IResourceView ::Desc & desc , 699uint32_t clearValue ) 700{ 701auto & api = m_commandBuffer -> m_renderer -> m_api ; 702auto clearOffset = desc .bufferRange .offset ; 703auto clearSize = desc .bufferRange .size == 0 ?bufferSize - clearOffset :desc .bufferRange .size ; 704api .vkCmdFillBuffer ( 705m_commandBuffer -> m_commandBuffer , 706buffer , 707clearOffset , 708clearSize , 709clearValue ); 710} 711 712void ResourceCommandEncoder ::clearResourceView ( 713IResourceView * view , 714ClearValue * clearValue , 715ClearResourceViewFlags ::Enum flags ) 716{ 717auto & api = m_commandBuffer -> m_renderer -> m_api ; 718switch (view -> getViewDesc ()-> type ) 719 { 720case IResourceView ::Type ::RenderTarget : 721 { 722auto viewImpl = static_cast < TextureResourceViewImpl *> (view ); 723_clearColorImage (viewImpl ,clearValue ); 724 } 725break ; 726case IResourceView ::Type ::DepthStencil : 727 { 728auto viewImpl = static_cast < TextureResourceViewImpl *> (view ); 729_clearDepthImage (viewImpl ,clearValue ,flags ); 730 } 731break ; 732case IResourceView ::Type ::UnorderedAccess : 733 { 734auto viewImplBase = static_cast < ResourceViewImpl *> (view ); 735switch (viewImplBase -> m_type ) 736 { 737case ResourceViewImpl ::ViewType ::Texture : 738 { 739auto viewImpl = static_cast < TextureResourceViewImpl *> (viewImplBase ); 740if ((flags & ClearResourceViewFlags ::ClearDepth )|| 741 (flags & ClearResourceViewFlags ::ClearStencil )) 742 { 743_clearDepthImage (viewImpl ,clearValue ,flags ); 744 } 745else 746 { 747_clearColorImage (viewImpl ,clearValue ); 748 } 749 } 750break ; 751case ResourceViewImpl ::ViewType ::PlainBuffer : 752 { 753assert ( 754clearValue -> color .uintValues [1 ]== clearValue -> color .uintValues [0 ]&& 755clearValue -> color .uintValues [2 ]== clearValue -> color .uintValues [0 ]&& 756clearValue -> color .uintValues [3 ]== clearValue -> color .uintValues [0 ]); 757auto viewImpl = static_cast < PlainBufferResourceViewImpl *> (viewImplBase ); 758uint64_t clearStart = viewImpl -> m_desc .bufferRange .offset ; 759uint64_t clearSize = viewImpl -> m_desc .bufferRange .size ; 760if (clearSize == 0 ) 761clearSize = viewImpl -> m_buffer -> getDesc ()-> sizeInBytes - clearStart ; 762api .vkCmdFillBuffer ( 763m_commandBuffer -> m_commandBuffer , 764viewImpl -> m_buffer -> m_buffer .m_buffer , 765clearStart , 766clearSize , 767clearValue -> color .uintValues [0 ]); 768 } 769break ; 770case ResourceViewImpl ::ViewType ::TexelBuffer : 771 { 772assert ( 773clearValue -> color .uintValues [1 ]== clearValue -> color .uintValues [0 ]&& 774clearValue -> color .uintValues [2 ]== clearValue -> color .uintValues [0 ]&& 775clearValue -> color .uintValues [3 ]== clearValue -> color .uintValues [0 ]); 776auto viewImpl = static_cast < TexelBufferResourceViewImpl *> (viewImplBase ); 777_clearBuffer ( 778viewImpl -> m_buffer -> m_buffer .m_buffer , 779viewImpl -> m_buffer -> getDesc ()-> sizeInBytes , 780viewImpl -> m_desc , 781clearValue -> color .uintValues [0 ]); 782 } 783break ; 784 } 785 } 786break ; 787 } 788} 789 790void ResourceCommandEncoder ::resolveResource ( 791ITextureResource * source , 792ResourceState sourceState , 793SubresourceRange sourceRange , 794ITextureResource * dest , 795ResourceState destState , 796SubresourceRange destRange ) 797{ 798auto srcTexture = static_cast < TextureResourceImpl *> (source ); 799auto srcExtent = srcTexture -> getDesc ()-> size ; 800auto dstTexture = static_cast < TextureResourceImpl *> (dest ); 801 802auto srcImage = srcTexture -> m_image ; 803auto dstImage = dstTexture -> m_image ; 804 805auto srcImageLayout = VulkanUtil ::getImageLayoutFromState (sourceState ); 806auto dstImageLayout = VulkanUtil ::getImageLayoutFromState (destState ); 807 808for (GfxIndex layer = 0 ;layer < sourceRange .layerCount ;++ layer ) 809 { 810for (GfxIndex mip = 0 ;mip < sourceRange .mipLevelCount ;++ mip ) 811 { 812VkImageResolve region = {}; 813region .srcSubresource .aspectMask = 814VulkanUtil ::getAspectMask (sourceRange .aspectMask ,srcTexture -> m_vkformat ); 815region .srcSubresource .baseArrayLayer = layer + sourceRange .baseArrayLayer ; 816region .srcSubresource .layerCount = 1 ; 817region .srcSubresource .mipLevel = mip + sourceRange .mipLevel ; 818region .srcOffset = {0 ,0 ,0 }; 819region .dstSubresource .aspectMask = 820VulkanUtil ::getAspectMask (destRange .aspectMask ,dstTexture -> m_vkformat ); 821region .dstSubresource .baseArrayLayer = layer + destRange .baseArrayLayer ; 822region .dstSubresource .layerCount = 1 ; 823region .dstSubresource .mipLevel = mip + destRange .mipLevel ; 824region .dstOffset = {0 ,0 ,0 }; 825region .extent = { 826 (uint32_t )srcExtent .width , 827 (uint32_t )srcExtent .height , 828 (uint32_t )srcExtent .depth }; 829 830auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 831vkApi .vkCmdResolveImage ( 832m_commandBuffer -> m_commandBuffer , 833srcImage , 834srcImageLayout , 835dstImage , 836dstImageLayout , 8371 , 838& region ); 839 } 840 } 841} 842 843void ResourceCommandEncoder ::resolveQuery ( 844IQueryPool * queryPool , 845GfxIndex index , 846GfxCount count , 847IBufferResource * buffer , 848Offset offset ) 849{ 850auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 851auto poolImpl = static_cast < QueryPoolImpl *> (queryPool ); 852auto bufferImpl = static_cast < BufferResourceImpl *> (buffer ); 853vkApi .vkCmdCopyQueryPoolResults ( 854m_commandBuffer -> m_commandBuffer , 855poolImpl -> m_pool , 856index , 857count , 858bufferImpl -> m_buffer .m_buffer , 859offset , 860sizeof (uint64_t ), 861VK_QUERY_RESULT_64_BIT |VK_QUERY_RESULT_WAIT_BIT ); 862} 863 864void ResourceCommandEncoder ::copyTextureToBuffer ( 865IBufferResource * dst , 866Offset dstOffset , 867Size dstSize , 868Size dstRowStride , 869ITextureResource * src , 870ResourceState srcState , 871SubresourceRange srcSubresource , 872ITextureResource ::Offset3D srcOffset , 873ITextureResource ::Extents extent ) 874{ 875assert (srcSubresource .mipLevelCount <=1 ); 876 877auto image = static_cast < TextureResourceImpl *> (src ); 878auto desc = image -> getDesc (); 879auto buffer = static_cast < BufferResourceImpl *> (dst ); 880auto srcImageLayout = VulkanUtil ::getImageLayoutFromState (srcState ); 881 882VkBufferImageCopy region = {}; 883region .bufferOffset = dstOffset ; 884region .bufferRowLength = 0 ; 885region .bufferImageHeight = 0 ; 886region .imageSubresource .aspectMask = 887VulkanUtil ::getAspectMask (srcSubresource .aspectMask ,image -> m_vkformat ); 888region .imageSubresource .mipLevel = srcSubresource .mipLevel ; 889region .imageSubresource .baseArrayLayer = srcSubresource .baseArrayLayer ; 890region .imageSubresource .layerCount = srcSubresource .layerCount ; 891region .imageOffset = {(int32_t )srcOffset .x , (int32_t )srcOffset .y , (int32_t )srcOffset .z }; 892region .imageExtent = {uint32_t (extent .width ),uint32_t (extent .height ),uint32_t (extent .depth )}; 893 894auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 895vkApi .vkCmdCopyImageToBuffer ( 896m_commandBuffer -> m_commandBuffer , 897image -> m_image , 898srcImageLayout , 899buffer -> m_buffer .m_buffer , 9001 , 901& region ); 902} 903 904void ResourceCommandEncoder ::textureSubresourceBarrier ( 905ITextureResource * texture , 906SubresourceRange subresourceRange , 907ResourceState src , 908ResourceState dst ) 909{ 910ShortList < VkImageMemoryBarrier > barriers ; 911auto image = static_cast < TextureResourceImpl *> (texture ); 912auto desc = image -> getDesc (); 913 914VkImageMemoryBarrier barrier = {}; 915barrier .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER ; 916barrier .image = image -> m_image ; 917barrier .oldLayout = translateImageLayout (src ); 918barrier .newLayout = translateImageLayout (dst ); 919barrier .subresourceRange .aspectMask = 920VulkanUtil ::getAspectMask (subresourceRange .aspectMask ,image -> m_vkformat ); 921barrier .subresourceRange .baseArrayLayer = subresourceRange .baseArrayLayer ; 922barrier .subresourceRange .baseMipLevel = subresourceRange .mipLevel ; 923barrier .subresourceRange .layerCount = subresourceRange .layerCount ; 924barrier .subresourceRange .levelCount = subresourceRange .mipLevelCount ; 925barrier .srcAccessMask = calcAccessFlags (src ); 926barrier .dstAccessMask = calcAccessFlags (dst ); 927barriers .add (barrier ); 928 929VkPipelineStageFlagBits srcStage = calcPipelineStageFlags (src , true); 930VkPipelineStageFlagBits dstStage = calcPipelineStageFlags (dst , false); 931 932auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 933vkApi .vkCmdPipelineBarrier ( 934m_commandBuffer -> m_commandBuffer , 935srcStage , 936dstStage , 9370 , 9380 , 939nullptr , 9400 , 941nullptr , 942 (uint32_t )barriers .getCount (), 943barriers .getArrayView ().getBuffer ()); 944} 945 946void ResourceCommandEncoder ::beginDebugEvent (const char * name ,float rgbColor [3 ]) 947{ 948auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 949if (vkApi .vkCmdDebugMarkerBeginEXT ) 950 { 951VkDebugMarkerMarkerInfoEXT eventInfo = {}; 952eventInfo .sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT ; 953eventInfo .pMarkerName = name ; 954eventInfo .color [0 ]= rgbColor [0 ]; 955eventInfo .color [1 ]= rgbColor [1 ]; 956eventInfo .color [2 ]= rgbColor [2 ]; 957eventInfo .color [3 ]= 1.0f ; 958vkApi .vkCmdDebugMarkerBeginEXT (m_commandBuffer -> m_commandBuffer ,& eventInfo ); 959 } 960} 961 962void ResourceCommandEncoder ::endDebugEvent () 963{ 964auto & vkApi = m_commandBuffer -> m_renderer -> m_api ; 965if (vkApi .vkCmdDebugMarkerEndEXT ) 966 { 967vkApi .vkCmdDebugMarkerEndEXT (m_commandBuffer -> m_commandBuffer ); 968 } 969} 970 971void RenderCommandEncoder ::beginPass (IRenderPassLayout * renderPass ,IFramebuffer * framebuffer ) 972{ 973FramebufferImpl * framebufferImpl = static_cast < FramebufferImpl *> (framebuffer ); 974if (!framebuffer ) 975framebufferImpl = this -> m_device -> m_emptyFramebuffer ; 976RenderPassLayoutImpl * renderPassImpl = static_cast < RenderPassLayoutImpl *> (renderPass ); 977VkClearValue clearValues [kMaxTargets ]= {}; 978VkRenderPassBeginInfo beginInfo = {}; 979beginInfo .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO ; 980beginInfo .framebuffer = framebufferImpl -> m_handle ; 981beginInfo .renderPass = renderPassImpl -> m_renderPass ; 982uint32_t targetCount = (uint32_t )framebufferImpl -> renderTargetViews .getCount (); 983if (framebufferImpl -> depthStencilView ) 984targetCount ++ ; 985beginInfo .clearValueCount = targetCount ; 986beginInfo .renderArea .extent .width = framebufferImpl -> m_width ; 987beginInfo .renderArea .extent .height = framebufferImpl -> m_height ; 988beginInfo .pClearValues = framebufferImpl -> m_clearValues ; 989auto & api = * m_api ; 990api .vkCmdBeginRenderPass (m_vkCommandBuffer ,& beginInfo ,VK_SUBPASS_CONTENTS_INLINE ); 991} 992 993void RenderCommandEncoder ::endEncoding () 994{ 995auto & api = * m_api ; 996api .vkCmdEndRenderPass (m_vkCommandBuffer ); 997endEncodingImpl (); 998} 999 1000Result RenderCommandEncoder ::bindPipeline ( 1001IPipelineState * pipelineState , 1002IShaderObject ** outRootObject ) 1003{ 1004return setPipelineStateImpl (pipelineState ,outRootObject ); 1005} 1006 1007Result RenderCommandEncoder ::bindPipelineWithRootObject ( 1008IPipelineState * pipelineState , 1009IShaderObject * rootObject ) 1010{ 1011return setPipelineStateWithRootObjectImpl (pipelineState ,rootObject ); 1012} 1013 1014void RenderCommandEncoder ::setViewports (GfxCount count ,const Viewport * viewports ) 1015{ 1016static const int kMaxViewports = 8 ;// TODO: base on device caps 1017assert (count <=kMaxViewports ); 1018 1019m_viewports .setCount (count ); 1020for (GfxIndex ii = 0 ;ii < count ;++ ii ) 1021 { 1022auto & inViewport = viewports [ii ]; 1023auto & vkViewport = m_viewports [ii ]; 1024 1025vkViewport .x = inViewport .originX ; 1026vkViewport .y = inViewport .originY + inViewport .extentY ; 1027vkViewport .width = inViewport .extentX ; 1028vkViewport .height = - inViewport .extentY ; 1029vkViewport .minDepth = inViewport .minZ ; 1030vkViewport .maxDepth = inViewport .maxZ ; 1031 } 1032 1033auto & api = * m_api ; 1034api .vkCmdSetViewport (m_vkCommandBuffer ,0 ,uint32_t (count ),m_viewports .getBuffer ()); 1035} 1036 1037void RenderCommandEncoder ::setScissorRects (GfxCount count ,const ScissorRect * rects ) 1038{ 1039static const int kMaxScissorRects = 8 ;// TODO: base on device caps 1040assert (count <=kMaxScissorRects ); 1041 1042m_scissorRects .setCount (count ); 1043for (GfxIndex ii = 0 ;ii < count ;++ ii ) 1044 { 1045auto & inRect = rects [ii ]; 1046auto & vkRect = m_scissorRects [ii ]; 1047 1048vkRect .offset .x = int32_t (inRect .minX ); 1049vkRect .offset .y = int32_t (inRect .minY ); 1050vkRect .extent .width = uint32_t (inRect .maxX - inRect .minX ); 1051vkRect .extent .height = uint32_t (inRect .maxY - inRect .minY ); 1052 } 1053 1054auto & api = * m_api ; 1055api .vkCmdSetScissor (m_vkCommandBuffer ,0 ,uint32_t (count ),m_scissorRects .getBuffer ()); 1056} 1057 1058void RenderCommandEncoder ::setPrimitiveTopology (PrimitiveTopology topology ) 1059{ 1060auto & api = * m_api ; 1061if (api .vkCmdSetPrimitiveTopologyEXT ) 1062 { 1063api .vkCmdSetPrimitiveTopologyEXT ( 1064m_vkCommandBuffer , 1065VulkanUtil ::getVkPrimitiveTopology (topology )); 1066 } 1067else 1068 { 1069switch (topology ) 1070 { 1071case PrimitiveTopology ::TriangleList : 1072break ; 1073default : 1074// We are using a non-list topology, but we don't have dynmaic state 1075// extension, error out. 1076assert (!"Non-list topology requires VK_EXT_extended_dynamic_states, which " 1077"is not present." ); 1078break ; 1079 } 1080 } 1081} 1082 1083void RenderCommandEncoder ::setVertexBuffers ( 1084GfxIndex startSlot , 1085GfxCount slotCount , 1086IBufferResource * const * buffers , 1087const Offset * offsets ) 1088{ 1089for (GfxIndex i = 0 ;i < GfxIndex (slotCount );i ++ ) 1090 { 1091GfxIndex slotIndex = startSlot + i ; 1092BufferResourceImpl * buffer = static_cast < BufferResourceImpl *> (buffers [i ]); 1093if (buffer ) 1094 { 1095VkBuffer vertexBuffers []= {buffer -> m_buffer .m_buffer }; 1096VkDeviceSize offset = VkDeviceSize (offsets [i ]); 1097 1098m_api -> vkCmdBindVertexBuffers ( 1099m_vkCommandBuffer , 1100 (uint32_t )slotIndex , 11011 , 1102vertexBuffers , 1103& offset ); 1104 } 1105 } 1106} 1107 1108void RenderCommandEncoder ::setIndexBuffer ( 1109IBufferResource * buffer , 1110Format indexFormat , 1111Offset offset ) 1112{ 1113VkIndexType indexType = VK_INDEX_TYPE_UINT16 ; 1114switch (indexFormat ) 1115 { 1116case Format ::R16_UINT : 1117indexType = VK_INDEX_TYPE_UINT16 ; 1118break ; 1119case Format ::R32_UINT : 1120indexType = VK_INDEX_TYPE_UINT32 ; 1121break ; 1122default : 1123assert (!"unsupported index format" ); 1124 } 1125 1126BufferResourceImpl * bufferImpl = static_cast < BufferResourceImpl *> (buffer ); 1127 1128m_api -> vkCmdBindIndexBuffer ( 1129m_vkCommandBuffer , 1130bufferImpl -> m_buffer .m_buffer , 1131 (VkDeviceSize )offset , 1132indexType ); 1133} 1134 1135Result RenderCommandEncoder ::prepareDraw () 1136{ 1137auto pipeline = static_cast < PipelineStateImpl *> (m_currentPipeline .Ptr ()); 1138if (!pipeline ) 1139 { 1140return SLANG_FAIL ; 1141 } 1142SLANG_RETURN_ON_FAIL (bindRenderState (VK_PIPELINE_BIND_POINT_GRAPHICS )); 1143return SLANG_OK ; 1144} 1145 1146Result RenderCommandEncoder ::draw (GfxCount vertexCount ,GfxIndex startVertex ) 1147{ 1148SLANG_RETURN_ON_FAIL (prepareDraw ()); 1149auto & api = * m_api ; 1150api .vkCmdDraw (m_vkCommandBuffer ,vertexCount ,1 ,0 ,0 ); 1151return SLANG_OK ; 1152} 1153 1154Result RenderCommandEncoder ::drawIndexed ( 1155GfxCount indexCount , 1156GfxIndex startIndex , 1157GfxIndex baseVertex ) 1158{ 1159SLANG_RETURN_ON_FAIL (prepareDraw ()); 1160auto & api = * m_api ; 1161api .vkCmdDrawIndexed (m_vkCommandBuffer ,indexCount ,1 ,startIndex ,baseVertex ,0 ); 1162return SLANG_OK ; 1163} 1164 1165void RenderCommandEncoder ::setStencilReference (uint32_t referenceValue ) 1166{ 1167auto & api = * m_api ; 1168api .vkCmdSetStencilReference (m_vkCommandBuffer ,VK_STENCIL_FRONT_AND_BACK ,referenceValue ); 1169} 1170 1171Result RenderCommandEncoder ::drawIndirect ( 1172GfxCount maxDrawCount , 1173IBufferResource * argBuffer , 1174Offset argOffset , 1175IBufferResource * countBuffer , 1176Offset countOffset ) 1177{ 1178SLANG_RETURN_ON_FAIL (prepareDraw ()); 1179auto & api = * m_api ; 1180auto argBufferImpl = static_cast < BufferResourceImpl *> (argBuffer ); 1181 1182if (countBuffer ) 1183 { 1184auto countBufferImpl = static_cast < BufferResourceImpl *> (countBuffer ); 1185api .vkCmdDrawIndirectCount ( 1186m_vkCommandBuffer , 1187argBufferImpl -> m_buffer .m_buffer , 1188argOffset , 1189countBufferImpl -> m_buffer .m_buffer , 1190countOffset , 1191maxDrawCount , 1192sizeof (VkDrawIndirectCommand )); 1193 } 1194else 1195 { 1196api .vkCmdDrawIndirect ( 1197m_vkCommandBuffer , 1198argBufferImpl -> m_buffer .m_buffer , 1199argOffset , 1200maxDrawCount , 1201sizeof (VkDrawIndirectCommand )); 1202 } 1203return SLANG_OK ; 1204} 1205 1206Result RenderCommandEncoder ::drawIndexedIndirect ( 1207GfxCount maxDrawCount , 1208IBufferResource * argBuffer , 1209Offset argOffset , 1210IBufferResource * countBuffer , 1211Offset countOffset ) 1212{ 1213SLANG_RETURN_ON_FAIL (prepareDraw ()); 1214auto & api = * m_api ; 1215auto argBufferImpl = static_cast < BufferResourceImpl *> (argBuffer ); 1216 1217if (countBuffer ) 1218 { 1219auto countBufferImpl = static_cast < BufferResourceImpl *> (countBuffer ); 1220api .vkCmdDrawIndexedIndirectCount ( 1221m_vkCommandBuffer , 1222argBufferImpl -> m_buffer .m_buffer , 1223argOffset , 1224countBufferImpl -> m_buffer .m_buffer , 1225countOffset , 1226maxDrawCount , 1227sizeof (VkDrawIndexedIndirectCommand )); 1228 } 1229else 1230 { 1231api .vkCmdDrawIndexedIndirect ( 1232m_vkCommandBuffer , 1233argBufferImpl -> m_buffer .m_buffer , 1234argOffset , 1235maxDrawCount , 1236sizeof (VkDrawIndexedIndirectCommand )); 1237 } 1238return SLANG_OK ; 1239} 1240 1241Result RenderCommandEncoder ::setSamplePositions ( 1242GfxCount samplesPerPixel , 1243GfxCount pixelCount , 1244const SamplePosition * samplePositions ) 1245{ 1246if (m_api -> vkCmdSetSampleLocationsEXT ) 1247 { 1248VkSampleLocationsInfoEXT sampleLocInfo = {}; 1249sampleLocInfo .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT ; 1250sampleLocInfo .sampleLocationsCount = samplesPerPixel * pixelCount ; 1251sampleLocInfo .sampleLocationsPerPixel = (VkSampleCountFlagBits )samplesPerPixel ; 1252m_api -> vkCmdSetSampleLocationsEXT (m_vkCommandBuffer ,& sampleLocInfo ); 1253return SLANG_OK ; 1254 } 1255return SLANG_E_NOT_AVAILABLE ; 1256} 1257 1258Result RenderCommandEncoder ::drawInstanced ( 1259GfxCount vertexCount , 1260GfxCount instanceCount , 1261GfxIndex startVertex , 1262GfxIndex startInstanceLocation ) 1263{ 1264SLANG_RETURN_ON_FAIL (prepareDraw ()); 1265auto & api = * m_api ; 1266api .vkCmdDraw ( 1267m_vkCommandBuffer , 1268vertexCount , 1269instanceCount , 1270startVertex , 1271startInstanceLocation ); 1272return SLANG_OK ; 1273} 1274 1275Result RenderCommandEncoder ::drawIndexedInstanced ( 1276GfxCount indexCount , 1277GfxCount instanceCount , 1278GfxIndex startIndexLocation , 1279GfxIndex baseVertexLocation , 1280GfxIndex startInstanceLocation ) 1281{ 1282SLANG_RETURN_ON_FAIL (prepareDraw ()); 1283auto & api = * m_api ; 1284api .vkCmdDrawIndexed ( 1285m_vkCommandBuffer , 1286indexCount , 1287instanceCount , 1288startIndexLocation , 1289baseVertexLocation , 1290startInstanceLocation ); 1291return SLANG_OK ; 1292} 1293 1294Result RenderCommandEncoder ::drawMeshTasks (int x ,int y ,int z ) 1295{ 1296SLANG_RETURN_ON_FAIL (prepareDraw ()); 1297auto & api = * m_api ; 1298api .vkCmdDrawMeshTasksEXT (m_vkCommandBuffer ,x ,y ,z ); 1299return SLANG_OK ; 1300} 1301 1302void ComputeCommandEncoder ::endEncoding () 1303{ 1304endEncodingImpl (); 1305} 1306 1307Result ComputeCommandEncoder ::bindPipeline ( 1308IPipelineState * pipelineState , 1309IShaderObject ** outRootObject ) 1310{ 1311return setPipelineStateImpl (pipelineState ,outRootObject ); 1312} 1313 1314Result ComputeCommandEncoder ::bindPipelineWithRootObject ( 1315IPipelineState * pipelineState , 1316IShaderObject * rootObject ) 1317{ 1318return setPipelineStateWithRootObjectImpl (pipelineState ,rootObject ); 1319} 1320 1321Result ComputeCommandEncoder ::dispatchCompute (int x ,int y ,int z ) 1322{ 1323auto pipeline = static_cast < PipelineStateImpl *> (m_currentPipeline .Ptr ()); 1324if (!pipeline ) 1325 { 1326return SLANG_FAIL ; 1327 } 1328 1329// Also create descriptor sets based on the given pipeline layout 1330SLANG_RETURN_ON_FAIL (bindRenderState (VK_PIPELINE_BIND_POINT_COMPUTE )); 1331m_api -> vkCmdDispatch (m_vkCommandBuffer ,x ,y ,z ); 1332return SLANG_OK ; 1333} 1334 1335Result ComputeCommandEncoder ::dispatchComputeIndirect (IBufferResource * argBuffer ,Offset offset ) 1336{ 1337auto pipeline = static_cast < PipelineStateImpl *> (m_currentPipeline .Ptr ()); 1338if (!pipeline ) 1339 { 1340return SLANG_FAIL ; 1341 } 1342 1343// Also create descriptor sets based on the given pipeline layout 1344SLANG_RETURN_ON_FAIL (bindRenderState (VK_PIPELINE_BIND_POINT_COMPUTE )); 1345auto argBufferImpl = static_cast < BufferResourceImpl *> (argBuffer ); 1346m_api -> vkCmdDispatchIndirect (m_vkCommandBuffer ,argBufferImpl -> m_buffer .m_buffer ,offset ); 1347return SLANG_OK ; 1348} 1349 1350void RayTracingCommandEncoder ::_memoryBarrier ( 1351int count , 1352IAccelerationStructure * const * structures , 1353AccessFlag srcAccess , 1354AccessFlag destAccess ) 1355{ 1356ShortList < VkBufferMemoryBarrier > memBarriers ; 1357memBarriers .setCount (count ); 1358for (int i = 0 ;i < count ;i ++ ) 1359 { 1360memBarriers [i ].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER ; 1361memBarriers [i ].pNext = nullptr ; 1362memBarriers [i ].dstAccessMask = translateAccelerationStructureAccessFlag (destAccess ); 1363memBarriers [i ].srcAccessMask = translateAccelerationStructureAccessFlag (srcAccess ); 1364memBarriers [i ].srcQueueFamilyIndex = m_commandBuffer -> m_renderer -> m_queueFamilyIndex ; 1365memBarriers [i ].dstQueueFamilyIndex = m_commandBuffer -> m_renderer -> m_queueFamilyIndex ; 1366 1367auto asImpl = static_cast < AccelerationStructureImpl *> (structures [i ]); 1368memBarriers [i ].buffer = asImpl -> m_buffer -> m_buffer .m_buffer ; 1369memBarriers [i ].offset = asImpl -> m_offset ; 1370memBarriers [i ].size = asImpl -> m_size ; 1371 } 1372m_commandBuffer -> m_renderer -> m_api .vkCmdPipelineBarrier ( 1373m_commandBuffer -> m_commandBuffer , 1374VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | 1375VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT , 1376VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR |VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | 1377VK_PIPELINE_STAGE_TRANSFER_BIT |VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | 1378VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | 1379VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR , 13800 , 13810 , 1382nullptr , 1383 (uint32_t )memBarriers .getCount (), 1384memBarriers .getArrayView ().getBuffer (), 13850 , 1386nullptr ); 1387} 1388 1389void RayTracingCommandEncoder ::_queryAccelerationStructureProperties ( 1390GfxCount accelerationStructureCount , 1391IAccelerationStructure * const * accelerationStructures , 1392GfxCount queryCount , 1393AccelerationStructureQueryDesc * queryDescs ) 1394{ 1395ShortList < VkAccelerationStructureKHR > vkHandles ; 1396vkHandles .setCount (accelerationStructureCount ); 1397for (GfxIndex i = 0 ;i < accelerationStructureCount ;i ++ ) 1398 { 1399vkHandles [i ]= 1400static_cast < AccelerationStructureImpl *> (accelerationStructures [i ])-> m_vkHandle ; 1401 } 1402auto vkHandlesView = vkHandles .getArrayView (); 1403for (GfxIndex i = 0 ;i < queryCount ;i ++ ) 1404 { 1405VkQueryType queryType ; 1406switch (queryDescs [i ].queryType ) 1407 { 1408case QueryType ::AccelerationStructureCompactedSize : 1409queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR ; 1410break ; 1411case QueryType ::AccelerationStructureSerializedSize : 1412queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR ; 1413break ; 1414case QueryType ::AccelerationStructureCurrentSize : 1415continue ; 1416default : 1417getDebugCallback ()-> handleMessage ( 1418DebugMessageType ::Error , 1419DebugMessageSource ::Layer , 1420"Invalid query type for use in queryAccelerationStructureProperties." ); 1421return ; 1422 } 1423auto queryPool = static_cast < QueryPoolImpl *> (queryDescs [i ].queryPool )-> m_pool ; 1424m_commandBuffer -> m_renderer -> m_api .vkCmdResetQueryPool ( 1425m_commandBuffer -> m_commandBuffer , 1426queryPool , 1427 (uint32_t )queryDescs [i ].firstQueryIndex , 14281 ); 1429m_commandBuffer -> m_renderer -> m_api .vkCmdWriteAccelerationStructuresPropertiesKHR ( 1430m_commandBuffer -> m_commandBuffer , 1431accelerationStructureCount , 1432vkHandlesView .getBuffer (), 1433queryType , 1434queryPool , 1435queryDescs [i ].firstQueryIndex ); 1436 } 1437} 1438 1439void RayTracingCommandEncoder ::buildAccelerationStructure ( 1440const IAccelerationStructure ::BuildDesc & desc , 1441GfxCount propertyQueryCount , 1442AccelerationStructureQueryDesc * queryDescs ) 1443{ 1444AccelerationStructureBuildGeometryInfoBuilder geomInfoBuilder ; 1445if (geomInfoBuilder .build (desc .inputs ,getDebugCallback ())!= SLANG_OK ) 1446return ; 1447 1448if (desc .dest ) 1449 { 1450geomInfoBuilder .buildInfo .dstAccelerationStructure = 1451static_cast < AccelerationStructureImpl *> (desc .dest )-> m_vkHandle ; 1452 } 1453if (desc .source ) 1454 { 1455geomInfoBuilder .buildInfo .srcAccelerationStructure = 1456static_cast < AccelerationStructureImpl *> (desc .source )-> m_vkHandle ; 1457 } 1458geomInfoBuilder .buildInfo .scratchData .deviceAddress = desc .scratchData ; 1459 1460List < VkAccelerationStructureBuildRangeInfoKHR > rangeInfos ; 1461rangeInfos .setCount (geomInfoBuilder .primitiveCounts .getCount ()); 1462for (Index i = 0 ;i < geomInfoBuilder .primitiveCounts .getCount ();i ++ ) 1463 { 1464auto & rangeInfo = rangeInfos [i ]; 1465rangeInfo .primitiveCount = geomInfoBuilder .primitiveCounts [i ]; 1466rangeInfo .firstVertex = 0 ; 1467rangeInfo .primitiveOffset = 0 ; 1468rangeInfo .transformOffset = 0 ; 1469 } 1470 1471auto rangeInfoPtr = rangeInfos .getBuffer (); 1472m_commandBuffer -> m_renderer -> m_api .vkCmdBuildAccelerationStructuresKHR ( 1473m_commandBuffer -> m_commandBuffer , 14741 , 1475& geomInfoBuilder .buildInfo , 1476& rangeInfoPtr ); 1477 1478if (propertyQueryCount ) 1479 { 1480_memoryBarrier (1 ,& desc .dest ,AccessFlag ::Write ,AccessFlag ::Read ); 1481_queryAccelerationStructureProperties (1 ,& desc .dest ,propertyQueryCount ,queryDescs ); 1482 } 1483} 1484 1485void RayTracingCommandEncoder ::copyAccelerationStructure ( 1486IAccelerationStructure * dest , 1487IAccelerationStructure * src , 1488AccelerationStructureCopyMode mode ) 1489{ 1490VkCopyAccelerationStructureInfoKHR copyInfo = { 1491VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR }; 1492copyInfo .src = static_cast < AccelerationStructureImpl *> (src )-> m_vkHandle ; 1493copyInfo .dst = static_cast < AccelerationStructureImpl *> (dest )-> m_vkHandle ; 1494switch (mode ) 1495 { 1496case AccelerationStructureCopyMode ::Clone : 1497copyInfo .mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR ; 1498break ; 1499case AccelerationStructureCopyMode ::Compact : 1500copyInfo .mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR ; 1501break ; 1502default : 1503getDebugCallback ()-> handleMessage ( 1504DebugMessageType ::Error , 1505DebugMessageSource ::Layer , 1506"Unsupported AccelerationStructureCopyMode." ); 1507return ; 1508 } 1509m_commandBuffer -> m_renderer -> m_api .vkCmdCopyAccelerationStructureKHR ( 1510m_commandBuffer -> m_commandBuffer , 1511& copyInfo ); 1512} 1513 1514void RayTracingCommandEncoder ::queryAccelerationStructureProperties ( 1515GfxCount accelerationStructureCount , 1516IAccelerationStructure * const * accelerationStructures , 1517GfxCount queryCount , 1518AccelerationStructureQueryDesc * queryDescs ) 1519{ 1520_queryAccelerationStructureProperties ( 1521accelerationStructureCount , 1522accelerationStructures , 1523queryCount , 1524queryDescs ); 1525} 1526 1527void RayTracingCommandEncoder ::serializeAccelerationStructure ( 1528DeviceAddress dest , 1529IAccelerationStructure * source ) 1530{ 1531VkCopyAccelerationStructureToMemoryInfoKHR copyInfo = { 1532VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR }; 1533copyInfo .src = static_cast < AccelerationStructureImpl *> (source )-> m_vkHandle ; 1534copyInfo .dst .deviceAddress = dest ; 1535copyInfo .mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR ; 1536m_commandBuffer -> m_renderer -> m_api .vkCmdCopyAccelerationStructureToMemoryKHR ( 1537m_commandBuffer -> m_commandBuffer , 1538& copyInfo ); 1539} 1540 1541void RayTracingCommandEncoder ::deserializeAccelerationStructure ( 1542IAccelerationStructure * dest , 1543DeviceAddress source ) 1544{ 1545VkCopyMemoryToAccelerationStructureInfoKHR copyInfo = { 1546VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR }; 1547copyInfo .src .deviceAddress = source ; 1548copyInfo .dst = static_cast < AccelerationStructureImpl *> (dest )-> m_vkHandle ; 1549copyInfo .mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR ; 1550m_commandBuffer -> m_renderer -> m_api .vkCmdCopyMemoryToAccelerationStructureKHR ( 1551m_commandBuffer -> m_commandBuffer , 1552& copyInfo ); 1553} 1554 1555Result RayTracingCommandEncoder ::bindPipeline ( 1556IPipelineState * pipeline , 1557IShaderObject ** outRootObject ) 1558{ 1559return setPipelineStateImpl (pipeline ,outRootObject ); 1560} 1561 1562Result RayTracingCommandEncoder ::bindPipelineWithRootObject ( 1563IPipelineState * pipelineState , 1564IShaderObject * rootObject ) 1565{ 1566return setPipelineStateWithRootObjectImpl (pipelineState ,rootObject ); 1567} 1568 1569Result RayTracingCommandEncoder ::dispatchRays ( 1570GfxIndex raygenShaderIndex , 1571IShaderTable * shaderTable , 1572GfxCount width , 1573GfxCount height , 1574GfxCount depth ) 1575{ 1576auto vkApi = m_commandBuffer -> m_renderer -> m_api ; 1577auto vkCommandBuffer = m_commandBuffer -> m_commandBuffer ; 1578 1579SLANG_RETURN_ON_FAIL (bindRenderState (VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR )); 1580 1581auto rtProps = vkApi .m_rtProperties ; 1582auto shaderTableImpl = (ShaderTableImpl * )shaderTable ; 1583auto alignedHandleSize = 1584VulkanUtil ::calcAligned (rtProps .shaderGroupHandleSize ,rtProps .shaderGroupHandleAlignment ); 1585 1586auto shaderTableBuffer = shaderTableImpl -> getOrCreateBuffer ( 1587m_currentPipeline , 1588m_commandBuffer -> m_transientHeap , 1589static_cast < ResourceCommandEncoder *> (this )); 1590auto shaderTableAddr = shaderTableBuffer -> getDeviceAddress (); 1591 1592VkStridedDeviceAddressRegionKHR raygenSBT ; 1593raygenSBT .stride = VulkanUtil ::calcAligned (alignedHandleSize ,rtProps .shaderGroupBaseAlignment ); 1594raygenSBT .deviceAddress = shaderTableAddr + raygenShaderIndex * raygenSBT .stride ; 1595raygenSBT .size = raygenSBT .stride ; 1596 1597VkStridedDeviceAddressRegionKHR missSBT ; 1598missSBT .deviceAddress = shaderTableAddr + shaderTableImpl -> m_raygenTableSize ; 1599missSBT .stride = alignedHandleSize ; 1600missSBT .size = shaderTableImpl -> m_missTableSize ; 1601 1602VkStridedDeviceAddressRegionKHR hitSBT ; 1603hitSBT .deviceAddress = missSBT .deviceAddress + missSBT .size ; 1604hitSBT .stride = alignedHandleSize ; 1605hitSBT .size = shaderTableImpl -> m_hitTableSize ; 1606 1607VkStridedDeviceAddressRegionKHR callableSBT ; 1608callableSBT .deviceAddress = hitSBT .deviceAddress + hitSBT .size ; 1609callableSBT .stride = alignedHandleSize ; 1610callableSBT .size = shaderTableImpl -> m_callableTableSize ; 1611 1612vkApi .vkCmdTraceRaysKHR ( 1613vkCommandBuffer , 1614& raygenSBT , 1615& missSBT , 1616& hitSBT , 1617& callableSBT , 1618 (uint32_t )width , 1619 (uint32_t )height , 1620 (uint32_t )depth ); 1621 1622return SLANG_OK ; 1623} 1624 1625void RayTracingCommandEncoder ::endEncoding () 1626{ 1627endEncodingImpl (); 1628} 1629 1630}// namespace vk 1631}// namespace gfx