yum-mirror/slang

Making it easier to work with shaders

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

kaizhangNVAdd implementation for 'uploadTextureData' in metal (#6443)edcb2f0b8

master
24.4 KiB763 linesraw
1// metal-command-encoder.cpp
2#include "metal-command-encoder.h"
3
4#include "metal-buffer.h"
5#include "metal-command-buffer.h"
6#include "metal-helper-functions.h"
7#include "metal-query.h"
8#include "metal-render-pass.h"
9#include "metal-resource-views.h"
10#include "metal-shader-object.h"
11#include "metal-shader-program.h"
12#include "metal-shader-table.h"
13#include "metal-texture.h"
14#include "metal-util.h"
15
16namespace gfx
17{
18
19using namespace Slang;
20
21namespace metal
22{
23
24void PipelineCommandEncoder::init(CommandBufferImpl* commandBuffer)
25{
26    m_commandBuffer = commandBuffer;
27    m_metalCommandBuffer = m_commandBuffer->m_commandBuffer.get();
28}
29
30void PipelineCommandEncoder::endEncodingImpl()
31{
32    m_commandBuffer->endMetalCommandEncoder();
33}
34
35Result PipelineCommandEncoder::setPipelineStateImpl(
36    IPipelineState* state,
37    IShaderObject** outRootObject)
38{
39    m_currentPipeline = static_cast<PipelineStateImpl*>(state);
40    // m_commandBuffer->m_mutableRootShaderObject = nullptr;
41    SLANG_RETURN_ON_FAIL(m_commandBuffer->m_rootObject.init(
42        m_commandBuffer->m_device,
43        m_currentPipeline->getProgram<ShaderProgramImpl>()->m_rootObjectLayout));
44    *outRootObject = &m_commandBuffer->m_rootObject;
45    return SLANG_OK;
46}
47
48void ResourceCommandEncoder::endEncoding()
49{
50    PipelineCommandEncoder::endEncodingImpl();
51}
52
53void ResourceCommandEncoder::writeTimestamp(IQueryPool* queryPool, GfxIndex index)
54{
55    auto encoder = m_commandBuffer->getMetalBlitCommandEncoder();
56    encoder->sampleCountersInBuffer(
57        static_cast<QueryPoolImpl*>(queryPool)->m_counterSampleBuffer.get(),
58        index,
59        true);
60}
61
62void ResourceCommandEncoder::copyBuffer(
63    IBufferResource* dst,
64    Offset dstOffset,
65    IBufferResource* src,
66    Offset srcOffset,
67    Size size)
68{
69    auto encoder = m_commandBuffer->getMetalBlitCommandEncoder();
70    encoder->copyFromBuffer(
71        static_cast<BufferResourceImpl*>(src)->m_buffer.get(),
72        srcOffset,
73        static_cast<BufferResourceImpl*>(dst)->m_buffer.get(),
74        dstOffset,
75        size);
76}
77
78void ResourceCommandEncoder::copyTexture(
79    ITextureResource* dst,
80    ResourceState dstState,
81    SubresourceRange dstSubresource,
82    ITextureResource::Offset3D dstOffset,
83    ITextureResource* src,
84    ResourceState srcState,
85    SubresourceRange srcSubresource,
86    ITextureResource::Offset3D srcOffset,
87    ITextureResource::Extents extent)
88{
89    auto encoder = m_commandBuffer->getMetalBlitCommandEncoder();
90
91    if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0 &&
92        srcSubresource.layerCount == 0 && srcSubresource.mipLevelCount == 0)
93    {
94        encoder->copyFromTexture(
95            static_cast<TextureResourceImpl*>(src)->m_texture.get(),
96            static_cast<TextureResourceImpl*>(dst)->m_texture.get());
97    }
98    else
99    {
100        for (GfxIndex layer = 0; layer < dstSubresource.layerCount; layer++)
101        {
102            encoder->copyFromTexture(
103                static_cast<TextureResourceImpl*>(src)->m_texture.get(),
104                srcSubresource.baseArrayLayer + layer,
105                srcSubresource.mipLevel,
106                MTL::Origin(srcOffset.x, srcOffset.y, srcOffset.z),
107                MTL::Size(extent.width, extent.height, extent.depth),
108                static_cast<TextureResourceImpl*>(dst)->m_texture.get(),
109                dstSubresource.baseArrayLayer + layer,
110                dstSubresource.mipLevel,
111                MTL::Origin(dstOffset.x, dstOffset.y, dstOffset.z));
112        }
113    }
114}
115
116void ResourceCommandEncoder::copyTextureToBuffer(
117    IBufferResource* dst,
118    Offset dstOffset,
119    Size dstSize,
120    Size dstRowStride,
121    ITextureResource* src,
122    ResourceState srcState,
123    SubresourceRange srcSubresource,
124    ITextureResource::Offset3D srcOffset,
125    ITextureResource::Extents extent)
126{
127    assert(srcSubresource.mipLevelCount <= 1);
128
129    auto encoder = m_commandBuffer->getMetalBlitCommandEncoder();
130    auto& desc = *static_cast<TextureResourceImpl*>(src)->getDesc();
131    const TextureResource::Extents mipSize = calcMipSize(desc.size, srcSubresource.mipLevel);
132    Size bytesPerImage = mipSize.height * dstRowStride;
133
134    encoder->copyFromTexture(
135        static_cast<TextureResourceImpl*>(src)->m_texture.get(),
136        srcSubresource.baseArrayLayer,
137        srcSubresource.mipLevel,
138        MTL::Origin(srcOffset.x, srcOffset.y, srcOffset.z),
139        MTL::Size(extent.width, extent.height, extent.depth),
140        static_cast<BufferResourceImpl*>(dst)->m_buffer.get(),
141        dstOffset,
142        dstRowStride,
143        extent.depth == 1 ? 0 : bytesPerImage);
144}
145
146void ResourceCommandEncoder::uploadBufferData(
147    IBufferResource* buffer,
148    Offset offset,
149    Size size,
150    void* data)
151{
152    SLANG_UNIMPLEMENTED_X("uploadBufferData");
153}
154
155void ResourceCommandEncoder::uploadTextureData(
156    ITextureResource* dst,
157    SubresourceRange subResourceRange,
158    ITextureResource::Offset3D offset,
159    ITextureResource::Extents extend,
160    ITextureResource::SubresourceData* subResourceData,
161    GfxCount subResourceDataCount)
162{
163    auto dstTexture = static_cast<TextureResourceImpl*>(dst);
164    auto& desc = *dstTexture->getDesc();
165
166    // Calculate buffer size needed
167    Size bufferSize = 0;
168    FormatInfo sizeInfo;
169    gfxGetFormatInfo(desc.format, &sizeInfo);
170    MTL::PixelFormat pixelFormat = MetalUtil::translatePixelFormat(desc.format);
171    bool isCompressed = gfxIsCompressedFormat(desc.format);
172
173    Size rowAlignment =
174        isCompressed
175            ? 1
176            : m_commandBuffer->m_device->m_device->minimumLinearTextureAlignmentForPixelFormat(
177                  pixelFormat);
178
179    for (GfxIndex i = 0; i < subResourceRange.mipLevelCount; ++i)
180    {
181        GfxIndex currentLevel = subResourceRange.mipLevel + i;
182        const TextureResource::Extents mipSize = calcMipSize(desc.size, currentLevel);
183
184        auto rowSizeInBytes = (mipSize.width + sizeInfo.blockWidth - 1) / sizeInfo.blockWidth *
185                              sizeInfo.blockSizeInBytes;
186        rowSizeInBytes = (rowSizeInBytes + rowAlignment - 1) & ~(rowAlignment - 1);
187
188        auto numRows = (mipSize.height + sizeInfo.blockHeight - 1) / sizeInfo.blockHeight;
189        bufferSize += (rowSizeInBytes * numRows) * mipSize.depth;
190    }
191    bufferSize *= subResourceRange.layerCount;
192
193    // Create staging buffer
194    NS::SharedPtr<MTL::Buffer> stagingBuffer = NS::TransferPtr(
195        m_commandBuffer->m_device->m_device->newBuffer(bufferSize, MTL::ResourceStorageModeShared));
196
197    if (!stagingBuffer)
198        return;
199
200    auto encoder = m_commandBuffer->getMetalBlitCommandEncoder();
201    if (!encoder)
202        return;
203
204    // Copy data to staging buffer and then to texture
205    Size bufferOffset = 0;
206    for (GfxIndex i = 0; i < subResourceRange.layerCount; i++)
207    {
208        // We only allocate staging buffer with size of one slice.
209        GfxIndex currentSlice = subResourceRange.baseArrayLayer + i;
210        uint8_t* bufferData = (uint8_t*)stagingBuffer->contents();
211        Size dstOffset = 0;
212
213        for (GfxIndex j = 0; j < subResourceRange.mipLevelCount; j++)
214        {
215            GfxIndex currentLevel = subResourceRange.mipLevel + j;
216            const auto& subresourceData = subResourceData[j];
217            const TextureResource::Extents mipSize = calcMipSize(desc.size, currentLevel);
218
219            auto rowSizeInBytes = (mipSize.width + sizeInfo.blockWidth - 1) / sizeInfo.blockWidth *
220                                  sizeInfo.blockSizeInBytes;
221            auto rowSizeInBytesAligned = (rowSizeInBytes + rowAlignment - 1) & ~(rowAlignment - 1);
222
223            auto numRows = (mipSize.height + sizeInfo.blockHeight - 1) / sizeInfo.blockHeight;
224
225            const uint8_t* srcData = (const uint8_t*)subresourceData.data;
226            if (rowSizeInBytesAligned == rowSizeInBytes)
227            {
228                // If the row size is already aligned, we can copy the data directly.
229                memcpy(bufferData + dstOffset, srcData, rowSizeInBytes * numRows * mipSize.depth);
230            }
231            else
232            {
233                for (GfxIndex k = 0; k < mipSize.depth; ++k)
234                {
235                    for (GfxIndex row = 0; row < numRows; ++row)
236                    {
237                        // Copy data to staging buffer, note that the staging buffer has to have the
238                        // same alignment as the texture while the src data doesn't have such
239                        // requirement, therefore we have to copy the data row by row. We don't care
240                        // about the content of the alignment padding.
241                        memcpy(bufferData + dstOffset, srcData, rowSizeInBytes);
242                        dstOffset += rowSizeInBytesAligned;
243                        srcData += rowSizeInBytes;
244                    }
245                }
246            }
247
248            // Copy from staging buffer to texture
249            encoder->copyFromBuffer(
250                stagingBuffer.get(),
251                bufferOffset,
252                rowSizeInBytesAligned,
253                rowSizeInBytesAligned * numRows,
254                MTL::Size(mipSize.width, mipSize.height, mipSize.depth),
255                dstTexture->m_texture.get(),
256                currentSlice,
257                currentLevel,
258                MTL::Origin(offset.x, offset.y, offset.z));
259
260            bufferOffset += rowSizeInBytes * numRows * mipSize.depth;
261        }
262    }
263}
264
265void ResourceCommandEncoder::bufferBarrier(
266    GfxCount count,
267    IBufferResource* const* buffers,
268    ResourceState src,
269    ResourceState dst)
270{
271    // We use automatic hazard tracking for now, no need for barriers.
272}
273
274void ResourceCommandEncoder::textureBarrier(
275    GfxCount count,
276    ITextureResource* const* textures,
277    ResourceState src,
278    ResourceState dst)
279{
280    // We use automatic hazard tracking for now, no need for barriers.
281}
282
283void ResourceCommandEncoder::textureSubresourceBarrier(
284    ITextureResource* texture,
285    SubresourceRange subresourceRange,
286    ResourceState src,
287    ResourceState dst)
288{
289    // We use automatic hazard tracking for now, no need for barriers.
290}
291
292void ResourceCommandEncoder::clearResourceView(
293    IResourceView* view,
294    ClearValue* clearValue,
295    ClearResourceViewFlags::Enum flags)
296{
297    SLANG_UNIMPLEMENTED_X("clearResourceView");
298}
299
300void ResourceCommandEncoder::resolveResource(
301    ITextureResource* source,
302    ResourceState sourceState,
303    SubresourceRange sourceRange,
304    ITextureResource* dest,
305    ResourceState destState,
306    SubresourceRange destRange)
307{
308    SLANG_UNIMPLEMENTED_X("resolveResource");
309}
310
311void ResourceCommandEncoder::resolveQuery(
312    IQueryPool* queryPool,
313    GfxIndex index,
314    GfxCount count,
315    IBufferResource* buffer,
316    Offset offset)
317{
318    auto encoder = m_commandBuffer->getMetalBlitCommandEncoder();
319    encoder->resolveCounters(
320        static_cast<QueryPoolImpl*>(queryPool)->m_counterSampleBuffer.get(),
321        NS::Range(index, count),
322        static_cast<BufferResourceImpl*>(buffer)->m_buffer.get(),
323        offset);
324}
325
326void ResourceCommandEncoder::beginDebugEvent(const char* name, float rgbColor[3])
327{
328    NS::SharedPtr<NS::String> string = MetalUtil::createString(name);
329    m_commandBuffer->m_commandBuffer->pushDebugGroup(string.get());
330}
331
332void ResourceCommandEncoder::endDebugEvent()
333{
334    m_commandBuffer->m_commandBuffer->popDebugGroup();
335}
336
337void RenderCommandEncoder::beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer)
338{
339    m_renderPassLayout = static_cast<RenderPassLayoutImpl*>(renderPass);
340    m_framebuffer = static_cast<FramebufferImpl*>(framebuffer);
341    if (!m_framebuffer)
342    {
343        // TODO use empty framebuffer
344        return;
345    }
346
347    // Create a copy of the render pass descriptor and fill in remaining information.
348    m_renderPassDesc = NS::TransferPtr(m_renderPassLayout->m_renderPassDesc->copy());
349
350    m_renderPassDesc->setRenderTargetWidth(m_framebuffer->m_width);
351    m_renderPassDesc->setRenderTargetHeight(m_framebuffer->m_height);
352
353    for (Index i = 0; i < m_framebuffer->m_renderTargetViews.getCount(); ++i)
354    {
355        TextureResourceViewImpl* renderTargetView = m_framebuffer->m_renderTargetViews[i];
356        MTL::RenderPassColorAttachmentDescriptor* colorAttachment =
357            m_renderPassDesc->colorAttachments()->object(i);
358        colorAttachment->setTexture(renderTargetView->m_textureView.get());
359        colorAttachment->setLevel(renderTargetView->m_desc.subresourceRange.mipLevel);
360        colorAttachment->setSlice(renderTargetView->m_desc.subresourceRange.baseArrayLayer);
361    }
362
363    if (m_framebuffer->m_depthStencilView)
364    {
365        TextureResourceViewImpl* depthStencilView = m_framebuffer->m_depthStencilView.get();
366        MTL::PixelFormat pixelFormat =
367            MetalUtil::translatePixelFormat(depthStencilView->m_desc.format);
368        if (MetalUtil::isDepthFormat(pixelFormat))
369        {
370            MTL::RenderPassDepthAttachmentDescriptor* depthAttachment =
371                m_renderPassDesc->depthAttachment();
372            depthAttachment->setTexture(depthStencilView->m_textureView.get());
373            depthAttachment->setLevel(depthStencilView->m_desc.subresourceRange.mipLevel);
374            depthAttachment->setSlice(depthStencilView->m_desc.subresourceRange.baseArrayLayer);
375        }
376        if (MetalUtil::isStencilFormat(pixelFormat))
377        {
378            MTL::RenderPassStencilAttachmentDescriptor* stencilAttachment =
379                m_renderPassDesc->stencilAttachment();
380            stencilAttachment->setTexture(depthStencilView->m_textureView.get());
381            stencilAttachment->setLevel(depthStencilView->m_desc.subresourceRange.mipLevel);
382            stencilAttachment->setSlice(depthStencilView->m_desc.subresourceRange.baseArrayLayer);
383        }
384    }
385}
386
387void RenderCommandEncoder::endEncoding()
388{
389    PipelineCommandEncoder::endEncodingImpl();
390}
391
392Result RenderCommandEncoder::bindPipeline(
393    IPipelineState* pipelineState,
394    IShaderObject** outRootObject)
395{
396    return setPipelineStateImpl(pipelineState, outRootObject);
397}
398
399Result RenderCommandEncoder::bindPipelineWithRootObject(
400    IPipelineState* pipelineState,
401    IShaderObject* rootObject)
402{
403    return SLANG_E_NOT_IMPLEMENTED;
404}
405
406void RenderCommandEncoder::setViewports(GfxCount count, const Viewport* viewports)
407{
408    m_viewports.setCount(count);
409    for (GfxIndex i = 0; i < count; ++i)
410    {
411        const auto& viewport = viewports[i];
412        auto& mtlViewport = m_viewports[i];
413        mtlViewport.originX = viewport.originX;
414        mtlViewport.originY = viewport.originY;
415        mtlViewport.width = viewport.extentX;
416        mtlViewport.height = viewport.extentY;
417        mtlViewport.znear = viewport.minZ;
418        mtlViewport.zfar = viewport.maxZ;
419    }
420}
421
422void RenderCommandEncoder::setScissorRects(GfxCount count, const ScissorRect* rects)
423{
424    m_scissorRects.setCount(count);
425    for (GfxIndex i = 0; i < count; ++i)
426    {
427        const auto& rect = rects[i];
428        auto& mtlRect = m_scissorRects[i];
429        mtlRect.x = rect.minX;
430        mtlRect.y = rect.minY;
431        mtlRect.width = rect.maxX - rect.minX;
432        mtlRect.height = rect.maxY - rect.minY;
433    }
434}
435
436void RenderCommandEncoder::setPrimitiveTopology(PrimitiveTopology topology)
437{
438    m_primitiveType = MetalUtil::translatePrimitiveType(topology);
439}
440
441void RenderCommandEncoder::setVertexBuffers(
442    GfxIndex startSlot,
443    GfxCount slotCount,
444    IBufferResource* const* buffers,
445    const Offset* offsets)
446{
447    Index count = Math::Max(m_vertexBuffers.getCount(), Index(startSlot + slotCount));
448    m_vertexBuffers.setCount(count);
449    m_vertexBufferOffsets.setCount(count);
450
451    for (Index i = 0; i < Index(slotCount); i++)
452    {
453        Index slotIndex = startSlot + i;
454        m_vertexBuffers[slotIndex] = static_cast<BufferResourceImpl*>(buffers[i])->m_buffer.get();
455        m_vertexBufferOffsets[slotIndex] = offsets[i];
456    }
457}
458
459void RenderCommandEncoder::setIndexBuffer(
460    IBufferResource* buffer,
461    Format indexFormat,
462    Offset offset)
463{
464    m_indexBuffer = static_cast<BufferResourceImpl*>(buffer)->m_buffer.get();
465    m_indexBufferOffset = offset;
466
467    switch (indexFormat)
468    {
469    case Format::R16_UINT:
470        m_indexBufferType = MTL::IndexTypeUInt16;
471        break;
472    case Format::R32_UINT:
473        m_indexBufferType = MTL::IndexTypeUInt32;
474        break;
475    default:
476        assert(!"unsupported index format");
477    }
478}
479
480void RenderCommandEncoder::setStencilReference(uint32_t referenceValue)
481{
482    m_stencilReferenceValue = referenceValue;
483}
484
485Result RenderCommandEncoder::setSamplePositions(
486    GfxCount samplesPerPixel,
487    GfxCount pixelCount,
488    const SamplePosition* samplePositions)
489{
490    return SLANG_E_NOT_AVAILABLE;
491}
492
493Result RenderCommandEncoder::prepareDraw(MTL::RenderCommandEncoder*& encoder)
494{
495    auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr());
496    pipeline->ensureAPIPipelineStateCreated();
497
498    encoder = m_commandBuffer->getMetalRenderCommandEncoder(m_renderPassDesc.get());
499    encoder->setRenderPipelineState(pipeline->m_renderPipelineState.get());
500
501    RenderBindingContext bindingContext;
502    bindingContext.init(m_commandBuffer->m_device, encoder);
503    auto program = static_cast<ShaderProgramImpl*>(m_currentPipeline->m_program.get());
504    m_commandBuffer->m_rootObject.bindAsRoot(&bindingContext, program->m_rootObjectLayout);
505
506    for (Index i = 0; i < m_vertexBuffers.getCount(); ++i)
507    {
508        encoder->setVertexBuffer(
509            m_vertexBuffers[i],
510            m_vertexBufferOffsets[i],
511            m_currentPipeline->m_vertexBufferOffset + i);
512    }
513
514    encoder->setViewports(m_viewports.getArrayView().getBuffer(), m_viewports.getCount());
515    encoder->setScissorRects(m_scissorRects.getArrayView().getBuffer(), m_scissorRects.getCount());
516
517    const RasterizerDesc& rasterDesc = pipeline->desc.graphics.rasterizer;
518    const DepthStencilDesc& depthStencilDesc = pipeline->desc.graphics.depthStencil;
519    encoder->setFrontFacingWinding(MetalUtil::translateWinding(rasterDesc.frontFace));
520    encoder->setCullMode(MetalUtil::translateCullMode(rasterDesc.cullMode));
521    encoder->setDepthClipMode(
522        rasterDesc.depthClipEnable ? MTL::DepthClipModeClip
523                                   : MTL::DepthClipModeClamp); // TODO correct?
524    encoder->setDepthBias(
525        rasterDesc.depthBias,
526        rasterDesc.slopeScaledDepthBias,
527        rasterDesc.depthBiasClamp);
528    encoder->setTriangleFillMode(MetalUtil::translateTriangleFillMode(rasterDesc.fillMode));
529    // encoder->setBlendColor(); // not supported by gfx
530    if (m_framebuffer->m_depthStencilView)
531    {
532        encoder->setDepthStencilState(pipeline->m_depthStencilState.get());
533    }
534    encoder->setStencilReferenceValue(m_stencilReferenceValue);
535
536    return SLANG_OK;
537}
538
539Result RenderCommandEncoder::draw(GfxCount vertexCount, GfxIndex startVertex)
540{
541    MTL::RenderCommandEncoder* encoder;
542    SLANG_RETURN_ON_FAIL(prepareDraw(encoder));
543    encoder->drawPrimitives(m_primitiveType, startVertex, vertexCount);
544    return SLANG_OK;
545}
546
547Result RenderCommandEncoder::drawIndexed(
548    GfxCount indexCount,
549    GfxIndex startIndex,
550    GfxIndex baseVertex)
551{
552    MTL::RenderCommandEncoder* encoder;
553    SLANG_RETURN_ON_FAIL(prepareDraw(encoder));
554    // TODO baseVertex is not supported by Metal
555    encoder->drawIndexedPrimitives(
556        m_primitiveType,
557        indexCount,
558        m_indexBufferType,
559        m_indexBuffer,
560        m_indexBufferOffset);
561    return SLANG_OK;
562}
563
564Result RenderCommandEncoder::drawIndirect(
565    GfxCount maxDrawCount,
566    IBufferResource* argBuffer,
567    Offset argOffset,
568    IBufferResource* countBuffer,
569    Offset countOffset)
570{
571    return SLANG_E_NOT_IMPLEMENTED;
572}
573
574Result RenderCommandEncoder::drawIndexedIndirect(
575    GfxCount maxDrawCount,
576    IBufferResource* argBuffer,
577    Offset argOffset,
578    IBufferResource* countBuffer,
579    Offset countOffset)
580{
581    return SLANG_E_NOT_IMPLEMENTED;
582}
583
584Result RenderCommandEncoder::drawInstanced(
585    GfxCount vertexCount,
586    GfxCount instanceCount,
587    GfxIndex startVertex,
588    GfxIndex startInstanceLocation)
589{
590    MTL::RenderCommandEncoder* encoder;
591    SLANG_RETURN_ON_FAIL(prepareDraw(encoder));
592    encoder->drawPrimitives(
593        m_primitiveType,
594        startVertex,
595        vertexCount,
596        instanceCount,
597        startInstanceLocation);
598    return SLANG_OK;
599}
600
601Result RenderCommandEncoder::drawIndexedInstanced(
602    GfxCount indexCount,
603    GfxCount instanceCount,
604    GfxIndex startIndexLocation,
605    GfxIndex baseVertexLocation,
606    GfxIndex startInstanceLocation)
607{
608    MTL::RenderCommandEncoder* encoder;
609    SLANG_RETURN_ON_FAIL(prepareDraw(encoder));
610    encoder->drawIndexedPrimitives(
611        m_primitiveType,
612        indexCount,
613        m_indexBufferType,
614        m_indexBuffer,
615        startIndexLocation,
616        instanceCount,
617        baseVertexLocation,
618        startIndexLocation);
619    return SLANG_OK;
620}
621
622Result RenderCommandEncoder::drawMeshTasks(int x, int y, int z)
623{
624    return SLANG_E_NOT_IMPLEMENTED;
625}
626
627void ComputeCommandEncoder::endEncoding()
628{
629    ResourceCommandEncoder::endEncoding();
630}
631
632Result ComputeCommandEncoder::bindPipeline(
633    IPipelineState* pipelineState,
634    IShaderObject** outRootObject)
635{
636    return setPipelineStateImpl(pipelineState, outRootObject);
637}
638
639Result ComputeCommandEncoder::bindPipelineWithRootObject(
640    IPipelineState* pipelineState,
641    IShaderObject* rootObject)
642{
643    return SLANG_E_NOT_IMPLEMENTED;
644}
645
646Result ComputeCommandEncoder::dispatchCompute(int x, int y, int z)
647{
648    MTL::ComputeCommandEncoder* encoder = m_commandBuffer->getMetalComputeCommandEncoder();
649
650    ComputeBindingContext bindingContext;
651    bindingContext.init(m_commandBuffer->m_device, encoder);
652    auto program = static_cast<ShaderProgramImpl*>(m_currentPipeline->m_program.get());
653    m_commandBuffer->m_rootObject.bindAsRoot(&bindingContext, program->m_rootObjectLayout);
654
655    auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr());
656    RootShaderObjectImpl* rootObjectImpl = &m_commandBuffer->m_rootObject;
657    RefPtr<PipelineStateBase> newPipeline;
658    SLANG_RETURN_ON_FAIL(m_commandBuffer->m_device->maybeSpecializePipeline(
659        m_currentPipeline,
660        rootObjectImpl,
661        newPipeline));
662    PipelineStateImpl* newPipelineImpl = static_cast<PipelineStateImpl*>(newPipeline.Ptr());
663
664    SLANG_RETURN_ON_FAIL(newPipelineImpl->ensureAPIPipelineStateCreated());
665    m_currentPipeline = newPipelineImpl;
666
667    m_currentPipeline->ensureAPIPipelineStateCreated();
668    encoder->setComputePipelineState(m_currentPipeline->m_computePipelineState.get());
669
670
671    encoder->dispatchThreadgroups(MTL::Size(x, y, z), m_currentPipeline->m_threadGroupSize);
672
673    return SLANG_OK;
674}
675
676Result ComputeCommandEncoder::dispatchComputeIndirect(IBufferResource* argBuffer, Offset offset)
677{
678    SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect");
679}
680
681void RayTracingCommandEncoder::_memoryBarrier(
682    int count,
683    IAccelerationStructure* const* structures,
684    AccessFlag srcAccess,
685    AccessFlag destAccess)
686{
687}
688
689void RayTracingCommandEncoder::_queryAccelerationStructureProperties(
690    GfxCount accelerationStructureCount,
691    IAccelerationStructure* const* accelerationStructures,
692    GfxCount queryCount,
693    AccelerationStructureQueryDesc* queryDescs)
694{
695}
696
697void RayTracingCommandEncoder::buildAccelerationStructure(
698    const IAccelerationStructure::BuildDesc& desc,
699    GfxCount propertyQueryCount,
700    AccelerationStructureQueryDesc* queryDescs)
701{
702}
703
704void RayTracingCommandEncoder::copyAccelerationStructure(
705    IAccelerationStructure* dest,
706    IAccelerationStructure* src,
707    AccelerationStructureCopyMode mode)
708{
709}
710
711void RayTracingCommandEncoder::queryAccelerationStructureProperties(
712    GfxCount accelerationStructureCount,
713    IAccelerationStructure* const* accelerationStructures,
714    GfxCount queryCount,
715    AccelerationStructureQueryDesc* queryDescs)
716{
717    _queryAccelerationStructureProperties(
718        accelerationStructureCount,
719        accelerationStructures,
720        queryCount,
721        queryDescs);
722}
723
724void RayTracingCommandEncoder::serializeAccelerationStructure(
725    DeviceAddress dest,
726    IAccelerationStructure* source)
727{
728}
729
730void RayTracingCommandEncoder::deserializeAccelerationStructure(
731    IAccelerationStructure* dest,
732    DeviceAddress source)
733{
734}
735
736Result RayTracingCommandEncoder::bindPipeline(
737    IPipelineState* pipeline,
738    IShaderObject** outRootObject)
739{
740    return SLANG_E_NOT_IMPLEMENTED;
741}
742
743Result RayTracingCommandEncoder::bindPipelineWithRootObject(
744    IPipelineState* pipelineState,
745    IShaderObject* rootObject)
746{
747    return SLANG_E_NOT_IMPLEMENTED;
748}
749
750Result RayTracingCommandEncoder::dispatchRays(
751    GfxIndex raygenShaderIndex,
752    IShaderTable* shaderTable,
753    GfxCount width,
754    GfxCount height,
755    GfxCount depth)
756{
757    return SLANG_E_NOT_IMPLEMENTED;
758}
759
760void RayTracingCommandEncoder::endEncoding() {}
761
762} // namespace metal
763} // namespace gfx