OpenGL: implement occlusion queries. On ResolveQuerySet(), get all available query results into a CPU-side vector. Copy the results from there to the destination buffer. Bug: dawn:2186 Change-Id: I49c58ff611633ca5362de679e27e260dcb9759e1 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/160780 Commit-Queue: Stephen White <senorblanco@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/opengl/CommandBufferGL.cpp b/src/dawn/native/opengl/CommandBufferGL.cpp index f6bd10e..be89cf9 100644 --- a/src/dawn/native/opengl/CommandBufferGL.cpp +++ b/src/dawn/native/opengl/CommandBufferGL.cpp
@@ -44,6 +44,7 @@ #include "dawn/native/opengl/Forward.h" #include "dawn/native/opengl/PersistentPipelineStateGL.h" #include "dawn/native/opengl/PipelineLayoutGL.h" +#include "dawn/native/opengl/QuerySetGL.h" #include "dawn/native/opengl/RenderPipelineGL.h" #include "dawn/native/opengl/SamplerGL.h" #include "dawn/native/opengl/TextureGL.h" @@ -825,8 +826,30 @@ } case Command::ResolveQuerySet: { - // TODO(crbug.com/dawn/434): Resolve non-precise occlusion query. - SkipCommand(&mCommands, type); + ResolveQuerySetCmd* cmd = mCommands.NextCommand<ResolveQuerySetCmd>(); + QuerySet* querySet = ToBackend(cmd->querySet.Get()); + Buffer* destination = ToBackend(cmd->destination.Get()); + + size_t size = cmd->queryCount * sizeof(uint64_t); + destination->EnsureDataInitializedAsDestination(cmd->destinationOffset, size); + + std::vector<uint64_t> values(cmd->queryCount); + auto availability = querySet->GetQueryAvailability(); + + for (uint32_t i = 0; i < cmd->queryCount; ++i) { + if (!availability[cmd->firstQuery + i]) { + values[i] = 0; + continue; + } + uint32_t query = querySet->Get(cmd->firstQuery + i); + GLuint value; + gl.GetQueryObjectuiv(query, GL_QUERY_RESULT, &value); + values[i] = value; + } + + gl.BindBuffer(GL_ARRAY_BUFFER, destination->GetHandle()); + gl.BufferSubData(GL_ARRAY_BUFFER, cmd->destinationOffset, size, values.data()); + break; } @@ -1317,11 +1340,16 @@ } case Command::BeginOcclusionQuery: { - return DAWN_UNIMPLEMENTED_ERROR("BeginOcclusionQuery unimplemented."); + BeginOcclusionQueryCmd* cmd = mCommands.NextCommand<BeginOcclusionQueryCmd>(); + QuerySet* querySet = ToBackend(renderPass->occlusionQuerySet.Get()); + gl.BeginQuery(GL_ANY_SAMPLES_PASSED, querySet->Get(cmd->queryIndex)); + break; } case Command::EndOcclusionQuery: { - return DAWN_UNIMPLEMENTED_ERROR("EndOcclusionQuery unimplemented."); + mCommands.NextCommand<EndOcclusionQueryCmd>(); + gl.EndQuery(GL_ANY_SAMPLES_PASSED); + break; } case Command::WriteTimestamp:
diff --git a/src/dawn/native/opengl/QuerySetGL.cpp b/src/dawn/native/opengl/QuerySetGL.cpp index 984e5f5..6907730 100644 --- a/src/dawn/native/opengl/QuerySetGL.cpp +++ b/src/dawn/native/opengl/QuerySetGL.cpp
@@ -32,8 +32,25 @@ namespace dawn::native::opengl { QuerySet::QuerySet(Device* device, const QuerySetDescriptor* descriptor) - : QuerySetBase(device, descriptor) {} + : QuerySetBase(device, descriptor), mQueries(descriptor->count) { + if (mQueries.size() > 0) { + const OpenGLFunctions& gl = device->GetGL(); + gl.GenQueries(descriptor->count, mQueries.data()); + } +} QuerySet::~QuerySet() = default; +void QuerySet::DestroyImpl() { + const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL(); + if (mQueries.size() > 0) { + gl.DeleteQueries(mQueries.size(), mQueries.data()); + } + QuerySetBase::DestroyImpl(); +} + +GLuint QuerySet::Get(uint32_t index) const { + return mQueries[index]; +} + } // namespace dawn::native::opengl
diff --git a/src/dawn/native/opengl/QuerySetGL.h b/src/dawn/native/opengl/QuerySetGL.h index 78ef510..cea8e4b 100644 --- a/src/dawn/native/opengl/QuerySetGL.h +++ b/src/dawn/native/opengl/QuerySetGL.h
@@ -28,7 +28,10 @@ #ifndef SRC_DAWN_NATIVE_OPENGL_QUERYSETGL_H_ #define SRC_DAWN_NATIVE_OPENGL_QUERYSETGL_H_ +#include <vector> + #include "dawn/native/QuerySet.h" +#include "dawn/native/opengl/opengl_platform.h" namespace dawn::native::opengl { @@ -37,9 +40,12 @@ class QuerySet final : public QuerySetBase { public: QuerySet(Device* device, const QuerySetDescriptor* descriptor); + GLuint Get(uint32_t index) const; private: ~QuerySet() override; + void DestroyImpl() override; + std::vector<GLuint> mQueries; }; } // namespace dawn::native::opengl
diff --git a/src/dawn/tests/end2end/QueryTests.cpp b/src/dawn/tests/end2end/QueryTests.cpp index fed9bcc..dc86062 100644 --- a/src/dawn/tests/end2end/QueryTests.cpp +++ b/src/dawn/tests/end2end/QueryTests.cpp
@@ -391,6 +391,9 @@ // TODO(dawn:1870): D3D11_QUERY_OCCLUSION_PREDICATE doesn't work on Intel Gen12. DAWN_SUPPRESS_TEST_IF(IsD3D11() && IsIntelGen12()); + // TODO(dawn:2247): Failing on ANGLE/D3D11 + DAWN_SUPPRESS_TEST_IF(IsANGLED3D11()); + constexpr uint32_t kQueryCount = 1; wgpu::QuerySet querySet = CreateOcclusionQuerySet(kQueryCount); @@ -475,6 +478,9 @@ // TODO(dawn:1870): D3D11_QUERY_OCCLUSION_PREDICATE doesn't work on Intel Gen12. DAWN_SUPPRESS_TEST_IF(IsD3D11() && IsIntelGen12()); + // TODO(dawn:2247): Failing on ANGLE/D3D11 + DAWN_SUPPRESS_TEST_IF(IsANGLED3D11()); + constexpr uint32_t kQueryCount = 1; utils::ComboRenderPipelineDescriptor descriptor; @@ -1291,6 +1297,8 @@ D3D12Backend(), MetalBackend(), MetalBackend({"metal_fill_empty_occlusion_queries_with_zero"}), + OpenGLBackend(), + OpenGLESBackend(), VulkanBackend()); DAWN_INSTANTIATE_TEST(TimestampQueryTests, D3D11Backend(),