Skip to content

Commit

Permalink
Metal: Clear visibility result buffer before use
Browse files Browse the repository at this point in the history
Ensured that the current visibility pool buffer does
not contain previous results if it was used before.

Fixed: angleproject:348206830
Change-Id: I8dbc36626ef8267d5466c96405dac0da2754cb6d
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5643453
Commit-Queue: Alexey Knyazev <[email protected]>
Reviewed-by: Quyen Le <[email protected]>
Reviewed-by: Geoff Lang <[email protected]>
  • Loading branch information
lexaknyazev authored and Angle LUCI CQ committed Jun 21, 2024
1 parent e3c8d57 commit 1202822
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/libANGLE/renderer/metal/ContextMtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,8 @@ GLint GetOwnershipIdentity(const egl::AttributeMap &attribs)
mBlitEncoder.endEncoding();
}

mOcclusionQueryPool.prepareRenderPassVisibilityPoolBuffer(this);

encoder->endEncoding();

// Resolve visibility results
Expand Down
3 changes: 3 additions & 0 deletions src/libANGLE/renderer/metal/mtl_occlusion_query_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class OcclusionQueryPool
size_t getNumRenderPassAllocatedQueries() const { return mAllocatedQueries.size(); }
// This function is called at the end of render pass
void resolveVisibilityResults(ContextMtl *contextMtl);
// Clear visibility pool buffer to drop previous results
void prepareRenderPassVisibilityPoolBuffer(ContextMtl *contextMtl);

private:
// Buffer to hold the visibility results for current render pass
Expand All @@ -57,6 +59,7 @@ class OcclusionQueryPool
std::vector<QueryMtl *> mAllocatedQueries;

bool mResetFirstQuery = false;
bool mUsed = false;
};

} // namespace mtl
Expand Down
26 changes: 26 additions & 0 deletions src/libANGLE/renderer/metal/mtl_occlusion_query_pool.mm
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
static_cast<uint32_t>(mAllocatedQueries.size()) * kOcclusionQueryResultSize;
if (!mRenderPassResultsPool)
{
ASSERT(!mUsed);
// First allocation
ANGLE_TRY(Buffer::MakeBufferWithStorageMode(contextMtl, MTLStorageModePrivate,
kOcclusionQueryResultSize, nullptr,
Expand All @@ -62,6 +63,7 @@
ANGLE_TRY(Buffer::MakeBufferWithStorageMode(contextMtl, MTLStorageModePrivate,
mRenderPassResultsPool->size() * 2, nullptr,
&mRenderPassResultsPool));
mUsed = false;
mRenderPassResultsPool->get().label = @"OcclusionQueryPool";
}

Expand Down Expand Up @@ -180,5 +182,29 @@
mAllocatedQueries.clear();
}

void OcclusionQueryPool::prepareRenderPassVisibilityPoolBuffer(ContextMtl *contextMtl)
{
if (mAllocatedQueries.empty())
{
return;
}

// If the current visibility pool buffer was not used before,
// ensure that it will be cleared next time.
if (!mUsed)
{
mUsed = true;
return;
}

// If the current visibility pool buffer was used before,
// ensure that it does not contain previous results.
auto blitEncoder = contextMtl->getBlitCommandEncoderWithoutEndingRenderEncoder();
blitEncoder->fillBuffer(mRenderPassResultsPool,
NSMakeRange(0, mAllocatedQueries.size() * kOcclusionQueryResultSize),
0);
blitEncoder->endEncoding();
}

} // namespace mtl
} // namespace rx
37 changes: 37 additions & 0 deletions src/tests/gl_tests/OcclusionQueriesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,43 @@ TEST_P(OcclusionQueriesTest, EmptyQueryAfterCompletedQuery)
EXPECT_FALSE(result);
}

// Some Metal drivers do not automatically clear visibility buffer
// at the beginning of a render pass. This test makes two queries
// that would use the same internal visibility buffer at the same
// offset and checks the query results.
TEST_P(OcclusionQueriesTest, EmptyQueryAfterCompletedQueryInterleaved)
{
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
!IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));

GLQueryEXT query;

// Make a draw call to start a new render pass
drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);

// Begin a query and make another draw call
glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);

// Check the query result to end command encoding
GLuint result = GL_FALSE;
glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
EXPECT_TRUE(result);
ASSERT_GL_NO_ERROR();

// Make a draw call to start a new render pass
drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);

// Begin and immediately resolve a new query; it must return false
result = GL_FALSE;
glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
EXPECT_FALSE(result);
ASSERT_GL_NO_ERROR();
}

// Test multiple occlusion queries.
TEST_P(OcclusionQueriesTest, MultiQueries)
{
Expand Down

0 comments on commit 1202822

Please sign in to comment.