diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 1e6e249a..c05b46b1 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -9071,37 +9071,6 @@ void main() { void VulkanRenderer::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - // The scissor test clips blit writes: intersect the destination rectangle with - // the scissor box and shrink the source proportionally. - if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) { - const IntVec4& scissor = MGB_CTX->GetScissorBox(); - const auto clipAxis = [](GLint& d0, GLint& d1, GLint& s0, GLint& s1, GLint clipLo, GLint clipHi) -> Bool { - const Bool dstFlipped = d1 < d0; - GLint lo = dstFlipped ? d1 : d0; - GLint hi = dstFlipped ? d0 : d1; - const GLint newLo = std::max(lo, clipLo); - const GLint newHi = std::min(hi, clipHi); - if (newLo >= newHi) { - return false; - } - const double srcSpan = static_cast(s1 - s0); - const double dstSpan = static_cast(d1 - d0); - const double scale = dstSpan != 0.0 ? srcSpan / dstSpan : 0.0; - const GLint origD0 = d0; - const GLint clippedD0 = dstFlipped ? newHi : newLo; - const GLint clippedD1 = dstFlipped ? newLo : newHi; - s0 = s0 + static_cast(std::lround((clippedD0 - origD0) * scale)); - s1 = s0 + static_cast(std::lround((clippedD1 - clippedD0) * scale)); - d0 = clippedD0; - d1 = clippedD1; - return true; - }; - if (!clipAxis(dstX0, dstX1, srcX0, srcX1, scissor.x(), scissor.x() + scissor.z()) || - !clipAxis(dstY0, dstY1, srcY0, srcY1, scissor.y(), scissor.y() + scissor.w())) { - return; // fully scissored out - } - } - #if MOBILEGL_BUILD_DISAGGREGATED if (MG_Config::Transport != MG_Config::TransportMode::Monolith) { BlitWireFramebuffers(srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter); @@ -9139,6 +9108,37 @@ void main() { return; } + // The scissor test clips blit writes: intersect the destination rectangle with + // the scissor box and shrink the source proportionally. + if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) { + const IntVec4& scissor = MGB_CTX->GetScissorBox(); + const auto clipAxis = [](GLint& d0, GLint& d1, GLint& s0, GLint& s1, GLint clipLo, GLint clipHi) -> Bool { + const Bool dstFlipped = d1 < d0; + GLint lo = dstFlipped ? d1 : d0; + GLint hi = dstFlipped ? d0 : d1; + const GLint newLo = std::max(lo, clipLo); + const GLint newHi = std::min(hi, clipHi); + if (newLo >= newHi) { + return false; + } + const double srcSpan = static_cast(s1 - s0); + const double dstSpan = static_cast(d1 - d0); + const double scale = dstSpan != 0.0 ? srcSpan / dstSpan : 0.0; + const GLint origD0 = d0; + const GLint clippedD0 = dstFlipped ? newHi : newLo; + const GLint clippedD1 = dstFlipped ? newLo : newHi; + s0 = s0 + static_cast(std::lround((clippedD0 - origD0) * scale)); + s1 = s0 + static_cast(std::lround((clippedD1 - clippedD0) * scale)); + d0 = clippedD0; + d1 = clippedD1; + return true; + }; + if (!clipAxis(dstX0, dstX1, srcX0, srcX1, scissor.x(), scissor.x() + scissor.z()) || + !clipAxis(dstY0, dstY1, srcY0, srcY1, scissor.y(), scissor.y() + scissor.w())) { + return; // fully scissored out + } + } + MOBILEGL_ASSERT(readFbo != nullptr, "VulkanRenderer::BlitFramebuffer: read framebuffer is null"); MOBILEGL_ASSERT(drawFbo != nullptr, "VulkanRenderer::BlitFramebuffer: draw framebuffer is null"); if (IsUnsupportedFramebufferForDirectVulkan(*readFbo) || diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc index f5bef129..91893634 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.inc @@ -250,6 +250,37 @@ void VulkanRenderer::BlitWireFramebuffers(GLint sx0, GLint sy0, GLint sx1, GLint sy1, GLint dx0, GLint dy0, GLint dx1, GLint dy1, GLbitfield mask, GLenum filter) { if (HasPendingRecordedWork() && !FlushPendingCommands()) MagmaWireFatal("wire-verb-flush"); + // The scissor test clips blit writes: intersect the destination rectangle with + // the scissor box and shrink the source proportionally. + if (MGB_CTX->IsCapabilityEnabled(CapabilityInput::ScissorTest)) { + const IntVec4& scissor = MGB_CTX->GetScissorBox(); + const auto clipAxis = [](GLint& d0, GLint& d1, GLint& s0, GLint& s1, GLint clipLo, GLint clipHi) -> Bool { + const Bool dstFlipped = d1 < d0; + GLint lo = dstFlipped ? d1 : d0; + GLint hi = dstFlipped ? d0 : d1; + const GLint newLo = std::max(lo, clipLo); + const GLint newHi = std::min(hi, clipHi); + if (newLo >= newHi) { + return false; + } + const double srcSpan = static_cast(s1 - s0); + const double dstSpan = static_cast(d1 - d0); + const double scale = dstSpan != 0.0 ? srcSpan / dstSpan : 0.0; + const GLint origD0 = d0; + const GLint clippedD0 = dstFlipped ? newHi : newLo; + const GLint clippedD1 = dstFlipped ? newLo : newHi; + s0 = s0 + static_cast(std::lround((clippedD0 - origD0) * scale)); + s1 = s0 + static_cast(std::lround((clippedD1 - clippedD0) * scale)); + d0 = clippedD0; + d1 = clippedD1; + return true; + }; + if (!clipAxis(dx0, dx1, sx0, sx1, scissor.x(), scissor.x() + scissor.z()) || + !clipAxis(dy0, dy1, sy0, sy1, scissor.y(), scissor.y() + scissor.w())) { + return; // fully scissored out + } + } + auto& state = MG_Pipe::MGPipeApplier(); const Bool named = !MG_Pipe::MGPipeHandleIsNull(state.VerbBlitReadFbo) || !MG_Pipe::MGPipeHandleIsNull(state.VerbBlitDrawFbo);