diff --git a/util/test/demos/d3d12/d3d12_helpers.cpp b/util/test/demos/d3d12/d3d12_helpers.cpp index a724fdccf9..a5e087126c 100644 --- a/util/test/demos/d3d12/d3d12_helpers.cpp +++ b/util/test/demos/d3d12/d3d12_helpers.cpp @@ -295,8 +295,9 @@ D3D12BufferCreator &D3D12BufferCreator::InitialState(D3D12_RESOURCE_STATES initi D3D12BufferCreator::operator ID3D12ResourcePtr() const { ID3D12ResourcePtr buf; - CHECK_HR(m_Dev->CreateCommittedResource(&m_HeapDesc, D3D12_HEAP_FLAG_NONE, &m_BufDesc, m_InitialState, - NULL, __uuidof(ID3D12Resource), (void **)&buf)); + CHECK_HR(m_Dev->CreateCommittedResource(&m_HeapDesc, D3D12_HEAP_FLAG_NONE, &m_BufDesc, + m_InitialState, NULL, __uuidof(ID3D12Resource), + (void **)&buf)); if(m_Initdata && m_Test) m_Test->SetBufferData(buf, D3D12_RESOURCE_STATE_COMMON, (const byte *)m_Initdata, @@ -419,9 +420,10 @@ D3D12TextureCreator &D3D12TextureCreator::ClearVal(const D3D12_CLEAR_VALUE &clea D3D12TextureCreator::operator ID3D12ResourcePtr() const { ID3D12ResourcePtr tex; - CHECK_HR(m_Dev->CreateCommittedResource(&m_HeapDesc, m_HeapFlags, &m_TexDesc, m_InitialState, - (m_ClearVal.Format == DXGI_FORMAT_UNKNOWN) ? NULL : &m_ClearVal, - __uuidof(ID3D12Resource), (void **)&tex)); + CHECK_HR(m_Dev->CreateCommittedResource( + &m_HeapDesc, m_HeapFlags, &m_TexDesc, m_InitialState, + (m_ClearVal.Format == DXGI_FORMAT_UNKNOWN) ? NULL : &m_ClearVal, __uuidof(ID3D12Resource), + (void **)&tex)); return tex; } diff --git a/util/test/demos/d3d12/d3d12_multi_wait_before_signal.cpp b/util/test/demos/d3d12/d3d12_multi_wait_before_signal.cpp new file mode 100644 index 0000000000..fe416de046 --- /dev/null +++ b/util/test/demos/d3d12/d3d12_multi_wait_before_signal.cpp @@ -0,0 +1,459 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2019-2023 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "d3d12_test.h" + +template +class ComputeQueues +{ + ID3D12DevicePtr m_dev; + ID3D12CommandQueuePtr m_computeQs[numQs]; + ID3D12FencePtr m_gpuQEndSyncFences[numQs]; + HANDLE m_gpuQSyncHandles[numQs]; + UINT64 m_gpuQSyncCounters[numQs]; + ID3D12CommandAllocatorPtr m_commandAllocators[numQs]; + std::vector m_freeCommandBuffers[numQs]; + std::vector m_pendingCommandBuffers[numQs]; + +public: + ComputeQueues() = delete; + ComputeQueues(const ComputeQueues &) = delete; + void operator=(const ComputeQueues &) = delete; + + ComputeQueues(ID3D12DevicePtr dev) : m_dev(dev) + { + D3D12_COMMAND_QUEUE_DESC qDesc = {}; + qDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; + wchar_t nameBuf[32]; + + for(UINT i = 0; i < numQs; ++i) + { + dev->CreateCommandQueue(&qDesc, __uuidof(ID3D12CommandQueue), (void **)&m_computeQs[i]); + dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, __uuidof(ID3D12Fence), + (void **)&m_gpuQEndSyncFences[i]); + wsprintf(nameBuf, L"Compute %u GPU end sync fence", i); + m_gpuQEndSyncFences[i]->SetName(nameBuf); + m_gpuQSyncHandles[i] = ::CreateEvent(NULL, FALSE, FALSE, NULL); + CHECK_HR(dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE, + __uuidof(ID3D12CommandAllocator), + (void **)&m_commandAllocators[i])); + wsprintf(nameBuf, L"Compute %u command allocator", i); + m_commandAllocators[i]->SetName(nameBuf); + m_gpuQSyncCounters[i] = 1u; + m_freeCommandBuffers[i].reserve(4); + m_pendingCommandBuffers[i].reserve(4); + + ID3D12GraphicsCommandListPtr list = NULL; + CHECK_HR(dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COMPUTE, m_commandAllocators[i], + NULL, __uuidof(ID3D12GraphicsCommandList), (void **)&list)); + list->Close(); // list starts opened, close it + m_freeCommandBuffers[i].push_back(list); + } + } + + ~ComputeQueues() + { + for(UINT i = 0; i < numQs; ++i) + { + m_gpuQSyncCounters[i]++; + CHECK_HR(m_computeQs[i]->Signal(m_gpuQEndSyncFences[i], m_gpuQSyncCounters[i])); + CHECK_HR(m_gpuQEndSyncFences[i]->SetEventOnCompletion(m_gpuQSyncCounters[i], + m_gpuQSyncHandles[i])); + } + WaitForMultipleObjects(numQs, &m_gpuQSyncHandles[0], TRUE /*waitAll*/, 10000); + + for(UINT i = 0; i < numQs; ++i) + { + m_pendingCommandBuffers[i].clear(); + m_freeCommandBuffers[i].clear(); + m_commandAllocators[i] = NULL; + CloseHandle(m_gpuQSyncHandles[i]); + m_gpuQEndSyncFences[i] = NULL; + m_computeQs[i] = NULL; + } + + m_dev = NULL; + } + + ID3D12GraphicsCommandListPtr GetResetCommandBuffer(UINT queueIdx) + { + if(m_freeCommandBuffers[queueIdx].empty()) + { + ID3D12GraphicsCommandListPtr list = NULL; + CHECK_HR(m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COMPUTE, + m_commandAllocators[queueIdx], NULL, + __uuidof(ID3D12GraphicsCommandList), (void **)&list)); + list->Close(); // list starts opened, close it + m_freeCommandBuffers[queueIdx].push_back(list); + } + + ID3D12GraphicsCommandListPtr ret = m_freeCommandBuffers[queueIdx].back(); + m_freeCommandBuffers[queueIdx].pop_back(); + + ret->Reset(m_commandAllocators[queueIdx], NULL); + return ret; + } + + void Wait(UINT queueIdx, ID3D12Fence *fence, UINT64 val) + { + TEST_ASSERT(queueIdx < numQs, "Out of bounds queueIdx"); + m_computeQs[queueIdx]->Wait(fence, val); + } + + void Signal(UINT queueIdx, ID3D12Fence *fence, UINT64 val) + { + TEST_ASSERT(queueIdx < numQs, "Out of bounds queueIdx"); + m_computeQs[queueIdx]->Signal(fence, val); + } + + void Submit(UINT queueIdx, ID3D12GraphicsCommandListPtr cmdList) + { + ID3D12CommandList *rawList = cmdList; + m_computeQs[queueIdx]->ExecuteCommandLists(1, &rawList); + m_pendingCommandBuffers[queueIdx].push_back(cmdList); + } + + void EndSyncFenceSignal(UINT queueIdx) + { + m_gpuQSyncCounters[queueIdx]++; + m_computeQs[queueIdx]->Signal(m_gpuQEndSyncFences[queueIdx], m_gpuQSyncCounters[queueIdx]); + } + + void PostPresentSyncAndReset() + { + for(UINT i = 0; i < numQs; ++i) + { + CHECK_HR(m_gpuQEndSyncFences[i]->SetEventOnCompletion(m_gpuQSyncCounters[i], + m_gpuQSyncHandles[i])); + } + WaitForMultipleObjects(numQs, &m_gpuQSyncHandles[0], TRUE /*waitAll*/, 10000); + + for(UINT i = 0; i < numQs; ++i) + { + m_freeCommandBuffers[i].insert(m_freeCommandBuffers[i].end(), + m_pendingCommandBuffers[i].begin(), + m_pendingCommandBuffers[i].end()); + m_pendingCommandBuffers[i].clear(); + m_commandAllocators[i]->Reset(); + } + } +}; + +RD_TEST(D3D12_Multi_Wait_Before_Signal, D3D12GraphicsTest) +{ + // Overview of work - + // + // Comp0: Wait GQ-------------------| Modify col0, Signal GQ! + // Comp1: Wait.GQ-------------------------------------------------------| Modify col1, Signal GQ! + // GfxQ: Init RTs/buff, Signal CQ0! Wait CQ0-------------| Signal CQ1! Wait CQ1-------------| Draw Tris + + static constexpr const char *Description = + "Draws two triangles that read their colours from a buffer that is " + "populated by two different compute queue dispatches. This tests " + "that any walking of queue command lists is able to deserialise multiple " + "queues that may initially appear blocked, waiting for a fence signal " + "from another queue."; + + enum CBVUAVSRVDescriptorHeapIdx : uint32_t + { + eBufferUAV = 0, + eBufferSRV, + }; + + std::string sources = R"EOSHADERS( + +cbuffer RootConstants : register(b0) +{ + uint rootConstant0; + uint rootConstant1; +}; +RWStructuredBuffer bufferRW : register(u0); +StructuredBuffer buffer : register(t0); + +[numthreads(2,1,1)] +void resetBufferCS(uint dispatchTID : SV_DispatchThreadID) +{ + bufferRW[dispatchTID] = float4(0.0f, 0.0f, 1.0f, 0.0f); +} + +[numthreads(1,1,1)] +void mainCS() +{ + uint myBufferIdx = rootConstant0; + float4 oldCol = bufferRW[myBufferIdx]; + float4 addCol = float4((float)(rootConstant1 & 0xffu) / 255.0f, (float)((rootConstant1>>8u) & 0xffu) / 255.0f, (float)((rootConstant1>>16u) & 0xffu) / 255.0f, (float)((rootConstant1>>24u) & 0xffu) / 255.0f); + bufferRW[myBufferIdx] = oldCol + addCol; +} + +float4 mainVS(in float3 pos : POSITION) : SV_POSITION +{ + return float4(pos, 1); +} + +float4 mainPS(in float4 pos : SV_POSITION) : SV_Target0 +{ + uint myBufferIdx = rootConstant0; + return buffer[myBufferIdx]; +} + +)EOSHADERS"; + + enum class CBVUAVSRVHeapIdx : uint32_t + { + eBufferUAV = 0, + eBufferSRV + }; + + int main() + { + // initialise, create window, create device, etc + if(!Init()) + return 3; + + ComputeQueues<2> computeQs(dev); + + ID3DBlobPtr resetBuffCSBlob = Compile(sources, "resetBufferCS", "cs_5_0"); + ID3DBlobPtr csBlob = Compile(sources, "mainCS", "cs_5_0"); + ID3DBlobPtr vsBlob = Compile(sources, "mainVS", "vs_4_0"); + ID3DBlobPtr psBlob = Compile(sources, "mainPS", "ps_4_0"); + + const Vec3f twoTrisVBDat[6] = { + Vec3f(-0.5f, -0.25f, 0.9f), Vec3f(0.25f, 0.5f, 0.9f), Vec3f(1.0f, -0.25f, 0.9f), + Vec3f(-0.75f, 0.75f, 0.5f), Vec3f(0.75f, -0.75f, 0.5f), Vec3f(-0.75f, -0.75f, 0.5f), + }; + ID3D12ResourcePtr vb = MakeBuffer().Data(twoTrisVBDat); + + uint32_t rootConstants[2]; + ID3D12RootSignaturePtr sig = MakeSig({ + constParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0, sizeof(rootConstants) / sizeof(uint32_t)), + tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 0, 1, + (uint32_t)CBVUAVSRVHeapIdx::eBufferUAV, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE), + tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 0, 1, + (uint32_t)CBVUAVSRVHeapIdx::eBufferSRV, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE), + }); + + static const std::vector vtxLayout = { + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, + D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, + }; + + ID3D12PipelineStatePtr reset_buff_cs_pso = MakePSO().RootSig(sig).CS(resetBuffCSBlob); + reset_buff_cs_pso->SetName(L"reset_buff_cs_pso"); + ID3D12PipelineStatePtr cs_pso = MakePSO().RootSig(sig).CS(csBlob); + cs_pso->SetName(L"cs_pso"); + D3D12PSOCreator gfx_pso_creator = + MakePSO().RootSig(sig).InputLayout(vtxLayout).VS(vsBlob).PS(psBlob).DSV(DXGI_FORMAT_D32_FLOAT); + gfx_pso_creator.GraphicsDesc.DepthStencilState.DepthEnable = TRUE; + gfx_pso_creator.GraphicsDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + gfx_pso_creator.GraphicsDesc.DepthStencilState.StencilEnable = FALSE; + gfx_pso_creator.GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; + ID3D12PipelineStatePtr gfx_pso = gfx_pso_creator; + gfx_pso->SetName(L"gfx_pso"); + + D3D12_CPU_DESCRIPTOR_HANDLE hBackBufferRTVDescs[2] = { + MakeRTV(bbTex[0]).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(0), + MakeRTV(bbTex[1]).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(1), + }; + + D3D12_CLEAR_VALUE clearVal; + clearVal.Format = DXGI_FORMAT_D32_FLOAT; + clearVal.DepthStencil.Depth = 0.0f; + clearVal.DepthStencil.Stencil = 0u; + ID3D12ResourcePtr dsvTex = MakeTexture(DXGI_FORMAT_D32_FLOAT, screenWidth, screenHeight) + .DSV() + .NoSRV() + .InitialState(D3D12_RESOURCE_STATE_DEPTH_WRITE) + .ClearVal(clearVal); + D3D12_CPU_DESCRIPTOR_HANDLE hDsvCpuDesc = MakeDSV(dsvTex).CreateCPU(0); + + ID3D12ResourcePtr buffer = + MakeBuffer().Size(32).UAV().InitialState(D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + buffer->SetName(L"buffer"); + D3D12_GPU_DESCRIPTOR_HANDLE hBuffUavGpuDesc = + MakeUAV(buffer).StructureStride(16).CreateGPU((uint32_t)CBVUAVSRVHeapIdx::eBufferUAV); + D3D12_GPU_DESCRIPTOR_HANDLE hBuffSrvGpuDesc = + MakeSRV(buffer).StructureStride(16).CreateGPU((uint32_t)CBVUAVSRVHeapIdx::eBufferSRV); + + ID3D12FencePtr gfxToCompute0Fence, gfxToCompute1Fence, compute0ToGfxFence, compute1ToGfxFence; + dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, __uuidof(ID3D12Fence), (void **)&gfxToCompute0Fence); + gfxToCompute0Fence->SetName(L"gfxToCompute0"); + dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, __uuidof(ID3D12Fence), (void **)&gfxToCompute1Fence); + gfxToCompute1Fence->SetName(L"gfxToCompute1"); + dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, __uuidof(ID3D12Fence), (void **)&compute0ToGfxFence); + compute0ToGfxFence->SetName(L"compute0ToGfx"); + dev->CreateFence(0, D3D12_FENCE_FLAG_SHARED, __uuidof(ID3D12Fence), (void **)&compute1ToGfxFence); + compute1ToGfxFence->SetName(L"compute1ToGfx"); + + UINT64 sharedGfxComputeSyncCounter = 1; + + // Transition resources from initial states to states they'll be after completion of each frame + ResourceBarrier(vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + + while(Running()) + { + sharedGfxComputeSyncCounter++; + + { // ComputeQ0's work for the entire frame + computeQs.Wait(0, gfxToCompute0Fence, sharedGfxComputeSyncCounter); + + ID3D12GraphicsCommandListPtr cmd = computeQs.GetResetCommandBuffer(0); + cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr()); + cmd->SetComputeRootSignature(sig); + cmd->SetPipelineState(cs_pso); + + rootConstants[0] = 0; // myBufferIdx + rootConstants[1] = 0x80u | (0x40u << 8) | (0x00u << 16) | + (0xffu << 24); // myCol (packed): Brown (purple, added to blue) + cmd->SetComputeRoot32BitConstants(0, 2, &rootConstants[0], 0); + cmd->SetComputeRootDescriptorTable(1, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->SetComputeRootDescriptorTable(2, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->Dispatch(1, 1, 1); + cmd->Close(); + + computeQs.Submit(0, cmd); + + computeQs.Signal(0, compute0ToGfxFence, sharedGfxComputeSyncCounter); + + computeQs.EndSyncFenceSignal(0); + } + + { // ComputeQ1's work for the entire frame + computeQs.Wait(1, gfxToCompute1Fence, sharedGfxComputeSyncCounter); + + ID3D12GraphicsCommandListPtr cmd = computeQs.GetResetCommandBuffer(1); + cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr()); + cmd->SetComputeRootSignature(sig); + cmd->SetPipelineState(cs_pso); + + rootConstants[0] = 1; // myBufferIdx + rootConstants[1] = 0x40u | (0xc0u << 8) | (0x00u << 16) | + (0xffu << 24); // myCol (packed): Green (light blue, added to blue) + cmd->SetComputeRoot32BitConstants(0, 2, &rootConstants[0], 0); + cmd->SetComputeRootDescriptorTable(1, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->SetComputeRootDescriptorTable(2, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->Dispatch(1, 1, 1); + cmd->Close(); + + computeQs.Submit(1, cmd); + + computeQs.Signal(1, compute1ToGfxFence, sharedGfxComputeSyncCounter); + + computeQs.EndSyncFenceSignal(1); + } + + { // Gfx work + // Clear RTs + ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer(); + Reset(cmd); + + ResourceBarrier(cmd, bbTex[texIdx], D3D12_RESOURCE_STATE_PRESENT, + D3D12_RESOURCE_STATE_RENDER_TARGET); + cmd->ClearDepthStencilView(hDsvCpuDesc, D3D12_CLEAR_FLAG_DEPTH, 0.0f, 0, 0, NULL); + const Vec4f clearCol(0.2f, 0.2f, 0.2f, 0.0f); + cmd->ClearRenderTargetView(hBackBufferRTVDescs[texIdx], &clearCol.x, 0, NULL); + + // Reset 'buffer' with initial colour (blue) + cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr()); + cmd->SetComputeRootSignature(sig); + cmd->SetPipelineState(reset_buff_cs_pso); + cmd->SetComputeRootDescriptorTable(1, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->SetComputeRootDescriptorTable(2, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->Dispatch(1, 1, 1); + + D3D12_RESOURCE_BARRIER buffer_uav_barrier; + buffer_uav_barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + buffer_uav_barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + buffer_uav_barrier.UAV.pResource = buffer; + cmd->ResourceBarrier(1, &buffer_uav_barrier); + + cmd->Close(); + + ID3D12CommandList *rawCmdListPtr = cmd; + queue->ExecuteCommandLists(1, &rawCmdListPtr); + + // Signal CQ0 + TEST_ASSERT(gfxToCompute0Fence->GetCompletedValue() < sharedGfxComputeSyncCounter, + "Compute0 hasn't waited for gfx signal!"); + queue->Signal(gfxToCompute0Fence, sharedGfxComputeSyncCounter); + + // Wait on CQ0 + queue->Wait(compute0ToGfxFence, sharedGfxComputeSyncCounter); + + // Signal CQ1 + TEST_ASSERT(gfxToCompute1Fence->GetCompletedValue() < sharedGfxComputeSyncCounter, + "Compute1 hasn't waited for gfx signal"); + queue->Signal(gfxToCompute1Fence, sharedGfxComputeSyncCounter); + + // Wait on CQ1 + queue->Wait(compute1ToGfxFence, sharedGfxComputeSyncCounter); + + // Draw Tris + cmd = GetCommandBuffer(); + Reset(cmd); + + ResourceBarrier(cmd, buffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + + cmd->SetDescriptorHeaps( + 1, &m_CBVUAVSRV.GetInterfacePtr()); // Must be done BEFORE setting root signatures + cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + IASetVertexBuffer(cmd, vb, sizeof(Vec3f), 0); + cmd->SetPipelineState(gfx_pso); + cmd->SetGraphicsRootSignature(sig); + RSSetViewport(cmd, {0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f}); + RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight}); + OMSetRenderTargets(cmd, {hBackBufferRTVDescs[texIdx]}, hDsvCpuDesc); + rootConstants[0] = 0; // myBufferIdx + cmd->SetGraphicsRoot32BitConstants(0, 1, &rootConstants[0], 0); + cmd->SetGraphicsRootDescriptorTable(1, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->SetGraphicsRootDescriptorTable(2, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->DrawInstanced(3, 1, 0, 0); + + rootConstants[0] = 1; // myBufferIdx + cmd->SetGraphicsRoot32BitConstants(0, 1, &rootConstants[0], 0); + cmd->DrawInstanced(3, 1, 3, 0); + + ResourceBarrier(cmd, bbTex[texIdx], D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_PRESENT); + texIdx = 1u - texIdx; + + // Transition resources back to their expected states at the start of the next frame + ResourceBarrier(cmd, buffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + cmd->Close(); + + Submit({cmd}); + } + + Present(); // Just deals with the gfx set of objects, so we'll do the equivalent + // sync & resetting for our compute work - + computeQs.PostPresentSyncAndReset(); + } + + return 0; + } +}; + +REGISTER_TEST(); diff --git a/util/test/demos/demos.vcxproj b/util/test/demos/demos.vcxproj index 4b3ca4a97d..99bd79592b 100644 --- a/util/test/demos/demos.vcxproj +++ b/util/test/demos/demos.vcxproj @@ -194,6 +194,7 @@ + diff --git a/util/test/demos/demos.vcxproj.filters b/util/test/demos/demos.vcxproj.filters index 234a05fef3..720bfaa870 100644 --- a/util/test/demos/demos.vcxproj.filters +++ b/util/test/demos/demos.vcxproj.filters @@ -682,6 +682,9 @@ D3D12\demos + + D3D12\demos + @@ -956,4 +959,7 @@ Android + + + \ No newline at end of file