1717#include " libANGLE/renderer/metal/DisplayMtl.h"
1818#include " libANGLE/renderer/metal/FrameBufferMtl.h"
1919#include " libANGLE/renderer/metal/ProgramMtl.h"
20+ #include " libANGLE/renderer/metal/QueryMtl.h"
2021#include " libANGLE/renderer/metal/RenderBufferMtl.h"
2122#include " libANGLE/renderer/metal/RenderTargetMtl.h"
2223#include " libANGLE/renderer/metal/ShaderMtl.h"
@@ -97,7 +98,7 @@ bool NeedToInvertDepthRange(float near, float far)
9798 : ContextImpl(state, errorSet),
9899 mtl::Context (display),
99100 mCmdBuffer(&display->cmdQueue ()),
100- mRenderEncoder(&mCmdBuffer ),
101+ mRenderEncoder(&mCmdBuffer , mOcclusionQueryPool ),
101102 mBlitEncoder(&mCmdBuffer ),
102103 mComputeEncoder(&mCmdBuffer )
103104{}
@@ -122,6 +123,7 @@ bool NeedToInvertDepthRange(float near, float far)
122123{
123124 mTriFanIndexBuffer .destroy (this );
124125 mLineLoopIndexBuffer .destroy (this );
126+ mOcclusionQueryPool .destroy (this );
125127
126128 mIncompleteTextures .onDestroy (context);
127129 mIncompleteTexturesInitialized = false ;
@@ -927,9 +929,7 @@ bool NeedToInvertDepthRange(float near, float far)
927929// Query and Fence creation
928930QueryImpl *ContextMtl::createQuery (gl::QueryType type)
929931{
930- // NOTE(hqle): ES 3.0
931- UNIMPLEMENTED ();
932- return nullptr ;
932+ return new QueryMtl (type);
933933}
934934FenceNVImpl *ContextMtl::createFenceNV ()
935935{
@@ -1131,9 +1131,18 @@ bool NeedToInvertDepthRange(float near, float far)
11311131 return mIncompleteTextures .getIncompleteTexture (context, type, nullptr , textureOut);
11321132}
11331133
1134- void ContextMtl::endEncoding (mtl::RenderCommandEncoder *encoder)
1134+ void ContextMtl::endRenderEncoding (mtl::RenderCommandEncoder *encoder)
11351135{
1136+ // End any pending visibility query in the render pass
1137+ if (mOcclusionQuery )
1138+ {
1139+ disableActiveOcclusionQueryInRenderPass ();
1140+ }
1141+
11361142 encoder->endEncoding ();
1143+
1144+ // Resolve visibility results
1145+ mOcclusionQueryPool .resolveVisibilityResults (this );
11371146}
11381147
11391148void ContextMtl::endEncoding (bool forceSaveRenderPassContent)
@@ -1146,7 +1155,7 @@ bool NeedToInvertDepthRange(float near, float far)
11461155 mRenderEncoder .setStoreAction (MTLStoreActionStore );
11471156 }
11481157
1149- mRenderEncoder . endEncoding ( );
1158+ endRenderEncoding (& mRenderEncoder );
11501159 }
11511160
11521161 if (mBlitEncoder .valid ())
@@ -1461,6 +1470,87 @@ bool NeedToInvertDepthRange(float near, float far)
14611470 onDrawFrameBufferChangedState (context, framebuffer, true );
14621471}
14631472
1473+ angle::Result ContextMtl::onOcclusionQueryBegin (const gl::Context *context, QueryMtl *query)
1474+ {
1475+ ASSERT (mOcclusionQuery == nullptr );
1476+ mOcclusionQuery = query;
1477+
1478+ if (mRenderEncoder .valid ())
1479+ {
1480+ // if render pass has started, start the query in the encoder
1481+ return startOcclusionQueryInRenderPass (query, true );
1482+ }
1483+ else
1484+ {
1485+ query->resetVisibilityResult (this );
1486+ }
1487+
1488+ return angle::Result::Continue;
1489+ }
1490+ void ContextMtl::onOcclusionQueryEnd (const gl::Context *context, QueryMtl *query)
1491+ {
1492+ ASSERT (mOcclusionQuery == query);
1493+
1494+ if (mRenderEncoder .valid ())
1495+ {
1496+ // if render pass has started, end the query in the encoder
1497+ disableActiveOcclusionQueryInRenderPass ();
1498+ }
1499+
1500+ mOcclusionQuery = nullptr ;
1501+ }
1502+ void ContextMtl::onOcclusionQueryDestroy (const gl::Context *context, QueryMtl *query)
1503+ {
1504+ if (query->getAllocatedVisibilityOffsets ().empty ())
1505+ {
1506+ return ;
1507+ }
1508+ if (mOcclusionQuery == query)
1509+ {
1510+ onOcclusionQueryEnd (context, query);
1511+ }
1512+ mOcclusionQueryPool .deallocateQueryOffset (this , query);
1513+ }
1514+
1515+ void ContextMtl::disableActiveOcclusionQueryInRenderPass ()
1516+ {
1517+ if (!mOcclusionQuery || mOcclusionQuery ->getAllocatedVisibilityOffsets ().empty ())
1518+ {
1519+ return ;
1520+ }
1521+
1522+ ASSERT (mRenderEncoder .valid ());
1523+ mRenderEncoder .setVisibilityResultMode (MTLVisibilityResultModeDisabled ,
1524+ mOcclusionQuery ->getAllocatedVisibilityOffsets ().back ());
1525+ }
1526+
1527+ angle::Result ContextMtl::restartActiveOcclusionQueryInRenderPass ()
1528+ {
1529+ if (!mOcclusionQuery || mOcclusionQuery ->getAllocatedVisibilityOffsets ().empty ())
1530+ {
1531+ return angle::Result::Continue;
1532+ }
1533+
1534+ return startOcclusionQueryInRenderPass (mOcclusionQuery , false );
1535+ }
1536+
1537+ angle::Result ContextMtl::startOcclusionQueryInRenderPass (QueryMtl *query, bool clearOldValue)
1538+ {
1539+ ASSERT (mRenderEncoder .valid ());
1540+
1541+ ANGLE_TRY (mOcclusionQueryPool .allocateQueryOffset (this , query, clearOldValue));
1542+
1543+ mRenderEncoder .setVisibilityResultMode (MTLVisibilityResultModeBoolean ,
1544+ query->getAllocatedVisibilityOffsets ().back ());
1545+
1546+ // We need to mark the query's buffer as being written in this command buffer now. Since the
1547+ // actual writing is deferred until the render pass ends and user could try to read the query
1548+ // result before the render pass ends.
1549+ mCmdBuffer .setWriteDependency (query->getVisibilityResultBuffer ());
1550+
1551+ return angle::Result::Continue;
1552+ }
1553+
14641554void ContextMtl::updateProgramExecutable (const gl::Context *context)
14651555{
14661556 // Need to rebind textures
@@ -1547,6 +1637,13 @@ bool NeedToInvertDepthRange(float near, float far)
15471637 invalidateState (context);
15481638 }
15491639
1640+ if (mOcclusionQuery && mOcclusionQueryPool .getNumRenderPassAllocatedQueries () == 0 )
1641+ {
1642+ // The occlusion query is still active, and a new render pass has started.
1643+ // We need to continue the querying process in the new render encoder.
1644+ ANGLE_TRY (startOcclusionQueryInRenderPass (mOcclusionQuery , false ));
1645+ }
1646+
15501647 Optional<mtl::RenderPipelineDesc> changedPipelineDesc;
15511648 ANGLE_TRY (checkIfPipelineChanged (context, mode, &changedPipelineDesc));
15521649
0 commit comments