Skip to content

Commit 9f23046

Browse files
[gfx] specify resource view buffer range in bytes (shader-slang#4149)
* refactor gfx buffer range to use byte range * create buffer view with zero struct stride for ClearUnorderedAccessViewUint/Float * create buffer descriptors on demand * avoid copying gfx.dll --------- Co-authored-by: Yong He <yonghe@outlook.com>
1 parent 04d3dd5 commit 9f23046

16 files changed

+64
-152
lines changed

.github/workflows/falcor-test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
5252
MSBuild.exe slang.sln -v:m -m -property:Configuration=${{matrix.configuration}} -property:Platform=${{matrix.platform}} -property:WindowsTargetPlatformVersion=10.0.19041.0 -maxcpucount:12
5353
54-
Copy-Item -Path '.\bin\windows-${{matrix.platform}}\${{matrix.configuration}}\*' -Destination '.\FalcorBin\build\windows-vs2022\bin\Release\' -Recurse -Exclude ("*.pdb")
54+
Copy-Item -Path '.\bin\windows-${{matrix.platform}}\${{matrix.configuration}}\*' -Destination '.\FalcorBin\build\windows-vs2022\bin\Release\' -Recurse -Exclude ("*.pdb", "gfx.dll")
5555
- name: falcor-unit-test
5656
run: |
5757
$ErrorActionPreference = "SilentlyContinue"

examples/autodiff-texture/main.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,6 @@ struct AutoDiffTexture : public WindowedAppBase
246246
{
247247
IResourceView::Desc desc = {};
248248
desc.type = IResourceView::Type::UnorderedAccess;
249-
desc.bufferElementSize = 0;
250249
return gDevice->createBufferView(buffer, nullptr, desc);
251250
}
252251
ComPtr<gfx::IResourceView> createUAV(ITextureResource* texture, int level)

examples/ray-tracing-pipeline/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ Slang::Result initialize()
318318
IBufferResource::Desc primitiveBufferDesc;
319319
primitiveBufferDesc.type = IResource::Type::Buffer;
320320
primitiveBufferDesc.sizeInBytes = kPrimitiveCount * sizeof(Primitive);
321+
primitiveBufferDesc.elementSize = sizeof(Primitive);
321322
primitiveBufferDesc.defaultState = ResourceState::ShaderResource;
322323
gPrimitiveBuffer = gDevice->createBufferResource(primitiveBufferDesc, &kPrimitiveData[0]);
323324
if (!gPrimitiveBuffer)
@@ -326,7 +327,6 @@ Slang::Result initialize()
326327
IResourceView::Desc primitiveSRVDesc = {};
327328
primitiveSRVDesc.format = Format::Unknown;
328329
primitiveSRVDesc.type = IResourceView::Type::ShaderResource;
329-
primitiveSRVDesc.bufferElementSize = sizeof(Primitive);
330330
gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc);
331331

332332
IBufferResource::Desc transformBufferDesc;

examples/ray-tracing/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ Slang::Result initialize()
309309
IBufferResource::Desc primitiveBufferDesc;
310310
primitiveBufferDesc.type = IResource::Type::Buffer;
311311
primitiveBufferDesc.sizeInBytes = kPrimitiveCount * sizeof(Primitive);
312+
primitiveBufferDesc.elementSize = sizeof(Primitive);
312313
primitiveBufferDesc.defaultState = ResourceState::ShaderResource;
313314
gPrimitiveBuffer = gDevice->createBufferResource(primitiveBufferDesc, &kPrimitiveData[0]);
314315
if (!gPrimitiveBuffer)
@@ -317,7 +318,6 @@ Slang::Result initialize()
317318
IResourceView::Desc primitiveSRVDesc = {};
318319
primitiveSRVDesc.format = Format::Unknown;
319320
primitiveSRVDesc.type = IResourceView::Type::ShaderResource;
320-
primitiveSRVDesc.bufferElementSize = sizeof(Primitive);
321321
gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc);
322322

323323
IBufferResource::Desc transformBufferDesc;

slang-gfx.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,8 @@ struct ClearValue
655655

656656
struct BufferRange
657657
{
658-
// TODO: Change to Index and Count?
659-
uint64_t firstElement;
660-
uint64_t elementCount;
658+
Offset offset; ///< Offset in bytes.
659+
Size size; ///< Size in bytes.
661660
};
662661

663662
enum class TextureAspect : uint32_t
@@ -872,8 +871,6 @@ class IResourceView : public ISlangUnknown
872871
SubresourceRange subresourceRange;
873872
// Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view.
874873
BufferRange bufferRange;
875-
// Specifies the element size in bytes of a structured buffer. Pass 0 for a raw buffer view.
876-
Size bufferElementSize;
877874
};
878875
virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() = 0;
879876

tools/gfx-unit-test/buffer-barrier-test.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ namespace gfx_test
4747
IResourceView::Desc viewDesc = {};
4848
viewDesc.type = unorderedAccess ? IResourceView::Type::UnorderedAccess : IResourceView::Type::ShaderResource;
4949
viewDesc.format = Format::Unknown;
50-
viewDesc.bufferElementSize = sizeof(float);
5150
GFX_CHECK_CALL_ABORT(device->createBufferView(
5251
outBuffer.buffer, nullptr, viewDesc, outBuffer.view.writeRef()));
5352
}

tools/gfx-unit-test/nested-parameter-block.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,17 @@ namespace gfx_test
6767
IResourceView::Desc srvDesc = {};
6868
srvDesc.type = IResourceView::Type::ShaderResource;
6969
srvDesc.format = Format::Unknown;
70-
srvDesc.bufferElementSize = sizeof(uint32_t) * 4;
71-
srvDesc.bufferRange.elementCount = 1;
72-
srvDesc.bufferRange.firstElement = 0;
70+
srvDesc.bufferRange.offset = 0;
71+
srvDesc.bufferRange.size = sizeof(uint32_t) * 4;
7372
srvs.add(device->createBufferView(srvBuffers[i], nullptr, srvDesc));
7473
}
7574
Slang::ComPtr<IBufferResource> resultBuffer =
7675
createBuffer(device, 0, gfx::ResourceState::UnorderedAccess);
7776
IResourceView::Desc resultBufferViewDesc = {};
7877
resultBufferViewDesc.type = IResourceView::Type::UnorderedAccess;
7978
resultBufferViewDesc.format = Format::Unknown;
80-
resultBufferViewDesc.bufferElementSize = sizeof(uint32_t) * 4;
81-
resultBufferViewDesc.bufferRange.elementCount = 1;
82-
resultBufferViewDesc.bufferRange.firstElement = 0;
79+
resultBufferViewDesc.bufferRange.offset = 0;
80+
resultBufferViewDesc.bufferRange.size = sizeof(uint32_t) * 4;
8381
Slang::ComPtr<IResourceView> resultBufferView;
8482
SLANG_CHECK(SLANG_SUCCEEDED(device->createBufferView(
8583
resultBuffer, nullptr, resultBufferViewDesc, resultBufferView.writeRef())));

tools/gfx/d3d12/d3d12-command-encoder.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -384,11 +384,14 @@ void ResourceCommandEncoderImpl::clearResourceView(
384384
case IResourceView::Type::UnorderedAccess:
385385
{
386386
ID3D12Resource* d3dResource = nullptr;
387+
D3D12Descriptor descriptor = viewImpl->m_descriptor;
387388
switch (viewImpl->m_resource->getType())
388389
{
389390
case IResource::Type::Buffer:
390391
d3dResource = static_cast<BufferResourceImpl*>(viewImpl->m_resource.Ptr())
391392
->m_resource.getResource();
393+
// D3D12 requires a UAV descriptor with zero buffer stride for calling ClearUnorderedAccessViewUint/Float.
394+
viewImpl->getBufferDescriptorForBinding(m_commandBuffer->m_renderer, viewImpl, 0, descriptor);
392395
break;
393396
default:
394397
d3dResource = static_cast<TextureResourceImpl*>(viewImpl->m_resource.Ptr())
@@ -407,15 +410,15 @@ void ResourceCommandEncoderImpl::clearResourceView(
407410
this->m_commandBuffer->m_renderer->m_device->CopyDescriptorsSimple(
408411
1,
409412
m_commandBuffer->m_transientHeap->getCurrentViewHeap().getCpuHandle(gpuHandleIndex),
410-
viewImpl->m_descriptor.cpuHandle,
413+
descriptor.cpuHandle,
411414
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
412415

413416
if (flags & ClearResourceViewFlags::FloatClearValues)
414417
{
415418
m_commandBuffer->m_cmdList->ClearUnorderedAccessViewFloat(
416419
m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle(
417420
gpuHandleIndex),
418-
viewImpl->m_descriptor.cpuHandle,
421+
descriptor.cpuHandle,
419422
d3dResource,
420423
clearValue->color.floatValues,
421424
0,
@@ -426,7 +429,7 @@ void ResourceCommandEncoderImpl::clearResourceView(
426429
m_commandBuffer->m_cmdList->ClearUnorderedAccessViewUint(
427430
m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle(
428431
gpuHandleIndex),
429-
viewImpl->m_descriptor.cpuHandle,
432+
descriptor.cpuHandle,
430433
d3dResource,
431434
clearValue->color.uintValues,
432435
0,

tools/gfx/d3d12/d3d12-device.cpp

+3-9
Original file line numberDiff line numberDiff line change
@@ -1674,15 +1674,9 @@ Result DeviceImpl::createBufferView(
16741674
viewImpl->m_counterResource = counterResourceImpl;
16751675
viewImpl->m_desc = desc;
16761676

1677-
SLANG_RETURN_ON_FAIL(createD3D12BufferDescriptor(
1678-
resourceImpl,
1679-
counterResourceImpl,
1680-
desc,
1681-
this,
1682-
m_cpuViewHeap.get(),
1683-
&viewImpl->m_descriptor));
1684-
if (viewImpl->m_descriptor.cpuHandle.ptr != 0)
1685-
viewImpl->m_allocator = m_cpuViewHeap.get();
1677+
// Buffer view descriptors are created on demand.
1678+
viewImpl->m_descriptor = {0};
1679+
viewImpl->m_allocator = m_cpuViewHeap.get();
16861680

16871681
returnComPtr(outView, viewImpl);
16881682
return SLANG_OK;

tools/gfx/d3d12/d3d12-resource-views.cpp

+25-76
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ SlangResult createD3D12BufferDescriptor(
2323
BufferResourceImpl* buffer,
2424
BufferResourceImpl* counterBuffer,
2525
IResourceView::Desc const& desc,
26+
uint32_t bufferStride,
2627
DeviceImpl* device,
2728
D3D12GeneralExpandingDescriptorHeap* descriptorHeap,
2829
D3D12Descriptor* outDescriptor)
@@ -32,6 +33,9 @@ SlangResult createD3D12BufferDescriptor(
3233
auto resourceDesc = *resourceImpl->getDesc();
3334
const auto counterResourceImpl = static_cast<BufferResourceImpl*>(counterBuffer);
3435

36+
uint64_t offset = desc.bufferRange.offset;
37+
uint64_t size = desc.bufferRange.size == 0 ? buffer->getDesc()->sizeInBytes - offset : desc.bufferRange.size;
38+
3539
switch (desc.type)
3640
{
3741
default:
@@ -42,39 +46,29 @@ SlangResult createD3D12BufferDescriptor(
4246
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
4347
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
4448
uavDesc.Format = D3DUtil::getMapFormat(desc.format);
45-
uavDesc.Buffer.FirstElement = desc.bufferRange.firstElement;
46-
uint64_t viewSize = 0;
47-
if (desc.bufferElementSize)
49+
if (bufferStride)
4850
{
49-
uavDesc.Buffer.StructureByteStride = (UINT)desc.bufferElementSize;
50-
uavDesc.Buffer.NumElements =
51-
desc.bufferRange.elementCount == 0
52-
? UINT(resourceDesc.sizeInBytes / desc.bufferElementSize)
53-
: (UINT)desc.bufferRange.elementCount;
54-
viewSize = (uint64_t)desc.bufferElementSize * uavDesc.Buffer.NumElements;
51+
uavDesc.Buffer.FirstElement = offset / bufferStride;
52+
uavDesc.Buffer.NumElements = UINT(size / bufferStride);
53+
uavDesc.Buffer.StructureByteStride = bufferStride;
5554
}
5655
else if (desc.format == Format::Unknown)
5756
{
5857
uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
59-
uavDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0
60-
? UINT(resourceDesc.sizeInBytes / 4)
61-
: UINT(desc.bufferRange.elementCount / 4);
58+
uavDesc.Buffer.FirstElement = offset / 4;
59+
uavDesc.Buffer.NumElements = UINT(size / 4);
6260
uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW;
63-
viewSize = 4ull * uavDesc.Buffer.NumElements;
6461
}
6562
else
6663
{
6764
FormatInfo sizeInfo;
6865
gfxGetFormatInfo(desc.format, &sizeInfo);
6966
assert(sizeInfo.pixelsPerBlock == 1);
70-
uavDesc.Buffer.NumElements =
71-
desc.bufferRange.elementCount == 0
72-
? UINT(resourceDesc.sizeInBytes / sizeInfo.blockSizeInBytes)
73-
: (UINT)desc.bufferRange.elementCount;
74-
viewSize = (uint64_t)uavDesc.Buffer.NumElements * sizeInfo.blockSizeInBytes;
67+
uavDesc.Buffer.FirstElement = offset / sizeInfo.blockSizeInBytes;
68+
uavDesc.Buffer.NumElements = UINT(size / sizeInfo.blockSizeInBytes);
7569
}
7670

77-
if (viewSize >= (1ull << 32) - 8)
71+
if (size >= (1ull << 32) - 8)
7872
{
7973
// D3D12 does not support view descriptors that has size near 4GB.
8074
// We will not create actual SRV/UAVs for such large buffers.
@@ -99,40 +93,30 @@ SlangResult createD3D12BufferDescriptor(
9993
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
10094
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
10195
srvDesc.Format = D3DUtil::getMapFormat(desc.format);
102-
srvDesc.Buffer.StructureByteStride = 0;
103-
srvDesc.Buffer.FirstElement = desc.bufferRange.firstElement;
10496
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
105-
uint64_t viewSize = 0;
106-
if (desc.bufferElementSize)
97+
if (bufferStride)
10798
{
108-
srvDesc.Buffer.StructureByteStride = (UINT)desc.bufferElementSize;
109-
srvDesc.Buffer.NumElements =
110-
desc.bufferRange.elementCount == 0
111-
? UINT(resourceDesc.sizeInBytes / desc.bufferElementSize)
112-
: (UINT)desc.bufferRange.elementCount;
113-
viewSize = (uint64_t)desc.bufferElementSize * srvDesc.Buffer.NumElements;
99+
srvDesc.Buffer.FirstElement = offset / bufferStride;
100+
srvDesc.Buffer.NumElements = UINT(size / bufferStride);
101+
srvDesc.Buffer.StructureByteStride = bufferStride;
114102
}
115103
else if (desc.format == Format::Unknown)
116104
{
117105
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
118-
srvDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0
119-
? UINT(resourceDesc.sizeInBytes / 4)
120-
: UINT(desc.bufferRange.elementCount / 4);
106+
srvDesc.Buffer.FirstElement = offset / 4;
107+
srvDesc.Buffer.NumElements = UINT(size / 4);
121108
srvDesc.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW;
122-
viewSize = 4ull * srvDesc.Buffer.NumElements;
123109
}
124110
else
125111
{
126112
FormatInfo sizeInfo;
127113
gfxGetFormatInfo(desc.format, &sizeInfo);
128114
assert(sizeInfo.pixelsPerBlock == 1);
129-
srvDesc.Buffer.NumElements =
130-
desc.bufferRange.elementCount == 0
131-
? UINT(resourceDesc.sizeInBytes / sizeInfo.blockSizeInBytes)
132-
: (UINT)desc.bufferRange.elementCount;
133-
viewSize = (uint64_t)srvDesc.Buffer.NumElements * sizeInfo.blockSizeInBytes;
115+
srvDesc.Buffer.FirstElement = offset / sizeInfo.blockSizeInBytes;
116+
srvDesc.Buffer.NumElements = UINT(size / sizeInfo.blockSizeInBytes);
134117
}
135-
if (viewSize >= (1ull << 32) - 8)
118+
119+
if (size >= (1ull << 32) - 8)
136120
{
137121
// D3D12 does not support view descriptors that has size near 4GB.
138122
// We will not create actual SRV/UAVs for such large buffers.
@@ -158,14 +142,7 @@ SlangResult ResourceViewInternalImpl::getBufferDescriptorForBinding(
158142
uint32_t bufferStride,
159143
D3D12Descriptor& outDescriptor)
160144
{
161-
// If stride is 0, just use the default descriptor.
162-
if (bufferStride == 0)
163-
{
164-
outDescriptor = m_descriptor;
165-
return SLANG_OK;
166-
}
167-
168-
// Otherwise, look for an existing descriptor from the cache if it exists.
145+
// Look for an existing descriptor from the cache if it exists.
169146
if (auto descriptor = m_mapBufferStrideToDescriptor.tryGetValue(bufferStride))
170147
{
171148
outDescriptor = *descriptor;
@@ -176,39 +153,11 @@ SlangResult ResourceViewInternalImpl::getBufferDescriptorForBinding(
176153
// the given buffer stride.
177154
auto bufferResImpl = static_cast<BufferResourceImpl*>(view->m_resource.get());
178155
auto desc = view->m_desc;
179-
uint64_t bufferSize = 0;
180-
if (desc.bufferElementSize == 0)
181-
{
182-
// If buffer element size is 0, we assume the buffer range from original desc is in bytes.
183-
bufferSize = desc.bufferRange.elementCount;
184-
if (bufferSize == 0)
185-
{
186-
bufferSize = bufferResImpl->getDesc()->sizeInBytes - desc.bufferRange.firstElement;
187-
}
188-
desc.bufferElementSize = bufferStride;
189-
desc.bufferRange.firstElement /= bufferStride;
190-
desc.bufferRange.elementCount = bufferSize / bufferStride;
191-
}
192-
else
193-
{
194-
// If buffer element size is not 0, we assume the buffer range from original desc is in elements
195-
// of original stride.
196-
if (desc.bufferRange.elementCount == 0)
197-
{
198-
bufferSize = bufferResImpl->getDesc()->sizeInBytes - desc.bufferRange.firstElement * desc.bufferElementSize;
199-
}
200-
else
201-
{
202-
bufferSize = desc.bufferRange.elementCount * desc.bufferElementSize;
203-
}
204-
desc.bufferElementSize = bufferStride;
205-
desc.bufferRange.firstElement = desc.bufferRange.firstElement * desc.bufferElementSize / bufferStride;
206-
desc.bufferRange.elementCount = bufferSize / bufferStride;
207-
}
208156
SLANG_RETURN_ON_FAIL(createD3D12BufferDescriptor(
209157
bufferResImpl,
210158
static_cast<BufferResourceImpl*>(view->m_counterResource.get()),
211159
desc,
160+
bufferStride,
212161
device,
213162
m_allocator,
214163
&outDescriptor));

tools/gfx/d3d12/d3d12-resource-views.h

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ SlangResult createD3D12BufferDescriptor(
3939
BufferResourceImpl* buffer,
4040
BufferResourceImpl* counterBuffer,
4141
IResourceView::Desc const& desc,
42+
uint32_t bufferStride,
4243
DeviceImpl* device,
4344
D3D12GeneralExpandingDescriptorHeap* descriptorHeap,
4445
D3D12Descriptor* outDescriptor);

tools/gfx/d3d12/d3d12-shader-object.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -965,13 +965,17 @@ Result ShaderObjectImpl::setResource(ShaderOffset const& offset, IResourceView*
965965
}
966966

967967
auto descriptorSlotIndex = bindingRange.baseIndex + (int32_t)offset.bindingArrayIndex;
968-
D3D12Descriptor srcDescriptor = {};
968+
D3D12Descriptor srcDescriptor = internalResourceView->m_descriptor;
969969

970-
SLANG_RETURN_ON_FAIL(internalResourceView->getBufferDescriptorForBinding(
971-
static_cast<DeviceImpl*>(m_device.get()),
972-
resourceViewImpl,
973-
bindingRange.bufferElementStride,
974-
srcDescriptor));
970+
// Buffer descriptors are created on demand.
971+
if (!srcDescriptor.cpuHandle.ptr)
972+
{
973+
SLANG_RETURN_ON_FAIL(internalResourceView->getBufferDescriptorForBinding(
974+
static_cast<DeviceImpl*>(m_device.get()),
975+
resourceViewImpl,
976+
bindingRange.bufferElementStride,
977+
srcDescriptor));
978+
}
975979

976980
if (srcDescriptor.cpuHandle.ptr)
977981
{

tools/gfx/gfx.slang

+2-5
Original file line numberDiff line numberDiff line change
@@ -446,9 +446,8 @@ public struct ClearValue
446446

447447
public struct BufferRange
448448
{
449-
// TODO: Change to Index and Count?
450-
public uint64_t firstElement;
451-
public uint64_t elementCount;
449+
public Offset offset; ///< Offset in bytes.
450+
public Size size; ///< Size in bytes.
452451
};
453452

454453
public enum class TextureAspect : uint32_t
@@ -651,8 +650,6 @@ public struct ResourceViewDesc
651650
public SubresourceRange subresourceRange;
652651
// Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view.
653652
public BufferRange bufferRange;
654-
// Specifies the element size in bytes of a structured buffer. Pass 0 for a raw buffer view.
655-
public Size bufferElementSize;
656653
};
657654

658655
[COM("7b6c4926-0884-408c-ad8a-50-3a-8e-23-98-a4")]

0 commit comments

Comments
 (0)