yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
6.6 KiB226 linesraw
1// d3d12-transient-heap.cpp
2#include "d3d12-transient-heap.h"
3
4#include "d3d12-buffer.h"
5#include "d3d12-command-buffer.h"
6#include "d3d12-device.h"
7
8namespace gfx
9{
10namespace d3d12
11{
12
13using namespace Slang;
14
15Result TransientResourceHeapImpl::synchronize()
16{
17    WaitForMultipleObjects(
18        (DWORD)m_waitHandles.getCount(),
19        m_waitHandles.getArrayView().getBuffer(),
20        TRUE,
21        INFINITE);
22    m_waitHandles.clear();
23    return SLANG_OK;
24}
25
26Result TransientResourceHeapImpl::synchronizeAndReset()
27{
28    synchronize();
29
30    m_currentViewHeapIndex = -1;
31    m_currentSamplerHeapIndex = -1;
32    allocateNewViewDescriptorHeap(m_device);
33    allocateNewSamplerDescriptorHeap(m_device);
34    m_stagingCpuSamplerHeap.freeAll();
35    m_stagingCpuViewHeap.freeAll();
36    m_commandListAllocId = 0;
37    SLANG_RETURN_ON_FAIL(m_commandAllocator->Reset());
38    Super::reset();
39    return SLANG_OK;
40}
41
42Result TransientResourceHeapImpl::finish()
43{
44    for (auto& waitInfo : m_waitInfos)
45    {
46        if (waitInfo.waitValue == 0)
47            continue;
48        if (waitInfo.fence)
49        {
50            waitInfo.queue->Signal(waitInfo.fence, waitInfo.waitValue);
51            waitInfo.fence->SetEventOnCompletion(waitInfo.waitValue, waitInfo.fenceEvent);
52            m_waitHandles.add(waitInfo.fenceEvent);
53        }
54    }
55    return SLANG_OK;
56}
57
58TransientResourceHeapImpl::QueueWaitInfo& TransientResourceHeapImpl::getQueueWaitInfo(
59    uint32_t queueIndex)
60{
61    if (queueIndex < (uint32_t)m_waitInfos.getCount())
62    {
63        return m_waitInfos[queueIndex];
64    }
65    auto oldCount = m_waitInfos.getCount();
66    m_waitInfos.setCount(queueIndex + 1);
67    for (auto i = oldCount; i < m_waitInfos.getCount(); i++)
68    {
69        m_waitInfos[i].waitValue = 0;
70        m_waitInfos[i].fenceEvent = CreateEventEx(nullptr, FALSE, 0, EVENT_ALL_ACCESS);
71    }
72    return m_waitInfos[queueIndex];
73}
74
75D3D12DescriptorHeap& TransientResourceHeapImpl::getCurrentViewHeap()
76{
77    return m_viewHeaps[m_currentViewHeapIndex];
78}
79
80D3D12DescriptorHeap& TransientResourceHeapImpl::getCurrentSamplerHeap()
81{
82    return m_samplerHeaps[m_currentSamplerHeapIndex];
83}
84
85Result TransientResourceHeapImpl::queryInterface(SlangUUID const& uuid, void** outObject)
86{
87    if (uuid == GfxGUID::IID_ITransientResourceHeapD3D12)
88    {
89        *outObject = static_cast<ITransientResourceHeapD3D12*>(this);
90        addRef();
91        return SLANG_OK;
92    }
93    return Super::queryInterface(uuid, outObject);
94}
95
96Result TransientResourceHeapImpl::allocateTransientDescriptorTable(
97    DescriptorType type,
98    GfxCount count,
99    Offset& outDescriptorOffset,
100    void** outD3DDescriptorHeapHandle)
101{
102    auto& heap =
103        (type == DescriptorType::ResourceView) ? getCurrentViewHeap() : getCurrentSamplerHeap();
104    int allocResult = heap.allocate((int)count);
105    if (allocResult == -1)
106    {
107        return SLANG_E_OUT_OF_MEMORY;
108    }
109    outDescriptorOffset = (Offset)allocResult;
110    *outD3DDescriptorHeapHandle = heap.getHeap();
111    return SLANG_OK;
112}
113
114TransientResourceHeapImpl::~TransientResourceHeapImpl()
115{
116    synchronize();
117    for (auto& waitInfo : m_waitInfos)
118        CloseHandle(waitInfo.fenceEvent);
119}
120
121Result TransientResourceHeapImpl::init(
122    const ITransientResourceHeap::Desc& desc,
123    DeviceImpl* device,
124    uint32_t viewHeapSize,
125    uint32_t samplerHeapSize)
126{
127    Super::init(desc, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT, device);
128    m_canResize = (desc.flags & ITransientResourceHeap::Flags::AllowResizing) != 0;
129    m_viewHeapSize = viewHeapSize;
130    m_samplerHeapSize = samplerHeapSize;
131
132    m_stagingCpuViewHeap.init(
133        device->m_device,
134        1000000,
135        D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
136        D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
137    m_stagingCpuSamplerHeap.init(
138        device->m_device,
139        1000000,
140        D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
141        D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
142
143    auto d3dDevice = device->m_device;
144    SLANG_RETURN_ON_FAIL(d3dDevice->CreateCommandAllocator(
145        D3D12_COMMAND_LIST_TYPE_DIRECT,
146        IID_PPV_ARGS(m_commandAllocator.writeRef())));
147
148    allocateNewViewDescriptorHeap(device);
149    allocateNewSamplerDescriptorHeap(device);
150
151    return SLANG_OK;
152}
153
154Result TransientResourceHeapImpl::allocateNewViewDescriptorHeap(DeviceImpl* device)
155{
156    auto nextHeapIndex = m_currentViewHeapIndex + 1;
157    if (nextHeapIndex < m_viewHeaps.getCount())
158    {
159        m_viewHeaps[nextHeapIndex].deallocateAll();
160        m_currentViewHeapIndex = nextHeapIndex;
161        return SLANG_OK;
162    }
163    auto d3dDevice = device->m_device;
164    D3D12DescriptorHeap viewHeap;
165    SLANG_RETURN_ON_FAIL(viewHeap.init(
166        d3dDevice,
167        m_viewHeapSize,
168        D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
169        D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
170    m_currentViewHeapIndex = (int32_t)m_viewHeaps.getCount();
171    m_viewHeaps.add(_Move(viewHeap));
172    return SLANG_OK;
173}
174
175Result TransientResourceHeapImpl::allocateNewSamplerDescriptorHeap(DeviceImpl* device)
176{
177    auto nextHeapIndex = m_currentSamplerHeapIndex + 1;
178    if (nextHeapIndex < m_samplerHeaps.getCount())
179    {
180        m_samplerHeaps[nextHeapIndex].deallocateAll();
181        m_currentSamplerHeapIndex = nextHeapIndex;
182        return SLANG_OK;
183    }
184    auto d3dDevice = device->m_device;
185    D3D12DescriptorHeap samplerHeap;
186    SLANG_RETURN_ON_FAIL(samplerHeap.init(
187        d3dDevice,
188        m_samplerHeapSize,
189        D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
190        D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
191    m_currentSamplerHeapIndex = (int32_t)m_samplerHeaps.getCount();
192    m_samplerHeaps.add(_Move(samplerHeap));
193    return SLANG_OK;
194}
195
196Result TransientResourceHeapImpl::createCommandBuffer(ICommandBuffer** outCmdBuffer)
197{
198    if ((Index)m_commandListAllocId < m_commandBufferPool.getCount())
199    {
200        auto result =
201            static_cast<CommandBufferImpl*>(m_commandBufferPool[m_commandListAllocId].Ptr());
202        m_d3dCommandListPool[m_commandListAllocId]->Reset(m_commandAllocator, nullptr);
203        result->reinit();
204        ++m_commandListAllocId;
205        returnComPtr(outCmdBuffer, result);
206        return SLANG_OK;
207    }
208    ComPtr<ID3D12GraphicsCommandList> cmdList;
209    SLANG_RETURN_ON_FAIL(m_device->m_device->CreateCommandList(
210        0,
211        D3D12_COMMAND_LIST_TYPE_DIRECT,
212        m_commandAllocator,
213        nullptr,
214        IID_PPV_ARGS(cmdList.writeRef())));
215
216    m_d3dCommandListPool.add(cmdList);
217    RefPtr<CommandBufferImpl> cmdBuffer = new CommandBufferImpl();
218    cmdBuffer->init(m_device, cmdList, this);
219    m_commandBufferPool.add(cmdBuffer);
220    ++m_commandListAllocId;
221    returnComPtr(outCmdBuffer, cmdBuffer);
222    return SLANG_OK;
223}
224
225} // namespace d3d12
226} // namespace gfx