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
6.9 KiB210 linesraw
1// d3d12-query.cpp
2#include "d3d12-query.h"
3
4#include "d3d12-command-queue.h"
5#include "d3d12-helper-functions.h"
6
7namespace gfx
8{
9namespace d3d12
10{
11
12using namespace Slang;
13
14Result QueryPoolImpl::init(const IQueryPool::Desc& desc, DeviceImpl* device)
15{
16    m_desc = desc;
17
18    // Translate query type.
19    D3D12_QUERY_HEAP_DESC heapDesc = {};
20    heapDesc.Count = (UINT)desc.count;
21    heapDesc.NodeMask = 1;
22    switch (desc.type)
23    {
24    case QueryType::Timestamp:
25        heapDesc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP;
26        m_queryType = D3D12_QUERY_TYPE_TIMESTAMP;
27        break;
28    default:
29        return SLANG_E_INVALID_ARG;
30    }
31
32    // Create query heap.
33    auto d3dDevice = device->m_device;
34    SLANG_RETURN_ON_FAIL(
35        d3dDevice->CreateQueryHeap(&heapDesc, IID_PPV_ARGS(m_queryHeap.writeRef())));
36
37    // Create readback buffer.
38    D3D12_HEAP_PROPERTIES heapProps;
39    heapProps.Type = D3D12_HEAP_TYPE_READBACK;
40    heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
41    heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
42    heapProps.CreationNodeMask = 1;
43    heapProps.VisibleNodeMask = 1;
44    D3D12_RESOURCE_DESC resourceDesc = {};
45    initBufferResourceDesc(sizeof(uint64_t) * desc.count, resourceDesc);
46    SLANG_RETURN_ON_FAIL(m_readBackBuffer.initCommitted(
47        d3dDevice,
48        heapProps,
49        D3D12_HEAP_FLAG_NONE,
50        resourceDesc,
51        D3D12_RESOURCE_STATE_COPY_DEST,
52        nullptr));
53
54    // Create command allocator.
55    SLANG_RETURN_ON_FAIL(d3dDevice->CreateCommandAllocator(
56        D3D12_COMMAND_LIST_TYPE_DIRECT,
57        IID_PPV_ARGS(m_commandAllocator.writeRef())));
58
59    // Create command list.
60    SLANG_RETURN_ON_FAIL(d3dDevice->CreateCommandList(
61        0,
62        D3D12_COMMAND_LIST_TYPE_DIRECT,
63        m_commandAllocator,
64        nullptr,
65        IID_PPV_ARGS(m_commandList.writeRef())));
66    m_commandList->Close();
67
68    // Create fence.
69    SLANG_RETURN_ON_FAIL(
70        d3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.writeRef())));
71
72    // Get command queue from device.
73    m_commandQueue = device->m_resourceCommandQueue->m_d3dQueue;
74
75    // Create wait event.
76    m_waitEvent = CreateEventEx(nullptr, FALSE, 0, EVENT_ALL_ACCESS);
77
78    return SLANG_OK;
79}
80
81Result QueryPoolImpl::getResult(GfxIndex queryIndex, GfxCount count, uint64_t* data)
82{
83    m_commandList->Reset(m_commandAllocator, nullptr);
84    m_commandList->ResolveQueryData(
85        m_queryHeap,
86        m_queryType,
87        (UINT)queryIndex,
88        (UINT)count,
89        m_readBackBuffer,
90        sizeof(uint64_t) * queryIndex);
91    m_commandList->Close();
92    ID3D12CommandList* cmdList = m_commandList;
93    m_commandQueue->ExecuteCommandLists(1, &cmdList);
94    m_eventValue++;
95    m_fence->SetEventOnCompletion(m_eventValue, m_waitEvent);
96    m_commandQueue->Signal(m_fence, m_eventValue);
97    WaitForSingleObject(m_waitEvent, INFINITE);
98    m_commandAllocator->Reset();
99
100    int8_t* mappedData = nullptr;
101    D3D12_RANGE readRange = {
102        sizeof(uint64_t) * queryIndex,
103        sizeof(uint64_t) * (queryIndex + count)};
104    m_readBackBuffer.getResource()->Map(0, &readRange, (void**)&mappedData);
105    memcpy(data, mappedData + sizeof(uint64_t) * queryIndex, sizeof(uint64_t) * count);
106    m_readBackBuffer.getResource()->Unmap(0, nullptr);
107    return SLANG_OK;
108}
109
110void QueryPoolImpl::writeTimestamp(ID3D12GraphicsCommandList* cmdList, GfxIndex index)
111{
112    cmdList->EndQuery(m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, (UINT)index);
113}
114
115IQueryPool* PlainBufferProxyQueryPoolImpl::getInterface(const Guid& guid)
116{
117    if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IQueryPool)
118        return static_cast<IQueryPool*>(this);
119    return nullptr;
120}
121
122Result PlainBufferProxyQueryPoolImpl::init(
123    const IQueryPool::Desc& desc,
124    DeviceImpl* device,
125    uint32_t stride)
126{
127    ComPtr<IBufferResource> bufferResource;
128    IBufferResource::Desc bufferDesc = {};
129    bufferDesc.defaultState = ResourceState::CopySource;
130    bufferDesc.elementSize = 0;
131    bufferDesc.type = IResource::Type::Buffer;
132    bufferDesc.sizeInBytes = desc.count * stride;
133    bufferDesc.format = Format::Unknown;
134    bufferDesc.allowedStates.add(ResourceState::UnorderedAccess);
135    SLANG_RETURN_ON_FAIL(
136        device->createBufferResource(bufferDesc, nullptr, bufferResource.writeRef()));
137    m_bufferResource = static_cast<BufferResourceImpl*>(bufferResource.get());
138    m_queryType = desc.type;
139    m_device = device;
140    m_stride = stride;
141    m_count = (uint32_t)desc.count;
142    m_desc = desc;
143    return SLANG_OK;
144}
145
146Result PlainBufferProxyQueryPoolImpl::reset()
147{
148    m_resultDirty = true;
149    auto encodeInfo = m_device->encodeResourceCommands();
150    D3D12_RESOURCE_BARRIER barrier = {};
151    barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
152    barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
153    barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
154    barrier.Transition.pResource = m_bufferResource->m_resource.getResource();
155    encodeInfo.d3dCommandList->ResourceBarrier(1, &barrier);
156    m_device->submitResourceCommandsAndWait(encodeInfo);
157    return SLANG_OK;
158}
159
160Result PlainBufferProxyQueryPoolImpl::getResult(GfxIndex queryIndex, GfxCount count, uint64_t* data)
161{
162    if (m_resultDirty)
163    {
164        auto encodeInfo = m_device->encodeResourceCommands();
165        D3D12_RESOURCE_BARRIER barrier = {};
166        barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
167        barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
168        barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
169        barrier.Transition.pResource = m_bufferResource->m_resource.getResource();
170        encodeInfo.d3dCommandList->ResourceBarrier(1, &barrier);
171
172        D3D12Resource stageBuf;
173
174        auto size = (Size)m_count * m_stride;
175        D3D12_HEAP_PROPERTIES heapProps;
176        heapProps.Type = D3D12_HEAP_TYPE_READBACK;
177        heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
178        heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
179        heapProps.CreationNodeMask = 1;
180        heapProps.VisibleNodeMask = 1;
181
182        D3D12_RESOURCE_DESC stagingDesc;
183        initBufferResourceDesc(size, stagingDesc);
184
185        SLANG_RETURN_ON_FAIL(stageBuf.initCommitted(
186            m_device->m_device,
187            heapProps,
188            D3D12_HEAP_FLAG_NONE,
189            stagingDesc,
190            D3D12_RESOURCE_STATE_COPY_DEST,
191            nullptr));
192
193        encodeInfo.d3dCommandList
194            ->CopyBufferRegion(stageBuf, 0, m_bufferResource->m_resource.getResource(), 0, size);
195        m_device->submitResourceCommandsAndWait(encodeInfo);
196        void* ptr = nullptr;
197        stageBuf.getResource()->Map(0, nullptr, &ptr);
198        m_result.setCount(m_count * m_stride);
199        memcpy(m_result.getBuffer(), ptr, m_result.getCount());
200
201        m_resultDirty = false;
202    }
203
204    memcpy(data, m_result.getBuffer() + queryIndex * m_stride, count * m_stride);
205
206    return SLANG_OK;
207}
208
209} // namespace d3d12
210} // namespace gfx