// // Copyright (c) 2020 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // QueryMtl.h: // Defines the class interface for QueryMtl, implementing QueryImpl. // #ifndef LIBANGLE_RENDERER_METAL_QUERYMTL_H_ #define LIBANGLE_RENDERER_METAL_QUERYMTL_H_ #include "libANGLE/renderer/QueryImpl.h" #include "libANGLE/renderer/metal/mtl_common.h" #include "libANGLE/renderer/metal/mtl_resources.h" namespace rx { class ContextMtl; // The class represents offset(s) allocated in the visiblity buffer for an occlusion query. // See doc/OcclusionQuery.md. // An occlusion query might have more than one offsets allocated, but all of them must be adjacent // to each other. Multiple offsets typically allocated when the query is paused and resumed during // viewport clear emulation with draw operations. In such case, Metal doesn't allow an offset to // be reused in a render pass, hence multiple offsets will be allocated, and their values will // be accumulated. class VisibilityBufferOffsetsMtl { public: void clear() { mStartOffset = mNumOffsets = 0; } bool empty() const { return mNumOffsets == 0; } uint32_t size() const { return mNumOffsets; } // Return last offset uint32_t back() const { ASSERT(!empty()); return mStartOffset + (mNumOffsets - 1) * mtl::kOcclusionQueryResultSize; } uint32_t front() const { ASSERT(!empty()); return mStartOffset; } void setStartOffset(uint32_t offset) { ASSERT(empty()); mStartOffset = offset; mNumOffsets = 1; } void addOffset() { ASSERT(!empty()); mNumOffsets++; } private: uint32_t mStartOffset = 0; uint32_t mNumOffsets = 0; }; class QueryMtl : public QueryImpl { public: QueryMtl(gl::QueryType type); ~QueryMtl() override; void onDestroy(const gl::Context *context) override; angle::Result begin(const gl::Context *context) override; angle::Result end(const gl::Context *context) override; angle::Result queryCounter(const gl::Context *context) override; angle::Result getResult(const gl::Context *context, GLint *params) override; angle::Result getResult(const gl::Context *context, GLuint *params) override; angle::Result getResult(const gl::Context *context, GLint64 *params) override; angle::Result getResult(const gl::Context *context, GLuint64 *params) override; angle::Result isResultAvailable(const gl::Context *context, bool *available) override; // Get allocated offsets in the render pass's occlusion query pool. const VisibilityBufferOffsetsMtl &getAllocatedVisibilityOffsets() const { return mVisibilityBufferOffsets; } // Set first allocated offset in the render pass's occlusion query pool. void setFirstAllocatedVisibilityOffset(uint32_t off) { mVisibilityBufferOffsets.setStartOffset(off); } // Add more offset allocated for the occlusion query void addAllocatedVisibilityOffset() { mVisibilityBufferOffsets.addOffset(); } void clearAllocatedVisibilityOffsets() { mVisibilityBufferOffsets.clear(); } // Returns the buffer containing the final occlusion query result. const mtl::BufferRef &getVisibilityResultBuffer() const { return mVisibilityResultBuffer; } // Reset the occlusion query result stored in buffer to zero void resetVisibilityResult(ContextMtl *contextMtl); void onTransformFeedbackEnd(const gl::Context *context); // If the timestamp query is still active upon context switch, // must set/unset the active timestamp query entry on the command // queue. void onContextMakeCurrent(const gl::Context *context); void onContextUnMakeCurrent(const gl::Context *context); private: template angle::Result waitAndGetResult(const gl::Context *context, T *params); // List of offsets in the render pass's occlusion query pool buffer allocated for this query VisibilityBufferOffsetsMtl mVisibilityBufferOffsets; mtl::BufferRef mVisibilityResultBuffer; size_t mTransformFeedbackPrimitivesDrawn = 0; uint64_t mTimeElapsedEntry = 0; }; } // namespace rx #endif /* LIBANGLE_RENDERER_METAL_QUERYMTL_H_ */