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
54.1 KiB1516 linesraw
1// d3d12-command-encoder.cpp
2#include "d3d12-command-encoder.h"
3
4#include "d3d12-command-buffer.h"
5#include "d3d12-device.h"
6#include "d3d12-helper-functions.h"
7#include "d3d12-pipeline-state.h"
8#include "d3d12-query.h"
9#include "d3d12-shader-object.h"
10#include "d3d12-shader-program.h"
11#include "d3d12-shader-table.h"
12#include "d3d12-texture.h"
13#include "d3d12-transient-heap.h"
14#include "d3d12-vertex-layout.h"
15
16namespace gfx
17{
18namespace d3d12
19{
20
21using namespace Slang;
22
23int PipelineCommandEncoder::getBindPointIndex(PipelineType type)
24{
25    switch (type)
26    {
27    case PipelineType::Graphics:
28        return 0;
29    case PipelineType::Compute:
30        return 1;
31    case PipelineType::RayTracing:
32        return 2;
33    default:
34        assert(!"unknown pipeline type.");
35        return -1;
36    }
37}
38
39void PipelineCommandEncoder::init(CommandBufferImpl* commandBuffer)
40{
41    m_commandBuffer = commandBuffer;
42    m_d3dCmdList = m_commandBuffer->m_cmdList;
43    m_d3dCmdList6 = m_commandBuffer->m_cmdList6;
44    m_renderer = commandBuffer->m_renderer;
45    m_transientHeap = commandBuffer->m_transientHeap;
46    m_device = commandBuffer->m_renderer->m_device;
47}
48
49Result PipelineCommandEncoder::bindPipelineImpl(
50    IPipelineState* pipelineState,
51    IShaderObject** outRootObject)
52{
53    m_currentPipeline = static_cast<PipelineStateBase*>(pipelineState);
54    auto rootObject = &m_commandBuffer->m_rootShaderObject;
55    m_commandBuffer->m_mutableRootShaderObject = nullptr;
56    SLANG_RETURN_ON_FAIL(rootObject->reset(
57        m_renderer,
58        m_currentPipeline->getProgram<ShaderProgramImpl>()->m_rootObjectLayout,
59        m_commandBuffer->m_transientHeap));
60    *outRootObject = rootObject;
61    m_bindingDirty = true;
62    return SLANG_OK;
63}
64
65Result PipelineCommandEncoder::bindPipelineWithRootObjectImpl(
66    IPipelineState* pipelineState,
67    IShaderObject* rootObject)
68{
69    m_currentPipeline = static_cast<PipelineStateBase*>(pipelineState);
70    m_commandBuffer->m_mutableRootShaderObject =
71        static_cast<MutableRootShaderObjectImpl*>(rootObject);
72    m_bindingDirty = true;
73    return SLANG_OK;
74}
75
76Result PipelineCommandEncoder::_bindRenderState(
77    Submitter* submitter,
78    RefPtr<PipelineStateBase>& newPipeline)
79{
80    RootShaderObjectImpl* rootObjectImpl = m_commandBuffer->m_mutableRootShaderObject
81                                               ? m_commandBuffer->m_mutableRootShaderObject.Ptr()
82                                               : &m_commandBuffer->m_rootShaderObject;
83    SLANG_RETURN_ON_FAIL(
84        m_renderer->maybeSpecializePipeline(m_currentPipeline, rootObjectImpl, newPipeline));
85    PipelineStateBase* newPipelineImpl = static_cast<PipelineStateBase*>(newPipeline.Ptr());
86    auto commandList = m_d3dCmdList;
87    auto pipelineTypeIndex = (int)newPipelineImpl->desc.type;
88    auto programImpl = static_cast<ShaderProgramImpl*>(newPipelineImpl->m_program.Ptr());
89    SLANG_RETURN_ON_FAIL(newPipelineImpl->ensureAPIPipelineStateCreated());
90    submitter->setRootSignature(programImpl->m_rootObjectLayout->m_rootSignature);
91    submitter->setPipelineState(newPipelineImpl);
92    RootShaderObjectLayoutImpl* rootLayoutImpl = programImpl->m_rootObjectLayout;
93
94    // We need to set up a context for binding shader objects to the pipeline state.
95    // This type mostly exists to bundle together a bunch of parameters that would
96    // otherwise need to be tunneled down through all the shader object binding
97    // logic.
98    //
99    BindingContext context = {};
100    context.encoder = this;
101    context.submitter = submitter;
102    context.device = m_renderer;
103    context.transientHeap = m_transientHeap;
104    context.outOfMemoryHeap = (D3D12_DESCRIPTOR_HEAP_TYPE)(-1);
105    // We kick off binding of shader objects at the root object, and the objects
106    // themselves will be responsible for allocating, binding, and filling in
107    // any descriptor tables or other root parameters needed.
108    //
109    m_commandBuffer->bindDescriptorHeaps();
110    if (rootObjectImpl->bindAsRoot(&context, rootLayoutImpl) == SLANG_E_OUT_OF_MEMORY)
111    {
112        if (!m_transientHeap->canResize())
113        {
114            return SLANG_E_OUT_OF_MEMORY;
115        }
116
117        // If we run out of heap space while binding, allocate new descriptor heaps and try again.
118        ID3D12DescriptorHeap* d3dheap = nullptr;
119        m_commandBuffer->invalidateDescriptorHeapBinding();
120        switch (context.outOfMemoryHeap)
121        {
122        case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
123            SLANG_RETURN_ON_FAIL(m_transientHeap->allocateNewViewDescriptorHeap(m_renderer));
124            d3dheap = m_transientHeap->getCurrentViewHeap().getHeap();
125            m_commandBuffer->bindDescriptorHeaps();
126            break;
127        case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
128            SLANG_RETURN_ON_FAIL(m_transientHeap->allocateNewSamplerDescriptorHeap(m_renderer));
129            d3dheap = m_transientHeap->getCurrentSamplerHeap().getHeap();
130            m_commandBuffer->bindDescriptorHeaps();
131            break;
132        default:
133            assert(!"shouldn't be here");
134            return SLANG_FAIL;
135        }
136
137        // Try again.
138        SLANG_RETURN_ON_FAIL(rootObjectImpl->bindAsRoot(&context, rootLayoutImpl));
139    }
140
141    return SLANG_OK;
142}
143
144void ResourceCommandEncoderImpl::bufferBarrier(
145    GfxCount count,
146    IBufferResource* const* buffers,
147    ResourceState src,
148    ResourceState dst)
149{
150    ShortList<D3D12_RESOURCE_BARRIER, 16> barriers;
151    for (GfxIndex i = 0; i < count; i++)
152    {
153        auto bufferImpl = static_cast<BufferResourceImpl*>(buffers[i]);
154
155        D3D12_RESOURCE_BARRIER barrier = {};
156        // If the src == dst, it must be a UAV barrier.
157        barrier.Type = (src == dst && dst == ResourceState::UnorderedAccess)
158                           ? D3D12_RESOURCE_BARRIER_TYPE_UAV
159                           : D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
160        barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
161
162        if (barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV)
163        {
164            barrier.UAV.pResource = bufferImpl->m_resource;
165        }
166        else
167        {
168            barrier.Transition.pResource = bufferImpl->m_resource;
169            barrier.Transition.StateBefore = D3DUtil::getResourceState(src);
170            barrier.Transition.StateAfter = D3DUtil::getResourceState(dst);
171            barrier.Transition.Subresource = 0;
172            if (barrier.Transition.StateAfter == barrier.Transition.StateBefore)
173                continue;
174        }
175        barriers.add(barrier);
176    }
177    if (barriers.getCount())
178    {
179        m_commandBuffer->m_cmdList4->ResourceBarrier(
180            (UINT)barriers.getCount(),
181            barriers.getArrayView().getBuffer());
182    }
183}
184
185void ResourceCommandEncoderImpl::writeTimestamp(IQueryPool* pool, GfxIndex index)
186{
187    static_cast<QueryPoolImpl*>(pool)->writeTimestamp(m_commandBuffer->m_cmdList, index);
188}
189
190void ResourceCommandEncoderImpl::copyTexture(
191    ITextureResource* dst,
192    ResourceState dstState,
193    SubresourceRange dstSubresource,
194    ITextureResource::Offset3D dstOffset,
195    ITextureResource* src,
196    ResourceState srcState,
197    SubresourceRange srcSubresource,
198    ITextureResource::Offset3D srcOffset,
199    ITextureResource::Extents extent)
200{
201    auto dstTexture = static_cast<TextureResourceImpl*>(dst);
202    auto srcTexture = static_cast<TextureResourceImpl*>(src);
203
204    if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0 &&
205        srcSubresource.layerCount == 0 && srcSubresource.mipLevelCount == 0)
206    {
207        m_commandBuffer->m_cmdList->CopyResource(
208            dstTexture->m_resource.getResource(),
209            srcTexture->m_resource.getResource());
210        return;
211    }
212
213    auto d3dFormat = D3DUtil::getMapFormat(dstTexture->getDesc()->format);
214    auto aspectMask = (int32_t)dstSubresource.aspectMask;
215    if (dstSubresource.aspectMask == TextureAspect::Default)
216        aspectMask = (int32_t)TextureAspect::Color;
217    while (aspectMask)
218    {
219        auto aspect = Math::getLowestBit((int32_t)aspectMask);
220        aspectMask &= ~aspect;
221        auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect);
222        for (GfxIndex layer = 0; layer < dstSubresource.layerCount; layer++)
223        {
224            for (GfxIndex mipLevel = 0; mipLevel < dstSubresource.mipLevelCount; mipLevel++)
225            {
226                D3D12_TEXTURE_COPY_LOCATION dstRegion = {};
227
228                dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
229                dstRegion.pResource = dstTexture->m_resource.getResource();
230                dstRegion.SubresourceIndex = D3DUtil::getSubresourceIndex(
231                    dstSubresource.mipLevel + mipLevel,
232                    dstSubresource.baseArrayLayer + layer,
233                    planeIndex,
234                    dstTexture->getDesc()->numMipLevels,
235                    dstTexture->getDesc()->arraySize);
236
237                D3D12_TEXTURE_COPY_LOCATION srcRegion = {};
238                srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
239                srcRegion.pResource = srcTexture->m_resource.getResource();
240                srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex(
241                    srcSubresource.mipLevel + mipLevel,
242                    srcSubresource.baseArrayLayer + layer,
243                    planeIndex,
244                    srcTexture->getDesc()->numMipLevels,
245                    srcTexture->getDesc()->arraySize);
246
247                D3D12_BOX srcBox = {};
248                srcBox.left = srcOffset.x;
249                srcBox.top = srcOffset.y;
250                srcBox.front = srcOffset.z;
251                srcBox.right = srcBox.left + extent.width;
252                srcBox.bottom = srcBox.top + extent.height;
253                srcBox.back = srcBox.front + extent.depth;
254
255                m_commandBuffer->m_cmdList->CopyTextureRegion(
256                    &dstRegion,
257                    dstOffset.x,
258                    dstOffset.y,
259                    dstOffset.z,
260                    &srcRegion,
261                    &srcBox);
262            }
263        }
264    }
265}
266
267void ResourceCommandEncoderImpl::uploadTextureData(
268    ITextureResource* dst,
269    SubresourceRange subResourceRange,
270    ITextureResource::Offset3D offset,
271    ITextureResource::Extents extent,
272    ITextureResource::SubresourceData* subResourceData,
273    GfxCount subResourceDataCount)
274{
275    auto dstTexture = static_cast<TextureResourceImpl*>(dst);
276    auto baseSubresourceIndex = D3DUtil::getSubresourceIndex(
277        subResourceRange.mipLevel,
278        subResourceRange.baseArrayLayer,
279        0,
280        dstTexture->getDesc()->numMipLevels,
281        dstTexture->getDesc()->arraySize);
282    auto textureSize = dstTexture->getDesc()->size;
283    FormatInfo formatInfo = {};
284    gfxGetFormatInfo(dstTexture->getDesc()->format, &formatInfo);
285    for (GfxCount i = 0; i < subResourceDataCount; i++)
286    {
287        auto subresourceIndex = baseSubresourceIndex + i;
288        // Get the footprint
289        D3D12_RESOURCE_DESC texDesc = dstTexture->m_resource.getResource()->GetDesc();
290
291        D3D12_TEXTURE_COPY_LOCATION dstRegion = {};
292
293        dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
294        dstRegion.SubresourceIndex = subresourceIndex;
295        dstRegion.pResource = dstTexture->m_resource.getResource();
296
297        D3D12_TEXTURE_COPY_LOCATION srcRegion = {};
298        srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
299        D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = srcRegion.PlacedFootprint;
300        footprint.Offset = 0;
301        footprint.Footprint.Format = texDesc.Format;
302        uint32_t mipLevel =
303            D3DUtil::getSubresourceMipLevel(subresourceIndex, dstTexture->getDesc()->numMipLevels);
304        if (extent.width != ITextureResource::kRemainingTextureSize)
305        {
306            footprint.Footprint.Width = extent.width;
307        }
308        else
309        {
310            footprint.Footprint.Width = Math::Max(1, (textureSize.width >> mipLevel)) - offset.x;
311        }
312        if (extent.height != ITextureResource::kRemainingTextureSize)
313        {
314            footprint.Footprint.Height = extent.height;
315        }
316        else
317        {
318            footprint.Footprint.Height = Math::Max(1, (textureSize.height >> mipLevel)) - offset.y;
319        }
320        if (extent.depth != ITextureResource::kRemainingTextureSize)
321        {
322            footprint.Footprint.Depth = extent.depth;
323        }
324        else
325        {
326            footprint.Footprint.Depth = Math::Max(1, (textureSize.depth >> mipLevel)) - offset.z;
327        }
328        auto rowSize = (footprint.Footprint.Width + formatInfo.blockWidth - 1) /
329                       formatInfo.blockWidth * formatInfo.blockSizeInBytes;
330        auto rowCount =
331            (footprint.Footprint.Height + formatInfo.blockHeight - 1) / formatInfo.blockHeight;
332        footprint.Footprint.RowPitch =
333            (UINT)D3DUtil::calcAligned(rowSize, (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
334
335        auto bufferSize = footprint.Footprint.RowPitch * rowCount * footprint.Footprint.Depth;
336
337        IBufferResource* stagingBuffer;
338        Offset stagingBufferOffset = 0;
339        m_commandBuffer->m_transientHeap->allocateStagingBuffer(
340            bufferSize,
341            stagingBuffer,
342            stagingBufferOffset,
343            MemoryType::Upload,
344            true);
345        assert(stagingBufferOffset == 0);
346        BufferResourceImpl* bufferImpl = static_cast<BufferResourceImpl*>(stagingBuffer);
347        uint8_t* bufferData = nullptr;
348        D3D12_RANGE mapRange = {0, 0};
349        bufferImpl->m_resource.getResource()->Map(0, &mapRange, (void**)&bufferData);
350        for (uint32_t z = 0; z < footprint.Footprint.Depth; z++)
351        {
352            auto imageStart = bufferData + footprint.Footprint.RowPitch * rowCount * (Size)z;
353            auto srcData = (uint8_t*)subResourceData->data + subResourceData->strideZ * z;
354            for (uint32_t row = 0; row < rowCount; row++)
355            {
356                memcpy(
357                    imageStart + row * (Size)footprint.Footprint.RowPitch,
358                    srcData + subResourceData->strideY * row,
359                    rowSize);
360            }
361        }
362        bufferImpl->m_resource.getResource()->Unmap(0, nullptr);
363        srcRegion.pResource = bufferImpl->m_resource.getResource();
364        m_commandBuffer->m_cmdList
365            ->CopyTextureRegion(&dstRegion, offset.x, offset.y, offset.z, &srcRegion, nullptr);
366    }
367}
368
369void ResourceCommandEncoderImpl::clearResourceView(
370    IResourceView* view,
371    ClearValue* clearValue,
372    ClearResourceViewFlags::Enum flags)
373{
374    auto viewImpl = static_cast<ResourceViewImpl*>(view);
375    m_commandBuffer->bindDescriptorHeaps();
376    switch (view->getViewDesc()->type)
377    {
378    case IResourceView::Type::RenderTarget:
379        m_commandBuffer->m_cmdList->ClearRenderTargetView(
380            viewImpl->m_descriptor.cpuHandle,
381            clearValue->color.floatValues,
382            0,
383            nullptr);
384        break;
385    case IResourceView::Type::DepthStencil:
386        {
387            D3D12_CLEAR_FLAGS clearFlags = (D3D12_CLEAR_FLAGS)0;
388            if (flags & ClearResourceViewFlags::ClearDepth)
389            {
390                clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
391            }
392            if (flags & ClearResourceViewFlags::ClearStencil)
393            {
394                clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
395            }
396            m_commandBuffer->m_cmdList->ClearDepthStencilView(
397                viewImpl->m_descriptor.cpuHandle,
398                clearFlags,
399                clearValue->depthStencil.depth,
400                (UINT8)clearValue->depthStencil.stencil,
401                0,
402                nullptr);
403            break;
404        }
405    case IResourceView::Type::UnorderedAccess:
406        {
407            ID3D12Resource* d3dResource = nullptr;
408            D3D12Descriptor descriptor = viewImpl->m_descriptor;
409            switch (viewImpl->m_resource->getType())
410            {
411            case IResource::Type::Buffer:
412                d3dResource = static_cast<BufferResourceImpl*>(viewImpl->m_resource.Ptr())
413                                  ->m_resource.getResource();
414                // D3D12 requires a UAV descriptor with zero buffer stride for calling
415                // ClearUnorderedAccessViewUint/Float.
416                viewImpl->getBufferDescriptorForBinding(
417                    m_commandBuffer->m_renderer,
418                    viewImpl,
419                    0,
420                    descriptor);
421                break;
422            default:
423                d3dResource = static_cast<TextureResourceImpl*>(viewImpl->m_resource.Ptr())
424                                  ->m_resource.getResource();
425                break;
426            }
427            auto gpuHandleIndex =
428                m_commandBuffer->m_transientHeap->getCurrentViewHeap().allocate(1);
429            if (gpuHandleIndex == -1)
430            {
431                m_commandBuffer->m_transientHeap->allocateNewViewDescriptorHeap(
432                    m_commandBuffer->m_renderer);
433                gpuHandleIndex = m_commandBuffer->m_transientHeap->getCurrentViewHeap().allocate(1);
434                m_commandBuffer->bindDescriptorHeaps();
435            }
436            this->m_commandBuffer->m_renderer->m_device->CopyDescriptorsSimple(
437                1,
438                m_commandBuffer->m_transientHeap->getCurrentViewHeap().getCpuHandle(gpuHandleIndex),
439                descriptor.cpuHandle,
440                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
441
442            if (flags & ClearResourceViewFlags::FloatClearValues)
443            {
444                m_commandBuffer->m_cmdList->ClearUnorderedAccessViewFloat(
445                    m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle(
446                        gpuHandleIndex),
447                    descriptor.cpuHandle,
448                    d3dResource,
449                    clearValue->color.floatValues,
450                    0,
451                    nullptr);
452            }
453            else
454            {
455                m_commandBuffer->m_cmdList->ClearUnorderedAccessViewUint(
456                    m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle(
457                        gpuHandleIndex),
458                    descriptor.cpuHandle,
459                    d3dResource,
460                    clearValue->color.uintValues,
461                    0,
462                    nullptr);
463            }
464            break;
465        }
466    default:
467        break;
468    }
469}
470
471void ResourceCommandEncoderImpl::resolveResource(
472    ITextureResource* source,
473    ResourceState sourceState,
474    SubresourceRange sourceRange,
475    ITextureResource* dest,
476    ResourceState destState,
477    SubresourceRange destRange)
478{
479    auto srcTexture = static_cast<TextureResourceImpl*>(source);
480    auto srcDesc = srcTexture->getDesc();
481    auto dstTexture = static_cast<TextureResourceImpl*>(dest);
482    auto dstDesc = dstTexture->getDesc();
483
484    for (GfxIndex layer = 0; layer < sourceRange.layerCount; ++layer)
485    {
486        for (GfxIndex mip = 0; mip < sourceRange.mipLevelCount; ++mip)
487        {
488            auto srcSubresourceIndex = D3DUtil::getSubresourceIndex(
489                mip + sourceRange.mipLevel,
490                layer + sourceRange.baseArrayLayer,
491                0,
492                srcDesc->numMipLevels,
493                srcDesc->arraySize);
494            auto dstSubresourceIndex = D3DUtil::getSubresourceIndex(
495                mip + destRange.mipLevel,
496                layer + destRange.baseArrayLayer,
497                0,
498                dstDesc->numMipLevels,
499                dstDesc->arraySize);
500
501            DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc->format);
502
503            m_commandBuffer->m_cmdList->ResolveSubresource(
504                dstTexture->m_resource.getResource(),
505                dstSubresourceIndex,
506                srcTexture->m_resource.getResource(),
507                srcSubresourceIndex,
508                format);
509        }
510    }
511}
512
513void ResourceCommandEncoderImpl::resolveQuery(
514    IQueryPool* queryPool,
515    GfxIndex index,
516    GfxCount count,
517    IBufferResource* buffer,
518    Offset offset)
519{
520    auto queryBase = static_cast<QueryPoolBase*>(queryPool);
521    switch (queryBase->m_desc.type)
522    {
523    case QueryType::AccelerationStructureCompactedSize:
524    case QueryType::AccelerationStructureCurrentSize:
525    case QueryType::AccelerationStructureSerializedSize:
526        {
527            auto queryPoolImpl = static_cast<PlainBufferProxyQueryPoolImpl*>(queryPool);
528            auto bufferImpl = static_cast<BufferResourceImpl*>(buffer);
529            auto srcQueryBuffer = queryPoolImpl->m_bufferResource->m_resource.getResource();
530
531            D3D12_RESOURCE_BARRIER barrier = {};
532            barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
533            barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
534            barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
535            barrier.Transition.pResource = srcQueryBuffer;
536            m_commandBuffer->m_cmdList->ResourceBarrier(1, &barrier);
537
538            m_commandBuffer->m_cmdList->CopyBufferRegion(
539                bufferImpl->m_resource.getResource(),
540                (uint64_t)offset,
541                srcQueryBuffer,
542                index * sizeof(uint64_t),
543                count * sizeof(uint64_t));
544
545            barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
546            barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
547            barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
548            barrier.Transition.pResource = srcQueryBuffer;
549            m_commandBuffer->m_cmdList->ResourceBarrier(1, &barrier);
550        }
551        break;
552    default:
553        {
554            auto queryPoolImpl = static_cast<QueryPoolImpl*>(queryPool);
555            auto bufferImpl = static_cast<BufferResourceImpl*>(buffer);
556            m_commandBuffer->m_cmdList->ResolveQueryData(
557                queryPoolImpl->m_queryHeap.get(),
558                queryPoolImpl->m_queryType,
559                index,
560                count,
561                bufferImpl->m_resource.getResource(),
562                offset);
563        }
564        break;
565    }
566}
567
568void ResourceCommandEncoderImpl::copyTextureToBuffer(
569    IBufferResource* dst,
570    Offset dstOffset,
571    Size dstSize,
572    Size dstRowStride,
573    ITextureResource* src,
574    ResourceState srcState,
575    SubresourceRange srcSubresource,
576    ITextureResource::Offset3D srcOffset,
577    ITextureResource::Extents extent)
578{
579    assert(srcSubresource.mipLevelCount <= 1);
580
581    auto srcTexture = static_cast<TextureResourceImpl*>(src);
582    auto dstBuffer = static_cast<BufferResourceImpl*>(dst);
583    auto baseSubresourceIndex = D3DUtil::getSubresourceIndex(
584        srcSubresource.mipLevel,
585        srcSubresource.baseArrayLayer,
586        0,
587        srcTexture->getDesc()->numMipLevels,
588        srcTexture->getDesc()->arraySize);
589    auto textureSize = srcTexture->getDesc()->size;
590    FormatInfo formatInfo = {};
591    gfxGetFormatInfo(srcTexture->getDesc()->format, &formatInfo);
592    if (srcSubresource.mipLevelCount == 0)
593        srcSubresource.mipLevelCount = srcTexture->getDesc()->numMipLevels;
594    if (srcSubresource.layerCount == 0)
595        srcSubresource.layerCount = srcTexture->getDesc()->arraySize;
596
597    for (GfxCount layer = 0; layer < srcSubresource.layerCount; layer++)
598    {
599        // Get the footprint
600        D3D12_RESOURCE_DESC texDesc = srcTexture->m_resource.getResource()->GetDesc();
601
602        D3D12_TEXTURE_COPY_LOCATION dstRegion = {};
603        dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
604        dstRegion.pResource = dstBuffer->m_resource.getResource();
605        D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = dstRegion.PlacedFootprint;
606
607        D3D12_TEXTURE_COPY_LOCATION srcRegion = {};
608        srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
609        srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex(
610            srcSubresource.mipLevel,
611            layer + srcSubresource.baseArrayLayer,
612            0,
613            srcTexture->getDesc()->numMipLevels,
614            srcTexture->getDesc()->arraySize);
615        srcRegion.pResource = srcTexture->m_resource.getResource();
616
617        footprint.Offset = dstOffset;
618        footprint.Footprint.Format = texDesc.Format;
619        uint32_t mipLevel = srcSubresource.mipLevel;
620        if (extent.width != 0xFFFFFFFF)
621        {
622            footprint.Footprint.Width = extent.width;
623        }
624        else
625        {
626            footprint.Footprint.Width = Math::Max(1, (textureSize.width >> mipLevel)) - srcOffset.x;
627        }
628        if (extent.height != 0xFFFFFFFF)
629        {
630            footprint.Footprint.Height = extent.height;
631        }
632        else
633        {
634            footprint.Footprint.Height =
635                Math::Max(1, (textureSize.height >> mipLevel)) - srcOffset.y;
636        }
637        if (extent.depth != 0xFFFFFFFF)
638        {
639            footprint.Footprint.Depth = extent.depth;
640        }
641        else
642        {
643            footprint.Footprint.Depth = Math::Max(1, (textureSize.depth >> mipLevel)) - srcOffset.z;
644        }
645
646        assert(dstRowStride % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT == 0);
647        footprint.Footprint.RowPitch = (UINT)dstRowStride;
648
649        auto bufferSize =
650            footprint.Footprint.RowPitch * footprint.Footprint.Height * footprint.Footprint.Depth;
651
652        D3D12_BOX srcBox = {};
653        srcBox.left = srcOffset.x;
654        srcBox.top = srcOffset.y;
655        srcBox.front = srcOffset.z;
656        srcBox.right = srcOffset.x + extent.width;
657        srcBox.bottom = srcOffset.y + extent.height;
658        srcBox.back = srcOffset.z + extent.depth;
659        m_commandBuffer->m_cmdList->CopyTextureRegion(&dstRegion, 0, 0, 0, &srcRegion, &srcBox);
660    }
661}
662
663void ResourceCommandEncoderImpl::textureSubresourceBarrier(
664    ITextureResource* texture,
665    SubresourceRange subresourceRange,
666    ResourceState src,
667    ResourceState dst)
668{
669    auto textureImpl = static_cast<TextureResourceImpl*>(texture);
670
671    ShortList<D3D12_RESOURCE_BARRIER> barriers;
672    D3D12_RESOURCE_BARRIER barrier;
673    barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
674    if (src == dst && src == ResourceState::UnorderedAccess)
675    {
676        barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
677        barrier.UAV.pResource = textureImpl->m_resource.getResource();
678        barriers.add(barrier);
679    }
680    else
681    {
682        barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
683        barrier.Transition.StateBefore = D3DUtil::getResourceState(src);
684        barrier.Transition.StateAfter = D3DUtil::getResourceState(dst);
685        if (barrier.Transition.StateBefore == barrier.Transition.StateAfter)
686            return;
687        barrier.Transition.pResource = textureImpl->m_resource.getResource();
688        auto d3dFormat = D3DUtil::getMapFormat(textureImpl->getDesc()->format);
689        auto aspectMask = (int32_t)subresourceRange.aspectMask;
690        if (subresourceRange.aspectMask == TextureAspect::Default)
691            aspectMask = (int32_t)TextureAspect::Color;
692        while (aspectMask)
693        {
694            auto aspect = Math::getLowestBit((int32_t)aspectMask);
695            aspectMask &= ~aspect;
696            auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect);
697            for (GfxCount layer = 0; layer < subresourceRange.layerCount; layer++)
698            {
699                for (GfxCount mip = 0; mip < subresourceRange.mipLevelCount; mip++)
700                {
701                    barrier.Transition.Subresource = D3DUtil::getSubresourceIndex(
702                        mip + subresourceRange.mipLevel,
703                        layer + subresourceRange.baseArrayLayer,
704                        planeIndex,
705                        textureImpl->getDesc()->numMipLevels,
706                        textureImpl->getDesc()->arraySize);
707                    barriers.add(barrier);
708                }
709            }
710        }
711    }
712    m_commandBuffer->m_cmdList->ResourceBarrier(
713        (UINT)barriers.getCount(),
714        barriers.getArrayView().getBuffer());
715}
716
717void ResourceCommandEncoderImpl::beginDebugEvent(const char* name, float rgbColor[3])
718{
719    auto beginEvent = m_commandBuffer->m_renderer->m_BeginEventOnCommandList;
720    if (beginEvent)
721    {
722        beginEvent(
723            m_commandBuffer->m_cmdList,
724            0xff000000 | (uint8_t(rgbColor[0] * 255.0f) << 16) |
725                (uint8_t(rgbColor[1] * 255.0f) << 8) | uint8_t(rgbColor[2] * 255.0f),
726            name);
727    }
728}
729
730void ResourceCommandEncoderImpl::endDebugEvent()
731{
732    auto endEvent = m_commandBuffer->m_renderer->m_EndEventOnCommandList;
733    if (endEvent)
734    {
735        endEvent(m_commandBuffer->m_cmdList);
736    }
737}
738
739void ResourceCommandEncoderImpl::copyBuffer(
740    IBufferResource* dst,
741    Offset dstOffset,
742    IBufferResource* src,
743    Offset srcOffset,
744    Size size)
745{
746    auto dstBuffer = static_cast<BufferResourceImpl*>(dst);
747    auto srcBuffer = static_cast<BufferResourceImpl*>(src);
748
749    m_commandBuffer->m_cmdList->CopyBufferRegion(
750        dstBuffer->m_resource.getResource(),
751        dstOffset,
752        srcBuffer->m_resource.getResource(),
753        srcOffset,
754        size);
755}
756
757void ResourceCommandEncoderImpl::uploadBufferData(
758    IBufferResource* dst,
759    Offset offset,
760    Size size,
761    void* data)
762{
763    uploadBufferDataImpl(
764        m_commandBuffer->m_renderer->m_device,
765        m_commandBuffer->m_cmdList,
766        m_commandBuffer->m_transientHeap,
767        static_cast<BufferResourceImpl*>(dst),
768        offset,
769        size,
770        data);
771}
772
773void ResourceCommandEncoderImpl::textureBarrier(
774    GfxCount count,
775    ITextureResource* const* textures,
776    ResourceState src,
777    ResourceState dst)
778{
779    ShortList<D3D12_RESOURCE_BARRIER> barriers;
780
781    for (GfxIndex i = 0; i < count; i++)
782    {
783        auto textureImpl = static_cast<TextureResourceImpl*>(textures[i]);
784        auto d3dFormat = D3DUtil::getMapFormat(textureImpl->getDesc()->format);
785        auto textureDesc = textureImpl->getDesc();
786        D3D12_RESOURCE_BARRIER barrier;
787        barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
788        if (src == dst && src == ResourceState::UnorderedAccess)
789        {
790            barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
791            barrier.UAV.pResource = textureImpl->m_resource.getResource();
792        }
793        else
794        {
795            barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
796            barrier.Transition.StateBefore = D3DUtil::getResourceState(src);
797            barrier.Transition.StateAfter = D3DUtil::getResourceState(dst);
798            if (barrier.Transition.StateBefore == barrier.Transition.StateAfter)
799                continue;
800            barrier.Transition.pResource = textureImpl->m_resource.getResource();
801            auto planeCount =
802                D3DUtil::getPlaneSliceCount(D3DUtil::getMapFormat(textureImpl->getDesc()->format));
803            auto arraySize = textureDesc->arraySize;
804            if (arraySize == 0)
805                arraySize = 1;
806            barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
807        }
808        barriers.add(barrier);
809    }
810    if (barriers.getCount())
811    {
812        m_commandBuffer->m_cmdList->ResourceBarrier(
813            (UINT)barriers.getCount(),
814            barriers.getArrayView().getBuffer());
815    }
816}
817
818void RenderCommandEncoderImpl::init(
819    DeviceImpl* renderer,
820    TransientResourceHeapImpl* transientHeap,
821    CommandBufferImpl* cmdBuffer,
822    RenderPassLayoutImpl* renderPass,
823    FramebufferImpl* framebuffer)
824{
825    PipelineCommandEncoder::init(cmdBuffer);
826    m_preCmdList = nullptr;
827    m_renderPass = renderPass;
828    m_framebuffer = framebuffer;
829    m_transientHeap = transientHeap;
830    m_boundVertexBuffers.clear();
831    m_boundIndexBuffer = nullptr;
832    m_primitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
833    m_primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
834    m_boundIndexFormat = DXGI_FORMAT_UNKNOWN;
835    m_boundIndexOffset = 0;
836    m_currentPipeline = nullptr;
837
838    // Set render target states.
839    if (!framebuffer)
840    {
841        return;
842    }
843    m_d3dCmdList->OMSetRenderTargets(
844        (UINT)framebuffer->renderTargetViews.getCount(),
845        framebuffer->renderTargetDescriptors.getArrayView().getBuffer(),
846        FALSE,
847        framebuffer->depthStencilView ? &framebuffer->depthStencilDescriptor : nullptr);
848
849    // Issue clear commands based on render pass set up.
850    for (Index i = 0; i < framebuffer->renderTargetViews.getCount(); i++)
851    {
852        if (i >= renderPass->m_renderTargetAccesses.getCount())
853            continue;
854
855        auto& access = renderPass->m_renderTargetAccesses[i];
856
857        // Transit resource states.
858        {
859            D3D12BarrierSubmitter submitter(m_d3dCmdList);
860            auto resourceViewImpl = framebuffer->renderTargetViews[i].Ptr();
861            if (resourceViewImpl)
862            {
863                auto textureResource =
864                    static_cast<TextureResourceImpl*>(resourceViewImpl->m_resource.Ptr());
865                if (textureResource)
866                {
867                    D3D12_RESOURCE_STATES initialState;
868                    if (access.initialState == ResourceState::Undefined)
869                    {
870                        initialState = textureResource->m_defaultState;
871                    }
872                    else
873                    {
874                        initialState = D3DUtil::getResourceState(access.initialState);
875                    }
876                    textureResource->m_resource.transition(
877                        initialState,
878                        D3D12_RESOURCE_STATE_RENDER_TARGET,
879                        submitter);
880                }
881            }
882        }
883        // Clear.
884        if (access.loadOp == IRenderPassLayout::TargetLoadOp::Clear)
885        {
886            m_d3dCmdList->ClearRenderTargetView(
887                framebuffer->renderTargetDescriptors[i],
888                framebuffer->renderTargetClearValues[i].values,
889                0,
890                nullptr);
891        }
892    }
893
894    if (renderPass->m_hasDepthStencil)
895    {
896        // Transit resource states.
897        {
898            D3D12BarrierSubmitter submitter(m_d3dCmdList);
899            auto resourceViewImpl = framebuffer->depthStencilView.Ptr();
900            auto textureResource =
901                static_cast<TextureResourceImpl*>(resourceViewImpl->m_resource.Ptr());
902            D3D12_RESOURCE_STATES initialState;
903            if (renderPass->m_depthStencilAccess.initialState == ResourceState::Undefined)
904            {
905                initialState = textureResource->m_defaultState;
906            }
907            else
908            {
909                initialState =
910                    D3DUtil::getResourceState(renderPass->m_depthStencilAccess.initialState);
911            }
912            textureResource->m_resource.transition(
913                initialState,
914                D3D12_RESOURCE_STATE_DEPTH_WRITE,
915                submitter);
916        }
917        // Clear.
918        uint32_t clearFlags = 0;
919        if (renderPass->m_depthStencilAccess.loadOp == IRenderPassLayout::TargetLoadOp::Clear)
920        {
921            clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
922        }
923        if (renderPass->m_depthStencilAccess.stencilLoadOp ==
924            IRenderPassLayout::TargetLoadOp::Clear)
925        {
926            clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
927        }
928        if (clearFlags)
929        {
930            m_d3dCmdList->ClearDepthStencilView(
931                framebuffer->depthStencilDescriptor,
932                (D3D12_CLEAR_FLAGS)clearFlags,
933                framebuffer->depthStencilClearValue.depth,
934                framebuffer->depthStencilClearValue.stencil,
935                0,
936                nullptr);
937        }
938    }
939}
940
941Result RenderCommandEncoderImpl::bindPipeline(IPipelineState* state, IShaderObject** outRootObject)
942{
943    return bindPipelineImpl(state, outRootObject);
944}
945
946Result RenderCommandEncoderImpl::bindPipelineWithRootObject(
947    IPipelineState* state,
948    IShaderObject* rootObject)
949{
950    return bindPipelineWithRootObjectImpl(state, rootObject);
951}
952
953void RenderCommandEncoderImpl::setViewports(GfxCount count, const Viewport* viewports)
954{
955    static const int kMaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
956    assert(count <= kMaxViewports && count <= kMaxRTVCount);
957    for (GfxIndex ii = 0; ii < count; ++ii)
958    {
959        auto& inViewport = viewports[ii];
960        auto& dxViewport = m_viewports[ii];
961
962        dxViewport.TopLeftX = inViewport.originX;
963        dxViewport.TopLeftY = inViewport.originY;
964        dxViewport.Width = inViewport.extentX;
965        dxViewport.Height = inViewport.extentY;
966        dxViewport.MinDepth = inViewport.minZ;
967        dxViewport.MaxDepth = inViewport.maxZ;
968    }
969    m_d3dCmdList->RSSetViewports(UINT(count), m_viewports);
970}
971
972void RenderCommandEncoderImpl::setScissorRects(GfxCount count, const ScissorRect* rects)
973{
974    static const int kMaxScissorRects = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
975    assert(count <= kMaxScissorRects && count <= kMaxRTVCount);
976
977    for (GfxIndex ii = 0; ii < count; ++ii)
978    {
979        auto& inRect = rects[ii];
980        auto& dxRect = m_scissorRects[ii];
981
982        dxRect.left = LONG(inRect.minX);
983        dxRect.top = LONG(inRect.minY);
984        dxRect.right = LONG(inRect.maxX);
985        dxRect.bottom = LONG(inRect.maxY);
986    }
987
988    m_d3dCmdList->RSSetScissorRects(UINT(count), m_scissorRects);
989}
990
991void RenderCommandEncoderImpl::setPrimitiveTopology(PrimitiveTopology topology)
992{
993    m_primitiveTopologyType = D3DUtil::getPrimitiveType(topology);
994    m_primitiveTopology = D3DUtil::getPrimitiveTopology(topology);
995}
996
997void RenderCommandEncoderImpl::setVertexBuffers(
998    GfxIndex startSlot,
999    GfxCount slotCount,
1000    IBufferResource* const* buffers,
1001    const Offset* offsets)
1002{
1003    {
1004        const Index num = startSlot + slotCount;
1005        if (num > m_boundVertexBuffers.getCount())
1006        {
1007            m_boundVertexBuffers.setCount(num);
1008        }
1009    }
1010
1011    for (GfxIndex i = 0; i < slotCount; i++)
1012    {
1013        BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]);
1014
1015        BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i];
1016        boundBuffer.m_buffer = buffer;
1017        boundBuffer.m_offset = int(offsets[i]);
1018    }
1019}
1020
1021void RenderCommandEncoderImpl::setIndexBuffer(
1022    IBufferResource* buffer,
1023    Format indexFormat,
1024    Offset offset)
1025{
1026    m_boundIndexBuffer = (BufferResourceImpl*)buffer;
1027    m_boundIndexFormat = D3DUtil::getMapFormat(indexFormat);
1028    m_boundIndexOffset = (UINT)offset;
1029}
1030
1031Result RenderCommandEncoderImpl::prepareDraw()
1032{
1033    auto pipelineState = m_currentPipeline.Ptr();
1034    if (!pipelineState || (pipelineState->desc.type != PipelineType::Graphics))
1035    {
1036        return SLANG_FAIL;
1037    }
1038
1039    // Submit - setting for graphics
1040    {
1041        GraphicsSubmitter submitter(m_d3dCmdList);
1042        RefPtr<PipelineStateBase> newPipeline;
1043        SLANG_RETURN_ON_FAIL(_bindRenderState(&submitter, newPipeline));
1044    }
1045
1046    m_d3dCmdList->IASetPrimitiveTopology(m_primitiveTopology);
1047
1048    // Set up vertex buffer views
1049    {
1050        auto inputLayout = (InputLayoutImpl*)pipelineState->inputLayout.Ptr();
1051        if (inputLayout)
1052        {
1053            int numVertexViews = 0;
1054            D3D12_VERTEX_BUFFER_VIEW vertexViews[16];
1055            for (Index i = 0; i < m_boundVertexBuffers.getCount(); i++)
1056            {
1057                const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[i];
1058                BufferResourceImpl* buffer = boundVertexBuffer.m_buffer;
1059                if (buffer)
1060                {
1061                    D3D12_VERTEX_BUFFER_VIEW& vertexView = vertexViews[numVertexViews++];
1062                    vertexView.BufferLocation =
1063                        buffer->m_resource.getResource()->GetGPUVirtualAddress() +
1064                        boundVertexBuffer.m_offset;
1065                    vertexView.SizeInBytes =
1066                        UINT(buffer->getDesc()->sizeInBytes - boundVertexBuffer.m_offset);
1067                    vertexView.StrideInBytes = inputLayout->m_vertexStreamStrides[i];
1068                }
1069            }
1070            m_d3dCmdList->IASetVertexBuffers(0, numVertexViews, vertexViews);
1071        }
1072    }
1073    // Set up index buffer
1074    if (m_boundIndexBuffer)
1075    {
1076        D3D12_INDEX_BUFFER_VIEW indexBufferView;
1077        indexBufferView.BufferLocation =
1078            m_boundIndexBuffer->m_resource.getResource()->GetGPUVirtualAddress() +
1079            m_boundIndexOffset;
1080        indexBufferView.SizeInBytes =
1081            UINT(m_boundIndexBuffer->getDesc()->sizeInBytes - m_boundIndexOffset);
1082        indexBufferView.Format = m_boundIndexFormat;
1083
1084        m_d3dCmdList->IASetIndexBuffer(&indexBufferView);
1085    }
1086    return SLANG_OK;
1087}
1088
1089Result RenderCommandEncoderImpl::draw(GfxCount vertexCount, GfxIndex startVertex)
1090{
1091    SLANG_RETURN_ON_FAIL(prepareDraw());
1092    m_d3dCmdList->DrawInstanced((uint32_t)vertexCount, 1, (uint32_t)startVertex, 0);
1093    return SLANG_OK;
1094}
1095
1096Result RenderCommandEncoderImpl::drawIndexed(
1097    GfxCount indexCount,
1098    GfxIndex startIndex,
1099    GfxIndex baseVertex)
1100{
1101    SLANG_RETURN_ON_FAIL(prepareDraw());
1102    m_d3dCmdList->DrawIndexedInstanced(
1103        (uint32_t)indexCount,
1104        1,
1105        (uint32_t)startIndex,
1106        (uint32_t)baseVertex,
1107        0);
1108    return SLANG_OK;
1109}
1110
1111void RenderCommandEncoderImpl::endEncoding()
1112{
1113    PipelineCommandEncoder::endEncodingImpl();
1114    if (!m_framebuffer)
1115        return;
1116    // Issue clear commands based on render pass set up.
1117    for (Index i = 0; i < m_renderPass->m_renderTargetAccesses.getCount(); i++)
1118    {
1119        auto& access = m_renderPass->m_renderTargetAccesses[i];
1120
1121        // Transit resource states.
1122        {
1123            D3D12BarrierSubmitter submitter(m_d3dCmdList);
1124            auto resourceViewImpl = m_framebuffer->renderTargetViews[i].Ptr();
1125            if (!resourceViewImpl)
1126                continue;
1127            auto textureResource =
1128                static_cast<TextureResourceImpl*>(resourceViewImpl->m_resource.Ptr());
1129            if (textureResource)
1130            {
1131                textureResource->m_resource.transition(
1132                    D3D12_RESOURCE_STATE_RENDER_TARGET,
1133                    D3DUtil::getResourceState(access.finalState),
1134                    submitter);
1135            }
1136        }
1137    }
1138
1139    if (m_renderPass->m_hasDepthStencil)
1140    {
1141        // Transit resource states.
1142        D3D12BarrierSubmitter submitter(m_d3dCmdList);
1143        auto resourceViewImpl = m_framebuffer->depthStencilView.Ptr();
1144        auto textureResource =
1145            static_cast<TextureResourceImpl*>(resourceViewImpl->m_resource.Ptr());
1146        textureResource->m_resource.transition(
1147            D3D12_RESOURCE_STATE_DEPTH_WRITE,
1148            D3DUtil::getResourceState(m_renderPass->m_depthStencilAccess.finalState),
1149            submitter);
1150    }
1151    m_framebuffer = nullptr;
1152}
1153
1154void RenderCommandEncoderImpl::setStencilReference(uint32_t referenceValue)
1155{
1156    m_d3dCmdList->OMSetStencilRef((UINT)referenceValue);
1157}
1158
1159Result RenderCommandEncoderImpl::drawIndirect(
1160    GfxCount maxDrawCount,
1161    IBufferResource* argBuffer,
1162    Offset argOffset,
1163    IBufferResource* countBuffer,
1164    Offset countOffset)
1165{
1166    SLANG_RETURN_ON_FAIL(prepareDraw());
1167
1168    auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer);
1169    auto countBufferImpl = static_cast<BufferResourceImpl*>(countBuffer);
1170
1171    m_d3dCmdList->ExecuteIndirect(
1172        m_renderer->drawIndirectCmdSignature,
1173        (uint32_t)maxDrawCount,
1174        argBufferImpl->m_resource,
1175        (uint64_t)argOffset,
1176        countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr,
1177        (uint64_t)countOffset);
1178    return SLANG_OK;
1179}
1180
1181Result RenderCommandEncoderImpl::drawIndexedIndirect(
1182    GfxCount maxDrawCount,
1183    IBufferResource* argBuffer,
1184    Offset argOffset,
1185    IBufferResource* countBuffer,
1186    Offset countOffset)
1187{
1188    SLANG_RETURN_ON_FAIL(prepareDraw());
1189
1190    auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer);
1191    auto countBufferImpl = static_cast<BufferResourceImpl*>(countBuffer);
1192
1193    m_d3dCmdList->ExecuteIndirect(
1194        m_renderer->drawIndexedIndirectCmdSignature,
1195        (uint32_t)maxDrawCount,
1196        argBufferImpl->m_resource,
1197        (uint64_t)argOffset,
1198        countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr,
1199        (uint64_t)countOffset);
1200
1201    return SLANG_OK;
1202}
1203
1204Result RenderCommandEncoderImpl::setSamplePositions(
1205    GfxCount samplesPerPixel,
1206    GfxCount pixelCount,
1207    const SamplePosition* samplePositions)
1208{
1209    if (m_commandBuffer->m_cmdList1)
1210    {
1211        m_commandBuffer->m_cmdList1->SetSamplePositions(
1212            (uint32_t)samplesPerPixel,
1213            (uint32_t)pixelCount,
1214            (D3D12_SAMPLE_POSITION*)samplePositions);
1215        return SLANG_OK;
1216    }
1217    return SLANG_E_NOT_AVAILABLE;
1218}
1219
1220Result RenderCommandEncoderImpl::drawInstanced(
1221    GfxCount vertexCount,
1222    GfxCount instanceCount,
1223    GfxIndex startVertex,
1224    GfxIndex startInstanceLocation)
1225{
1226    SLANG_RETURN_ON_FAIL(prepareDraw());
1227    m_d3dCmdList->DrawInstanced(
1228        (uint32_t)vertexCount,
1229        (uint32_t)instanceCount,
1230        (uint32_t)startVertex,
1231        (uint32_t)startInstanceLocation);
1232    return SLANG_OK;
1233}
1234
1235Result RenderCommandEncoderImpl::drawIndexedInstanced(
1236    GfxCount indexCount,
1237    GfxCount instanceCount,
1238    GfxIndex startIndexLocation,
1239    GfxIndex baseVertexLocation,
1240    GfxIndex startInstanceLocation)
1241{
1242    SLANG_RETURN_ON_FAIL(prepareDraw());
1243    m_d3dCmdList->DrawIndexedInstanced(
1244        (uint32_t)indexCount,
1245        (uint32_t)instanceCount,
1246        (uint32_t)startIndexLocation,
1247        baseVertexLocation,
1248        (uint32_t)startInstanceLocation);
1249    return SLANG_OK;
1250}
1251
1252Result RenderCommandEncoderImpl::drawMeshTasks(int x, int y, int z)
1253{
1254    SLANG_RETURN_ON_FAIL(prepareDraw());
1255    m_d3dCmdList6->DispatchMesh(x, y, z);
1256    return SLANG_OK;
1257}
1258
1259void ComputeCommandEncoderImpl::endEncoding()
1260{
1261    PipelineCommandEncoder::endEncodingImpl();
1262}
1263
1264void ComputeCommandEncoderImpl::init(
1265    DeviceImpl* renderer,
1266    TransientResourceHeapImpl* transientHeap,
1267    CommandBufferImpl* cmdBuffer)
1268{
1269    PipelineCommandEncoder::init(cmdBuffer);
1270    m_preCmdList = nullptr;
1271    m_transientHeap = transientHeap;
1272    m_currentPipeline = nullptr;
1273}
1274
1275Result ComputeCommandEncoderImpl::bindPipeline(IPipelineState* state, IShaderObject** outRootObject)
1276{
1277    return bindPipelineImpl(state, outRootObject);
1278}
1279
1280Result ComputeCommandEncoderImpl::bindPipelineWithRootObject(
1281    IPipelineState* state,
1282    IShaderObject* rootObject)
1283{
1284    return bindPipelineWithRootObjectImpl(state, rootObject);
1285}
1286
1287Result ComputeCommandEncoderImpl::dispatchCompute(int x, int y, int z)
1288{
1289    // Submit binding for compute
1290    {
1291        ComputeSubmitter submitter(m_d3dCmdList);
1292        RefPtr<PipelineStateBase> newPipeline;
1293        SLANG_RETURN_ON_FAIL(_bindRenderState(&submitter, newPipeline));
1294    }
1295    m_d3dCmdList->Dispatch(x, y, z);
1296    return SLANG_OK;
1297}
1298
1299Result ComputeCommandEncoderImpl::dispatchComputeIndirect(IBufferResource* argBuffer, Offset offset)
1300{
1301    // Submit binding for compute
1302    {
1303        ComputeSubmitter submitter(m_d3dCmdList);
1304        RefPtr<PipelineStateBase> newPipeline;
1305        SLANG_RETURN_ON_FAIL(_bindRenderState(&submitter, newPipeline));
1306    }
1307    auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer);
1308
1309    m_d3dCmdList->ExecuteIndirect(
1310        m_renderer->dispatchIndirectCmdSignature,
1311        1,
1312        argBufferImpl->m_resource,
1313        (uint64_t)offset,
1314        nullptr,
1315        0);
1316    return SLANG_OK;
1317}
1318
1319#if SLANG_GFX_HAS_DXR_SUPPORT
1320
1321void RayTracingCommandEncoderImpl::buildAccelerationStructure(
1322    const IAccelerationStructure::BuildDesc& desc,
1323    GfxCount propertyQueryCount,
1324    AccelerationStructureQueryDesc* queryDescs)
1325{
1326    if (!m_commandBuffer->m_cmdList4)
1327    {
1328        getDebugCallback()->handleMessage(
1329            DebugMessageType::Error,
1330            DebugMessageSource::Layer,
1331            "Ray-tracing is not supported on current system.");
1332        return;
1333    }
1334    AccelerationStructureImpl* destASImpl = nullptr;
1335    if (desc.dest)
1336        destASImpl = static_cast<AccelerationStructureImpl*>(desc.dest);
1337    AccelerationStructureImpl* srcASImpl = nullptr;
1338    if (desc.source)
1339        srcASImpl = static_cast<AccelerationStructureImpl*>(desc.source);
1340
1341    D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC buildDesc = {};
1342    buildDesc.DestAccelerationStructureData = destASImpl->getDeviceAddress();
1343    buildDesc.SourceAccelerationStructureData = srcASImpl ? srcASImpl->getDeviceAddress() : 0;
1344    buildDesc.ScratchAccelerationStructureData = desc.scratchData;
1345    D3DAccelerationStructureInputsBuilder builder;
1346    builder.build(desc.inputs, getDebugCallback());
1347    buildDesc.Inputs = builder.desc;
1348
1349    List<D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC> postBuildInfoDescs;
1350    translatePostBuildInfoDescs(propertyQueryCount, queryDescs, postBuildInfoDescs);
1351    m_commandBuffer->m_cmdList4->BuildRaytracingAccelerationStructure(
1352        &buildDesc,
1353        (UINT)propertyQueryCount,
1354        postBuildInfoDescs.getBuffer());
1355}
1356
1357void RayTracingCommandEncoderImpl::copyAccelerationStructure(
1358    IAccelerationStructure* dest,
1359    IAccelerationStructure* src,
1360    AccelerationStructureCopyMode mode)
1361{
1362    auto destASImpl = static_cast<AccelerationStructureImpl*>(dest);
1363    auto srcASImpl = static_cast<AccelerationStructureImpl*>(src);
1364    D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE copyMode;
1365    switch (mode)
1366    {
1367    case AccelerationStructureCopyMode::Clone:
1368        copyMode = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE;
1369        break;
1370    case AccelerationStructureCopyMode::Compact:
1371        copyMode = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_COMPACT;
1372        break;
1373    default:
1374        getDebugCallback()->handleMessage(
1375            DebugMessageType::Error,
1376            DebugMessageSource::Layer,
1377            "Unsupported AccelerationStructureCopyMode.");
1378        return;
1379    }
1380    m_commandBuffer->m_cmdList4->CopyRaytracingAccelerationStructure(
1381        destASImpl->getDeviceAddress(),
1382        srcASImpl->getDeviceAddress(),
1383        copyMode);
1384}
1385
1386void RayTracingCommandEncoderImpl::queryAccelerationStructureProperties(
1387    GfxCount accelerationStructureCount,
1388    IAccelerationStructure* const* accelerationStructures,
1389    GfxCount queryCount,
1390    AccelerationStructureQueryDesc* queryDescs)
1391{
1392    List<D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC> postBuildInfoDescs;
1393    List<DeviceAddress> asAddresses;
1394    asAddresses.setCount(accelerationStructureCount);
1395    for (GfxIndex i = 0; i < accelerationStructureCount; i++)
1396        asAddresses[i] = accelerationStructures[i]->getDeviceAddress();
1397    translatePostBuildInfoDescs(queryCount, queryDescs, postBuildInfoDescs);
1398    m_commandBuffer->m_cmdList4->EmitRaytracingAccelerationStructurePostbuildInfo(
1399        postBuildInfoDescs.getBuffer(),
1400        (UINT)accelerationStructureCount,
1401        asAddresses.getBuffer());
1402}
1403
1404void RayTracingCommandEncoderImpl::serializeAccelerationStructure(
1405    DeviceAddress dest,
1406    IAccelerationStructure* src)
1407{
1408    auto srcASImpl = static_cast<AccelerationStructureImpl*>(src);
1409    m_commandBuffer->m_cmdList4->CopyRaytracingAccelerationStructure(
1410        dest,
1411        srcASImpl->getDeviceAddress(),
1412        D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_SERIALIZE);
1413}
1414
1415void RayTracingCommandEncoderImpl::deserializeAccelerationStructure(
1416    IAccelerationStructure* dest,
1417    DeviceAddress source)
1418{
1419    auto destASImpl = static_cast<AccelerationStructureImpl*>(dest);
1420    m_commandBuffer->m_cmdList4->CopyRaytracingAccelerationStructure(
1421        dest->getDeviceAddress(),
1422        source,
1423        D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_DESERIALIZE);
1424}
1425
1426Result RayTracingCommandEncoderImpl::bindPipeline(
1427    IPipelineState* state,
1428    IShaderObject** outRootObject)
1429{
1430    return bindPipelineImpl(state, outRootObject);
1431}
1432
1433Result RayTracingCommandEncoderImpl::dispatchRays(
1434    GfxIndex rayGenShaderIndex,
1435    IShaderTable* shaderTable,
1436    GfxCount width,
1437    GfxCount height,
1438    GfxCount depth)
1439{
1440    RefPtr<PipelineStateBase> newPipeline;
1441    PipelineStateBase* pipeline = m_currentPipeline.Ptr();
1442    {
1443        struct RayTracingSubmitter : public ComputeSubmitter
1444        {
1445            ID3D12GraphicsCommandList4* m_cmdList4;
1446            RayTracingSubmitter(ID3D12GraphicsCommandList4* cmdList4)
1447                : ComputeSubmitter(cmdList4), m_cmdList4(cmdList4)
1448            {
1449            }
1450            virtual void setPipelineState(PipelineStateBase* pipeline) override
1451            {
1452                auto pipelineImpl = static_cast<RayTracingPipelineStateImpl*>(pipeline);
1453                m_cmdList4->SetPipelineState1(pipelineImpl->m_stateObject.get());
1454            }
1455        };
1456        RayTracingSubmitter submitter(m_commandBuffer->m_cmdList4);
1457        SLANG_RETURN_ON_FAIL(_bindRenderState(&submitter, newPipeline));
1458        if (newPipeline)
1459            pipeline = newPipeline.Ptr();
1460    }
1461    auto pipelineImpl = static_cast<RayTracingPipelineStateImpl*>(pipeline);
1462
1463    auto shaderTableImpl = static_cast<ShaderTableImpl*>(shaderTable);
1464
1465    auto shaderTableBuffer = shaderTableImpl->getOrCreateBuffer(
1466        pipelineImpl,
1467        m_transientHeap,
1468        static_cast<ResourceCommandEncoderImpl*>(this));
1469    auto shaderTableAddr = shaderTableBuffer->getDeviceAddress();
1470
1471    D3D12_DISPATCH_RAYS_DESC dispatchDesc = {};
1472
1473    dispatchDesc.RayGenerationShaderRecord.StartAddress = shaderTableAddr +
1474                                                          shaderTableImpl->m_rayGenTableOffset +
1475                                                          rayGenShaderIndex * kRayGenRecordSize;
1476    dispatchDesc.RayGenerationShaderRecord.SizeInBytes = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
1477
1478    if (shaderTableImpl->m_missShaderCount > 0)
1479    {
1480        dispatchDesc.MissShaderTable.StartAddress =
1481            shaderTableAddr + shaderTableImpl->m_missTableOffset;
1482        dispatchDesc.MissShaderTable.SizeInBytes =
1483            shaderTableImpl->m_missShaderCount * D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
1484        dispatchDesc.MissShaderTable.StrideInBytes = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
1485    }
1486
1487    if (shaderTableImpl->m_hitGroupCount > 0)
1488    {
1489        dispatchDesc.HitGroupTable.StartAddress =
1490            shaderTableAddr + shaderTableImpl->m_hitGroupTableOffset;
1491        dispatchDesc.HitGroupTable.SizeInBytes =
1492            shaderTableImpl->m_hitGroupCount * D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
1493        dispatchDesc.HitGroupTable.StrideInBytes = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
1494    }
1495
1496    if (shaderTableImpl->m_callableShaderCount > 0)
1497    {
1498        dispatchDesc.CallableShaderTable.StartAddress =
1499            shaderTableAddr + shaderTableImpl->m_callableTableOffset;
1500        dispatchDesc.CallableShaderTable.SizeInBytes =
1501            shaderTableImpl->m_callableShaderCount * D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
1502        dispatchDesc.CallableShaderTable.StrideInBytes = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
1503    }
1504
1505    dispatchDesc.Width = (UINT)width;
1506    dispatchDesc.Height = (UINT)height;
1507    dispatchDesc.Depth = (UINT)depth;
1508    m_commandBuffer->m_cmdList4->DispatchRays(&dispatchDesc);
1509
1510    return SLANG_OK;
1511}
1512
1513#endif
1514
1515} // namespace d3d12
1516} // namespace gfx