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
6.7 KiB226 linesraw
1#if 0
2
3// Duplicated: This test is similar to slang-rhi\tests\test-surface.cpp
4
5#include "gfx-test-util.h"
6#include "platform/window.h"
7#include "unit-test/slang-unit-test.h"
8
9#include <slang-rhi.h>
10#include <slang-rhi/shader-cursor.h>
11
12using namespace rhi;
13
14namespace gfx_test
15{
16struct Vertex
17{
18    float position[3];
19};
20
21static const int kVertexCount = 3;
22static const Vertex kVertexData[kVertexCount] = {
23    {0, 0, 1},
24    {4, 0, 1},
25    {0, 4, 1},
26};
27
28struct SwapchainResizeTest
29{
30    IDevice* device;
31    UnitTestContext* context;
32
33    ComPtr<platform::Window> window;
34    ComPtr<ICommandQueue> queue;
35    ComPtr<ISurface> surface;
36
37    ComPtr<ITexture> swapchainImages[2];
38    uint32_t swapchainImageCount = 2;
39    Format desiredFormat = Format::RGBA8Unorm;
40
41    ComPtr<IBuffer> vertexBuffer;
42    ComPtr<IInputLayout> inputLayout;
43    ComPtr<IRenderPipeline> pipeline;
44    ComPtr<IShaderProgram> shaderProgram;
45    ComPtr<IShaderObject> rootShaderObject;
46
47    uint32_t width = 500;
48    uint32_t height = 500;
49
50    void init(IDevice* device, UnitTestContext* context)
51    {
52        this->device = device;
53        this->context = context;
54    }
55
56    void createSwapchainAndResources()
57    {
58        // Create window
59        platform::Application::init();
60        platform::WindowDesc windowDesc;
61        windowDesc.title = "";
62        windowDesc.width = width;
63        windowDesc.height = height;
64        windowDesc.style = platform::WindowStyle::Default;
65        window = platform::Application::createWindow(windowDesc);
66
67        // Create surface
68        WindowHandle windowHandle = WindowHandle::fromHwnd((void*)window->getNativeHandle().handleValues[0]);
69        surface = device->createSurface(windowHandle);
70
71        // Configure surface (swapchain)
72        SurfaceConfig config = {};
73        config.format = desiredFormat;
74        config.width = width;
75        config.height = height;
76        config.desiredImageCount = swapchainImageCount;
77        config.vsync = true;
78        surface->configure(config);
79
80        // Create vertex buffer
81        BufferDesc vertexBufferDesc = {};
82        vertexBufferDesc.size = sizeof(Vertex) * kVertexCount;
83        vertexBufferDesc.memoryType = MemoryType::DeviceLocal;
84        vertexBufferDesc.usage = BufferUsage::VertexBuffer;
85        vertexBufferDesc.defaultState = ResourceState::VertexBuffer;
86        vertexBuffer = device->createBuffer(vertexBufferDesc, kVertexData);
87
88        // Input layout
89        InputElementDesc inputElements[] = {
90            {"POSITIONA", 0, Format::RGB32Float, offsetof(Vertex, position), 0},
91        };
92        VertexStreamDesc vertexStreams[] = {
93            {sizeof(Vertex), InputSlotClass::PerVertex, 0},
94        };
95        InputLayoutDesc inputLayoutDesc = {};
96        inputLayoutDesc.inputElementCount = sizeof(inputElements) / sizeof(InputElementDesc);
97        inputLayoutDesc.inputElements = inputElements;
98        inputLayoutDesc.vertexStreamCount = sizeof(vertexStreams) / sizeof(VertexStreamDesc);;
99        inputLayoutDesc.vertexStreams = vertexStreams;
100
101        GFX_CHECK_CALL_ABORT(device->createInputLayout(inputLayoutDesc, inputLayout.writeRef()));
102
103        ComPtr<IShaderProgram> shaderProgram;
104        slang::ProgramLayout* slangReflection = nullptr;
105        GFX_CHECK_CALL_ABORT(loadGraphicsProgram(
106            device,
107            shaderProgram,
108            "swapchain-shader",
109            "vertexMain",
110            "fragmentMain",
111            slangReflection
112        ));
113
114
115        // Pipeline
116        ColorTargetDesc colorTarget = {};
117        colorTarget.format = desiredFormat;
118        RenderPipelineDesc pipelineDesc = {};
119        pipelineDesc.program = shaderProgram.get();
120        pipelineDesc.inputLayout = inputLayout.get();
121        pipelineDesc.primitiveTopology = PrimitiveTopology::TriangleList;
122        pipelineDesc.targets = &colorTarget;
123        pipelineDesc.targetCount = 1;
124        pipeline = device->createRenderPipeline(pipelineDesc);
125    }
126
127    void renderFrame(uint32_t imageIndex)  
128    {  
129        // Acquire next image  
130        ComPtr<ITexture> backBuffer;  
131        if (SLANG_FAILED(surface->acquireNextImage(backBuffer.writeRef())))  
132        {  
133            return;  
134        }  
135
136        // Create command encoder  
137        ComPtr<ICommandQueue> queue = device->getQueue(QueueType::Graphics);  
138        ComPtr<ICommandEncoder> encoder = queue->createCommandEncoder();  
139
140        // Render pass setup  
141        RenderPassColorAttachment colorAttachment = {};  
142        colorAttachment.view = backBuffer->getDefaultView();  
143        colorAttachment.loadOp = LoadOp::Clear;  
144        colorAttachment.storeOp = StoreOp::Store;  
145        float clearColor[4] = {0.2f, 0.2f, 0.2f, 1.0f};  
146        memcpy(colorAttachment.clearValue, clearColor, sizeof(clearColor));  
147        RenderPassDesc passDesc = {};  
148        passDesc.colorAttachments = &colorAttachment;  
149        passDesc.colorAttachmentCount = 1;  
150
151        // Begin render pass  
152        auto pass = encoder->beginRenderPass(passDesc);  
153
154        // Bind pipeline and root object  
155        pass->bindPipeline(pipeline, rootShaderObject);  
156
157        // Set render state  
158        RenderState state = {};  
159        state.vertexBuffers[0] = BufferOffsetPair(vertexBuffer, 0);  
160        state.vertexBufferCount = 1;  
161        // Set viewport  
162        Viewport viewport = Viewport::fromSize((float)width, (float)height);  
163        state.viewportCount = 1;
164        state.viewports[0] = viewport;
165
166        pass->setRenderState(state);  
167
168        // Draw  
169        DrawArguments args = {};  
170        args.vertexCount = kVertexCount;  
171        pass->draw(args);  
172
173        pass->end();  
174        ComPtr<ICommandBuffer> cmdBuffer;  
175        encoder->finish(cmdBuffer.writeRef());  
176        queue->submit(cmdBuffer);  
177
178        // Present  
179        surface->present();  
180    }
181
182    void run()
183    {
184        createSwapchainAndResources();
185        for (uint32_t i = 0; i < 5; ++i)
186        {
187            renderFrame(i % swapchainImageCount);
188        }
189        queue->waitOnHost();
190
191        // Resize swapchain
192        width = 700;
193        height = 700;
194        SurfaceConfig config = surface->getConfig();
195        config.width = width;
196        config.height = height;
197        surface->configure(config);
198
199        for (uint32_t i = 0; i < 5; ++i)
200        {
201            renderFrame(i % swapchainImageCount);
202        }
203        queue->waitOnHost();
204    }
205};
206
207void swapchainResizeTestImpl(IDevice* device, UnitTestContext* context)
208{
209    SwapchainResizeTest t;
210    t.init(device, context);
211    t.run();
212}
213
214SLANG_UNIT_TEST(swapchainResizeD3D12)
215{
216    runTestImpl(swapchainResizeTestImpl, unitTestContext, DeviceType::D3D12);
217}
218
219SLANG_UNIT_TEST(swapchainResizeVulkan)
220{
221    runTestImpl(swapchainResizeTestImpl, unitTestContext, DeviceType::Vulkan);
222}
223
224} // namespace gfx_test
225
226#endif