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
8.8 KiB266 linesraw
1#if 0
2// Duplicated: This is identical to slang-rhi\tests\test-texture-shared.cpp
3
4#include "core/slang-basic.h"
5#include "gfx-test-util.h"
6#include "slang-gfx.h"
7#include "slang-rhi/shader-cursor.h"
8#include "unit-test/slang-unit-test.h"
9
10using namespace gfx;
11
12namespace gfx_test
13{
14void setUpAndRunShader(
15    IDevice* device,
16    ComPtr<ITextureResource> tex,
17    ComPtr<IResourceView> texView,
18    ComPtr<IResourceView> bufferView,
19    const char* entryPoint,
20    ComPtr<ISamplerState> sampler = nullptr)
21{
22    Slang::ComPtr<ITransientResourceHeap> transientHeap;
23    ITransientResourceHeap::Desc transientHeapDesc = {};
24    transientHeapDesc.constantBufferSize = 4096;
25    GFX_CHECK_CALL_ABORT(
26        device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef()));
27
28    ComPtr<IShaderProgram> shaderProgram;
29    slang::ProgramLayout* slangReflection;
30    GFX_CHECK_CALL_ABORT(
31        loadComputeProgram(device, shaderProgram, "trivial-copy", entryPoint, slangReflection));
32
33    ComputePipelineStateDesc pipelineDesc = {};
34    pipelineDesc.program = shaderProgram.get();
35    ComPtr<gfx::IPipelineState> pipelineState;
36    GFX_CHECK_CALL_ABORT(
37        device->createComputePipelineState(pipelineDesc, pipelineState.writeRef()));
38
39    // We have done all the set up work, now it is time to start recording a command buffer for
40    // GPU execution.
41    {
42        ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics};
43        auto queue = device->createCommandQueue(queueDesc);
44
45        auto commandBuffer = transientHeap->createCommandBuffer();
46        auto encoder = commandBuffer->encodeComputeCommands();
47
48        auto rootObject = encoder->bindPipeline(pipelineState);
49
50        ShaderCursor entryPointCursor(
51            rootObject->getEntryPoint(0)); // get a cursor the the first entry-point.
52
53        auto& desc = *tex->getDesc();
54        entryPointCursor["width"].setData(desc.size.width);
55        entryPointCursor["height"].setData(desc.size.height);
56
57        // Bind texture view to the entry point
58        entryPointCursor["tex"].setResource(texView);
59
60        if (sampler)
61            entryPointCursor["sampler"].setSampler(sampler);
62
63        // Bind buffer view to the entry point.
64        entryPointCursor["buffer"].setResource(bufferView);
65
66        encoder->dispatchCompute(1, 1, 1);
67        encoder->endEncoding();
68        commandBuffer->close();
69        queue->executeCommandBuffer(commandBuffer);
70        queue->waitOnHost();
71    }
72}
73
74ComPtr<ITextureResource> createTexture(
75    IDevice* device,
76    ITextureResource::Extents extents,
77    gfx::Format format,
78    ITextureResource::SubresourceData* initialData)
79{
80    ITextureResource::Desc texDesc = {};
81    texDesc.type = IResource::Type::Texture2D;
82    texDesc.numMipLevels = 1;
83    texDesc.arraySize = 1;
84    texDesc.size = extents;
85    texDesc.defaultState = ResourceState::UnorderedAccess;
86    texDesc.allowedStates = ResourceStateSet(
87        ResourceState::ShaderResource,
88        ResourceState::UnorderedAccess,
89        ResourceState::CopyDestination,
90        ResourceState::CopySource);
91    texDesc.format = format;
92    texDesc.isShared = true;
93
94    ComPtr<ITextureResource> inTex;
95    GFX_CHECK_CALL_ABORT(device->createTextureResource(texDesc, initialData, inTex.writeRef()));
96    return inTex;
97}
98
99ComPtr<IResourceView> createTexView(IDevice* device, ComPtr<ITextureResource> inTexture)
100{
101    ComPtr<IResourceView> texView;
102    IResourceView::Desc texViewDesc = {};
103    texViewDesc.type = IResourceView::Type::UnorderedAccess;
104    texViewDesc.format =
105        inTexture->getDesc()->format; // TODO: Handle typeless formats - gfxIsTypelessFormat(format)
106                                      // ? convertTypelessFormat(format) : format;
107    GFX_CHECK_CALL_ABORT(device->createTextureView(inTexture, texViewDesc, texView.writeRef()));
108    return texView;
109}
110
111template<typename T>
112ComPtr<IBufferResource> createBuffer(IDevice* device, int size, void* initialData)
113{
114    IBufferResource::Desc bufferDesc = {};
115    bufferDesc.sizeInBytes = size * sizeof(T);
116    bufferDesc.format = gfx::Format::Unknown;
117    bufferDesc.elementSize = sizeof(T);
118    bufferDesc.allowedStates = ResourceStateSet(
119        ResourceState::ShaderResource,
120        ResourceState::UnorderedAccess,
121        ResourceState::CopyDestination,
122        ResourceState::CopySource);
123    bufferDesc.defaultState = ResourceState::UnorderedAccess;
124    bufferDesc.memoryType = MemoryType::DeviceLocal;
125
126    ComPtr<IBufferResource> outBuffer;
127    GFX_CHECK_CALL_ABORT(
128        device->createBufferResource(bufferDesc, initialData, outBuffer.writeRef()));
129    return outBuffer;
130}
131
132ComPtr<IResourceView> createOutBufferView(IDevice* device, ComPtr<IBufferResource> outBuffer)
133{
134    ComPtr<IResourceView> bufferView;
135    IResourceView::Desc viewDesc = {};
136    viewDesc.type = IResourceView::Type::UnorderedAccess;
137    viewDesc.format = Format::Unknown;
138    GFX_CHECK_CALL_ABORT(
139        device->createBufferView(outBuffer, nullptr, viewDesc, bufferView.writeRef()));
140    return bufferView;
141}
142
143void sharedTextureTestImpl(IDevice* srcDevice, IDevice* dstDevice, UnitTestContext* context)
144{
145    ISamplerState::Desc samplerDesc;
146    auto sampler = dstDevice->createSamplerState(samplerDesc);
147
148    float initFloatData[16] = {0.0f};
149    auto floatResults = createBuffer<float>(dstDevice, 16, initFloatData);
150    auto floatBufferView = createOutBufferView(dstDevice, floatResults);
151
152    uint32_t initUintData[16] = {0u};
153    auto uintResults = createBuffer<uint32_t>(dstDevice, 16, initUintData);
154    auto uintBufferView = createOutBufferView(dstDevice, uintResults);
155
156    int32_t initIntData[16] = {0};
157    auto intResults = createBuffer<uint32_t>(dstDevice, 16, initIntData);
158    auto intBufferView = createOutBufferView(dstDevice, intResults);
159
160    ITextureResource::Extents size = {};
161    size.width = 2;
162    size.height = 2;
163    size.depth = 1;
164
165    ITextureResource::Extents bcSize = {};
166    bcSize.width = 4;
167    bcSize.height = 4;
168    bcSize.depth = 1;
169
170    {
171        float texData[] = {
172            1.0f,
173            0.0f,
174            0.0f,
175            1.0f,
176            0.0f,
177            1.0f,
178            0.0f,
179            1.0f,
180            0.0f,
181            0.0f,
182            1.0f,
183            1.0f,
184            0.5f,
185            0.5f,
186            0.5f,
187            1.0f};
188        ITextureResource::SubresourceData subData = {(void*)texData, 32, 0};
189
190        // Create a shareable texture using srcDevice, get its handle, then create a texture using
191        // the handle using dstDevice. Read back the texture and check that its contents are
192        // correct.
193        auto srcTexture = createTexture(srcDevice, size, gfx::Format::R32G32B32A32_FLOAT, &subData);
194
195        InteropHandle sharedHandle;
196        GFX_CHECK_CALL_ABORT(srcTexture->getSharedHandle(&sharedHandle));
197        ComPtr<ITextureResource> dstTexture;
198        size_t sizeInBytes = 0;
199        size_t alignment = 0;
200        GFX_CHECK_CALL_ABORT(srcDevice->getTextureAllocationInfo(
201            *(srcTexture->getDesc()),
202            &sizeInBytes,
203            &alignment));
204        GFX_CHECK_CALL_ABORT(dstDevice->createTextureFromSharedHandle(
205            sharedHandle,
206            *(srcTexture->getDesc()),
207            sizeInBytes,
208            dstTexture.writeRef()));
209        // Reading back the buffer from srcDevice to make sure it's been filled in before reading
210        // anything back from dstDevice
211        // TODO: Implement actual synchronization (and not this hacky solution)
212        compareComputeResult(dstDevice, dstTexture, ResourceState::ShaderResource, texData, 32, 2);
213
214        auto texView = createTexView(dstDevice, dstTexture);
215        setUpAndRunShader(dstDevice, dstTexture, texView, floatBufferView, "copyTexFloat4");
216        compareComputeResult(
217            dstDevice,
218            floatResults,
219            Slang::makeArray<float>(
220                1.0f,
221                0.0f,
222                0.0f,
223                1.0f,
224                0.0f,
225                1.0f,
226                0.0f,
227                1.0f,
228                0.0f,
229                0.0f,
230                1.0f,
231                1.0f,
232                0.5f,
233                0.5f,
234                0.5f,
235                1.0f));
236    }
237}
238
239void sharedTextureTestAPI(
240    UnitTestContext* context,
241    Slang::RenderApiFlag::Enum srcApi,
242    Slang::RenderApiFlag::Enum dstApi)
243{
244    auto srcDevice = createTestingDevice(context, srcApi);
245    auto dstDevice = createTestingDevice(context, dstApi);
246    if (!srcDevice || !dstDevice)
247    {
248        SLANG_IGNORE_TEST;
249    }
250
251    sharedTextureTestImpl(srcDevice, dstDevice, context);
252}
253#if SLANG_WIN64
254SLANG_UNIT_TEST(sharedTextureD3D12ToCUDA)
255{
256    sharedTextureTestAPI(unitTestContext, Slang::RenderApiFlag::D3D12, Slang::RenderApiFlag::CUDA);
257}
258
259SLANG_UNIT_TEST(sharedTextureVulkanToCUDA)
260{
261    sharedTextureTestAPI(unitTestContext, Slang::RenderApiFlag::Vulkan, Slang::RenderApiFlag::CUDA);
262}
263#endif
264} // namespace gfx_test
265
266#endif