mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +09:00
glVertexAttribLFormat validated its arguments and then refused unconditionally with "64-bit vertex attributes are not supported", so direct_state_access.vertex_arrays_attribute_format failed every GL_DOUBLE subcase on both backends - the format never landed, the draw fetched whatever the attribute held before, and the captured values came back as reinterpreted garbage. The attribute is now real state. IsLong is its own bit rather than being inferred from Float64, because glVertexAttribFormat(GL_DOUBLE) also reads doubles - it just asks for them converted to float - so the type alone cannot tell the two apart. It participates in the format comparison, so an L-format call over a plain one still bumps the version, and glVertexAttribPointer clears it inside the mutation block so the clear and the bump stay atomic. GL_VERTEX_ATTRIB_ARRAY_LONG stops being hardcoded false, and the pname is now accepted by the attribute queries at all. Support is detected, never assumed. SupportsFloat64VertexAttributes comes from VkPhysicalDeviceFeatures::shaderFloat64 on DirectVulkan and is false on DirectGLES - not a driver question there and never will be, since ES has no GL_DOUBLE vertex format and ESSL has no fp64 type to consume one with. A backend without it declines in the entry point, with the GL error and a log line naming the reason, rather than accepting state no draw could honour. Both cases get a DriverPost row so the loss is named at startup instead of at draw setup. On DirectVulkan the attribute deliberately does not use VK_FORMAT_R64*_SFLOAT: those are optional and lavapipe advertises zero features for all four of them. It is fetched as its 32-bit word pair (R32G32_UINT / R32G32B32A32_UINT) and bitcast back to double in the shader by a new SPIR-V pass, which is bit-exact and needs no format capability at all. The pass re-declares the input as uvec2 / uvec4, demotes the original variable to a Private global and seeds it once at the top of the entry point, so every existing load keeps its id and its double type and no other instruction is rewritten. Both halves branch on nothing but "is this attribute long", so they cannot disagree - and if the pass ever fails, the assertion fires rather than letting a UINT format sit under a double input. The pointer types are all created before any variable that names them and the demoted variable is moved after them, since the types-and-variables section may not forward-reference a type. dvec3/dvec4 are declined rather than fetched wrong: six or eight uint32 components have no single VkFormat, and GL spreads such an input over two attribute locations, which the location-per-index model here does not express. Fixes vertex_arrays_attribute_format on Magma (369/371). On Espryt it stays failing, now as a detected and explained decline rather than a blanket refusal.
44 lines
2.2 KiB
C++
44 lines
2.2 KiB
C++
// MobileGL - MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/PackDoubleVertexInputsPass.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 "source/opt/pass.h"
|
|
#include "spirv-tools/optimizer.hpp"
|
|
|
|
#include <Includes.h>
|
|
|
|
namespace MobileGL {
|
|
namespace MG_Util {
|
|
namespace ShaderTranspiler {
|
|
// Re-declares every 64-bit floating-point *vertex input* as the 32-bit unsigned word
|
|
// pair that holds the same bytes (double -> uvec2, dvec2 -> uvec4), demotes the
|
|
// original variable to a Private global, and seeds it once at the top of the entry
|
|
// point with an OpBitcast of the new input. Everything downstream keeps loading the
|
|
// same id and the same double type, so no other instruction is rewritten.
|
|
//
|
|
// Why not just use VK_FORMAT_R64*_SFLOAT: those formats are optional, and lavapipe
|
|
// reports zero bufferFeatures for all four of them, so a 64-bit vertex fetch is
|
|
// impossible there even though shaderFloat64 is supported. The word-pair form needs no
|
|
// format capability at all and is bit-exact, so it is applied unconditionally rather
|
|
// than as a fallback - which also keeps it in lockstep with
|
|
// VertexInputStateFactory::ToVkVertexFormat, since both branch on nothing but "is this
|
|
// a 64-bit vertex input".
|
|
//
|
|
// DirectVulkan only. The 64-bit *arithmetic* still needs the Float64 capability, i.e.
|
|
// an enabled VkPhysicalDeviceFeatures::shaderFloat64.
|
|
class PackDoubleVertexInputsPass : public spvtools::opt::Pass {
|
|
public:
|
|
const char* name() const override { return "mobilegl-pack-double-vertex-inputs"; }
|
|
Status Process() override;
|
|
|
|
static spvtools::Optimizer::PassToken CreatePackDoubleVertexInputsPass();
|
|
};
|
|
} // namespace ShaderTranspiler
|
|
} // namespace MG_Util
|
|
} // namespace MobileGL
|