@@ -4726,14 +4726,224 @@ static void TestGroupDefragmentation(const TestContext& ctx)
47264726 TestDefragmentationIncrementalComplex (ctx);
47274727}
47284728
4729+ void SpecialTest (const TestContext& ctx)
4730+ {
4731+ wprintf (L" SpecialTest\n " );
4732+
4733+ constexpr uint32_t BUFFER_SIZE = 1024 * 1024 * 1024 ; // 1 GB
4734+ constexpr uint32_t LOAD_OFFSET = BUFFER_SIZE + 4096 ;
4735+ constexpr bool USE_GOOD_DESCRIPTOR = false ;
4736+
4737+ using namespace D3D12MA ;
4738+
4739+ wprintf (L" BUFFER_SIZE = 0x%08X\n " , BUFFER_SIZE);
4740+ wprintf (L" LOAD_OFFSET = 0x%08X\n " , LOAD_OFFSET);
4741+ wprintf (L" USE_GOOD_DESCRIPTOR = %d\n " , int (USE_GOOD_DESCRIPTOR));
4742+
4743+ std::vector<char > shader_data;
4744+ ReadFile (shader_data, L" ../src/Shaders/SpecialCS.dxil" );
4745+ assert (!shader_data.empty ());
4746+
4747+ // Create a CBV in UPLOAD heap to hold just 1 uint. Use D3D12MA for that.
4748+ ComPtr<Allocation> cbAlloc;
4749+ ComPtr<ID3D12Resource> cbResource;
4750+ {
4751+ const UINT64 cbRawSize = sizeof (UINT);
4752+ const UINT64 cbSize = AlignUp<UINT64>(cbRawSize, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
4753+
4754+ D3D12_RESOURCE_DESC cbDesc = {};
4755+ FillResourceDescForBuffer (cbDesc, cbSize);
4756+
4757+ CALLOCATION_DESC allocDesc = CALLOCATION_DESC{D3D12_HEAP_TYPE_UPLOAD};
4758+
4759+ CHECK_HR (ctx.allocator ->CreateResource (&allocDesc, &cbDesc, D3D12_RESOURCE_STATE_GENERIC_READ,
4760+ nullptr , &cbAlloc, IID_PPV_ARGS (&cbResource)));
4761+
4762+ // Map and write uint value
4763+ void * mapped = nullptr ;
4764+ D3D12_RANGE readRange = { 0 , 0 };
4765+ CHECK_HR (cbResource->Map (0 , &readRange, &mapped));
4766+ UINT* p = (UINT*)mapped;
4767+ p[0 ] = LOAD_OFFSET;
4768+ cbResource->Unmap (0 , nullptr );
4769+ }
4770+
4771+ // Create a 1 GB buffer to be used as UAV. Use D3D12MA for that.
4772+ ComPtr<Allocation> uavAlloc;
4773+ ComPtr<ID3D12Resource> uavResource;
4774+ {
4775+ D3D12_RESOURCE_DESC resDesc = {};
4776+ FillResourceDescForBuffer (resDesc, BUFFER_SIZE);
4777+ resDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
4778+
4779+ CALLOCATION_DESC allocDesc = CALLOCATION_DESC{ D3D12_HEAP_TYPE_DEFAULT };
4780+
4781+ CHECK_HR (ctx.allocator ->CreateResource (&allocDesc, &resDesc,
4782+ D3D12_RESOURCE_STATE_COMMON, nullptr , &uavAlloc, IID_PPV_ARGS (&uavResource)));
4783+
4784+ wprintf (L" Buffer GPU address = 0x%08llX\n " , uavResource->GetGPUVirtualAddress ());
4785+ wprintf (L" Buffer GPU end address = 0x%08llX\n " , uavResource->GetGPUVirtualAddress () + BUFFER_SIZE);
4786+ wprintf (L" Buffer GPU address + load_offset = 0x%08llX\n " , uavResource->GetGPUVirtualAddress () + LOAD_OFFSET);
4787+
4788+ }
4789+
4790+ // Create a descriptor heap just for 1 CBV b0 and 1 UAV u0.
4791+ ComPtr<ID3D12DescriptorHeap> descHeap;
4792+ {
4793+ D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
4794+ heapDesc.NumDescriptors = 2 ;
4795+ heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
4796+ heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
4797+ heapDesc.NodeMask = 0 ;
4798+ CHECK_HR (ctx.device ->CreateDescriptorHeap (&heapDesc, IID_PPV_ARGS (&descHeap)));
4799+ }
4800+
4801+
4802+ const UINT descriptorSize = ctx.device ->GetDescriptorHandleIncrementSize (D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
4803+ D3D12_CPU_DESCRIPTOR_HANDLE cpuStart = descHeap->GetCPUDescriptorHandleForHeapStart ();
4804+ D3D12_GPU_DESCRIPTOR_HANDLE gpuStart = descHeap->GetGPUDescriptorHandleForHeapStart ();
4805+
4806+ // Create CBV at descriptor 0
4807+ {
4808+ D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
4809+ cbvDesc.BufferLocation = cbResource->GetGPUVirtualAddress ();
4810+ // SizeInBytes must be multiple of 256
4811+ cbvDesc.SizeInBytes = (UINT)AlignUp<UINT64>(sizeof (UINT), D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
4812+ ctx.device ->CreateConstantBufferView (&cbvDesc, cpuStart);
4813+ }
4814+
4815+ // Create UAV at descriptor 1
4816+ {
4817+ D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
4818+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
4819+ uavDesc.Buffer .FirstElement = 0 ;
4820+ uavDesc.Buffer .NumElements = (UINT)( (uavResource->GetDesc ().Width ) / sizeof (UINT) );
4821+ uavDesc.Buffer .StructureByteStride = 0 ; // Zero for both raw and typed buffer.
4822+ uavDesc.Buffer .CounterOffsetInBytes = 0 ;
4823+
4824+ if (USE_GOOD_DESCRIPTOR)
4825+ {
4826+ // Declare proper ByteAdddress (raw) buffer.
4827+ uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
4828+ uavDesc.Buffer .Flags = D3D12_BUFFER_UAV_FLAG_RAW;
4829+ }
4830+ else
4831+ {
4832+ // Declare typed buffer.
4833+ uavDesc.Format = DXGI_FORMAT_R32_UINT;
4834+ uavDesc.Buffer .Flags = D3D12_BUFFER_UAV_FLAG_NONE;
4835+ }
4836+
4837+ D3D12_CPU_DESCRIPTOR_HANDLE cpuUavHandle = cpuStart;
4838+ cpuUavHandle.ptr += descriptorSize * 1 ;
4839+ // Create UAV (no counter resource)
4840+ ctx.device ->CreateUnorderedAccessView (uavResource.Get (), nullptr , &uavDesc, cpuUavHandle);
4841+ }
4842+
4843+ // Create a compute root signature with:
4844+ // - descriptor table (CBV at b0)
4845+ // - descriptor table (UAV at u0)
4846+ ComPtr<ID3D12RootSignature> rootSignature;
4847+ {
4848+ D3D12_DESCRIPTOR_RANGE cbvRange = {};
4849+ cbvRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
4850+ cbvRange.NumDescriptors = 1 ;
4851+ cbvRange.BaseShaderRegister = 0 ;
4852+ cbvRange.RegisterSpace = 0 ;
4853+ cbvRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
4854+
4855+ D3D12_DESCRIPTOR_RANGE uavRange = {};
4856+ uavRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
4857+ uavRange.NumDescriptors = 1 ;
4858+ uavRange.BaseShaderRegister = 0 ;
4859+ uavRange.RegisterSpace = 0 ;
4860+ uavRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
4861+
4862+ D3D12_ROOT_PARAMETER params[2 ] = {};
4863+ params[0 ].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
4864+ params[0 ].DescriptorTable .NumDescriptorRanges = 1 ;
4865+ params[0 ].DescriptorTable .pDescriptorRanges = &cbvRange;
4866+ params[0 ].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
4867+
4868+ params[1 ].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
4869+ params[1 ].DescriptorTable .NumDescriptorRanges = 1 ;
4870+ params[1 ].DescriptorTable .pDescriptorRanges = &uavRange;
4871+ params[1 ].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
4872+
4873+ D3D12_ROOT_SIGNATURE_DESC rsDesc = {};
4874+ rsDesc.NumParameters = _countof (params);
4875+ rsDesc.pParameters = params;
4876+ rsDesc.NumStaticSamplers = 0 ;
4877+ rsDesc.pStaticSamplers = nullptr ;
4878+ rsDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
4879+
4880+ ComPtr<ID3DBlob> sigBlob, errorBlob;
4881+ CHECK_HR (D3D12SerializeRootSignature (&rsDesc, D3D_ROOT_SIGNATURE_VERSION_1, &sigBlob, &errorBlob));
4882+ CHECK_HR (ctx.device ->CreateRootSignature (0 , sigBlob->GetBufferPointer (), sigBlob->GetBufferSize (), IID_PPV_ARGS (&rootSignature)));
4883+ }
4884+
4885+ // Create a compute pipeline state object using shader_data.
4886+ ComPtr<ID3D12PipelineState> pso;
4887+ {
4888+ D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {};
4889+ desc.pRootSignature = rootSignature.Get ();
4890+ desc.CS .pShaderBytecode = shader_data.data ();
4891+ desc.CS .BytecodeLength = shader_data.size ();
4892+ desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
4893+ CHECK_HR (ctx.device ->CreateComputePipelineState (&desc, IID_PPV_ARGS (&pso)));
4894+ }
4895+
4896+ fflush (stdout);
4897+ Sleep (500 );
4898+
4899+ // Record commands: set descriptor heap, root signature, descriptor tables, dispatch.
4900+ ID3D12GraphicsCommandList* cmd_list = BeginCommandList ();
4901+
4902+ // Transition UAV to UAV state
4903+ {
4904+ D3D12_RESOURCE_BARRIER barrier = {};
4905+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
4906+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
4907+ barrier.Transition .pResource = uavResource.Get ();
4908+ barrier.Transition .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
4909+ barrier.Transition .StateBefore = D3D12_RESOURCE_STATE_COMMON;
4910+ barrier.Transition .StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
4911+ cmd_list->ResourceBarrier (1 , &barrier);
4912+ }
4913+
4914+ ID3D12DescriptorHeap* heaps[] = { descHeap.Get () };
4915+ cmd_list->SetDescriptorHeaps (1 , heaps);
4916+
4917+ cmd_list->SetComputeRootSignature (rootSignature.Get ());
4918+
4919+ // GPU handles: CBV at offset 0, UAV at offset 1
4920+ D3D12_GPU_DESCRIPTOR_HANDLE gpuCbv = gpuStart;
4921+ D3D12_GPU_DESCRIPTOR_HANDLE gpuUav = gpuStart;
4922+ gpuUav.ptr += descriptorSize * 1 ;
4923+
4924+ // Root parameter 0 -> CBV table, 1 -> UAV table
4925+ cmd_list->SetComputeRootDescriptorTable (0 , gpuCbv);
4926+ cmd_list->SetComputeRootDescriptorTable (1 , gpuUav);
4927+
4928+ cmd_list->SetPipelineState (pso.Get ());
4929+
4930+ // Dispatch a single group
4931+ cmd_list->Dispatch (1 , 1 , 1 );
4932+
4933+ EndCommandList (cmd_list);
4934+
4935+ wprintf (L" SpecialTest done.\n " );
4936+ }
4937+
47294938void Test (const TestContext& ctx)
47304939{
47314940 wprintf (L" TESTS BEGIN\n " );
47324941
4733- if (false )
4942+ if (true )
47344943 {
47354944 // //////////////////////////////////////////////////////////////////////////////
47364945 // Temporarily insert custom tests here:
4946+ SpecialTest (ctx);
47374947 return ;
47384948 }
47394949
0 commit comments