From 9ce60a0b6ee61f2c8cb3abc0fedbcd5995220ff4 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 29 Jul 2020 15:39:04 +0100 Subject: [PATCH] Test that OpenExistingHeapFromAddress can be captured and replayed --- util/test/demos/d3d12/d3d12_existing_heap.cpp | 131 ++++++++++++++++++ util/test/demos/d3d12/d3d12_parameter_zoo.cpp | 2 - util/test/demos/d3d12/d3d12_sharing.cpp | 12 +- util/test/demos/d3d12/d3d12_test.cpp | 5 + util/test/demos/d3d12/d3d12_test.h | 4 + util/test/demos/demos.vcxproj | 1 + util/test/demos/demos.vcxproj.filters | 3 + util/test/tests/D3D12/D3D12_Existing_Heap.py | 45 ++++++ 8 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 util/test/demos/d3d12/d3d12_existing_heap.cpp create mode 100644 util/test/tests/D3D12/D3D12_Existing_Heap.py diff --git a/util/test/demos/d3d12/d3d12_existing_heap.cpp b/util/test/demos/d3d12/d3d12_existing_heap.cpp new file mode 100644 index 000000000..2b06529c0 --- /dev/null +++ b/util/test/demos/d3d12/d3d12_existing_heap.cpp @@ -0,0 +1,131 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2019-2020 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" + +RD_TEST(D3D12_Existing_Heap, D3D12GraphicsTest) +{ + static constexpr const char *Description = + "Check that creating a heap with OpenExistingHeapFromAddress can be correctly captured and " + "replayed"; + + void Prepare(int argc, char **argv) + { + D3D12GraphicsTest::Prepare(argc, argv); + + if(m_12On7) + Avail = "OpenExistingHeapFromAddress not implemented on D3D12On7"; + } + + int main() + { + // initialise, create window, create device, etc + if(!Init()) + return 3; + + if(!dev3) + { + TEST_ERROR("Didn't get ID3D12Device3*"); + return 4; + } + + ID3DBlobPtr vsblob = Compile(D3DDefaultVertex, "main", "vs_4_0"); + ID3DBlobPtr psblob = Compile(D3DDefaultPixel, "main", "ps_4_0"); + + void *addr = VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READWRITE); + + memcpy(addr, DefaultTri, sizeof(DefaultTri)); + + ID3D12HeapPtr existingHeap; + CHECK_HR(dev3->OpenExistingHeapFromAddress(addr, __uuidof(ID3D12Heap), (void **)&existingHeap)); + + D3D12_RESOURCE_DESC desc; + desc.Alignment = 0; + desc.DepthOrArraySize = 1; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.Height = 1; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Width = sizeof(DefaultTri); + desc.MipLevels = 1; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + + ID3D12ResourcePtr vb; + CHECK_HR(dev->CreatePlacedResource(existingHeap, 0, &desc, D3D12_RESOURCE_STATE_COMMON, NULL, + __uuidof(ID3D12Resource), (void **)&vb)); + + ID3D12RootSignaturePtr sig = MakeSig({}); + + ID3D12PipelineStatePtr pso = MakePSO().RootSig(sig).InputLayout().VS(vsblob).PS(psblob); + + ResourceBarrier(vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + + ID3D12ResourcePtr rtvtex = MakeTexture(DXGI_FORMAT_R32G32B32A32_FLOAT, 4, 4) + .RTV() + .InitialState(D3D12_RESOURCE_STATE_RENDER_TARGET); + + while(Running()) + { + ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer(); + + Reset(cmd); + + ID3D12ResourcePtr bb = StartUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); + + D3D12_CPU_DESCRIPTOR_HANDLE rtv = + MakeRTV(bb).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(0); + + ClearRenderTargetView(cmd, rtv, {0.2f, 0.2f, 0.2f, 1.0f}); + + ClearRenderTargetView(cmd, MakeRTV(rtvtex).CreateCPU(1), {0.2f, 0.2f, 0.2f, 1.0f}); + + cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0); + cmd->SetPipelineState(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, {rtv}, {}); + + cmd->DrawInstanced(3, 1, 0, 0); + + FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET); + + cmd->Close(); + + Submit({cmd}); + + Present(); + } + + return 0; + } +}; + +REGISTER_TEST(); diff --git a/util/test/demos/d3d12/d3d12_parameter_zoo.cpp b/util/test/demos/d3d12/d3d12_parameter_zoo.cpp index 024745bea..cc2c1cdbd 100644 --- a/util/test/demos/d3d12/d3d12_parameter_zoo.cpp +++ b/util/test/demos/d3d12/d3d12_parameter_zoo.cpp @@ -65,8 +65,6 @@ float4 main() : SV_Target0 ID3D12PipelineStatePtr pso = psoCreator; - ID3D12Device4Ptr dev4 = dev; - // if D3D12.4 (??) is available, use different interfaces if(dev4) { diff --git a/util/test/demos/d3d12/d3d12_sharing.cpp b/util/test/demos/d3d12/d3d12_sharing.cpp index e637c7b5f..2d4f1b31c 100644 --- a/util/test/demos/d3d12/d3d12_sharing.cpp +++ b/util/test/demos/d3d12/d3d12_sharing.cpp @@ -61,8 +61,8 @@ RD_TEST(D3D12_Sharing, D3D12GraphicsTest) if(!d3d11.Init(pDXGIAdapter)) return 4; - ID3D12DevicePtr dev2 = CreateDevice({pDXGIAdapter}, D3D_FEATURE_LEVEL_11_0); - if(!dev2) + ID3D12DevicePtr devB = CreateDevice({pDXGIAdapter}, D3D_FEATURE_LEVEL_11_0); + if(!devB) return 2; ID3DBlobPtr vsblob = Compile(D3DDefaultVertex, "main", "vs_4_0"); @@ -86,15 +86,15 @@ RD_TEST(D3D12_Sharing, D3D12GraphicsTest) ID3D12RootSignaturePtr sig = MakeSig({}); - // swap dev with dev2, to force pso to be created on the 'second' device (should be identical to + // swap dev with devB, to force pso to be created on the 'second' device (should be identical to // the first). This may be completely redundant as we might have two identical pointers, but // that's not guaranteed. - std::swap(dev, dev2); + std::swap(dev, devB); ID3D12PipelineStatePtr pso = MakePSO().RootSig(sig).InputLayout().VS(vsblob).PS(psblob); // set them back - std::swap(dev, dev2); + std::swap(dev, devB); ResourceBarrier(d3d12vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); @@ -192,7 +192,7 @@ RD_TEST(D3D12_Sharing, D3D12GraphicsTest) Present(); } - dev2 = NULL; + devB = NULL; return 0; } diff --git a/util/test/demos/d3d12/d3d12_test.cpp b/util/test/demos/d3d12/d3d12_test.cpp index 42d66918b..75e20e34a 100644 --- a/util/test/demos/d3d12/d3d12_test.cpp +++ b/util/test/demos/d3d12/d3d12_test.cpp @@ -426,6 +426,11 @@ float4 main(float4 pos : SV_Position) : SV_Target0 infoqueue = dev; + dev1 = dev; + dev2 = dev; + dev3 = dev; + dev4 = dev; + if(infoqueue) { D3D12_INFO_QUEUE_FILTER filter = {}; diff --git a/util/test/demos/d3d12/d3d12_test.h b/util/test/demos/d3d12/d3d12_test.h index e0ce24920..2f6411595 100644 --- a/util/test/demos/d3d12/d3d12_test.h +++ b/util/test/demos/d3d12/d3d12_test.h @@ -215,6 +215,10 @@ struct D3D12GraphicsTest : public GraphicsTest ID3D12InfoQueuePtr infoqueue; ID3D12DevicePtr dev; + ID3D12Device1Ptr dev1; + ID3D12Device2Ptr dev2; + ID3D12Device3Ptr dev3; + ID3D12Device4Ptr dev4; ID3D12DescriptorHeapPtr m_RTV, m_DSV, m_CBVUAVSRV, m_Clear, m_Sampler; diff --git a/util/test/demos/demos.vcxproj b/util/test/demos/demos.vcxproj index dfb6a6beb..14bfba4a0 100644 --- a/util/test/demos/demos.vcxproj +++ b/util/test/demos/demos.vcxproj @@ -176,6 +176,7 @@ + diff --git a/util/test/demos/demos.vcxproj.filters b/util/test/demos/demos.vcxproj.filters index 6100a9924..9ae2cae90 100644 --- a/util/test/demos/demos.vcxproj.filters +++ b/util/test/demos/demos.vcxproj.filters @@ -535,6 +535,9 @@ Vulkan\demos + + D3D12\demos + diff --git a/util/test/tests/D3D12/D3D12_Existing_Heap.py b/util/test/tests/D3D12/D3D12_Existing_Heap.py new file mode 100644 index 000000000..c5422158f --- /dev/null +++ b/util/test/tests/D3D12/D3D12_Existing_Heap.py @@ -0,0 +1,45 @@ +import renderdoc as rd +import rdtest + + +class D3D12_Existing_Heap(rdtest.TestCase): + demos_test_name = 'D3D12_Existing_Heap' + + def check_capture(self): + last_draw: rd.DrawcallDescription = self.get_last_draw() + + self.controller.SetFrameEvent(last_draw.eventId, True) + + self.check_triangle(out=last_draw.copyDestination) + + draw = self.find_draw("Draw") + + self.controller.SetFrameEvent(draw.eventId, False) + + postvs_data = self.get_postvs(draw, rd.MeshDataStage.VSOut, 0, draw.numIndices) + + postvs_ref = { + 0: { + 'vtx': 0, + 'idx': 0, + 'SV_POSITION': [-0.5, -0.5, 0.0, 1.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + 'TEXCOORD': [0.0, 0.0], + }, + 1: { + 'vtx': 1, + 'idx': 1, + 'SV_POSITION': [0.0, 0.5, 0.0, 1.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + 'TEXCOORD': [0.0, 1.0], + }, + 2: { + 'vtx': 2, + 'idx': 2, + 'SV_POSITION': [0.5, -0.5, 0.0, 1.0], + 'COLOR': [0.0, 1.0, 0.0, 1.0], + 'TEXCOORD': [1.0, 0.0], + }, + } + + self.check_mesh_data(postvs_ref, postvs_data) \ No newline at end of file