yum-mirror/slang

Making it easier to work with shaders

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

Ellie HermaszewskaMove switch statement bodies to their own lines (#5493)b118451e3

master
28.3 KiB813 linesraw
1#include "immediate-renderer-base.h"
2
3#include "command-encoder-com-forward.h"
4#include "command-writer.h"
5#include "core/slang-basic.h"
6#include "core/slang-blob.h"
7#include "simple-render-pass-layout.h"
8#include "simple-transient-resource-heap.h"
9
10namespace gfx
11{
12using Slang::RefPtr;
13using Slang::List;
14using Slang::ShortList;
15using Slang::ListBlob;
16using Slang::Index;
17using Slang::RefObject;
18using Slang::ComPtr;
19using Slang::Guid;
20
21namespace
22{
23
24class CommandBufferImpl : public ICommandBuffer, public Slang::ComObject
25{
26public:
27    SLANG_COM_OBJECT_IUNKNOWN_ALL
28    ICommandBuffer* getInterface(const Guid& guid)
29    {
30        if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ICommandBuffer)
31            return static_cast<ICommandBuffer*>(this);
32        return nullptr;
33    }
34
35public:
36    CommandWriter m_writer;
37    bool m_hasWriteTimestamps = false;
38    RefPtr<ImmediateRendererBase> m_renderer;
39    RefPtr<ShaderObjectBase> m_rootShaderObject;
40    TransientResourceHeapBase* m_transientHeap;
41
42    void init(ImmediateRendererBase* renderer, TransientResourceHeapBase* transientHeap)
43    {
44        m_renderer = renderer;
45        m_transientHeap = transientHeap;
46    }
47
48    void reset() { m_writer.clear(); }
49
50    class ResourceCommandEncoderImpl : public IResourceCommandEncoder
51    {
52    public:
53        CommandWriter* m_writer;
54        CommandBufferImpl* m_commandBuffer;
55        void init(CommandBufferImpl* cmdBuffer)
56        {
57            m_writer = &cmdBuffer->m_writer;
58            m_commandBuffer = cmdBuffer;
59        }
60
61        virtual void* getInterface(SlangUUID const& uuid)
62        {
63            if (uuid == GfxGUID::IID_IResourceCommandEncoder ||
64                uuid == ISlangUnknown::getTypeGuid())
65            {
66                return this;
67            }
68            return nullptr;
69        }
70        virtual SLANG_NO_THROW SlangResult SLANG_MCALL
71        queryInterface(SlangUUID const& uuid, void** outObject) override
72        {
73            if (auto ptr = getInterface(uuid))
74            {
75                *outObject = ptr;
76                return SLANG_OK;
77            }
78            return SLANG_E_NO_INTERFACE;
79        }
80        virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; }
81        virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; }
82
83        virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {}
84        virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer(
85            IBufferResource* dst,
86            size_t dstOffset,
87            IBufferResource* src,
88            size_t srcOffset,
89            size_t size) override
90        {
91            m_writer->copyBuffer(dst, dstOffset, src, srcOffset, size);
92        }
93
94        virtual SLANG_NO_THROW void SLANG_MCALL
95        uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) override
96        {
97            m_writer->uploadBufferData(dst, offset, size, data);
98        }
99
100        virtual SLANG_NO_THROW void SLANG_MCALL
101        writeTimestamp(IQueryPool* pool, GfxIndex index) override
102        {
103            m_writer->writeTimestamp(pool, index);
104        }
105
106        virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier(
107            GfxCount count,
108            ITextureResource* const* textures,
109            ResourceState src,
110            ResourceState dst) override
111        {
112        }
113
114        virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier(
115            GfxCount count,
116            IBufferResource* const* buffers,
117            ResourceState src,
118            ResourceState dst) override
119        {
120        }
121
122        virtual SLANG_NO_THROW void SLANG_MCALL copyTexture(
123            ITextureResource* dst,
124            ResourceState dstState,
125            SubresourceRange dstSubresource,
126            ITextureResource::Offset3D dstOffset,
127            ITextureResource* src,
128            ResourceState srcState,
129            SubresourceRange srcSubresource,
130            ITextureResource::Offset3D srcOffset,
131            ITextureResource::Extents extent) override
132        {
133            SLANG_UNUSED(dst);
134            SLANG_UNUSED(dstState);
135            SLANG_UNUSED(dstSubresource);
136            SLANG_UNUSED(dstOffset);
137            SLANG_UNUSED(src);
138            SLANG_UNUSED(srcState);
139            SLANG_UNUSED(srcSubresource);
140            SLANG_UNUSED(srcOffset);
141            SLANG_UNUSED(extent);
142            SLANG_UNIMPLEMENTED_X("copyTexture");
143        }
144
145        virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData(
146            ITextureResource* dst,
147            SubresourceRange subResourceRange,
148            ITextureResource::Offset3D offset,
149            ITextureResource::Extents extend,
150            ITextureResource::SubresourceData* subResourceData,
151            GfxCount subResourceDataCount) override
152        {
153            SLANG_UNUSED(dst);
154            SLANG_UNUSED(subResourceRange);
155            SLANG_UNUSED(offset);
156            SLANG_UNUSED(extend);
157            SLANG_UNUSED(subResourceData);
158            SLANG_UNUSED(subResourceDataCount);
159            SLANG_UNIMPLEMENTED_X("uploadTextureData");
160        }
161
162        virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView(
163            IResourceView* view,
164            ClearValue* clearValue,
165            ClearResourceViewFlags::Enum flags) override
166        {
167            SLANG_UNUSED(view);
168            SLANG_UNUSED(clearValue);
169            SLANG_UNUSED(flags);
170            SLANG_UNIMPLEMENTED_X("clearResourceView");
171        }
172
173        virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
174            ITextureResource* source,
175            ResourceState sourceState,
176            SubresourceRange sourceRange,
177            ITextureResource* dest,
178            ResourceState destState,
179            SubresourceRange destRange) override
180        {
181            SLANG_UNUSED(source);
182            SLANG_UNUSED(sourceState);
183            SLANG_UNUSED(sourceRange);
184            SLANG_UNUSED(dest);
185            SLANG_UNUSED(destState);
186            SLANG_UNUSED(destRange);
187            SLANG_UNIMPLEMENTED_X("resolveResource");
188        }
189
190        virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(
191            IQueryPool* queryPool,
192            GfxIndex index,
193            GfxCount count,
194            IBufferResource* buffer,
195            Offset offset) override
196        {
197            SLANG_UNUSED(queryPool);
198            SLANG_UNUSED(index);
199            SLANG_UNUSED(count);
200            SLANG_UNUSED(buffer);
201            SLANG_UNUSED(offset);
202            SLANG_UNIMPLEMENTED_X("resolveQuery");
203        }
204
205        virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(
206            IBufferResource* dst,
207            Offset dstOffset,
208            Size dstSize,
209            Size dstRowStride,
210            ITextureResource* src,
211            ResourceState srcState,
212            SubresourceRange srcSubresource,
213            ITextureResource::Offset3D srcOffset,
214            ITextureResource::Extents extent) override
215        {
216            SLANG_UNUSED(dst);
217            SLANG_UNUSED(dstOffset);
218            SLANG_UNUSED(dstSize);
219            SLANG_UNUSED(dstRowStride);
220            SLANG_UNUSED(src);
221            SLANG_UNUSED(srcState);
222            SLANG_UNUSED(srcSubresource);
223            SLANG_UNUSED(srcOffset);
224            SLANG_UNUSED(extent);
225            SLANG_UNIMPLEMENTED_X("copyTextureToBuffer");
226        }
227
228        virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier(
229            ITextureResource* texture,
230            SubresourceRange subresourceRange,
231            ResourceState src,
232            ResourceState dst) override
233        {
234            SLANG_UNUSED(texture);
235            SLANG_UNUSED(subresourceRange);
236            SLANG_UNUSED(src);
237            SLANG_UNUSED(dst);
238            SLANG_UNIMPLEMENTED_X("textureSubresourceBarrier");
239        }
240
241        virtual SLANG_NO_THROW void SLANG_MCALL
242        beginDebugEvent(const char* name, float rgbColor[3]) override
243        {
244            SLANG_UNUSED(name);
245            SLANG_UNUSED(rgbColor);
246        }
247        virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override {}
248    };
249
250    ResourceCommandEncoderImpl m_resourceCommandEncoder;
251
252    virtual SLANG_NO_THROW void SLANG_MCALL
253    encodeResourceCommands(IResourceCommandEncoder** outEncoder) override
254    {
255        m_resourceCommandEncoder.init(this);
256        *outEncoder = &m_resourceCommandEncoder;
257    }
258
259    class RenderCommandEncoderImpl : public IRenderCommandEncoder, public ResourceCommandEncoderImpl
260    {
261    public:
262        SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl)
263        virtual void* getInterface(SlangUUID const& uuid) override
264        {
265            if (uuid == GfxGUID::IID_IResourceCommandEncoder ||
266                uuid == GfxGUID::IID_IRenderCommandEncoder || uuid == ISlangUnknown::getTypeGuid())
267            {
268                return this;
269            }
270            return nullptr;
271        }
272
273    public:
274        virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {}
275
276        void init(
277            CommandBufferImpl* cmdBuffer,
278            SimpleRenderPassLayout* renderPass,
279            IFramebuffer* framebuffer)
280        {
281            ResourceCommandEncoderImpl::init(cmdBuffer);
282
283            // Encode clear commands.
284            m_writer->setFramebuffer(framebuffer);
285            uint32_t clearMask = 0;
286            for (Index i = 0; i < renderPass->m_renderTargetAccesses.getCount(); i++)
287            {
288                auto& access = renderPass->m_renderTargetAccesses[i];
289                // Clear.
290                if (access.loadOp == IRenderPassLayout::TargetLoadOp::Clear)
291                {
292                    clearMask |= (1 << (uint32_t)i);
293                }
294            }
295            bool clearDepth = false;
296            bool clearStencil = false;
297            if (renderPass->m_hasDepthStencil)
298            {
299                // Clear.
300                if (renderPass->m_depthStencilAccess.loadOp ==
301                    IRenderPassLayout::TargetLoadOp::Clear)
302                {
303                    clearDepth = true;
304                }
305                if (renderPass->m_depthStencilAccess.stencilLoadOp ==
306                    IRenderPassLayout::TargetLoadOp::Clear)
307                {
308                    clearStencil = true;
309                }
310            }
311            m_writer->clearFrame(clearMask, clearDepth, clearStencil);
312        }
313
314        virtual SLANG_NO_THROW Result SLANG_MCALL
315        bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override
316        {
317            m_writer->setPipelineState(state);
318            auto stateImpl = static_cast<PipelineStateBase*>(state);
319            SLANG_RETURN_ON_FAIL(m_commandBuffer->m_renderer->createRootShaderObject(
320                stateImpl->m_program,
321                m_commandBuffer->m_rootShaderObject.writeRef()));
322            *outRootObject = m_commandBuffer->m_rootShaderObject.Ptr();
323            return SLANG_OK;
324        }
325
326        virtual SLANG_NO_THROW Result SLANG_MCALL
327        bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) override
328        {
329            m_writer->setPipelineState(state);
330            auto stateImpl = static_cast<PipelineStateBase*>(state);
331            SLANG_RETURN_ON_FAIL(m_commandBuffer->m_renderer->createRootShaderObject(
332                stateImpl->m_program,
333                m_commandBuffer->m_rootShaderObject.writeRef()));
334            m_commandBuffer->m_rootShaderObject->copyFrom(
335                rootObject,
336                m_commandBuffer->m_transientHeap);
337            return SLANG_OK;
338        }
339
340        virtual SLANG_NO_THROW void SLANG_MCALL
341        setViewports(GfxCount count, const Viewport* viewports) override
342        {
343            m_writer->setViewports(count, viewports);
344        }
345        virtual SLANG_NO_THROW void SLANG_MCALL
346        setScissorRects(GfxCount count, const ScissorRect* scissors) override
347        {
348            m_writer->setScissorRects(count, scissors);
349        }
350        virtual SLANG_NO_THROW void SLANG_MCALL
351        setPrimitiveTopology(PrimitiveTopology topology) override
352        {
353            m_writer->setPrimitiveTopology(topology);
354        }
355        virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers(
356            GfxIndex startSlot,
357            GfxCount slotCount,
358            IBufferResource* const* buffers,
359            const Offset* offsets) override
360        {
361            m_writer->setVertexBuffers(startSlot, slotCount, buffers, offsets);
362        }
363
364        virtual SLANG_NO_THROW void SLANG_MCALL
365        setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset) override
366        {
367            m_writer->setIndexBuffer(buffer, indexFormat, offset);
368        }
369
370        virtual SLANG_NO_THROW Result SLANG_MCALL
371        draw(GfxCount vertexCount, GfxIndex startVertex) override
372        {
373            m_writer->bindRootShaderObject(m_commandBuffer->m_rootShaderObject);
374            m_writer->draw(vertexCount, startVertex);
375            return SLANG_OK;
376        }
377
378        virtual SLANG_NO_THROW Result SLANG_MCALL
379        drawIndexed(GfxCount indexCount, GfxIndex startIndex, GfxIndex baseVertex) override
380        {
381            m_writer->bindRootShaderObject(m_commandBuffer->m_rootShaderObject);
382            m_writer->drawIndexed(indexCount, startIndex, baseVertex);
383            return SLANG_OK;
384        }
385
386        virtual SLANG_NO_THROW void SLANG_MCALL
387        setStencilReference(uint32_t referenceValue) override
388        {
389            m_writer->setStencilReference(referenceValue);
390        }
391
392        virtual SLANG_NO_THROW Result SLANG_MCALL drawIndirect(
393            GfxCount maxDrawCount,
394            IBufferResource* argBuffer,
395            Offset argOffset,
396            IBufferResource* countBuffer,
397            Offset countOffset) override
398        {
399            SLANG_UNUSED(maxDrawCount);
400            SLANG_UNUSED(argBuffer);
401            SLANG_UNUSED(argOffset);
402            SLANG_UNUSED(countBuffer);
403            SLANG_UNUSED(countOffset);
404            SLANG_UNIMPLEMENTED_X("ImmediateRenderBase::drawIndirect");
405            return SLANG_OK;
406        }
407
408        virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexedIndirect(
409            GfxCount maxDrawCount,
410            IBufferResource* argBuffer,
411            Offset argOffset,
412            IBufferResource* countBuffer,
413            Offset countOffset) override
414        {
415            SLANG_UNUSED(maxDrawCount);
416            SLANG_UNUSED(argBuffer);
417            SLANG_UNUSED(argOffset);
418            SLANG_UNUSED(countBuffer);
419            SLANG_UNUSED(countOffset);
420            SLANG_UNIMPLEMENTED_X("ImmediateRenderBase::drawIndirect");
421            return SLANG_OK;
422        }
423
424        virtual SLANG_NO_THROW Result SLANG_MCALL drawMeshTasks(int, int, int) override
425        {
426            SLANG_UNIMPLEMENTED_X("ImmediateRenderBase::drawMeshTasks");
427        }
428
429        virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions(
430            GfxCount samplesPerPixel,
431            GfxCount pixelCount,
432            const SamplePosition* samplePositions) override
433        {
434            SLANG_UNUSED(samplesPerPixel);
435            SLANG_UNUSED(pixelCount);
436            SLANG_UNUSED(samplePositions);
437            return SLANG_E_NOT_AVAILABLE;
438        }
439
440        virtual SLANG_NO_THROW Result SLANG_MCALL drawInstanced(
441            GfxCount vertexCount,
442            GfxCount instanceCount,
443            GfxIndex startVertex,
444            GfxIndex startInstanceLocation) override
445        {
446            m_writer->bindRootShaderObject(m_commandBuffer->m_rootShaderObject);
447            m_writer->drawInstanced(vertexCount, instanceCount, startVertex, startInstanceLocation);
448            return SLANG_OK;
449        }
450
451        virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexedInstanced(
452            GfxCount indexCount,
453            GfxCount instanceCount,
454            GfxIndex startIndexLocation,
455            GfxIndex baseVertexLocation,
456            GfxIndex startInstanceLocation) override
457        {
458            m_writer->bindRootShaderObject(m_commandBuffer->m_rootShaderObject);
459            m_writer->drawIndexedInstanced(
460                indexCount,
461                instanceCount,
462                startIndexLocation,
463                baseVertexLocation,
464                startInstanceLocation);
465            return SLANG_OK;
466        }
467    };
468
469    RenderCommandEncoderImpl m_renderCommandEncoder;
470    virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands(
471        IRenderPassLayout* renderPass,
472        IFramebuffer* framebuffer,
473        IRenderCommandEncoder** outEncoder) override
474    {
475        m_renderCommandEncoder.init(
476            this,
477            static_cast<SimpleRenderPassLayout*>(renderPass),
478            framebuffer);
479        *outEncoder = &m_renderCommandEncoder;
480    }
481
482    class ComputeCommandEncoderImpl : public IComputeCommandEncoder,
483                                      public ResourceCommandEncoderImpl
484    {
485    public:
486        SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl)
487        virtual void* getInterface(SlangUUID const& uuid) override
488        {
489            if (uuid == GfxGUID::IID_IResourceCommandEncoder ||
490                uuid == GfxGUID::IID_IComputeCommandEncoder || uuid == ISlangUnknown::getTypeGuid())
491            {
492                return this;
493            }
494            return nullptr;
495        }
496
497    public:
498        virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {}
499
500        virtual SLANG_NO_THROW Result SLANG_MCALL
501        bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override
502        {
503            m_writer->setPipelineState(state);
504            auto stateImpl = static_cast<PipelineStateBase*>(state);
505            SLANG_RETURN_ON_FAIL(m_commandBuffer->m_renderer->createRootShaderObject(
506                stateImpl->m_program,
507                m_commandBuffer->m_rootShaderObject.writeRef()));
508            *outRootObject = m_commandBuffer->m_rootShaderObject.Ptr();
509            return SLANG_OK;
510        }
511
512        virtual SLANG_NO_THROW Result SLANG_MCALL
513        bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) override
514        {
515            m_writer->setPipelineState(state);
516            auto stateImpl = static_cast<PipelineStateBase*>(state);
517            SLANG_RETURN_ON_FAIL(m_commandBuffer->m_renderer->createRootShaderObject(
518                stateImpl->m_program,
519                m_commandBuffer->m_rootShaderObject.writeRef()));
520            m_commandBuffer->m_rootShaderObject->copyFrom(
521                rootObject,
522                m_commandBuffer->m_transientHeap);
523            return SLANG_OK;
524        }
525
526        virtual SLANG_NO_THROW Result SLANG_MCALL dispatchCompute(int x, int y, int z) override
527        {
528            m_writer->bindRootShaderObject(m_commandBuffer->m_rootShaderObject);
529            m_writer->dispatchCompute(x, y, z);
530            return SLANG_OK;
531        }
532
533        virtual SLANG_NO_THROW Result SLANG_MCALL
534        dispatchComputeIndirect(IBufferResource* argBuffer, Offset offset) override
535        {
536            SLANG_UNIMPLEMENTED_X("ImmediateRenderBase::dispatchComputeIndirect");
537        }
538    };
539
540    ComputeCommandEncoderImpl m_computeCommandEncoder;
541    virtual SLANG_NO_THROW void SLANG_MCALL
542    encodeComputeCommands(IComputeCommandEncoder** outEncoder) override
543    {
544        m_computeCommandEncoder.init(this);
545        *outEncoder = &m_computeCommandEncoder;
546    }
547
548    virtual SLANG_NO_THROW void SLANG_MCALL
549    encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override
550    {
551        *outEncoder = nullptr;
552    }
553
554    virtual SLANG_NO_THROW void SLANG_MCALL close() override {}
555
556    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override
557    {
558        return SLANG_FAIL;
559    }
560
561    void execute()
562    {
563        for (auto& cmd : m_writer.m_commands)
564        {
565            auto name = cmd.name;
566            switch (name)
567            {
568            case CommandName::SetPipelineState:
569                m_renderer->setPipelineState(
570                    m_writer.getObject<PipelineStateBase>(cmd.operands[0]));
571                break;
572            case CommandName::BindRootShaderObject:
573                m_renderer->bindRootShaderObject(
574                    m_writer.getObject<ShaderObjectBase>(cmd.operands[0]));
575                break;
576            case CommandName::SetFramebuffer:
577                m_renderer->setFramebuffer(m_writer.getObject<FramebufferBase>(cmd.operands[0]));
578                break;
579            case CommandName::ClearFrame:
580                m_renderer->clearFrame(
581                    cmd.operands[0],
582                    (cmd.operands[1] != 0),
583                    (cmd.operands[2] != 0));
584                break;
585            case CommandName::SetViewports:
586                m_renderer->setViewports(
587                    (UInt)cmd.operands[0],
588                    m_writer.getData<Viewport>(cmd.operands[1]));
589                break;
590            case CommandName::SetScissorRects:
591                m_renderer->setScissorRects(
592                    (UInt)cmd.operands[0],
593                    m_writer.getData<ScissorRect>(cmd.operands[1]));
594                break;
595            case CommandName::SetPrimitiveTopology:
596                m_renderer->setPrimitiveTopology((PrimitiveTopology)cmd.operands[0]);
597                break;
598            case CommandName::SetVertexBuffers:
599                {
600                    ShortList<IBufferResource*> bufferResources;
601                    for (uint32_t i = 0; i < cmd.operands[1]; i++)
602                    {
603                        bufferResources.add(
604                            m_writer.getObject<BufferResource>(cmd.operands[2] + i));
605                    }
606                    m_renderer->setVertexBuffers(
607                        cmd.operands[0],
608                        cmd.operands[1],
609                        bufferResources.getArrayView().getBuffer(),
610                        m_writer.getData<Offset>(cmd.operands[3]));
611                }
612                break;
613            case CommandName::SetIndexBuffer:
614                m_renderer->setIndexBuffer(
615                    m_writer.getObject<BufferResource>(cmd.operands[0]),
616                    (Format)cmd.operands[1],
617                    (UInt)cmd.operands[2]);
618                break;
619            case CommandName::Draw:
620                m_renderer->draw(cmd.operands[0], cmd.operands[1]);
621                break;
622            case CommandName::DrawIndexed:
623                m_renderer->drawIndexed(cmd.operands[0], cmd.operands[1], cmd.operands[2]);
624                break;
625            case CommandName::DrawInstanced:
626                m_renderer->drawInstanced(
627                    cmd.operands[0],
628                    cmd.operands[1],
629                    cmd.operands[2],
630                    cmd.operands[3]);
631                break;
632            case CommandName::DrawIndexedInstanced:
633                m_renderer->drawIndexedInstanced(
634                    cmd.operands[0],
635                    cmd.operands[1],
636                    cmd.operands[2],
637                    cmd.operands[3],
638                    cmd.operands[4]);
639                break;
640            case CommandName::SetStencilReference:
641                m_renderer->setStencilReference(cmd.operands[0]);
642                break;
643            case CommandName::DispatchCompute:
644                m_renderer->dispatchCompute(
645                    int(cmd.operands[0]),
646                    int(cmd.operands[1]),
647                    int(cmd.operands[2]));
648                break;
649            case CommandName::UploadBufferData:
650                m_renderer->uploadBufferData(
651                    m_writer.getObject<BufferResource>(cmd.operands[0]),
652                    cmd.operands[1],
653                    cmd.operands[2],
654                    m_writer.getData<uint8_t>(cmd.operands[3]));
655                break;
656            case CommandName::CopyBuffer:
657                m_renderer->copyBuffer(
658                    m_writer.getObject<BufferResource>(cmd.operands[0]),
659                    cmd.operands[1],
660                    m_writer.getObject<BufferResource>(cmd.operands[2]),
661                    cmd.operands[3],
662                    cmd.operands[4]);
663                break;
664            case CommandName::WriteTimestamp:
665                m_renderer->writeTimestamp(
666                    m_writer.getObject<QueryPoolBase>(cmd.operands[0]),
667                    (GfxIndex)cmd.operands[1]);
668                break;
669            default:
670                assert(!"unknown command");
671                break;
672            }
673        }
674        m_writer.clear();
675    }
676};
677
678class CommandQueueImpl : public ImmediateCommandQueueBase
679{
680public:
681    ICommandQueue::Desc m_desc;
682
683    ImmediateRendererBase* getRenderer()
684    {
685        return static_cast<ImmediateRendererBase*>(m_renderer.get());
686    }
687
688    CommandQueueImpl(ImmediateRendererBase* renderer)
689    {
690        // Don't establish strong reference to `Device` at start, because
691        // there will be only one instance of command queue and it will be
692        // owned by `Device`. We should establish a strong reference only
693        // when there are external references to the command queue.
694        m_renderer.setWeakReference(renderer);
695        m_desc.type = ICommandQueue::QueueType::Graphics;
696    }
697
698    ~CommandQueueImpl() { getRenderer()->m_queueCreateCount--; }
699
700    virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
701
702    virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers(
703        GfxCount count,
704        ICommandBuffer* const* commandBuffers,
705        IFence* fence,
706        uint64_t valueToSignal) override
707    {
708        // TODO: implement fence signal.
709        assert(fence == nullptr);
710
711        CommandBufferInfo info = {};
712        for (GfxIndex i = 0; i < count; i++)
713        {
714            info.hasWriteTimestamps |=
715                static_cast<CommandBufferImpl*>(commandBuffers[i])->m_writer.m_hasWriteTimestamps;
716        }
717        static_cast<ImmediateRendererBase*>(m_renderer.get())->beginCommandBuffer(info);
718        for (GfxIndex i = 0; i < count; i++)
719        {
720            static_cast<CommandBufferImpl*>(commandBuffers[i])->execute();
721        }
722        static_cast<ImmediateRendererBase*>(m_renderer.get())->endCommandBuffer(info);
723    }
724
725    virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override { getRenderer()->waitForGpu(); }
726
727    virtual SLANG_NO_THROW Result SLANG_MCALL
728    waitForFenceValuesOnDevice(GfxCount fenceCount, IFence** fences, uint64_t* waitValues) override
729    {
730        return SLANG_FAIL;
731    }
732
733    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override
734    {
735        return getRenderer()->m_queue->getNativeHandle(outHandle);
736    }
737};
738
739using TransientResourceHeapImpl =
740    SimpleTransientResourceHeap<ImmediateRendererBase, CommandBufferImpl>;
741
742} // namespace
743
744ImmediateRendererBase::ImmediateRendererBase()
745{
746    m_queue = new CommandQueueImpl(this);
747}
748
749SLANG_NO_THROW Result SLANG_MCALL ImmediateRendererBase::createTransientResourceHeap(
750    const ITransientResourceHeap::Desc& desc,
751    ITransientResourceHeap** outHeap)
752{
753    RefPtr<TransientResourceHeapImpl> result = new TransientResourceHeapImpl();
754    SLANG_RETURN_ON_FAIL(result->init(this, desc));
755    returnComPtr(outHeap, result);
756    return SLANG_OK;
757}
758
759SLANG_NO_THROW Result SLANG_MCALL
760ImmediateRendererBase::createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue)
761{
762    SLANG_UNUSED(desc);
763    // Only one queue is supported.
764    if (m_queueCreateCount != 0)
765        return SLANG_FAIL;
766    m_queue->establishStrongReferenceToDevice();
767    returnComPtr(outQueue, m_queue);
768    return SLANG_OK;
769}
770
771SLANG_NO_THROW Result SLANG_MCALL ImmediateRendererBase::createRenderPassLayout(
772    const IRenderPassLayout::Desc& desc,
773    IRenderPassLayout** outRenderPassLayout)
774{
775    RefPtr<SimpleRenderPassLayout> renderPass = new SimpleRenderPassLayout();
776    renderPass->init(desc);
777    returnComPtr(outRenderPassLayout, renderPass);
778    return SLANG_OK;
779}
780
781void ImmediateRendererBase::uploadBufferData(
782    IBufferResource* dst,
783    size_t offset,
784    size_t size,
785    void* data)
786{
787    auto buffer = map(dst, gfx::MapFlavor::WriteDiscard);
788    memcpy((uint8_t*)buffer + offset, data, size);
789    unmap(dst, offset, size);
790}
791
792SLANG_NO_THROW SlangResult SLANG_MCALL ImmediateRendererBase::readBufferResource(
793    IBufferResource* buffer,
794    size_t offset,
795    size_t size,
796    ISlangBlob** outBlob)
797{
798    List<uint8_t> blobData;
799
800    blobData.setCount((Index)size);
801    auto content = (uint8_t*)map(buffer, gfx::MapFlavor::HostRead);
802    if (!content)
803        return SLANG_FAIL;
804    memcpy(blobData.getBuffer(), content + offset, size);
805    unmap(buffer, offset, size);
806
807    auto blob = ListBlob::moveCreate(blobData);
808
809    returnComPtr(outBlob, blob);
810    return SLANG_OK;
811}
812
813} // namespace gfx