summaryrefslogtreecommitdiffstats
path: root/tools/gfx-unit-test
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-04-15 23:28:28 -0700
committerGitHub <noreply@github.com>2024-04-15 23:28:28 -0700
commit3192f34f57abd3245995342a0a5971ebbbbd945c (patch)
treedc139be9fe9f4995bac96513571cc9e0526ce547 /tools/gfx-unit-test
parent030d7f45726187b5b23a3cfb9743166aa60fae30 (diff)
[GFX] Fix d3d12 buffer view creation logic for StructuredBuffers. (#3954)
Diffstat (limited to 'tools/gfx-unit-test')
-rw-r--r--tools/gfx-unit-test/uint16-buffer.slang14
-rw-r--r--tools/gfx-unit-test/uint16-structured-buffer.cpp96
2 files changed, 110 insertions, 0 deletions
diff --git a/tools/gfx-unit-test/uint16-buffer.slang b/tools/gfx-unit-test/uint16-buffer.slang
new file mode 100644
index 000000000..bdc09c7d8
--- /dev/null
+++ b/tools/gfx-unit-test/uint16-buffer.slang
@@ -0,0 +1,14 @@
+// uint16-buffer.slang - Simple shader that takes a buffer of uint16 type and increments all elements by 1.
+
+// This is to verify that GFX can correct set correct buffer strides for structured buffer bindings.
+
+uniform RWStructuredBuffer<uint16_t> buffer;
+
+[shader("compute")]
+[numthreads(4,1,1)]
+void computeMain(
+ uint3 sv_dispatchThreadID : SV_DispatchThreadID)
+{
+ var input = buffer[sv_dispatchThreadID.x];
+ buffer[sv_dispatchThreadID.x] = input + 1;
+}
diff --git a/tools/gfx-unit-test/uint16-structured-buffer.cpp b/tools/gfx-unit-test/uint16-structured-buffer.cpp
new file mode 100644
index 000000000..8f2f2cb97
--- /dev/null
+++ b/tools/gfx-unit-test/uint16-structured-buffer.cpp
@@ -0,0 +1,96 @@
+#include "tools/unit-test/slang-unit-test.h"
+
+#include "slang-gfx.h"
+#include "gfx-test-util.h"
+#include "tools/gfx-util/shader-cursor.h"
+#include "source/core/slang-basic.h"
+
+using namespace gfx;
+
+namespace gfx_test
+{
+ void uint16BufferTestImpl(IDevice* device, UnitTestContext* context)
+ {
+ Slang::ComPtr<ITransientResourceHeap> transientHeap;
+ ITransientResourceHeap::Desc transientHeapDesc = {};
+ transientHeapDesc.constantBufferSize = 4096;
+ GFX_CHECK_CALL_ABORT(
+ device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef()));
+
+ ComPtr<IShaderProgram> shaderProgram;
+ slang::ProgramLayout* slangReflection;
+ GFX_CHECK_CALL_ABORT(loadComputeProgram(device, shaderProgram, "uint16-buffer", "computeMain", slangReflection));
+
+ ComputePipelineStateDesc pipelineDesc = {};
+ pipelineDesc.program = shaderProgram.get();
+ ComPtr<gfx::IPipelineState> pipelineState;
+ GFX_CHECK_CALL_ABORT(
+ device->createComputePipelineState(pipelineDesc, pipelineState.writeRef()));
+
+ const int numberCount = 4;
+ uint16_t initialData[] = { 0, 1, 2, 3 };
+ IBufferResource::Desc bufferDesc = {};
+ bufferDesc.sizeInBytes = numberCount * sizeof(uint16_t);
+ bufferDesc.format = gfx::Format::Unknown;
+ // Note: we don't specify any element size here, and gfx should be able to derive the
+ // correct element size from the reflection infomation.
+ bufferDesc.elementSize = 0;
+ bufferDesc.allowedStates = ResourceStateSet(
+ ResourceState::ShaderResource,
+ ResourceState::UnorderedAccess,
+ ResourceState::CopyDestination,
+ ResourceState::CopySource);
+ bufferDesc.defaultState = ResourceState::UnorderedAccess;
+ bufferDesc.memoryType = MemoryType::DeviceLocal;
+
+ ComPtr<IBufferResource> numbersBuffer;
+ GFX_CHECK_CALL_ABORT(device->createBufferResource(
+ bufferDesc,
+ (void*)initialData,
+ numbersBuffer.writeRef()));
+
+ ComPtr<IResourceView> bufferView;
+ IResourceView::Desc viewDesc = {};
+ viewDesc.type = IResourceView::Type::UnorderedAccess;
+ viewDesc.format = Format::Unknown;
+ GFX_CHECK_CALL_ABORT(
+ device->createBufferView(numbersBuffer, nullptr, viewDesc, bufferView.writeRef()));
+
+ // We have done all the set up work, now it is time to start recording a command buffer for
+ // GPU execution.
+ {
+ ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics };
+ auto queue = device->createCommandQueue(queueDesc);
+
+ auto commandBuffer = transientHeap->createCommandBuffer();
+ auto encoder = commandBuffer->encodeComputeCommands();
+
+ auto rootObject = encoder->bindPipeline(pipelineState);
+
+ // Bind buffer view to the entry point.
+ ShaderCursor(rootObject).getPath("buffer").setResource(bufferView);
+
+ encoder->dispatchCompute(1, 1, 1);
+ encoder->endEncoding();
+ commandBuffer->close();
+ queue->executeCommandBuffer(commandBuffer);
+ queue->waitOnHost();
+ }
+
+ compareComputeResult(
+ device,
+ numbersBuffer,
+ Slang::makeArray<uint16_t>(1, 2, 3, 4));
+ }
+
+ SLANG_UNIT_TEST(uint16BufferTestD3D12)
+ {
+ runTestImpl(uint16BufferTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12);
+ }
+
+ SLANG_UNIT_TEST(uint16BufferTestVulkan)
+ {
+ runTestImpl(uint16BufferTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+
+}