yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
b118451e3
master
1// d3d12-resource-views.cpp 2#include "d3d12-resource-views.h" 3 4#include "d3d12-device.h" 5 6namespace gfx 7{ 8namespace d3d12 9{ 10 11using namespace Slang ; 12 13ResourceViewInternalImpl ::~ResourceViewInternalImpl () 14{ 15if (m_descriptor .cpuHandle .ptr ) 16m_allocator -> free (m_descriptor ); 17for (auto desc :m_mapBufferStrideToDescriptor ) 18 { 19m_allocator -> free (desc .second ); 20 } 21} 22 23SlangResult createD3D12BufferDescriptor ( 24BufferResourceImpl * buffer , 25BufferResourceImpl * counterBuffer , 26IResourceView ::Desc const & desc , 27uint32_t bufferStride , 28DeviceImpl * device , 29D3D12GeneralExpandingDescriptorHeap * descriptorHeap , 30D3D12Descriptor * outDescriptor ) 31{ 32 33auto resourceImpl = (BufferResourceImpl * )buffer ; 34auto resourceDesc = * resourceImpl -> getDesc (); 35const auto counterResourceImpl = static_cast < BufferResourceImpl *> (counterBuffer ); 36 37uint64_t offset = desc .bufferRange .offset ; 38uint64_t size = desc .bufferRange .size == 0 ?buffer -> getDesc ()-> sizeInBytes - offset 39 :desc .bufferRange .size ; 40 41switch (desc .type ) 42 { 43default : 44return SLANG_FAIL ; 45 46case IResourceView ::Type ::UnorderedAccess : 47 { 48D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; 49uavDesc .ViewDimension = D3D12_UAV_DIMENSION_BUFFER ; 50uavDesc .Format = D3DUtil ::getMapFormat (desc .format ); 51if (bufferStride ) 52 { 53uavDesc .Buffer .FirstElement = offset /bufferStride ; 54uavDesc .Buffer .NumElements = UINT (size /bufferStride ); 55uavDesc .Buffer .StructureByteStride = bufferStride ; 56 } 57else if (desc .format == Format ::Unknown ) 58 { 59uavDesc .Format = DXGI_FORMAT_R32_TYPELESS ; 60uavDesc .Buffer .FirstElement = offset /4 ; 61uavDesc .Buffer .NumElements = UINT (size /4 ); 62uavDesc .Buffer .Flags |=D3D12_BUFFER_UAV_FLAG_RAW ; 63 } 64else 65 { 66FormatInfo sizeInfo ; 67gfxGetFormatInfo (desc .format ,& sizeInfo ); 68assert (sizeInfo .pixelsPerBlock == 1 ); 69uavDesc .Buffer .FirstElement = offset /sizeInfo .blockSizeInBytes ; 70uavDesc .Buffer .NumElements = UINT (size /sizeInfo .blockSizeInBytes ); 71 } 72 73if (size >= (1ull <<32 )- 8 ) 74 { 75// D3D12 does not support view descriptors that has size near 4GB. 76// We will not create actual SRV/UAVs for such large buffers. 77// However, a buffer this large can still be bound as root parameter. 78// So instead of failing, we quietly ignore descriptor creation. 79outDescriptor -> cpuHandle .ptr = 0 ; 80 } 81else 82 { 83SLANG_RETURN_ON_FAIL (descriptorHeap -> allocate (outDescriptor )); 84device -> m_device -> CreateUnorderedAccessView ( 85resourceImpl -> m_resource , 86counterResourceImpl ?counterResourceImpl -> m_resource .getResource () :nullptr , 87& uavDesc , 88outDescriptor -> cpuHandle ); 89 } 90 } 91break ; 92 93case IResourceView ::Type ::ShaderResource : 94 { 95D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; 96srvDesc .ViewDimension = D3D12_SRV_DIMENSION_BUFFER ; 97srvDesc .Format = D3DUtil ::getMapFormat (desc .format ); 98srvDesc .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING ; 99if (bufferStride ) 100 { 101srvDesc .Buffer .FirstElement = offset /bufferStride ; 102srvDesc .Buffer .NumElements = UINT (size /bufferStride ); 103srvDesc .Buffer .StructureByteStride = bufferStride ; 104 } 105else if (desc .format == Format ::Unknown ) 106 { 107srvDesc .Format = DXGI_FORMAT_R32_TYPELESS ; 108srvDesc .Buffer .FirstElement = offset /4 ; 109srvDesc .Buffer .NumElements = UINT (size /4 ); 110srvDesc .Buffer .Flags |=D3D12_BUFFER_SRV_FLAG_RAW ; 111 } 112else 113 { 114FormatInfo sizeInfo ; 115gfxGetFormatInfo (desc .format ,& sizeInfo ); 116assert (sizeInfo .pixelsPerBlock == 1 ); 117srvDesc .Buffer .FirstElement = offset /sizeInfo .blockSizeInBytes ; 118srvDesc .Buffer .NumElements = UINT (size /sizeInfo .blockSizeInBytes ); 119 } 120 121if (size >= (1ull <<32 )- 8 ) 122 { 123// D3D12 does not support view descriptors that has size near 4GB. 124// We will not create actual SRV/UAVs for such large buffers. 125// However, a buffer this large can still be bound as root parameter. 126// So instead of failing, we quietly ignore descriptor creation. 127outDescriptor -> cpuHandle .ptr = 0 ; 128 } 129else 130 { 131SLANG_RETURN_ON_FAIL (descriptorHeap -> allocate (outDescriptor )); 132device -> m_device -> CreateShaderResourceView ( 133resourceImpl -> m_resource , 134& srvDesc , 135outDescriptor -> cpuHandle ); 136 } 137 } 138break ; 139 } 140return SLANG_OK ; 141} 142 143SlangResult ResourceViewInternalImpl ::getBufferDescriptorForBinding ( 144DeviceImpl * device , 145ResourceViewImpl * view , 146uint32_t bufferStride , 147D3D12Descriptor & outDescriptor ) 148{ 149// Look for an existing descriptor from the cache if it exists. 150if (auto descriptor = m_mapBufferStrideToDescriptor .tryGetValue (bufferStride )) 151 { 152outDescriptor = * descriptor ; 153return SLANG_OK ; 154 } 155 156// We need to create and cache a d3d12 descriptor for the resource view that encodes 157// the given buffer stride. 158auto bufferResImpl = static_cast < BufferResourceImpl *> (view -> m_resource .get ()); 159auto desc = view -> m_desc ; 160SLANG_RETURN_ON_FAIL (createD3D12BufferDescriptor ( 161bufferResImpl , 162static_cast < BufferResourceImpl *> (view -> m_counterResource .get ()), 163desc , 164bufferStride , 165device , 166m_allocator , 167& outDescriptor )); 168m_mapBufferStrideToDescriptor [bufferStride ]= outDescriptor ; 169 170return SLANG_OK ; 171} 172 173Result ResourceViewImpl ::getNativeHandle (InteropHandle * outHandle ) 174{ 175outHandle -> api = InteropHandleAPI ::D3D12CpuDescriptorHandle ; 176outHandle -> handleValue = m_descriptor .cpuHandle .ptr ; 177return SLANG_OK ; 178} 179 180#if SLANG_GFX_HAS_DXR_SUPPORT 181 182DeviceAddress AccelerationStructureImpl ::getDeviceAddress () 183{ 184return m_buffer -> getDeviceAddress ()+ m_offset ; 185} 186 187Result AccelerationStructureImpl ::getNativeHandle (InteropHandle * outHandle ) 188{ 189outHandle -> api = InteropHandleAPI ::DeviceAddress ; 190outHandle -> handleValue = getDeviceAddress (); 191return SLANG_OK ; 192} 193 194#endif // SLANG_GFX_HAS_DXR_SUPPORT 195 196}// namespace d3d12 197}// namespace gfx