MVKOcclusionQueryCommandEncoderState validate occlusion query during encoding step.
This commit is contained in:
parent
73984ba20c
commit
860e1ef2fb
@ -563,13 +563,12 @@ public:
|
||||
protected:
|
||||
void encodeImpl(uint32_t) override;
|
||||
void resetImpl() override;
|
||||
bool validateOcclusionQuery(MVKOcclusionQueryPool* pQueryPool, uint32_t query);
|
||||
void endCurrentOcclusionQuery();
|
||||
|
||||
id<MTLBuffer> _visibilityResultMTLBuffer = nil;
|
||||
MTLVisibilityResultMode _mtlVisibilityResultMode = MTLVisibilityResultModeDisabled;
|
||||
NSUInteger _mtlVisibilityResultOffset = 0;
|
||||
std::unordered_map<MVKQueryKey, id<MTLRenderCommandEncoder>> _mtlEncodersUsed;
|
||||
std::unordered_map<MVKQuerySpec, id<MTLRenderCommandEncoder>> _mtlEncodersUsed;
|
||||
MVKQuerySpec _currentQuery;
|
||||
};
|
||||
|
||||
|
||||
|
@ -855,11 +855,7 @@ void MVKComputeResourcesCommandEncoderState::resetImpl() {
|
||||
|
||||
void MVKOcclusionQueryCommandEncoderState::beginOcclusionQuery(MVKOcclusionQueryPool* pQueryPool, uint32_t query, VkQueryControlFlags flags) {
|
||||
|
||||
// If the occlusion query is not valid, don't set it up, and end the current query
|
||||
if ( !validateOcclusionQuery(pQueryPool, query) ) {
|
||||
endCurrentOcclusionQuery();
|
||||
return;
|
||||
}
|
||||
_currentQuery.set(pQueryPool, query);
|
||||
|
||||
NSUInteger offset = pQueryPool->getVisibilityResultOffset(query);
|
||||
NSUInteger maxOffset = _cmdEncoder->_pDeviceMetalFeatures->maxQueryBufferSize - kMVKQuerySlotSizeInBytes;
|
||||
@ -874,42 +870,33 @@ void MVKOcclusionQueryCommandEncoderState::beginOcclusionQuery(MVKOcclusionQuery
|
||||
}
|
||||
|
||||
void MVKOcclusionQueryCommandEncoderState::endOcclusionQuery(MVKOcclusionQueryPool* pQueryPool, uint32_t query) {
|
||||
endCurrentOcclusionQuery();
|
||||
reset();
|
||||
}
|
||||
|
||||
void MVKOcclusionQueryCommandEncoderState::endCurrentOcclusionQuery() {
|
||||
_mtlVisibilityResultMode = MTLVisibilityResultModeDisabled;
|
||||
_mtlVisibilityResultOffset = 0;
|
||||
|
||||
markDirty();
|
||||
}
|
||||
|
||||
bool MVKOcclusionQueryCommandEncoderState::validateOcclusionQuery(MVKOcclusionQueryPool* pQueryPool, uint32_t query) {
|
||||
|
||||
// If the query was already used for the current Metal render encoder, log an error and return the query as invalid
|
||||
id<MTLRenderCommandEncoder> currMTLRendEnc = _cmdEncoder->_mtlRenderEncoder;
|
||||
if (currMTLRendEnc) {
|
||||
MVKQueryKey qKey = {pQueryPool, query};
|
||||
if (_mtlEncodersUsed[qKey] == currMTLRendEnc) {
|
||||
MVKLogError("vkCmdBeginQuery(): Metal does not support using the same query more than once within a single Vulkan render subpass.");
|
||||
return false;
|
||||
}
|
||||
_mtlEncodersUsed[qKey] = currMTLRendEnc; // Remember which MTLRenderEncoder was used for this query
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the MTLBuffer has not yet been set, see if the command buffer is configured with it
|
||||
id<MTLBuffer> MVKOcclusionQueryCommandEncoderState::getVisibilityResultMTLBuffer() { return _visibilityResultMTLBuffer; }
|
||||
|
||||
void MVKOcclusionQueryCommandEncoderState::encodeImpl(uint32_t stage) {
|
||||
if (stage != kMVKGraphicsStageRasterization) { return; }
|
||||
[_cmdEncoder->_mtlRenderEncoder setVisibilityResultMode: _mtlVisibilityResultMode
|
||||
offset: _mtlVisibilityResultOffset];
|
||||
if (stage != kMVKGraphicsStageRasterization) { return; }
|
||||
|
||||
// Metal does not allow a query to be run twice on a single render encoder.
|
||||
// If the query is active and was already used for the current Metal render encoder,
|
||||
// log an error and terminate the current query. Remember which MTLRenderEncoder
|
||||
// was used for this query to test for this situation on future queries.
|
||||
if (_mtlVisibilityResultMode != MTLVisibilityResultModeDisabled) {
|
||||
id<MTLRenderCommandEncoder> currMTLRendEnc = _cmdEncoder->_mtlRenderEncoder;
|
||||
if (currMTLRendEnc == _mtlEncodersUsed[_currentQuery]) {
|
||||
MVKLogError("vkCmdBeginQuery(): Metal does not support using the same occlusion query more than once within a single Vulkan render subpass.");
|
||||
resetImpl();
|
||||
}
|
||||
_mtlEncodersUsed[_currentQuery] = currMTLRendEnc;
|
||||
}
|
||||
|
||||
[_cmdEncoder->_mtlRenderEncoder setVisibilityResultMode: _mtlVisibilityResultMode
|
||||
offset: _mtlVisibilityResultOffset];
|
||||
}
|
||||
|
||||
void MVKOcclusionQueryCommandEncoderState::resetImpl() {
|
||||
_currentQuery.reset();
|
||||
_visibilityResultMTLBuffer = _cmdEncoder->_cmdBuffer->_initialVisibilityResultMTLBuffer;
|
||||
_mtlVisibilityResultMode = MTLVisibilityResultModeDisabled;
|
||||
_mtlVisibilityResultOffset = 0;
|
||||
|
@ -331,24 +331,29 @@ namespace std {
|
||||
}
|
||||
|
||||
/**
|
||||
* Key for looking up query results.
|
||||
* Spec for a query.
|
||||
*
|
||||
* This structure can be used as a key in a std::map and std::unordered_map.
|
||||
*/
|
||||
typedef struct MVKQueryKey {
|
||||
MVKQueryPool* queryPool;
|
||||
uint32_t query;
|
||||
typedef struct MVKQuerySpec {
|
||||
MVKQueryPool* queryPool = nullptr;
|
||||
uint32_t query = 0;
|
||||
|
||||
bool operator==(const MVKQueryKey& rhs) const {
|
||||
inline void set(MVKQueryPool* qryPool, uint32_t qry) { queryPool = qryPool; query = qry; }
|
||||
inline void reset() { set(nullptr, 0); }
|
||||
|
||||
bool operator==(const MVKQuerySpec& rhs) const {
|
||||
return (queryPool == rhs.queryPool) && (query == rhs.query);
|
||||
}
|
||||
|
||||
std::size_t hash() const { return (size_t)queryPool ^ query; }
|
||||
} MVKQueryKey;
|
||||
|
||||
} MVKQuerySpec;
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<MVKQueryKey> {
|
||||
std::size_t operator()(const MVKQueryKey& k) const { return k.hash(); }
|
||||
struct hash<MVKQuerySpec> {
|
||||
std::size_t operator()(const MVKQuerySpec& k) const { return k.hash(); }
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user