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(),