mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
Magma: an enabled scissor test over a never-written box clips nothing instead of everything (DefaultScissorFollowsSurfaceScenario runs on DirectVulkan instead of skipping).
This commit is contained in:
@@ -670,6 +670,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
vkCmdSetLineWidth(commandBuffer, lineWidth);
|
||||
}
|
||||
|
||||
// Whether the GL scissor test clips viewport index `index`. The scissor rectangles start
|
||||
// all-zero, and all-zero there means "never written" (RenderState's constructor), not an
|
||||
// empty box: GL's initial box is the whole window, so until the application's first
|
||||
// glScissor an enabled test clips nothing. Read as a box it would clip EVERYTHING, so every
|
||||
// reader of the box asks this first. The resolution matches the viewport's (ComputeGLViewport
|
||||
// resolves a never-written viewport to the current framebuffer's extent).
|
||||
static Bool GLScissorTestClips(Uint32 index = 0) {
|
||||
const RenderStateParameters& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
const Uint32 bit = 1u << index;
|
||||
return (parameters.ScissorTestEnabledMask & bit) != 0 && (parameters.ScissorBoxWrittenMask & bit) != 0;
|
||||
}
|
||||
|
||||
static VkRect2D MakeClampedScissorRect(const IntVec4& scissorBox, const IntVec2& framebufferExtent) {
|
||||
const Int x0 = std::max<Int>(0, scissorBox.x());
|
||||
const Int y0 = std::max<Int>(0, scissorBox.y());
|
||||
@@ -3393,7 +3405,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkSurfaceTransformFlagBitsKHR preTransform,
|
||||
Bool isDefaultFbo) const {
|
||||
const auto& parameters = MG_Pipe::gPipeInputs.GetRenderStateParameters();
|
||||
if ((parameters.ScissorTestEnabledMask & (1u << index)) == 0) {
|
||||
if (!GLScissorTestClips(index)) {
|
||||
VkRect2D full{};
|
||||
full.offset = {0, 0};
|
||||
full.extent = {static_cast<Uint32>(extent.x()), static_cast<Uint32>(extent.y())};
|
||||
@@ -3515,7 +3527,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
key.stencilWriteMask[face] = p.StencilStates[face].WriteMask;
|
||||
key.stencilRef[face] = p.StencilStates[face].Ref;
|
||||
}
|
||||
key.scissorEnabled = (p.ScissorTestEnabledMask & 1u) != 0;
|
||||
key.scissorEnabled = GLScissorTestClips(0);
|
||||
key.scissorBox[0] = p.ScissorBoxes[0].x();
|
||||
key.scissorBox[1] = p.ScissorBoxes[0].y();
|
||||
key.scissorBox[2] = p.ScissorBoxes[0].z();
|
||||
|
||||
@@ -1046,7 +1046,7 @@
|
||||
if (count == 0) return remaining & ~handled;
|
||||
|
||||
VkRect2D area{{0, 0}, {key.width, key.height}};
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
if (GLScissorTestClips()) {
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const Int32 x0 = std::max(box.x(), 0), y0 = std::max(box.y(), 0);
|
||||
const Int32 x1 = std::min(box.x() + box.z(), static_cast<Int32>(key.width));
|
||||
|
||||
@@ -369,7 +369,7 @@
|
||||
const VkCommandBuffer passBuffer = active->commandBuffer;
|
||||
const Uint64 passHash = active->hash;
|
||||
VkRect2D area{{0, 0}, {key.width, key.height}};
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
if (GLScissorTestClips()) {
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const Int32 x0 = std::max(box.x(), 0), y0 = std::max(box.y(), 0);
|
||||
const Int32 x1 = std::min(box.x() + box.z(), static_cast<Int32>(key.width));
|
||||
@@ -469,7 +469,7 @@
|
||||
const ClearAttachmentPayload& payload, GLint drawbuffer) {
|
||||
GLbitfield remaining = payload.mask & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
if (!remaining || fbo.IsDefault || drawbuffer >= 0 || m_wirePreparationDepth != 0) return remaining;
|
||||
const Bool scissor = MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest);
|
||||
const Bool scissor = GLScissorTestClips();
|
||||
const auto wholeImage = [&](const WireImage& image) {
|
||||
if (!scissor) return true;
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
@@ -614,7 +614,7 @@
|
||||
if (!image.image) return;
|
||||
m_textureManager->FlushPendingUploads();
|
||||
VkRect2D area{{0, 0}, image.extent};
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
if (GLScissorTestClips()) {
|
||||
const auto& box = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const Int32 x0 = std::max(box.x(), 0), y0 = std::max(box.y(), 0);
|
||||
const Int32 x1 = std::min(box.x() + box.z(), static_cast<Int32>(image.extent.width));
|
||||
@@ -1263,7 +1263,7 @@
|
||||
RetireWireDrawPass();
|
||||
// The scissor test clips blit writes: intersect the destination rectangle with
|
||||
// the scissor box and shrink the source proportionally.
|
||||
if (MG_Pipe::gPipeInputs.IsCapabilityEnabled(CapabilityInput::ScissorTest)) {
|
||||
if (GLScissorTestClips()) {
|
||||
const IntVec4& scissor = MG_Pipe::gPipeInputs.GetScissorBox();
|
||||
const auto clipAxis = [](GLint& d0, GLint& d1, GLint& s0, GLint& s1, GLint clipLo, GLint clipHi) -> Bool {
|
||||
const Bool dstFlipped = d1 < d0;
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
// keeps the surface size in a memo that a swap, a change of draw surface, or a surface's creation
|
||||
// or destruction invalidates. This case makes a second, larger surface current on the same
|
||||
// context and clears it with the scissor test on: the clear must reach the larger surface's far
|
||||
// corner, which a size remembered from the first surface would cut off.
|
||||
// corner, which a size remembered from the first surface would cut off. DirectVulkan resolves a
|
||||
// never-written box to the whole framebuffer it draws into, so the same clear reaches the corner
|
||||
// there too (it used to read the all-zero box as an empty one and clear nothing).
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -36,7 +38,6 @@ class DefaultScissorFollowsSurfaceScenario : public ScenarioTest {};
|
||||
|
||||
TEST_F(DefaultScissorFollowsSurfaceScenario, AClearOnALargerSurfaceMadeCurrentReachesItsFarCorner) {
|
||||
if (!Ready() || IsSkipped()) return;
|
||||
if (Gl().BackendName() != "DirectGLES") GTEST_SKIP() << "the substituted scissor box is DirectGLES's";
|
||||
const EGLDisplay display = eglGetCurrentDisplay();
|
||||
const EGLSurface first = eglGetCurrentSurface(EGL_DRAW);
|
||||
const EGLContext context = eglGetCurrentContext();
|
||||
|
||||
Reference in New Issue
Block a user