Add GPUQueryType::BinaryOcclusion for simpler visibility checks
This commit is contained in:
@@ -410,6 +410,11 @@ enum class GPUQueryType
|
||||
/// </summary>
|
||||
Occlusion = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Tests object visibility by checking depth and stencil tests. Works like Occlusion query, except returns simply a binary 0/1 result: 0 indicates that no samples passed depth and stencil testing; 1 indicates that at least one sample passed.
|
||||
/// </summary>
|
||||
BinaryOcclusion = 2,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
|
||||
@@ -303,7 +303,7 @@ void GPUContextDX11::SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView
|
||||
|
||||
void GPUContextDX11::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts)
|
||||
{
|
||||
ASSERT(Math::IsInRange(rts.Length(), 1, GPU_MAX_RT_BINDED));
|
||||
ASSERT(Math::IsInRange(rts.Length(), 0, GPU_MAX_RT_BINDED));
|
||||
|
||||
auto depthBufferDX11 = static_cast<GPUTextureViewDX11*>(depthBuffer);
|
||||
ID3D11DepthStencilView* dsv = depthBufferDX11 ? depthBufferDX11->DSV() : nullptr;
|
||||
@@ -590,7 +590,18 @@ uint64 GPUContextDX11::BeginQuery(GPUQueryType type)
|
||||
auto& query = _device->_queries.AddOne();
|
||||
query.Type = type;
|
||||
D3D11_QUERY_DESC queryDesc;
|
||||
queryDesc.Query = type == GPUQueryType::Occlusion ? D3D11_QUERY_OCCLUSION : D3D11_QUERY_TIMESTAMP;
|
||||
switch (type)
|
||||
{
|
||||
case GPUQueryType::Timer:
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
break;
|
||||
case GPUQueryType::Occlusion:
|
||||
queryDesc.Query = D3D11_QUERY_OCCLUSION;
|
||||
break;
|
||||
case GPUQueryType::BinaryOcclusion:
|
||||
queryDesc.Query = D3D11_QUERY_OCCLUSION_PREDICATE;
|
||||
break;
|
||||
}
|
||||
queryDesc.MiscFlags = 0;
|
||||
HRESULT hr = _device->GetDevice()->CreateQuery(&queryDesc, &query.Query);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(hr, 0);
|
||||
|
||||
@@ -1060,9 +1060,15 @@ RETRY:
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (q.Type == (uint16)GPUQueryType::Occlusion)
|
||||
{
|
||||
hasData = context->GetData(query.Query, &result, sizeof(UINT64), 0) == S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasData = context->GetData(query.Query, &result, sizeof(uint64), 0) == S_OK;
|
||||
BOOL resultBool;
|
||||
hasData = context->GetData(query.Query, &resultBool, sizeof(BOOL), 0) == S_OK;
|
||||
result = resultBool ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!hasData && wait)
|
||||
|
||||
@@ -93,7 +93,7 @@ private:
|
||||
bool _allowTearing = false;
|
||||
GPUBuffer* _dummyVB = nullptr;
|
||||
Array<GPUQueryDataDX11> _queries;
|
||||
Array<uint16> _readyQueries[2]; // Timer and Occlusion
|
||||
Array<uint16> _readyQueries[3]; // Timer and Occlusion and BinaryOcclusion
|
||||
|
||||
// Static Samplers
|
||||
ID3D11SamplerState* _samplerLinearClamp = nullptr;
|
||||
|
||||
@@ -948,7 +948,7 @@ void GPUContextDX12::SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView
|
||||
|
||||
void GPUContextDX12::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts)
|
||||
{
|
||||
ASSERT(Math::IsInRange(rts.Length(), 1, GPU_MAX_RT_BINDED));
|
||||
ASSERT(Math::IsInRange(rts.Length(), 0, GPU_MAX_RT_BINDED));
|
||||
|
||||
const auto depthBufferDX12 = static_cast<GPUTextureViewDX12*>(depthBuffer);
|
||||
|
||||
|
||||
@@ -1061,7 +1061,7 @@ GPUQueryDX12 GPUDeviceDX12::AllocQuery(GPUQueryType type)
|
||||
// Allocate a new query heap
|
||||
PROFILE_MEM(GraphicsCommands);
|
||||
auto heap = New<QueryHeapDX12>();
|
||||
int32 size = type == GPUQueryType::Occlusion ? 4096 : 1024;
|
||||
int32 size = type == GPUQueryType::Timer ? 1024 : 4096;
|
||||
if (heap->Init(this, type, size))
|
||||
{
|
||||
Delete(heap);
|
||||
|
||||
@@ -28,6 +28,11 @@ bool QueryHeapDX12::Init(GPUDeviceDX12* device, GPUQueryType type, uint32 size)
|
||||
QueryType = D3D12_QUERY_TYPE_OCCLUSION;
|
||||
heapDesc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION;
|
||||
break;
|
||||
case GPUQueryType::BinaryOcclusion:
|
||||
_resultSize = sizeof(uint64);
|
||||
QueryType = D3D12_QUERY_TYPE_BINARY_OCCLUSION;
|
||||
heapDesc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION;
|
||||
break;
|
||||
case GPUQueryType::MAX:
|
||||
return true;
|
||||
}
|
||||
@@ -100,11 +105,6 @@ void QueryHeapDX12::EndQueryBatchAndResolveQueryData(GPUContextDX12* context)
|
||||
StartQueryBatch();
|
||||
}
|
||||
|
||||
bool QueryHeapDX12::CanAlloc(int32 count) const
|
||||
{
|
||||
return _currentBatch.Open && _currentIndex + count <= GetQueryHeapCount();
|
||||
}
|
||||
|
||||
void QueryHeapDX12::Alloc(ElementHandle& handle)
|
||||
{
|
||||
ASSERT(_currentBatch.Open);
|
||||
|
||||
@@ -153,7 +153,10 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="count">How many elements to allocate?</param>
|
||||
/// <returns>True if can alloc new query within the same batch.</returns>
|
||||
bool CanAlloc(int32 count = 1) const;
|
||||
bool CanAlloc(int32 count = 1) const
|
||||
{
|
||||
return _currentBatch.Open && _currentIndex + count <= _queryHeapCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates the query heap element.
|
||||
|
||||
@@ -1466,6 +1466,9 @@ uint64 GPUContextVulkan::BeginQuery(GPUQueryType type)
|
||||
case GPUQueryType::Occlusion:
|
||||
vkCmdBeginQuery(cmdBuffer->GetHandle(), pool->GetHandle(), query.QueryIndex, 0);
|
||||
break;
|
||||
case GPUQueryType::BinaryOcclusion:
|
||||
vkCmdBeginQuery(cmdBuffer->GetHandle(), pool->GetHandle(), query.QueryIndex, VK_QUERY_CONTROL_PRECISE_BIT);
|
||||
break;
|
||||
}
|
||||
pool->MarkQueryAsStarted(query.QueryIndex);
|
||||
|
||||
@@ -1492,6 +1495,7 @@ void GPUContextVulkan::EndQuery(uint64 queryID)
|
||||
#endif
|
||||
break;
|
||||
case GPUQueryType::Occlusion:
|
||||
case GPUQueryType::BinaryOcclusion:
|
||||
vkCmdEndQuery(cmdBuffer->GetHandle(), pool->GetHandle(), query.QueryIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -642,7 +642,7 @@ QueryPoolVulkan::QueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, GPUQue
|
||||
{
|
||||
VkQueryPoolCreateInfo createInfo;
|
||||
RenderToolsVulkan::ZeroStruct(createInfo, VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
|
||||
createInfo.queryType = type == GPUQueryType::Occlusion ? VK_QUERY_TYPE_OCCLUSION : VK_QUERY_TYPE_TIMESTAMP;
|
||||
createInfo.queryType = type != GPUQueryType::Timer ? VK_QUERY_TYPE_TIMESTAMP : VK_QUERY_TYPE_OCCLUSION;
|
||||
createInfo.queryCount = capacity;
|
||||
VALIDATE_VULKAN_RESULT(vkCreateQueryPool(device->Device, &createInfo, nullptr, &_handle));
|
||||
|
||||
@@ -1282,7 +1282,7 @@ int32 GPUDeviceVulkan::GetOrCreateQueryPool(GPUQueryType type)
|
||||
|
||||
PROFILE_CPU_NAMED("Create Create Pool");
|
||||
PROFILE_MEM(GraphicsCommands);
|
||||
auto pool = New<BufferedQueryPoolVulkan>(this, type == GPUQueryType::Occlusion ? 4096 : 1024, type);
|
||||
auto pool = New<BufferedQueryPoolVulkan>(this, type == GPUQueryType::Timer ? 1024 : 4096, type);
|
||||
QueryPools.Add(pool);
|
||||
return QueryPools.Count() - 1;
|
||||
}
|
||||
@@ -2217,13 +2217,17 @@ RETRY:
|
||||
}
|
||||
break;
|
||||
case GPUQueryType::Occlusion:
|
||||
case GPUQueryType::BinaryOcclusion:
|
||||
hasData = pool->GetResults(query.QueryIndex, result);
|
||||
if (hasData && pool->Type == GPUQueryType::BinaryOcclusion && result > 1)
|
||||
result = 1; // Clamp binary result
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hasData && wait)
|
||||
{
|
||||
// Wait until data is ready
|
||||
// TODO: use VK_QUERY_RESULT_WAIT_BIT maybe?
|
||||
Platform::Yield();
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ void GPUContextWebGPU::SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureVi
|
||||
|
||||
void GPUContextWebGPU::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts)
|
||||
{
|
||||
ASSERT(Math::IsInRange(rts.Length(), 1, GPU_MAX_RT_BINDED));
|
||||
ASSERT(Math::IsInRange(rts.Length(), 0, GPU_MAX_RT_BINDED));
|
||||
auto depthBufferGPU = (GPUTextureViewWebGPU*)depthBuffer;
|
||||
if (_renderTargetCount != rts.Length() || _depthStencil != depthBufferGPU || Platform::MemoryCompare(_renderTargets, rts.Get(), rts.Length() * sizeof(void*)) != 0)
|
||||
{
|
||||
|
||||
@@ -860,7 +860,7 @@ GPUQueryWebGPU GPUDeviceWebGPU::AllocateQuery(GPUQueryType type)
|
||||
|
||||
// Allocate a new query heap
|
||||
PROFILE_MEM(GraphicsCommands);
|
||||
uint32 size = type == GPUQueryType::Occlusion ? 4096 : 1024;
|
||||
uint32 size = type == GPUQueryType::Timer ? 1024 : 4096;
|
||||
auto set = New<GPUQuerySetWebGPU>(Device, type, size);
|
||||
QuerySets[QuerySetsCount++] = set;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user