mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-11-10 16:09:09 +00:00
Add a demo project with extremely high overlap/sparseness buffers
* For stressing memory overhead in buffer initial states
This commit is contained in:
5 files changed
+265
-1
No files matched your search
@@ -0,0 +1,247 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019-2025 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_Memory_Overlap, D3D12GraphicsTest)
|
||||
{
|
||||
static constexpr const char *Description =
|
||||
"Test that allocates a lot of 'virtual' memory that doesn't require much physical memory - "
|
||||
"overlapping resources and sparse buffers that are mostly unmapped.";
|
||||
|
||||
std::string pixel = R"EOSHADER(
|
||||
|
||||
StructuredBuffer<uint> buffers[8000] : register(t0);
|
||||
|
||||
float4 main() : SV_Target0
|
||||
{
|
||||
uint bufIdx = 0;
|
||||
uint byteOffset = 0;
|
||||
|
||||
for(int i=0; i < 20; i++)
|
||||
{
|
||||
uint a = buffers[bufIdx][byteOffset/4];
|
||||
uint b = buffers[bufIdx][(byteOffset/4) + 1];
|
||||
|
||||
if(a == 999999 && b == 999999)
|
||||
return float4(0, 1, 0, 1);
|
||||
|
||||
bufIdx = a;
|
||||
byteOffset = b;
|
||||
}
|
||||
|
||||
return float4(1, 0, 0, 1);
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
int main()
|
||||
{
|
||||
// initialise, create window, create device, etc
|
||||
if(!Init())
|
||||
return 3;
|
||||
|
||||
ID3DBlobPtr vsblob = Compile(D3DDefaultVertex, "main", "vs_6_0");
|
||||
ID3DBlobPtr psblob = Compile(pixel, "main", "ps_6_0");
|
||||
|
||||
ID3D12RootSignaturePtr sig = MakeSig({
|
||||
tableParam(D3D12_SHADER_VISIBILITY_PIXEL, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 0, 8000, 0),
|
||||
});
|
||||
|
||||
ID3D12PipelineStatePtr pso = MakePSO().RootSig(sig).InputLayout().VS(vsblob).PS(psblob);
|
||||
|
||||
// 256MB heap gives us plenty of unique possibilities for buffers
|
||||
|
||||
D3D12_HEAP_DESC heapDesc;
|
||||
heapDesc.SizeInBytes = 256 * 1024 * 1024;
|
||||
heapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||
heapDesc.Alignment = 0;
|
||||
heapDesc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapDesc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapDesc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapDesc.Properties.CreationNodeMask = 1;
|
||||
heapDesc.Properties.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC resDesc;
|
||||
resDesc.Alignment = 0;
|
||||
resDesc.DepthOrArraySize = 1;
|
||||
resDesc.Width = heapDesc.SizeInBytes;
|
||||
resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
resDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resDesc.Height = 1;
|
||||
resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resDesc.MipLevels = 1;
|
||||
resDesc.SampleDesc.Count = 1;
|
||||
resDesc.SampleDesc.Quality = 0;
|
||||
|
||||
D3D12_RESOURCE_ALLOCATION_INFO info = dev->GetResourceAllocationInfo(0, 1, &resDesc);
|
||||
|
||||
ID3D12HeapPtr heap;
|
||||
CHECK_HR(dev->CreateHeap(&heapDesc, __uuidof(ID3D12Heap), (void **)&heap));
|
||||
|
||||
heapDesc.SizeInBytes = 128 * 1024 * 1024;
|
||||
ID3D12HeapPtr sparseHeap;
|
||||
CHECK_HR(dev->CreateHeap(&heapDesc, __uuidof(ID3D12Heap), (void **)&sparseHeap));
|
||||
|
||||
std::vector<ID3D12ResourcePtr> bufs;
|
||||
|
||||
// create a max-size buffer at many possible offsets. Saving the contents of each buffer
|
||||
// separately will result in a huge expansion of needed memory.
|
||||
// We cut down the number of resources a bit since tracking overlaps is expensive and this makes
|
||||
// the test run slower - no real application will have this amount of overlapping
|
||||
UINT64 offs = 0;
|
||||
while(resDesc.Width > 0)
|
||||
{
|
||||
ID3D12ResourcePtr buf;
|
||||
CHECK_HR(dev->CreatePlacedResource(heap, offs, &resDesc, D3D12_RESOURCE_STATE_COMMON, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&buf));
|
||||
bufs.push_back(buf);
|
||||
|
||||
resDesc.Width -= D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT * 2;
|
||||
offs += D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT * 2;
|
||||
}
|
||||
|
||||
const uint32_t firstSparse = (uint32_t)bufs.size();
|
||||
|
||||
// create a few sparse buffers with only tiny amounts mapped - again saving the buffer contents
|
||||
// instead of backing memory will expand memory use
|
||||
resDesc.Width = 1536 * 1024 * 1024;
|
||||
|
||||
std::vector<ID3D12ResourcePtr> sparsebufs;
|
||||
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
ID3D12ResourcePtr buf;
|
||||
dev->CreateReservedResource(&resDesc, D3D12_RESOURCE_STATE_COMMON, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&buf);
|
||||
sparsebufs.push_back(buf);
|
||||
bufs.push_back(buf);
|
||||
}
|
||||
|
||||
// we don't test textures currently as we save those entirely :)...
|
||||
|
||||
for(size_t i = 0; i < bufs.size(); i++)
|
||||
{
|
||||
MakeSRV(bufs[i]).Format(DXGI_FORMAT_R32_UINT).CreateGPU(int(i));
|
||||
}
|
||||
|
||||
// we chase around a few buffers to ensure their data is correct. Starting from buffer 0, offset
|
||||
// 0 each time we read a pair of uints
|
||||
uint32_t data[] = {
|
||||
3,
|
||||
128,
|
||||
|
||||
10,
|
||||
1024,
|
||||
|
||||
firstSparse,
|
||||
1024 * 1024 + 64,
|
||||
|
||||
firstSparse + 10,
|
||||
7 * 1024 * 1024 + 512,
|
||||
|
||||
// success value
|
||||
999999,
|
||||
999999,
|
||||
};
|
||||
|
||||
ID3D12ResourcePtr uploadBuf = MakeBuffer().Upload().Data(data);
|
||||
|
||||
// need to map the
|
||||
D3D12_TILED_RESOURCE_COORDINATE start = {
|
||||
(1024 * 1024) / 65536,
|
||||
};
|
||||
D3D12_TILE_REGION_SIZE size = {
|
||||
1, FALSE, 1, 1, 1,
|
||||
};
|
||||
UINT heapRangeStart = (92 * 1024 * 1024 + 128 * 1024) / 65536;
|
||||
UINT rangeTileCount = 1;
|
||||
queue->UpdateTileMappings(sparsebufs[0], 1, &start, &size, sparseHeap, 1, NULL, &heapRangeStart,
|
||||
&rangeTileCount, D3D12_TILE_MAPPING_FLAG_NONE);
|
||||
|
||||
start.X = (7 * 1024 * 1024) / 65536;
|
||||
heapRangeStart = (100 * 1024 * 1024 + 768 * 1024) / 65536;
|
||||
queue->UpdateTileMappings(sparsebufs[10], 1, &start, &size, sparseHeap, 1, NULL,
|
||||
&heapRangeStart, &rangeTileCount, D3D12_TILE_MAPPING_FLAG_NONE);
|
||||
|
||||
{
|
||||
ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer();
|
||||
|
||||
Reset(cmd);
|
||||
|
||||
uint32_t bufIdx = 0;
|
||||
uint32_t byteOffset = 0;
|
||||
|
||||
uint32_t srcOffs = 0;
|
||||
while(bufIdx != 999999)
|
||||
{
|
||||
cmd->CopyBufferRegion(bufs[bufIdx], byteOffset, uploadBuf, srcOffs, 8);
|
||||
bufIdx = data[srcOffs / sizeof(uint32_t)];
|
||||
byteOffset = data[srcOffs / sizeof(uint32_t) + 1];
|
||||
srcOffs += 8;
|
||||
}
|
||||
|
||||
cmd->Close();
|
||||
|
||||
Submit({cmd});
|
||||
}
|
||||
|
||||
while(Running())
|
||||
{
|
||||
ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer();
|
||||
|
||||
Reset(cmd);
|
||||
|
||||
cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr());
|
||||
|
||||
ID3D12ResourcePtr bb = StartUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
|
||||
ClearRenderTargetView(cmd, BBRTV, {0.2f, 0.2f, 0.2f, 1.0f});
|
||||
|
||||
cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
IASetVertexBuffer(cmd, DefaultTriVB, sizeof(DefaultA2V), 0);
|
||||
cmd->SetPipelineState(pso);
|
||||
cmd->SetGraphicsRootSignature(sig);
|
||||
cmd->SetGraphicsRootDescriptorTable(0, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
SetMainWindowViewScissor(cmd);
|
||||
|
||||
OMSetRenderTargets(cmd, {BBRTV}, {});
|
||||
|
||||
cmd->DrawInstanced(3, 1, 0, 0);
|
||||
|
||||
FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
|
||||
cmd->Close();
|
||||
|
||||
SubmitAndPresent({cmd});
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST();
|
||||
@@ -588,7 +588,7 @@ void D3D12GraphicsTest::PostDeviceCreate()
|
||||
|
||||
m_Sampler->SetName(L"Sampler heap");
|
||||
|
||||
desc.NumDescriptors = 1030;
|
||||
desc.NumDescriptors = 8192;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
|
||||
CHECK_HR(dev->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), (void **)&m_CBVUAVSRV));
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
<ClCompile Include="d3d12\d3d12_existing_heap.cpp" />
|
||||
<ClCompile Include="d3d12\d3d12_groupshared.cpp" />
|
||||
<ClCompile Include="d3d12\d3d12_helpers.cpp" />
|
||||
<ClCompile Include="d3d12\d3d12_memory_overlap.cpp" />
|
||||
<ClCompile Include="d3d12\d3d12_mesh_shader.cpp" />
|
||||
<ClCompile Include="d3d12\d3d12_multi_wait_before_signal.cpp" />
|
||||
<ClCompile Include="d3d12\d3d12_large_buffer.cpp" />
|
||||
|
||||
@@ -736,6 +736,9 @@
|
||||
<ClCompile Include="d3d12\d3d12_blend.cpp">
|
||||
<Filter>D3D12\demos</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d3d12\d3d12_memory_overlap.cpp">
|
||||
<Filter>D3D12\demos</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="D3D11">
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import renderdoc as rd
|
||||
import rdtest
|
||||
|
||||
|
||||
class D3D12_Memory_Overlap(rdtest.TestCase):
|
||||
demos_test_name = 'D3D12_Memory_Overlap'
|
||||
|
||||
def check_capture(self):
|
||||
last_action: rd.ActionDescription = self.get_last_action()
|
||||
|
||||
self.controller.SetFrameEvent(last_action.eventId, True)
|
||||
|
||||
self.check_triangle(out=last_action.copyDestination)
|
||||
Reference in new issue
Block a user