mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[MG_Backend, MG_Test] (P7): resolve multisample depth/stencil with the shader arm first on Qualcomm
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
#include <MG_Impl/Pipe/SlotAllocator.h>
|
||||
// P7 wave 2 package B3: rule I's tally for WireDraw.inc's silent draw drops.
|
||||
#include "WireDeclineTally.h"
|
||||
#include "WireDepthResolveArm.h"
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
@@ -15147,6 +15148,14 @@ void main() {
|
||||
if (m_wireShaderStencilExport)
|
||||
EnableOptionalDeviceExtension(availableExtensions, enabledDeviceExtensions,
|
||||
VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
|
||||
// P7 gate 5 (g5-msrbo): the Adreno's no-draw depth/stencil resolve pass writes nothing,
|
||||
// so the shader resolve goes first there (WireDepthResolveArm.h says why and where).
|
||||
m_wirePreferShaderDepthResolve = MG_Config::Transport != MG_Config::TransportMode::Monolith &&
|
||||
WirePrefersShaderDepthResolve(m_physicalDevice.properties.vendorID);
|
||||
if (m_wirePreferShaderDepthResolve)
|
||||
MGLOG_I("DirectVulkan: vendor 0x%x - the wire arm resolves multisample depth/stencil with the "
|
||||
"shader pass first (the no-draw resolve render pass is the fallback)",
|
||||
m_physicalDevice.properties.vendorID);
|
||||
#endif
|
||||
if ((descriptorIndexingCore || descriptorIndexingExtension) && getPhysicalDeviceFeatures2 != nullptr &&
|
||||
getPhysicalDeviceProperties2 != nullptr) {
|
||||
|
||||
@@ -556,6 +556,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
WireMultisampleResolveResources* m_wireMultisampleResolveResources = nullptr;
|
||||
void DestroyWireMultisampleResolveResources();
|
||||
Bool m_wireShaderStencilExport = false;
|
||||
// WirePrefersShaderDepthResolve(vendorID) for this device (WireDepthResolveArm.h): the
|
||||
// shader arm resolves first, the render-pass arm is the fallback (P7 gate 5).
|
||||
Bool m_wirePreferShaderDepthResolve = false;
|
||||
Bool BlitWireColorToDefault(WireImage source, WireImage destination,
|
||||
GLint sx0, GLint sy0, GLint sx1, GLint sy1,
|
||||
GLint dx0, GLint dy0, GLint dx1, GLint dy1, GLenum filter);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/WireDepthResolveArm.h
|
||||
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||
// Licensed under the GNU Lesser General Public License v3.0:
|
||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
// End of Source File Header
|
||||
#pragma once
|
||||
|
||||
#include <Includes.h>
|
||||
|
||||
// P7 gate 5 (g5-msrbo): WHICH ARM RESOLVES A MULTISAMPLE DEPTH/STENCIL ASPECT FIRST.
|
||||
//
|
||||
// The wire arm has two (WireFramebuffer.inc, ResolveWireDepthStencil): a render pass that carries
|
||||
// a VK_KHR_depth_stencil_resolve attachment and no draw, and the baked shader pass of
|
||||
// WireMultisampleResolve.inc, which draws. P7 wave 2-B2 took the render pass wherever the
|
||||
// extension exists. On the Redmi (Adreno 830, Vulkan 1.3.284, driver 512.800.71) that pass left
|
||||
// its resolve target unwritten - KHR-GL46.direct_state_access.renderbuffers_storage_multisample
|
||||
// read every resolved depth and stencil value back as 0 on the inproc arm while the monolith arm
|
||||
// passed, and the same case passed on the device with the shader arm forced
|
||||
// (MGITEST_MAGMA_FORCE_SHADER_DEPTH_RESOLVE=1). So on a Qualcomm device the shader arm goes first;
|
||||
// the render pass stays the fallback for what the shader cannot write (a stencil aspect without
|
||||
// VK_EXT_shader_stencil_export). Every other vendor keeps B2's order: nothing measured says
|
||||
// otherwise, and a vendor list that grew on a guess would be the same mistake the other way round.
|
||||
//
|
||||
// A pure function of the vendor id so the policy is a unit-testable fact rather than a branch
|
||||
// buried in the apply thread.
|
||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
inline constexpr Uint32 kWireVendorIdQualcomm = 0x5143u;
|
||||
|
||||
inline constexpr Bool WirePrefersShaderDepthResolve(Uint32 vendorId) {
|
||||
return vendorId == kWireVendorIdQualcomm;
|
||||
}
|
||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||
@@ -723,7 +723,22 @@
|
||||
VkImageView views[2]{};
|
||||
VkRenderPass pass = VK_NULL_HANDLE;
|
||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||
if (extensionResolve) {
|
||||
// P7 gate 5 (g5-msrbo): WHERE THE EXTENSION ARM IS KNOWN NOT TO RESOLVE, THE SHADER ARM
|
||||
// GOES FIRST. The extension arm is a render pass with no draw in it, and on the Redmi
|
||||
// (Adreno 830, driver 512.800.71) that pass left the resolve target unwritten:
|
||||
// KHR-GL46.direct_state_access.renderbuffers_storage_multisample read every resolved depth
|
||||
// and stencil value back as 0 on the inproc arm - exactly its samples 2/4/4 iterations,
|
||||
// every format - and the same case PASSED on that device with
|
||||
// MGITEST_MAGMA_FORCE_SHADER_DEPTH_RESOLVE=1. The shader arm draws, so nothing about it
|
||||
// can be elided. It still declines what it cannot express (a stencil aspect without
|
||||
// VK_EXT_shader_stencil_export), and then the extension arm is the fallback rather than
|
||||
// a decline. m_wirePreferShaderDepthResolve is WirePrefersShaderDepthResolve's answer for
|
||||
// this device (WireDepthResolveArm.h); everywhere else the order is the one B2 chose.
|
||||
const Bool shaderFirst = m_wirePreferShaderDepthResolve || !extensionResolve;
|
||||
const Bool resolvedByShader =
|
||||
shaderFirst && ResolveWireDepthStencilWithShader(source, resolved, source.aspect, sxMin, syMin,
|
||||
static_cast<Uint32>(width), static_cast<Uint32>(height));
|
||||
if (!resolvedByShader && extensionResolve) {
|
||||
TransitionWireImage(source, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
TransitionWireImage(resolved, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
@@ -780,8 +795,7 @@
|
||||
begin.renderArea = {{sxMin, syMin}, {static_cast<Uint32>(width), static_cast<Uint32>(height)}};
|
||||
vkCmdBeginRenderPass(m_frameContext.GetCurrent().commandBuffer, &begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdEndRenderPass(m_frameContext.GetCurrent().commandBuffer);
|
||||
} else if (!ResolveWireDepthStencilWithShader(source, resolved, source.aspect, sxMin, syMin,
|
||||
static_cast<Uint32>(width), static_cast<Uint32>(height))) {
|
||||
} else if (!resolvedByShader) {
|
||||
// NEITHER ARM, and rule I (a) says what that is: this device has no
|
||||
// VK_KHR_depth_stencil_resolve and the pass cannot stand in for it either - the
|
||||
// commonest reason being a stencil-only resolve without VK_EXT_shader_stencil_export,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <MG_Backend/DirectVulkan/Renderer/ProgramFactory.h>
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
#include <MG_Backend/DirectVulkan/Renderer/WireRenderPassCompatibility.h>
|
||||
#include <MG_Backend/DirectVulkan/Renderer/WireDepthResolveArm.h>
|
||||
#endif
|
||||
|
||||
using namespace MobileGL;
|
||||
@@ -515,3 +516,20 @@ TEST(WirePipelineCompatibility, HashUsesCompatibilityIdentityAndSeparatesNativeD
|
||||
GTEST_SKIP() << "wire pipeline compatibility requires disaggregated build";
|
||||
#endif
|
||||
}
|
||||
|
||||
// P7 gate 5 (g5-msrbo): the multisample depth/stencil resolve's arm order. On the Redmi (Adreno
|
||||
// 830) the no-draw VK_KHR_depth_stencil_resolve render pass left its target unwritten and the
|
||||
// shader arm resolved correctly, so a Qualcomm device takes the shader arm first; every other
|
||||
// vendor keeps P7 wave 2-B2's order (render pass first) until a device says otherwise.
|
||||
TEST(PipelineQuirkTest, WireDepthResolvePrefersTheShaderArmOnQualcommOnly) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
using MobileGL::MG_Backend::DirectVulkan::WirePrefersShaderDepthResolve;
|
||||
EXPECT_TRUE(WirePrefersShaderDepthResolve(kVendorIdQualcomm))
|
||||
<< "the Adreno's no-draw resolve pass wrote nothing; the shader arm must go first there";
|
||||
EXPECT_FALSE(WirePrefersShaderDepthResolve(kVendorIdArm));
|
||||
EXPECT_FALSE(WirePrefersShaderDepthResolve(0x10005u)) << "Mesa (lavapipe) keeps the render-pass arm first";
|
||||
EXPECT_FALSE(WirePrefersShaderDepthResolve(0x10DEu));
|
||||
#else
|
||||
GTEST_SKIP() << "the wire resolve arms exist only in the disaggregated build";
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user