简体   繁体   English

多个常量缓冲区 - 寄存器 - dx12

[英]Multiple constant buffer - register - dx12

I learn dx12 with that tutorial : https://www.braynzarsoft.net/viewtutorial/q16390-directx-12-constant-buffers-root-descriptor-tables#c0我通过该教程学习 dx12: https ://www.braynzarsoft.net/viewtutorial/q16390-directx-12-constant-buffers-root-descriptor-tables#c0

I tried to modify this step to got 2 constant buffer (so a register b0 and a b1, if i understood well).我试图修改这一步以获得 2 个常量缓冲区(所以一个寄存器 b0 和一个 b1,如果我理解得很好)。

For that I begin to say in my root sign there is 2 parameters:为此,我开始在我的根符号中说有 2 个参数:

// create root signature

// create a descriptor range (descriptor table) and fill it out
// this is a range of descriptors inside a descriptor heap
D3D12_DESCRIPTOR_RANGE  descriptorTableRanges[1]; // only one range right now
descriptorTableRanges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; // this is a range of constant buffer views (descriptors)
descriptorTableRanges[0].NumDescriptors = 2; // we only have one constant buffer, so the range is only 1
descriptorTableRanges[0].BaseShaderRegister = 0; // start index of the shader registers in the range
descriptorTableRanges[0].RegisterSpace = 0; // space 0. can usually be zero
descriptorTableRanges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; // this appends the range to the end of the root signature descriptor tables

// create a descriptor table
D3D12_ROOT_DESCRIPTOR_TABLE descriptorTable;
descriptorTable.NumDescriptorRanges = 0;// _countof(descriptorTableRanges); // we only have one range
descriptorTable.pDescriptorRanges = &descriptorTableRanges[0]; // the pointer to the beginning of our ranges array
D3D12_ROOT_DESCRIPTOR_TABLE descriptorTable2;
descriptorTable2.NumDescriptorRanges = 1;// _countof(descriptorTableRanges); // we only have one range
descriptorTable2.pDescriptorRanges = &descriptorTableRanges[0]; // the pointer to the beginning of our ranges array


// create a root parameter and fill it out
D3D12_ROOT_PARAMETER  rootParameters[2]; // only one parameter right now
rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; // this is a descriptor table
rootParameters[0].DescriptorTable = descriptorTable; // this is our descriptor table for this root parameter
rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; // our pixel shader will be the only shader accessing this parameter for now
rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; // this is a descriptor table
rootParameters[1].DescriptorTable = descriptorTable2; // this is our descriptor table for this root parameter
rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; // our pixel shader will be the only shader accessing this parameter for now

But now I failed to link constant buffer to a variable, I try to modify in this part of the code:但是现在我无法将常量缓冲区链接到变量,我尝试修改这部分代码:

 // Create a constant buffer descriptor heap for each frame
// this is the descriptor heap that will store our constant buffer descriptor
for (int i = 0; i < frameBufferCount; ++i)
{
    D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
    heapDesc.NumDescriptors = 1;
    heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
    heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
    hr = device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&mainDescriptorHeap[i]));
    if (FAILED(hr))
    {
        Running = false;
    }
}

// create the constant buffer resource heap
// We will update the constant buffer one or more times per frame, so we will use only an upload heap
// unlike previously we used an upload heap to upload the vertex and index data, and then copied over
// to a default heap. If you plan to use a resource for more than a couple frames, it is usually more
// efficient to copy to a default heap where it stays on the gpu. In this case, our constant buffer
// will be modified and uploaded at least once per frame, so we only use an upload heap

// create a resource heap, descriptor heap, and pointer to cbv for each frame
for (int i = 0; i < frameBufferCount; ++i)
{
    hr = device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), // this heap will be used to upload the constant buffer data
        D3D12_HEAP_FLAG_NONE, // no flags
        &CD3DX12_RESOURCE_DESC::Buffer(1024 * 64), // size of the resource heap. Must be a multiple of 64KB for single-textures and constant buffers
        D3D12_RESOURCE_STATE_GENERIC_READ, // will be data that is read from so we keep it in the generic read state
        nullptr, // we do not have use an optimized clear value for constant buffers
        IID_PPV_ARGS(&constantBufferUploadHeap[i]));
    constantBufferUploadHeap[i]->SetName(L"Constant Buffer Upload Resource Heap");

    D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
    cbvDesc.BufferLocation = constantBufferUploadHeap[i]->GetGPUVirtualAddress();
    cbvDesc.SizeInBytes = (sizeof(ConstantBuffer) + 255) & ~255;    // CB size is required to be 256-byte aligned.
    device->CreateConstantBufferView(&cbvDesc, mainDescriptorHeap[i]->GetCPUDescriptorHandleForHeapStart());

    ZeroMemory(&cbColorMultiplierData, sizeof(cbColorMultiplierData));

    CD3DX12_RANGE readRange(0, 0);    // We do not intend to read from this resource on the CPU. (End is less than or equal to begin)
    hr = constantBufferUploadHeap[i]->Map(0, &readRange, reinterpret_cast<void**>(&cbColorMultiplierGPUAddress[i]));
    memcpy(cbColorMultiplierGPUAddress[i], &cbColorMultiplierData, sizeof(cbColorMultiplierData));
}

Thank谢谢

Your root signature is incorrect, you are trying to set a descriptor table with no range. 您的根签名不正确,您正在尝试设置没有范围的描述符表。

You have 3 ways to register a constant buffer in a root signature, with root constants, with a root constant buffer and with descriptor tables. 您可以通过3种方法在根签名中注册常量缓冲区,根常量,根常量缓冲区和描述符表。 The first two connect one constant buffer per root parameter, while the third allow to set multiple constant buffers in a single table. 前两个参数为每个根参数连接一个常量缓冲区,而第三个参数允许在单个表中设置多个常量缓冲区。

In your case, a single root parameter of type descriptor table, with a single range refering to an array of 2 is enough to let you bind 2 constant buffer. 在您的情况下,类型描述符表的单个根参数(单个范围引用2的数组)足以让您绑定2个常量缓冲区。

I recommend you to read how root signatures are declared in HLSL to better understand the concept and how it translates to the C++ declaration. 我建议您阅读如何在HLSL中声明根签名 ,以更好地理解该概念及其如何转换为C ++声明。

As for the runtime portion of manipulating constant buffer. 至于操作常量缓冲区的运行时部分。 You will have to be very careful again, their is no life time management in d3d12 nor the driver like it was with d3d11, you cannot update in place a constant buffer memory without making sure the GPU is already done using the previous content. 您将不得不再次非常小心,它们不是d3d12中的生命周期管理,也不是d3d11中的驱动程序,您无法在不确保GPU已使用先前内容完成的情况下就地更新恒定的缓冲存储器。 The solution is often to work with a ring buffer to allocate your frame constant buffer, and to use fence to keep you from overwriting too soon. 解决方案通常是使用环形缓冲区分配帧常量缓冲区,并使用fence防止过早覆盖。

I highly recommend you to stick to d3d11. 我强烈建议您坚持使用d3d11。 d3d12 is not a replacement of it, it is made to overcome some of this performance issues that are only to be find in extremely complex renderer and to be used by people with expert knowledge of the GPU already and d3d11, if your application is not to the level of complexity of a GTA V ( just an example ), you are only shooting you in the foot by switching to d3d12. d3d12不能替代它,它是为了克服某些性能问题,这些问题只能在极其复杂的渲染器中找到,并且已经拥有GPU和d3d11的专业知识的人可以使用,如果您的应用程序不希望这样做的话。就GTA V的复杂程度而言(仅作为示例),您只需要切换到d3d12就可以射击。

Your real problem is: You defined 2 pieces of CBV descriptor in one range, and than defined 2 pieces of descriptor table with this range.你真正的问题是:你在一个范围内定义了 2 个 CBV 描述符,然后用这个范围定义了 2 个描述符表。 So , you defined 4 pieces of CBVs instead of 2, and when you define the descriptor heap, you set the heapDesc.NumDescriptors to 1 instead of 4, because you defined 4 constant-buffer descriptor in the code, not 2.因此,您定义了 4 个 CBV 而不是 2 个,并且在定义描述符堆时,您将 heapDesc.NumDescriptors 设置为 1 而不是 4,因为您在代码中定义了 4 个常量缓冲区描述符,而不是 2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM