yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
8.3 KiB298 linesraw
1#pragma once
2
3#include "core/slang-basic.h"
4#include "renderer-shared.h"
5#include "slang-com-ptr.h"
6#include "slang-gfx.h"
7
8namespace gfx
9{
10
11enum class CommandName
12{
13    SetPipelineState,
14    BindRootShaderObject,
15    SetFramebuffer,
16    ClearFrame,
17    SetViewports,
18    SetScissorRects,
19    SetPrimitiveTopology,
20    SetVertexBuffers,
21    SetIndexBuffer,
22    Draw,
23    DrawIndexed,
24    DrawInstanced,
25    DrawIndexedInstanced,
26    SetStencilReference,
27    DispatchCompute,
28    UploadBufferData,
29    CopyBuffer,
30    WriteTimestamp,
31};
32
33const uint8_t kMaxCommandOperands = 5;
34
35struct Command
36{
37    CommandName name;
38    uint32_t operands[kMaxCommandOperands];
39    Command() = default;
40    Command(CommandName inName, uint32_t op)
41        : name(inName)
42    {
43        operands[0] = op;
44    }
45    Command(CommandName inName, uint32_t op1, uint32_t op2)
46        : name(inName)
47    {
48        operands[0] = op1;
49        operands[1] = op2;
50    }
51    Command(CommandName inName, uint32_t op1, uint32_t op2, uint32_t op3)
52        : name(inName)
53    {
54        operands[0] = op1;
55        operands[1] = op2;
56        operands[2] = op3;
57    }
58    Command(CommandName inName, uint32_t op1, uint32_t op2, uint32_t op3, uint32_t op4)
59        : name(inName)
60    {
61        operands[0] = op1;
62        operands[1] = op2;
63        operands[2] = op3;
64        operands[3] = op4;
65    }
66    Command(
67        CommandName inName,
68        uint32_t op1,
69        uint32_t op2,
70        uint32_t op3,
71        uint32_t op4,
72        uint32_t op5)
73        : name(inName)
74    {
75        operands[0] = op1;
76        operands[1] = op2;
77        operands[2] = op3;
78        operands[3] = op4;
79        operands[4] = op5;
80    }
81};
82
83class CommandWriter
84{
85public:
86    Slang::List<Command> m_commands;
87    Slang::List<Slang::RefPtr<Slang::RefObject>> m_objects;
88    Slang::List<uint8_t> m_data;
89    bool m_hasWriteTimestamps = false;
90
91public:
92    void clear()
93    {
94        m_commands.clear();
95        for (auto& obj : m_objects)
96            obj = nullptr;
97        m_objects.clear();
98        m_data.clear();
99        m_hasWriteTimestamps = false;
100    }
101
102    // Copies user data into `m_data` buffer and returns the offset to retrieve the data.
103    Offset encodeData(const void* data, Size size)
104    {
105        Offset offset = (Offset)m_data.getCount();
106        m_data.setCount(m_data.getCount() + size);
107        memcpy(m_data.getBuffer() + offset, data, size);
108        return offset;
109    }
110
111    Offset encodeObject(Slang::RefObject* obj)
112    {
113        Offset offset = (Offset)m_objects.getCount();
114        m_objects.add(obj);
115        return offset;
116    }
117
118    template<typename T>
119    T* getObject(uint32_t offset)
120    {
121        return static_cast<T*>(m_objects[offset].Ptr());
122    }
123
124    template<typename T>
125    T* getData(Offset offset)
126    {
127        return reinterpret_cast<T*>(m_data.getBuffer() + offset);
128    }
129
130    void setPipelineState(IPipelineState* state)
131    {
132        auto offset = encodeObject(static_cast<PipelineStateBase*>(state));
133        m_commands.add(Command(CommandName::SetPipelineState, (uint32_t)offset));
134    }
135
136    void bindRootShaderObject(IShaderObject* object)
137    {
138        auto rootOffset = encodeObject(static_cast<ShaderObjectBase*>(object));
139        m_commands.add(Command(CommandName::BindRootShaderObject, (uint32_t)rootOffset));
140    }
141
142    void uploadBufferData(IBufferResource* buffer, Offset offset, Size size, void* data)
143    {
144        auto bufferOffset = encodeObject(static_cast<BufferResource*>(buffer));
145        auto dataOffset = encodeData(data, size);
146        m_commands.add(Command(
147            CommandName::UploadBufferData,
148            (uint32_t)bufferOffset,
149            (uint32_t)offset,
150            (uint32_t)size,
151            (uint32_t)dataOffset));
152    }
153
154    void copyBuffer(
155        IBufferResource* dst,
156        Offset dstOffset,
157        IBufferResource* src,
158        Offset srcOffset,
159        Size size)
160    {
161        auto dstBuffer = encodeObject(static_cast<BufferResource*>(dst));
162        auto srcBuffer = encodeObject(static_cast<BufferResource*>(src));
163        m_commands.add(Command(
164            CommandName::CopyBuffer,
165            (uint32_t)dstBuffer,
166            (uint32_t)dstOffset,
167            (uint32_t)srcBuffer,
168            (uint32_t)srcOffset,
169            (uint32_t)size));
170    }
171
172    void setFramebuffer(IFramebuffer* frameBuffer)
173    {
174        auto framebufferOffset = encodeObject(static_cast<FramebufferBase*>(frameBuffer));
175        m_commands.add(Command(CommandName::SetFramebuffer, (uint32_t)framebufferOffset));
176    }
177
178    void clearFrame(uint32_t colorBufferMask, bool clearDepth, bool clearStencil)
179    {
180        m_commands.add(Command(
181            CommandName::ClearFrame,
182            colorBufferMask,
183            clearDepth ? 1 : 0,
184            clearStencil ? 1 : 0));
185    }
186
187    void setViewports(GfxCount count, const Viewport* viewports)
188    {
189        auto offset = encodeData(viewports, sizeof(Viewport) * count);
190        m_commands.add(Command(CommandName::SetViewports, (uint32_t)count, (uint32_t)offset));
191    }
192
193    void setScissorRects(GfxCount count, const ScissorRect* scissors)
194    {
195        auto offset = encodeData(scissors, sizeof(ScissorRect) * count);
196        m_commands.add(Command(CommandName::SetScissorRects, (uint32_t)count, (uint32_t)offset));
197    }
198
199    void setPrimitiveTopology(PrimitiveTopology topology)
200    {
201        m_commands.add(Command(CommandName::SetPrimitiveTopology, (uint32_t)topology));
202    }
203
204    void setVertexBuffers(
205        GfxIndex startSlot,
206        GfxCount slotCount,
207        IBufferResource* const* buffers,
208        const Offset* offsets)
209    {
210        Offset bufferOffset = 0;
211        for (GfxCount i = 0; i < slotCount; i++)
212        {
213            auto offset = encodeObject(static_cast<BufferResource*>(buffers[i]));
214            if (i == 0)
215                bufferOffset = offset;
216        }
217        auto offsetsOffset = encodeData(offsets, sizeof(Size) * slotCount);
218        m_commands.add(Command(
219            CommandName::SetVertexBuffers,
220            (uint32_t)startSlot,
221            (uint32_t)slotCount,
222            (uint32_t)bufferOffset,
223            (uint32_t)offsetsOffset));
224    }
225
226    void setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset)
227    {
228        auto bufferOffset = encodeObject(static_cast<BufferResource*>(buffer));
229        m_commands.add(Command(
230            CommandName::SetIndexBuffer,
231            (uint32_t)bufferOffset,
232            (uint32_t)indexFormat,
233            (uint32_t)offset));
234    }
235
236    void draw(GfxCount vertexCount, GfxIndex startVertex)
237    {
238        m_commands.add(Command(CommandName::Draw, (uint32_t)vertexCount, (uint32_t)startVertex));
239    }
240
241    void drawIndexed(GfxCount indexCount, GfxIndex startIndex, GfxIndex baseVertex)
242    {
243        m_commands.add(Command(
244            CommandName::DrawIndexed,
245            (uint32_t)indexCount,
246            (uint32_t)startIndex,
247            (uint32_t)baseVertex));
248    }
249
250    void drawInstanced(
251        GfxCount vertexCount,
252        GfxCount instanceCount,
253        GfxIndex startVertex,
254        GfxIndex startInstanceLocation)
255    {
256        m_commands.add(Command(
257            CommandName::DrawInstanced,
258            (uint32_t)vertexCount,
259            (uint32_t)instanceCount,
260            (uint32_t)startVertex,
261            (uint32_t)startInstanceLocation));
262    }
263
264    void drawIndexedInstanced(
265        GfxCount indexCount,
266        GfxCount instanceCount,
267        GfxIndex startIndexLocation,
268        GfxIndex baseVertexLocation,
269        GfxIndex startInstanceLocation)
270    {
271        m_commands.add(Command(
272            CommandName::DrawIndexedInstanced,
273            (uint32_t)indexCount,
274            (uint32_t)instanceCount,
275            (uint32_t)startIndexLocation,
276            (uint32_t)baseVertexLocation,
277            (uint32_t)startInstanceLocation));
278    }
279
280    void setStencilReference(uint32_t referenceValue)
281    {
282        m_commands.add(Command(CommandName::SetStencilReference, referenceValue));
283    }
284
285    void dispatchCompute(int x, int y, int z)
286    {
287        m_commands.add(
288            Command(CommandName::DispatchCompute, (uint32_t)x, (uint32_t)y, (uint32_t)z));
289    }
290
291    void writeTimestamp(IQueryPool* pool, GfxIndex index)
292    {
293        auto poolOffset = encodeObject(static_cast<QueryPoolBase*>(pool));
294        m_commands.add(Command(CommandName::WriteTimestamp, (uint32_t)poolOffset, (uint32_t)index));
295        m_hasWriteTimestamps = true;
296    }
297};
298} // namespace gfx