Fix case where viewport/scissor doesn't get set properly when mixing dynamic and static-configured pipelines in the same command buffer.

This commit is contained in:
Michael Barriault 2019-04-22 19:26:00 +01:00
parent e89e9dcfd6
commit a336e64bea
2 changed files with 49 additions and 15 deletions

View File

@ -147,7 +147,7 @@ protected:
void encodeImpl(uint32_t stage) override; void encodeImpl(uint32_t stage) override;
void resetImpl() override; void resetImpl() override;
MVKVectorInline<MTLViewport, kMVKCachedViewportCount> _mtlViewports; MVKVectorInline<MTLViewport, kMVKCachedViewportCount> _mtlViewports, _mtlDynamicViewports;
}; };
@ -176,7 +176,7 @@ protected:
void encodeImpl(uint32_t stage) override; void encodeImpl(uint32_t stage) override;
void resetImpl() override; void resetImpl() override;
MVKVectorInline<MTLScissorRect, kMVKCachedScissorCount> _mtlScissors; MVKVectorInline<MTLScissorRect, kMVKCachedScissorCount> _mtlScissors, _mtlDynamicScissors;
}; };

View File

@ -54,34 +54,51 @@ void MVKViewportCommandEncoderState::setViewports(const MVKVector<MTLViewport> &
uint32_t firstViewport, uint32_t firstViewport,
bool isSettingDynamically) { bool isSettingDynamically) {
bool mustSetDynamically = _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
uint32_t maxViewports = _cmdEncoder->getDevice()->_pProperties->limits.maxViewports; uint32_t maxViewports = _cmdEncoder->getDevice()->_pProperties->limits.maxViewports;
if ((mustSetDynamically == isSettingDynamically) && mtlViewports.size() > 0 && if (isSettingDynamically && mtlViewports.size() > 0 &&
(firstViewport + mtlViewports.size() <= maxViewports) && (firstViewport + mtlViewports.size() <= maxViewports) &&
(firstViewport < maxViewports)) { (firstViewport < maxViewports)) {
if (firstViewport + mtlViewports.size() > _mtlDynamicViewports.size()) {
_mtlDynamicViewports.resize(firstViewport + mtlViewports.size());
}
std::copy(mtlViewports.begin(), mtlViewports.end(), _mtlDynamicViewports.begin() + firstViewport);
markDirty();
} else if (!isSettingDynamically &&
(firstViewport + mtlViewports.size() <= maxViewports) &&
(firstViewport < maxViewports)) {
bool mustSetDynamically = _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
if (firstViewport + mtlViewports.size() > _mtlViewports.size()) { if (firstViewport + mtlViewports.size() > _mtlViewports.size()) {
_mtlViewports.resize(firstViewport + mtlViewports.size()); _mtlViewports.resize(firstViewport + mtlViewports.size());
} }
std::copy(mtlViewports.begin(), mtlViewports.end(), _mtlViewports.begin() + firstViewport); if (mtlViewports.size() > 0 && !mustSetDynamically)
std::copy(mtlViewports.begin(), mtlViewports.end(), _mtlViewports.begin() + firstViewport);
else
_mtlViewports.clear();
markDirty(); markDirty();
} }
} }
void MVKViewportCommandEncoderState::encodeImpl(uint32_t stage) { void MVKViewportCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; } if (stage != kMVKGraphicsStageRasterization) { return; }
MVKAssert(!_mtlViewports.empty(), "Must specify at least one viewport"); auto& mtlViewports = _mtlViewports.size() > 0 ? _mtlViewports : _mtlDynamicViewports;
MVKAssert(!mtlViewports.empty(), "Must specify at least one viewport");
if (_cmdEncoder->_pDeviceFeatures->multiViewport) { if (_cmdEncoder->_pDeviceFeatures->multiViewport) {
[_cmdEncoder->_mtlRenderEncoder setViewports: &_mtlViewports[0] count: _mtlViewports.size()]; [_cmdEncoder->_mtlRenderEncoder setViewports: &mtlViewports[0] count: mtlViewports.size()];
} else { } else {
[_cmdEncoder->_mtlRenderEncoder setViewport: _mtlViewports[0]]; [_cmdEncoder->_mtlRenderEncoder setViewport: mtlViewports[0]];
} }
} }
void MVKViewportCommandEncoderState::resetImpl() { void MVKViewportCommandEncoderState::resetImpl() {
_mtlViewports.clear(); _mtlViewports.clear();
_mtlDynamicViewports.clear();
} }
@ -92,26 +109,42 @@ void MVKScissorCommandEncoderState::setScissors(const MVKVector<MTLScissorRect>
uint32_t firstScissor, uint32_t firstScissor,
bool isSettingDynamically) { bool isSettingDynamically) {
bool mustSetDynamically = _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_SCISSOR);
uint32_t maxScissors = _cmdEncoder->getDevice()->_pProperties->limits.maxViewports; uint32_t maxScissors = _cmdEncoder->getDevice()->_pProperties->limits.maxViewports;
if ((mustSetDynamically == isSettingDynamically) && mtlScissors.size() > 0 && if (isSettingDynamically && mtlScissors.size() > 0 &&
(firstScissor + mtlScissors.size() <= maxScissors) && (firstScissor + mtlScissors.size() <= maxScissors) &&
(firstScissor < maxScissors)) { (firstScissor < maxScissors)) {
if (firstScissor + mtlScissors.size() > _mtlDynamicScissors.size()) {
_mtlDynamicScissors.resize(firstScissor + mtlScissors.size());
}
std::copy(mtlScissors.begin(), mtlScissors.end(), _mtlDynamicScissors.begin() + firstScissor);
markDirty();
} else if (!isSettingDynamically &&
(firstScissor + mtlScissors.size() <= maxScissors) &&
(firstScissor < maxScissors)) {
bool mustSetDynamically = _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_SCISSOR);
if (firstScissor + mtlScissors.size() > _mtlScissors.size()) { if (firstScissor + mtlScissors.size() > _mtlScissors.size()) {
_mtlScissors.resize(firstScissor + mtlScissors.size()); _mtlScissors.resize(firstScissor + mtlScissors.size());
} }
std::copy(mtlScissors.begin(), mtlScissors.end(), _mtlScissors.begin() + firstScissor); if (mtlScissors.size() > 0 && !mustSetDynamically)
std::copy(mtlScissors.begin(), mtlScissors.end(), _mtlScissors.begin() + firstScissor);
else
_mtlScissors.clear();
markDirty(); markDirty();
} }
} }
void MVKScissorCommandEncoderState::encodeImpl(uint32_t stage) { void MVKScissorCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; } if (stage != kMVKGraphicsStageRasterization) { return; }
MVKAssert(!_mtlScissors.empty(), "Must specify at least one scissor rect"); auto& mtlScissors = _mtlScissors.size() > 0 ? _mtlScissors : _mtlDynamicScissors;
auto clippedScissors(_mtlScissors); MVKAssert(!mtlScissors.empty(), "Must specify at least one scissor rect");
auto clippedScissors(mtlScissors);
std::for_each(clippedScissors.begin(), clippedScissors.end(), [this](MTLScissorRect& scissor) { std::for_each(clippedScissors.begin(), clippedScissors.end(), [this](MTLScissorRect& scissor) {
scissor = _cmdEncoder->clipToRenderArea(scissor); scissor = _cmdEncoder->clipToRenderArea(scissor);
}); });
@ -124,6 +157,7 @@ void MVKScissorCommandEncoderState::encodeImpl(uint32_t stage) {
void MVKScissorCommandEncoderState::resetImpl() { void MVKScissorCommandEncoderState::resetImpl() {
_mtlScissors.clear(); _mtlScissors.clear();
_mtlDynamicScissors.clear();
} }