yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie HermaszewskaMove switch statement bodies to their own lines (#5493)b118451e3

master
6.8 KiB197 linesraw
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{
15    if (m_descriptor.cpuHandle.ptr)
16        m_allocator->free(m_descriptor);
17    for (auto desc : m_mapBufferStrideToDescriptor)
18    {
19        m_allocator->free(desc.second);
20    }
21}
22
23SlangResult createD3D12BufferDescriptor(
24    BufferResourceImpl* buffer,
25    BufferResourceImpl* counterBuffer,
26    IResourceView::Desc const& desc,
27    uint32_t bufferStride,
28    DeviceImpl* device,
29    D3D12GeneralExpandingDescriptorHeap* descriptorHeap,
30    D3D12Descriptor* outDescriptor)
31{
32
33    auto resourceImpl = (BufferResourceImpl*)buffer;
34    auto resourceDesc = *resourceImpl->getDesc();
35    const auto counterResourceImpl = static_cast<BufferResourceImpl*>(counterBuffer);
36
37    uint64_t offset = desc.bufferRange.offset;
38    uint64_t size = desc.bufferRange.size == 0 ? buffer->getDesc()->sizeInBytes - offset
39                                               : desc.bufferRange.size;
40
41    switch (desc.type)
42    {
43    default:
44        return SLANG_FAIL;
45
46    case IResourceView::Type::UnorderedAccess:
47        {
48            D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
49            uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
50            uavDesc.Format = D3DUtil::getMapFormat(desc.format);
51            if (bufferStride)
52            {
53                uavDesc.Buffer.FirstElement = offset / bufferStride;
54                uavDesc.Buffer.NumElements = UINT(size / bufferStride);
55                uavDesc.Buffer.StructureByteStride = bufferStride;
56            }
57            else if (desc.format == Format::Unknown)
58            {
59                uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
60                uavDesc.Buffer.FirstElement = offset / 4;
61                uavDesc.Buffer.NumElements = UINT(size / 4);
62                uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW;
63            }
64            else
65            {
66                FormatInfo sizeInfo;
67                gfxGetFormatInfo(desc.format, &sizeInfo);
68                assert(sizeInfo.pixelsPerBlock == 1);
69                uavDesc.Buffer.FirstElement = offset / sizeInfo.blockSizeInBytes;
70                uavDesc.Buffer.NumElements = UINT(size / sizeInfo.blockSizeInBytes);
71            }
72
73            if (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.
79                outDescriptor->cpuHandle.ptr = 0;
80            }
81            else
82            {
83                SLANG_RETURN_ON_FAIL(descriptorHeap->allocate(outDescriptor));
84                device->m_device->CreateUnorderedAccessView(
85                    resourceImpl->m_resource,
86                    counterResourceImpl ? counterResourceImpl->m_resource.getResource() : nullptr,
87                    &uavDesc,
88                    outDescriptor->cpuHandle);
89            }
90        }
91        break;
92
93    case IResourceView::Type::ShaderResource:
94        {
95            D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
96            srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
97            srvDesc.Format = D3DUtil::getMapFormat(desc.format);
98            srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
99            if (bufferStride)
100            {
101                srvDesc.Buffer.FirstElement = offset / bufferStride;
102                srvDesc.Buffer.NumElements = UINT(size / bufferStride);
103                srvDesc.Buffer.StructureByteStride = bufferStride;
104            }
105            else if (desc.format == Format::Unknown)
106            {
107                srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
108                srvDesc.Buffer.FirstElement = offset / 4;
109                srvDesc.Buffer.NumElements = UINT(size / 4);
110                srvDesc.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW;
111            }
112            else
113            {
114                FormatInfo sizeInfo;
115                gfxGetFormatInfo(desc.format, &sizeInfo);
116                assert(sizeInfo.pixelsPerBlock == 1);
117                srvDesc.Buffer.FirstElement = offset / sizeInfo.blockSizeInBytes;
118                srvDesc.Buffer.NumElements = UINT(size / sizeInfo.blockSizeInBytes);
119            }
120
121            if (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.
127                outDescriptor->cpuHandle.ptr = 0;
128            }
129            else
130            {
131                SLANG_RETURN_ON_FAIL(descriptorHeap->allocate(outDescriptor));
132                device->m_device->CreateShaderResourceView(
133                    resourceImpl->m_resource,
134                    &srvDesc,
135                    outDescriptor->cpuHandle);
136            }
137        }
138        break;
139    }
140    return SLANG_OK;
141}
142
143SlangResult ResourceViewInternalImpl::getBufferDescriptorForBinding(
144    DeviceImpl* device,
145    ResourceViewImpl* view,
146    uint32_t bufferStride,
147    D3D12Descriptor& outDescriptor)
148{
149    // Look for an existing descriptor from the cache if it exists.
150    if (auto descriptor = m_mapBufferStrideToDescriptor.tryGetValue(bufferStride))
151    {
152        outDescriptor = *descriptor;
153        return 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.
158    auto bufferResImpl = static_cast<BufferResourceImpl*>(view->m_resource.get());
159    auto desc = view->m_desc;
160    SLANG_RETURN_ON_FAIL(createD3D12BufferDescriptor(
161        bufferResImpl,
162        static_cast<BufferResourceImpl*>(view->m_counterResource.get()),
163        desc,
164        bufferStride,
165        device,
166        m_allocator,
167        &outDescriptor));
168    m_mapBufferStrideToDescriptor[bufferStride] = outDescriptor;
169
170    return SLANG_OK;
171}
172
173Result ResourceViewImpl::getNativeHandle(InteropHandle* outHandle)
174{
175    outHandle->api = InteropHandleAPI::D3D12CpuDescriptorHandle;
176    outHandle->handleValue = m_descriptor.cpuHandle.ptr;
177    return SLANG_OK;
178}
179
180#if SLANG_GFX_HAS_DXR_SUPPORT
181
182DeviceAddress AccelerationStructureImpl::getDeviceAddress()
183{
184    return m_buffer->getDeviceAddress() + m_offset;
185}
186
187Result AccelerationStructureImpl::getNativeHandle(InteropHandle* outHandle)
188{
189    outHandle->api = InteropHandleAPI::DeviceAddress;
190    outHandle->handleValue = getDeviceAddress();
191    return SLANG_OK;
192}
193
194#endif // SLANG_GFX_HAS_DXR_SUPPORT
195
196} // namespace d3d12
197} // namespace gfx