MVKOcclusionQueryCommandEncoderState validate occlusion query during encoding step.
This commit is contained in:
parent
73984ba20c
commit
860e1ef2fb
@ -563,13 +563,12 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void encodeImpl(uint32_t) override;
|
void encodeImpl(uint32_t) override;
|
||||||
void resetImpl() override;
|
void resetImpl() override;
|
||||||
bool validateOcclusionQuery(MVKOcclusionQueryPool* pQueryPool, uint32_t query);
|
|
||||||
void endCurrentOcclusionQuery();
|
|
||||||
|
|
||||||
id<MTLBuffer> _visibilityResultMTLBuffer = nil;
|
id<MTLBuffer> _visibilityResultMTLBuffer = nil;
|
||||||
MTLVisibilityResultMode _mtlVisibilityResultMode = MTLVisibilityResultModeDisabled;
|
MTLVisibilityResultMode _mtlVisibilityResultMode = MTLVisibilityResultModeDisabled;
|
||||||
NSUInteger _mtlVisibilityResultOffset = 0;
|
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) {
|
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
|
_currentQuery.set(pQueryPool, query);
|
||||||
if ( !validateOcclusionQuery(pQueryPool, query) ) {
|
|
||||||
endCurrentOcclusionQuery();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSUInteger offset = pQueryPool->getVisibilityResultOffset(query);
|
NSUInteger offset = pQueryPool->getVisibilityResultOffset(query);
|
||||||
NSUInteger maxOffset = _cmdEncoder->_pDeviceMetalFeatures->maxQueryBufferSize - kMVKQuerySlotSizeInBytes;
|
NSUInteger maxOffset = _cmdEncoder->_pDeviceMetalFeatures->maxQueryBufferSize - kMVKQuerySlotSizeInBytes;
|
||||||
@ -874,42 +870,33 @@ void MVKOcclusionQueryCommandEncoderState::beginOcclusionQuery(MVKOcclusionQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MVKOcclusionQueryCommandEncoderState::endOcclusionQuery(MVKOcclusionQueryPool* pQueryPool, uint32_t query) {
|
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; }
|
id<MTLBuffer> MVKOcclusionQueryCommandEncoderState::getVisibilityResultMTLBuffer() { return _visibilityResultMTLBuffer; }
|
||||||
|
|
||||||
void MVKOcclusionQueryCommandEncoderState::encodeImpl(uint32_t stage) {
|
void MVKOcclusionQueryCommandEncoderState::encodeImpl(uint32_t stage) {
|
||||||
if (stage != kMVKGraphicsStageRasterization) { return; }
|
if (stage != kMVKGraphicsStageRasterization) { return; }
|
||||||
[_cmdEncoder->_mtlRenderEncoder setVisibilityResultMode: _mtlVisibilityResultMode
|
|
||||||
offset: _mtlVisibilityResultOffset];
|
// 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() {
|
void MVKOcclusionQueryCommandEncoderState::resetImpl() {
|
||||||
|
_currentQuery.reset();
|
||||||
_visibilityResultMTLBuffer = _cmdEncoder->_cmdBuffer->_initialVisibilityResultMTLBuffer;
|
_visibilityResultMTLBuffer = _cmdEncoder->_cmdBuffer->_initialVisibilityResultMTLBuffer;
|
||||||
_mtlVisibilityResultMode = MTLVisibilityResultModeDisabled;
|
_mtlVisibilityResultMode = MTLVisibilityResultModeDisabled;
|
||||||
_mtlVisibilityResultOffset = 0;
|
_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.
|
* This structure can be used as a key in a std::map and std::unordered_map.
|
||||||
*/
|
*/
|
||||||
typedef struct MVKQueryKey {
|
typedef struct MVKQuerySpec {
|
||||||
MVKQueryPool* queryPool;
|
MVKQueryPool* queryPool = nullptr;
|
||||||
uint32_t query;
|
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);
|
return (queryPool == rhs.queryPool) && (query == rhs.query);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t hash() const { return (size_t)queryPool ^ query; }
|
std::size_t hash() const { return (size_t)queryPool ^ query; }
|
||||||
} MVKQueryKey;
|
|
||||||
|
} MVKQuerySpec;
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct hash<MVKQueryKey> {
|
struct hash<MVKQuerySpec> {
|
||||||
std::size_t operator()(const MVKQueryKey& k) const { return k.hash(); }
|
std::size_t operator()(const MVKQuerySpec& k) const { return k.hash(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user