yum-mirror/slang

Making it easier to work with shaders

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

Gangzheng TongConvert gfx unit tests and examples to use slang-rhi (#7577)43d0c2100

master
4.4 KiB134 linesraw
1#include "core/slang-basic.h"
2#include "gfx-test-util.h"
3#include "slang-rhi.h"
4#include "slang-rhi/shader-cursor.h"
5#include "unit-test/slang-unit-test.h"
6using namespace rhi;
7
8namespace gfx_test
9{
10Slang::ComPtr<IBuffer> createBuffer(IDevice* device, uint32_t data, ResourceState defaultState)
11{
12    uint32_t initialData[] = {data, data, data, data};
13    const int numberCount = SLANG_COUNT_OF(initialData);
14    BufferDesc bufferDesc = {};
15    bufferDesc.size = sizeof(initialData);
16    bufferDesc.format = rhi::Format::Undefined;
17    bufferDesc.elementSize = sizeof(uint32_t) * 4;
18    bufferDesc.defaultState = defaultState;
19    bufferDesc.memoryType = MemoryType::DeviceLocal;
20
21    // Set appropriate usage flags based on the default state
22    if (defaultState == ResourceState::ShaderResource)
23    {
24        bufferDesc.usage = BufferUsage::ShaderResource;
25    }
26    else if (defaultState == ResourceState::UnorderedAccess)
27    {
28        bufferDesc.usage = BufferUsage::UnorderedAccess | BufferUsage::CopySource;
29    }
30
31    ComPtr<IBuffer> numbersBuffer;
32    GFX_CHECK_CALL_ABORT(
33        device->createBuffer(bufferDesc, (void*)initialData, numbersBuffer.writeRef()));
34    return numbersBuffer;
35}
36
37struct uint4
38{
39    uint32_t x, y, z, w;
40};
41
42void nestedParameterBlockTestImpl(IDevice* device, UnitTestContext* context)
43{
44    ComPtr<IShaderProgram> shaderProgram;
45    slang::ProgramLayout* slangReflection;
46    GFX_CHECK_CALL_ABORT(loadComputeProgram(
47        device,
48        shaderProgram,
49        "nested-parameter-block",
50        "computeMain",
51        slangReflection));
52
53    ComputePipelineDesc pipelineDesc = {};
54    pipelineDesc.program = shaderProgram.get();
55    ComPtr<rhi::IComputePipeline> pipeline;
56    pipeline = device->createComputePipeline(pipelineDesc);
57
58    ComPtr<IShaderObject> shaderObject;
59    SLANG_CHECK(
60        SLANG_SUCCEEDED(device->createRootShaderObject(shaderProgram, shaderObject.writeRef())));
61
62    Slang::List<Slang::ComPtr<IBuffer>> srvBuffers;
63
64    for (uint32_t i = 0; i < 6; i++)
65    {
66        srvBuffers.add(createBuffer(device, i, rhi::ResourceState::ShaderResource));
67    }
68    Slang::ComPtr<IBuffer> resultBuffer =
69        createBuffer(device, 0, rhi::ResourceState::UnorderedAccess);
70
71    Slang::ComPtr<IShaderObject> materialObject;
72    SLANG_CHECK(SLANG_SUCCEEDED(device->createShaderObject(
73        slangReflection->findTypeByName("MaterialSystem"),
74        ShaderObjectContainerType::None,
75        materialObject.writeRef())));
76
77    Slang::ComPtr<IShaderObject> sceneObject;
78    SLANG_CHECK(SLANG_SUCCEEDED(device->createShaderObject(
79        slangReflection->findTypeByName("Scene"),
80        ShaderObjectContainerType::None,
81        sceneObject.writeRef())));
82
83    ShaderCursor cursor(shaderObject);
84    cursor["resultBuffer"].setBinding(Binding(resultBuffer));
85    cursor["scene"].setObject(sceneObject);
86
87    Slang::ComPtr<IShaderObject> globalCB;
88    SLANG_CHECK(SLANG_SUCCEEDED(device->createShaderObject(
89        cursor[0].getTypeLayout()->getType(),
90        ShaderObjectContainerType::None,
91        globalCB.writeRef())));
92
93    cursor[0].setObject(globalCB);
94    auto initialData = uint4{20, 20, 20, 20};
95    globalCB->setData(ShaderOffset(), &initialData, sizeof(initialData));
96
97    ShaderCursor sceneCursor(sceneObject);
98    sceneCursor["sceneCb"].setData(uint4{100, 100, 100, 100});
99    sceneCursor["data"].setBinding(Binding(srvBuffers[1]));
100    sceneCursor["material"].setObject(materialObject);
101
102    ShaderCursor materialCursor(materialObject);
103    materialCursor["cb"].setData(uint4{1000, 1000, 1000, 1000});
104    materialCursor["data"].setBinding(Binding(srvBuffers[2]));
105
106    // We have done all the set up work, now it is time to start recording a command buffer for
107    // GPU execution.
108    {
109        auto queue = device->getQueue(QueueType::Graphics);
110
111        auto commandEncoder = queue->createCommandEncoder();
112        auto encoder = commandEncoder->beginComputePass();
113
114        encoder->bindPipeline(pipeline, shaderObject);
115
116        encoder->dispatchCompute(1, 1, 1);
117        encoder->end();
118        queue->submit(commandEncoder->finish());
119        queue->waitOnHost();
120    }
121
122    compareComputeResult(device, resultBuffer, std::array{1123u, 1123u, 1123u, 1123u});
123}
124
125SLANG_UNIT_TEST(nestedParameterBlockTestD3D12)
126{
127    runTestImpl(nestedParameterBlockTestImpl, unitTestContext, DeviceType::D3D12);
128}
129
130SLANG_UNIT_TEST(nestedParameterBlockTestVulkan)
131{
132    runTestImpl(nestedParameterBlockTestImpl, unitTestContext, DeviceType::Vulkan);
133}
134} // namespace gfx_test