blob: 7878a18582332cd2b409eee558448140c63a870f [file] [log] [blame]
//
// 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);
private:
template <typename T>
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;
};
} // namespace rx
#endif /* LIBANGLE_RENDERER_METAL_QUERYMTL_H_ */