mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix, Test] (GLState, ShaderTranspiler): reject a storage-block binding at or past GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "ShaderCompileTask.h"
|
||||
|
||||
#include <MG_State/GLState/BufferState/BufferState.h>
|
||||
#include <MG_Util/Converters/MGToGL/ProgramEnumConverter.h>
|
||||
#include <MG_Util/ShaderTranspiler/ShaderCompiler.h>
|
||||
#include <MG_Util/ShaderTranspiler/ShaderSourceProcessor.h>
|
||||
@@ -15,6 +16,7 @@
|
||||
|
||||
#include <glslang/Include/PoolAlloc.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <charconv>
|
||||
|
||||
namespace {
|
||||
@@ -137,8 +139,21 @@ namespace {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// What glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS) answers, recomputed rather than
|
||||
// queried: the compile runs on a worker with no context, and the pname is not a plain backend
|
||||
// parameter - the getter caps the backend's count by the state layer's fixed binding-point
|
||||
// array (GL_Getter's GetIndexedBufferQueryPointCount). A shader must be judged against the
|
||||
// number the application was told, not against either half of it.
|
||||
static MobileGL::Int MaxShaderStorageBufferBindings(
|
||||
const MobileGL::MG_Util::ShaderTranspiler::CompileEnv& env) {
|
||||
const MobileGL::Int frontendPoints =
|
||||
static_cast<MobileGL::Int>(MobileGL::MG_State::GLState::BufferBindingPointCount);
|
||||
if (!env.HasBackend()) return frontendPoints;
|
||||
return std::min(frontendPoints, std::max(env.params.MaxShaderStorageBufferBindings, 0));
|
||||
}
|
||||
|
||||
// The half of a compile that depends on nothing but the source text, the stage and the
|
||||
// environment snapshot: preprocessing, the two lexical rejections, and the two lexical
|
||||
// environment snapshot: preprocessing, the three lexical rejections, and the two lexical
|
||||
// side-channel extractions. Split out so P0b layer 2 can memoize exactly this and
|
||||
// nothing else - the glslang parse stays per-object because its TShader is consume-once.
|
||||
// Deliberately free of any per-object state so the memo is sound.
|
||||
@@ -172,6 +187,13 @@ namespace {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (const std::optional<String> bindingError = FindShaderStorageBindingViolation(
|
||||
result.preprocessedSource, MaxShaderStorageBufferBindings(env))) {
|
||||
result.outcome = ShaderPreprocessOutcome::ResourceBindingRejected;
|
||||
result.infoLog = *bindingError;
|
||||
return result;
|
||||
}
|
||||
|
||||
// The parse this feeds runs in the link-compatible configuration (Vulkan-client
|
||||
// env with relaxed rules): the TShader it produces is what glLinkProgram links and
|
||||
// what the backends' SPIR-V is generated from - there is no second, GL-client
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace MobileGL::MG_State::GLState {
|
||||
ComputeLocalSizeRejected,
|
||||
// FindReservedIdentifierViolation rejected it.
|
||||
ReservedIdentifierRejected,
|
||||
// FindShaderStorageBindingViolation rejected it: a storage block declared a binding at or
|
||||
// past GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS.
|
||||
ResourceBindingRejected,
|
||||
// The source-only half was clean but glslang rejected the preprocessed source.
|
||||
// Memoizing this saves the parse itself on every later object with that source.
|
||||
ParseFailed,
|
||||
|
||||
Reference in New Issue
Block a user