预测查询
D3D12PredicationQueries 示例演示了使用 DirectX 12 查询堆和预测进行遮挡剔除。 本演练介绍了扩展 HelloConstBuffer 示例以处理谓词查询所需的其他代码。
创建深度模具描述符堆和遮挡查询堆
在 LoadPipeline 方法中创建一个深度模具描述符堆。
// Describe and create a depth stencil view (DSV) descriptor heap.
D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
dsvHeapDesc.NumDescriptors = 1;
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap)));
调用流程 | 参数 |
---|---|
D3D12_DESCRIPTOR_HEAP_DESC |
[D3D12_DESCRIPTOR_HEAP_FLAG](/windows/desktop/api/d3d12/ne-d3d12-d3d12_descriptor_heap_flags) |
CreateDescriptorHeap |
在 LoadAssets 方法中,为遮挡查询创建一个堆。
// Describe and create a heap for occlusion queries.
D3D12_QUERY_HEAP_DESC queryHeapDesc = {};
queryHeapDesc.Count = 1;
queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION;
ThrowIfFailed(m_device->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_queryHeap)));
调用流程 | 参数 |
---|---|
D3D12_QUERY_HEAP_DESC | D3D12_QUERY_HEAP_TYPE |
CreateQueryHeap |
启用 alpha 值混合处理
该示例绘制了两个四边形,并演示了一个二进制遮挡查询。 前面的四边形动态显示在屏幕上,后面的四边形偶尔会被遮挡。 在 LoadAssets 方法中,为此示例启用了 alpha 值混合处理,以便我们能看到 D3D 在哪些情况下将后面的四边形视为被遮挡。
// Enable alpha blending so we can visualize the occlusion query results.
CD3DX12_BLEND_DESC blendDesc(CD3DX12_DEFAULT);
blendDesc.RenderTarget[0] =
{
TRUE, FALSE,
D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
D3D12_LOGIC_OP_NOOP,
D3D12_COLOR_WRITE_ENABLE_ALL,
};
调用流程 | 参数 |
---|---|
CD3DX12_BLEND_DESC |
[D3D12_BLEND](/windows/desktop/api/d3d12/ne-d3d12-d3d12_blend) [D3D12_BLEND_OP](/windows/desktop/api/d3d12/ne-d3d12-d3d12_blend_op) [D3D12_LOGIC_OP](/windows/desktop/api/d3d12/ne-d3d12-d3d12_logic_op) [D3D12_COLOR_WRITE_ENABLE](/windows/desktop/api/d3d12/ne-d3d12-d3d12_color_write_enable) |
禁用颜色和深度写入
遮挡查询是通过呈现四边形来执行的,该四边形覆盖的区域与我们想要测试其可见性的四边形相同。 在更复杂的场景中,查询可能是一个包围盒,而不是简单的四边形。 无论是哪种情况,都会创建一个新的管道状态,禁止写入呈现目标和 Z 缓冲区,以便遮挡查询本身不会影响呈现通道的可见输出。
在 LoadAssets 方法中,禁用遮挡查询状态的颜色写入和深度写入。
// Disable color writes and depth writes for the occlusion query's state.
psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0;
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_queryState)));
调用流程 | 参数 |
---|---|
D3D12_GRAPHICS_PIPELINE_STATE_DESC | D3D12_DEPTH_WRITE_MASK |
CreateGraphicsPipelineState |
创建用于存储查询结果的缓冲区
需要在 LoadAssets 方法中创建一个缓冲区来存储查询结果。 每个查询在 GPU 内存中需要 8 个字节的空间。 此示例仅执行一个查询,为简单起见,它创建了一个恰好具有此大小的缓冲区(即使此函数调用将分配 64K 页的 GPU 内存也是如此;大多数实际应用可能会创建一个更大的缓冲区)。
// Create the query result buffer.
CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT);
auto queryBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(8);
ThrowIfFailed(m_device->CreateCommittedResource(
&heapProps,
D3D12_HEAP_FLAG_NONE,
&queryBufferDesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_queryResult)
));
调用流程 | 参数 |
---|---|
CreateCommittedResource |
[D3D12_HEAP_TYPE](/windows/desktop/api/d3d12/ne-d3d12-d3d12_heap_type) [D3D12_HEAP_FLAG](/windows/desktop/api/d3d12/ne-d3d12-d3d12_heap_flags) [CD3DX12_RESOURCE_DESC](cd3dx12-resource-desc.md) [D3D12_RESOURCE_STATES](/windows/desktop/api/d3d12/ne-d3d12-d3d12_resource_states) |
绘制四边形并执行和解析遮挡查询
完成设置后,主循环会在 PopulateCommandLists 方法中更新。
- 1. 从后到前绘制象限,使透明度效果正常工作。 从后向前绘制四边形取决于前一帧查询的结果,这是一种相当常见的技术。
2. 更改 PSO 以禁用呈现目标和深度模具写入。
3. 执行封闭查询。
4. 解决封闭查询。
// Draw the quads and perform the occlusion query.
{
CD3DX12_GPU_DESCRIPTOR_HANDLE cbvFarQuad(m_cbvHeap->GetGPUDescriptorHandleForHeapStart(), m_frameIndex * CbvCountPerFrame, m_cbvSrvDescriptorSize);
CD3DX12_GPU_DESCRIPTOR_HANDLE cbvNearQuad(cbvFarQuad, m_cbvSrvDescriptorSize);
m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
// Draw the far quad conditionally based on the result of the occlusion query
// from the previous frame.
m_commandList->SetGraphicsRootDescriptorTable(0, cbvFarQuad);
m_commandList->SetPredication(m_queryResult.Get(), 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
m_commandList->DrawInstanced(4, 1, 0, 0);
// Disable predication and always draw the near quad.
m_commandList->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
m_commandList->SetGraphicsRootDescriptorTable(0, cbvNearQuad);
m_commandList->DrawInstanced(4, 1, 4, 0);
// Run the occlusion query with the bounding box quad.
m_commandList->SetGraphicsRootDescriptorTable(0, cbvFarQuad);
m_commandList->SetPipelineState(m_queryState.Get());
m_commandList->BeginQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, 0);
m_commandList->DrawInstanced(4, 1, 8, 0);
m_commandList->EndQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, 0);
// Resolve the occlusion query and store the results in the query result buffer
// to be used on the subsequent frame.
m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_queryResult.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_DEST));
m_commandList->ResolveQueryData(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, 0, 1, m_queryResult.Get(), 0);
m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_queryResult.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));
}
调用流程 | 参数 |
---|---|
CD3DX12_GPU_DESCRIPTOR_HANDLE | GetGPUDescriptorHandleForHeapStart |
IASetPrimitiveTopology | D3D_PRIMITIVE_TOPOLOGY |
IASetVertexBuffers | |
SetGraphicsRootDescriptorTable | |
SetPredication | D3D12_PREDICATION_OP |
DrawInstanced | |
SetPredication | D3D12_PREDICATION_OP |
SetGraphicsRootDescriptorTable | |
DrawInstanced | |
SetGraphicsRootDescriptorTable | |
SetPipelineState | |
BeginQuery | D3D12_QUERY_TYPE |
DrawInstanced | |
EndQuery | D3D12_QUERY_TYPE |
ResourceBarrier |
[D3D12_RESOURCE_STATES](/windows/desktop/api/d3d12/ne-d3d12-d3d12_resource_states) |
ResolveQueryData | D3D12_QUERY_TYPE |
ResourceBarrier |
[D3D12_RESOURCE_STATES](/windows/desktop/api/d3d12/ne-d3d12-d3d12_resource_states) |
运行示例
未遮挡:
遮挡:
部分遮挡:
相关主题