mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (GL): report tessellation-stage image uniform limits from the backend and enforce them at link
This commit is contained in:
@@ -411,6 +411,8 @@ namespace MobileGL {
|
||||
Int MaxImageUnits = 8;
|
||||
Int MaxCombinedImageUniforms = 8;
|
||||
Int MaxVertexImageUniforms = 0;
|
||||
Int MaxTessControlImageUniforms = 0;
|
||||
Int MaxTessEvaluationImageUniforms = 0;
|
||||
Int MaxGeometryImageUniforms = 0;
|
||||
Int MaxFragmentImageUniforms = 8;
|
||||
Int MaxComputeImageUniforms = 8;
|
||||
|
||||
@@ -1820,6 +1820,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
m_dynamicParameters.MaxCombinedImageUniforms});
|
||||
};
|
||||
m_dynamicParameters.MaxVertexImageUniforms = clampStageImageUniforms(m_GLESCapabilities.MaxVertexImageUniforms);
|
||||
m_dynamicParameters.MaxTessControlImageUniforms =
|
||||
clampStageImageUniforms(m_GLESCapabilities.MaxTessControlImageUniforms);
|
||||
m_dynamicParameters.MaxTessEvaluationImageUniforms =
|
||||
clampStageImageUniforms(m_GLESCapabilities.MaxTessEvaluationImageUniforms);
|
||||
m_dynamicParameters.MaxGeometryImageUniforms =
|
||||
clampStageImageUniforms(m_GLESCapabilities.MaxGeometryImageUniforms);
|
||||
m_dynamicParameters.MaxFragmentImageUniforms =
|
||||
|
||||
@@ -11188,6 +11188,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
[[maybe_unused]] Int AdvertisedStageImageUniformLimit(ShaderStage stage) {
|
||||
switch (stage) {
|
||||
case ShaderStage::Vertex: return g_GLESCapabilities.MaxVertexImageUniforms;
|
||||
case ShaderStage::TessControl: return g_GLESCapabilities.MaxTessControlImageUniforms;
|
||||
case ShaderStage::TessEval: return g_GLESCapabilities.MaxTessEvaluationImageUniforms;
|
||||
case ShaderStage::Geometry: return g_GLESCapabilities.MaxGeometryImageUniforms;
|
||||
case ShaderStage::Fragment: return g_GLESCapabilities.MaxFragmentImageUniforms;
|
||||
case ShaderStage::Compute: return g_GLESCapabilities.MaxComputeImageUniforms;
|
||||
|
||||
@@ -1281,6 +1281,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// device reports it, so these are the exact limits the logical device can compile and run.
|
||||
m_dynamicParameters.MaxVertexImageUniforms =
|
||||
m_vulkanCaps.SupportsVertexPipelineStoresAndAtomics ? maxPerStageImageUniforms : 0;
|
||||
// The tessellation stages are vertex-pipeline stages too, so the same feature gates them.
|
||||
m_dynamicParameters.MaxTessControlImageUniforms = m_dynamicParameters.MaxVertexImageUniforms;
|
||||
m_dynamicParameters.MaxTessEvaluationImageUniforms = m_dynamicParameters.MaxVertexImageUniforms;
|
||||
m_dynamicParameters.MaxGeometryImageUniforms =
|
||||
m_vulkanCaps.SupportsVertexPipelineStoresAndAtomics && m_vulkanCaps.SupportsGeometryShader
|
||||
? maxPerStageImageUniforms
|
||||
|
||||
@@ -2195,10 +2195,14 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
*params = kFrontendMaxTessEvaluationAtomicCounterBuffers;
|
||||
return;
|
||||
case GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS:
|
||||
*params = 0;
|
||||
*params = MG_Backend::pActiveBackendObject
|
||||
? MG_Backend::pActiveBackendObject->GetDynamicParameters().MaxTessControlImageUniforms
|
||||
: MG_Backend::DynamicBackendParameters{}.MaxTessControlImageUniforms;
|
||||
return;
|
||||
case GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS:
|
||||
*params = 0;
|
||||
*params = MG_Backend::pActiveBackendObject
|
||||
? MG_Backend::pActiveBackendObject->GetDynamicParameters().MaxTessEvaluationImageUniforms
|
||||
: MG_Backend::DynamicBackendParameters{}.MaxTessEvaluationImageUniforms;
|
||||
return;
|
||||
case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS:
|
||||
*params = StageStorageBlockCount(&MG_Backend::DynamicBackendParameters::MaxTessControlShaderStorageBlocks);
|
||||
|
||||
@@ -379,6 +379,7 @@
|
||||
F(MaxComputeWorkGroupCount) F(MaxComputeWorkGroupSize) F(MaxShaderStorageBufferBindings) \
|
||||
F(MaxTextureBufferSize) F(TextureBufferOffsetAlignment) F(MaxUniformBufferBindings) \
|
||||
F(MaxUniformBlockSize) F(MaxImageUnits) F(MaxCombinedImageUniforms) F(MaxVertexImageUniforms) \
|
||||
F(MaxTessControlImageUniforms) F(MaxTessEvaluationImageUniforms) \
|
||||
F(MaxGeometryImageUniforms) F(MaxFragmentImageUniforms) F(MaxComputeImageUniforms) \
|
||||
F(MaxDrawBuffers) F(MaxColorAttachments) F(MaxClipDistances) F(MaxCullDistances) \
|
||||
F(MaxCombinedClipAndCullDistances) F(MaxViewports) F(LayerProvokingVertex) \
|
||||
|
||||
@@ -632,6 +632,8 @@ inline constexpr WireLayoutMember kMGPipeWireLayoutMembers[] = {
|
||||
{"DynamicBackendParameters.MaxImageUnits", offsetof(DynamicBackendParameters, MaxImageUnits), sizeof(((DynamicBackendParameters*)nullptr)->MaxImageUnits)},
|
||||
{"DynamicBackendParameters.MaxCombinedImageUniforms", offsetof(DynamicBackendParameters, MaxCombinedImageUniforms), sizeof(((DynamicBackendParameters*)nullptr)->MaxCombinedImageUniforms)},
|
||||
{"DynamicBackendParameters.MaxVertexImageUniforms", offsetof(DynamicBackendParameters, MaxVertexImageUniforms), sizeof(((DynamicBackendParameters*)nullptr)->MaxVertexImageUniforms)},
|
||||
{"DynamicBackendParameters.MaxTessControlImageUniforms", offsetof(DynamicBackendParameters, MaxTessControlImageUniforms), sizeof(((DynamicBackendParameters*)nullptr)->MaxTessControlImageUniforms)},
|
||||
{"DynamicBackendParameters.MaxTessEvaluationImageUniforms", offsetof(DynamicBackendParameters, MaxTessEvaluationImageUniforms), sizeof(((DynamicBackendParameters*)nullptr)->MaxTessEvaluationImageUniforms)},
|
||||
{"DynamicBackendParameters.MaxGeometryImageUniforms", offsetof(DynamicBackendParameters, MaxGeometryImageUniforms), sizeof(((DynamicBackendParameters*)nullptr)->MaxGeometryImageUniforms)},
|
||||
{"DynamicBackendParameters.MaxFragmentImageUniforms", offsetof(DynamicBackendParameters, MaxFragmentImageUniforms), sizeof(((DynamicBackendParameters*)nullptr)->MaxFragmentImageUniforms)},
|
||||
{"DynamicBackendParameters.MaxComputeImageUniforms", offsetof(DynamicBackendParameters, MaxComputeImageUniforms), sizeof(((DynamicBackendParameters*)nullptr)->MaxComputeImageUniforms)},
|
||||
|
||||
@@ -255,9 +255,9 @@ namespace {
|
||||
// its linker never counts uniforms against them - so a program declaring one image uniform
|
||||
// more than the limit linked cleanly and then rendered nothing.
|
||||
//
|
||||
// The limits are the ones glGetIntegerv answers (MG_Impl/GLImpl/Getter/GL_Getter.cpp), the
|
||||
// hardcoded tessellation zeros included: a program may not exceed a limit the implementation
|
||||
// advertises, whatever the driver underneath would have taken.
|
||||
// The limits are the ones glGetIntegerv answers (MG_Impl/GLImpl/Getter/GL_Getter.cpp): a
|
||||
// program may not exceed a limit the implementation advertises, whatever the driver
|
||||
// underneath would have taken.
|
||||
//
|
||||
// Counts the APPLICATION's image uniforms. The DirectGLES read/write split emits a second
|
||||
// declaration for an image a stage both reads and writes (MG_Backend/DirectGLES/Utils.h), but
|
||||
@@ -279,8 +279,8 @@ namespace {
|
||||
"GL_MAX_FRAGMENT_IMAGE_UNIFORMS", "GL_MAX_COMPUTE_IMAGE_UNIFORMS"};
|
||||
constexpr SizeT kStageCount = sizeof(kStages) / sizeof(kStages[0]);
|
||||
const Int limits[kStageCount] = {env.params.MaxVertexImageUniforms,
|
||||
0,
|
||||
0,
|
||||
env.params.MaxTessControlImageUniforms,
|
||||
env.params.MaxTessEvaluationImageUniforms,
|
||||
env.params.MaxGeometryImageUniforms,
|
||||
env.params.MaxFragmentImageUniforms,
|
||||
env.params.MaxComputeImageUniforms};
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace {
|
||||
GLint glesMinorVersion = 1;
|
||||
GLint maxVertexImageUniforms = 2;
|
||||
GLint maxGeometryImageUniforms = 3;
|
||||
GLint maxTessControlImageUniforms = 6;
|
||||
GLint maxTessEvaluationImageUniforms = 7;
|
||||
GLint maxFragmentImageUniforms = 4;
|
||||
GLint maxComputeImageUniforms = 5;
|
||||
bool maxGeometryImageUniformsQueried = false;
|
||||
@@ -194,6 +196,14 @@ namespace {
|
||||
g_fake.maxGeometryImageUniformsQueried = true;
|
||||
*data = g_fake.maxGeometryImageUniforms;
|
||||
break;
|
||||
case GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS:
|
||||
g_fake.maxGeometryImageUniformsQueried = true;
|
||||
*data = g_fake.maxTessControlImageUniforms;
|
||||
break;
|
||||
case GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS:
|
||||
g_fake.maxGeometryImageUniformsQueried = true;
|
||||
*data = g_fake.maxTessEvaluationImageUniforms;
|
||||
break;
|
||||
case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
|
||||
*data = g_fake.maxFragmentImageUniforms;
|
||||
break;
|
||||
@@ -689,6 +699,8 @@ TEST(ImageUniformCapabilities, QueriesRealPerStageLimitsAndConservativelyGatesGe
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(es31Caps, funcs));
|
||||
EXPECT_EQ(es31Caps.MaxVertexImageUniforms, g_fake.maxVertexImageUniforms);
|
||||
EXPECT_EQ(es31Caps.MaxGeometryImageUniforms, 0);
|
||||
EXPECT_EQ(es31Caps.MaxTessControlImageUniforms, 0);
|
||||
EXPECT_EQ(es31Caps.MaxTessEvaluationImageUniforms, 0);
|
||||
EXPECT_EQ(es31Caps.MaxFragmentImageUniforms, g_fake.maxFragmentImageUniforms);
|
||||
EXPECT_EQ(es31Caps.MaxComputeImageUniforms, g_fake.maxComputeImageUniforms);
|
||||
EXPECT_FALSE(g_fake.maxGeometryImageUniformsQueried);
|
||||
@@ -700,6 +712,8 @@ TEST(ImageUniformCapabilities, QueriesRealPerStageLimitsAndConservativelyGatesGe
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(es32Caps, funcs));
|
||||
EXPECT_EQ(es32Caps.MaxVertexImageUniforms, g_fake.maxVertexImageUniforms);
|
||||
EXPECT_EQ(es32Caps.MaxGeometryImageUniforms, g_fake.maxGeometryImageUniforms);
|
||||
EXPECT_EQ(es32Caps.MaxTessControlImageUniforms, g_fake.maxTessControlImageUniforms);
|
||||
EXPECT_EQ(es32Caps.MaxTessEvaluationImageUniforms, g_fake.maxTessEvaluationImageUniforms);
|
||||
EXPECT_EQ(es32Caps.MaxFragmentImageUniforms, g_fake.maxFragmentImageUniforms);
|
||||
EXPECT_EQ(es32Caps.MaxComputeImageUniforms, g_fake.maxComputeImageUniforms);
|
||||
EXPECT_TRUE(g_fake.maxGeometryImageUniformsQueried);
|
||||
|
||||
@@ -951,6 +951,71 @@ void main() {
|
||||
}
|
||||
}
|
||||
|
||||
// The same rule for the tessellation stages, whose limits come from the backend like the
|
||||
// others (they used to be hard-coded zeros). Sized off the advertised limit for the same
|
||||
// reason as above: one image over it must fail and name the limit, and exactly at it must
|
||||
// link whenever the limit is non-zero.
|
||||
TEST_F(ProgramInterfaceTest, TessellationImageUniformsAreCheckedAgainstTheirOwnLimit) {
|
||||
GLint maxTesImages = -1;
|
||||
GetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &maxTesImages);
|
||||
ASSERT_EQ(TakeError(), GL_NO_ERROR);
|
||||
ASSERT_GE(maxTesImages, 0);
|
||||
|
||||
const auto linkWithTesImages = [](GLint count) {
|
||||
const std::string n = std::to_string(count);
|
||||
const std::string tcs = R"(#version 430
|
||||
layout(vertices = 3) out;
|
||||
void main() {
|
||||
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
|
||||
gl_TessLevelOuter[0] = 1.0; gl_TessLevelOuter[1] = 1.0; gl_TessLevelOuter[2] = 1.0;
|
||||
gl_TessLevelInner[0] = 1.0;
|
||||
}
|
||||
)";
|
||||
const std::string tes = std::string(R"(#version 430
|
||||
layout(triangles) in;
|
||||
layout(r32i) uniform iimage2D u_tesImage[)") + n + R"(];
|
||||
void main() {
|
||||
int value = 1;
|
||||
for (int i = 0; i < )" + n + R"(; ++i) {
|
||||
value = imageAtomicAdd(u_tesImage[i], ivec2(0), value);
|
||||
}
|
||||
gl_Position = gl_in[0].gl_Position * float(value);
|
||||
}
|
||||
)";
|
||||
const GLuint program = CreateProgram();
|
||||
const auto attach = [program](GLenum stage, const char* source) {
|
||||
const GLuint sh = CreateShader(stage);
|
||||
ShaderSource(sh, 1, &source, nullptr);
|
||||
CompileShader(sh);
|
||||
GLint compiled = 0;
|
||||
GetShaderiv(sh, GL_COMPILE_STATUS, &compiled);
|
||||
EXPECT_EQ(compiled, GL_TRUE) << "stage " << stage << " must compile";
|
||||
AttachShader(program, sh);
|
||||
};
|
||||
attach(GL_VERTEX_SHADER, kSimpleVs);
|
||||
attach(GL_TESS_CONTROL_SHADER, tcs.c_str());
|
||||
attach(GL_TESS_EVALUATION_SHADER, tes.c_str());
|
||||
attach(GL_FRAGMENT_SHADER, kSimpleFs);
|
||||
LinkProgram(program);
|
||||
return program;
|
||||
};
|
||||
|
||||
const GLuint over = linkWithTesImages(maxTesImages + 1);
|
||||
GLint status = -1;
|
||||
GetProgramiv(over, GL_LINK_STATUS, &status);
|
||||
EXPECT_EQ(status, GL_FALSE);
|
||||
char log[4096] = "";
|
||||
GetProgramInfoLog(over, sizeof(log), nullptr, log);
|
||||
EXPECT_NE(std::string(log).find("GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"), std::string::npos)
|
||||
<< "info log was: " << log;
|
||||
ClearErrors();
|
||||
|
||||
if (maxTesImages > 0) {
|
||||
ExpectLinked(linkWithTesImages(maxTesImages));
|
||||
ClearErrors();
|
||||
}
|
||||
}
|
||||
|
||||
// Uniform blocks are counted the same way, and the synthesized block that carries the
|
||||
// default-block uniforms is not one of them.
|
||||
TEST_F(ProgramInterfaceTest, UniformBlocksOverAStageLimitFailToLink) {
|
||||
|
||||
@@ -664,6 +664,8 @@ TEST(DirectVulkanSanity, GatesPerStageImageUniformLimitsOnPhysicalDeviceFeatures
|
||||
|
||||
const auto& withoutGeometry = backend.GetDynamicParameters();
|
||||
EXPECT_EQ(withoutGeometry.MaxVertexImageUniforms, 10);
|
||||
EXPECT_EQ(withoutGeometry.MaxTessControlImageUniforms, 10);
|
||||
EXPECT_EQ(withoutGeometry.MaxTessEvaluationImageUniforms, 10);
|
||||
EXPECT_EQ(withoutGeometry.MaxGeometryImageUniforms, 0);
|
||||
EXPECT_EQ(withoutGeometry.MaxFragmentImageUniforms, 10);
|
||||
EXPECT_EQ(withoutGeometry.MaxComputeImageUniforms, 9);
|
||||
@@ -676,6 +678,8 @@ TEST(DirectVulkanSanity, GatesPerStageImageUniformLimitsOnPhysicalDeviceFeatures
|
||||
caps.SupportsFragmentStoresAndAtomics = false;
|
||||
backend.ApplyVulkanCapabilitiesForTesting(caps);
|
||||
EXPECT_EQ(backend.GetDynamicParameters().MaxVertexImageUniforms, 0);
|
||||
EXPECT_EQ(backend.GetDynamicParameters().MaxTessControlImageUniforms, 0);
|
||||
EXPECT_EQ(backend.GetDynamicParameters().MaxTessEvaluationImageUniforms, 0);
|
||||
EXPECT_EQ(backend.GetDynamicParameters().MaxGeometryImageUniforms, 0);
|
||||
EXPECT_EQ(backend.GetDynamicParameters().MaxFragmentImageUniforms, 0);
|
||||
EXPECT_EQ(backend.GetDynamicParameters().MaxComputeImageUniforms, 9);
|
||||
@@ -689,6 +693,8 @@ TEST(DirectGLESSanity, PreservesHostPerStageImageUniformLimits) {
|
||||
caps.MaxImageUnits = 8;
|
||||
caps.MaxCombinedImageUniforms = 16;
|
||||
caps.MaxVertexImageUniforms = 2;
|
||||
caps.MaxTessControlImageUniforms = 6;
|
||||
caps.MaxTessEvaluationImageUniforms = 7;
|
||||
caps.MaxGeometryImageUniforms = 3;
|
||||
caps.MaxFragmentImageUniforms = 4;
|
||||
caps.MaxComputeImageUniforms = 5;
|
||||
@@ -696,6 +702,8 @@ TEST(DirectGLESSanity, PreservesHostPerStageImageUniformLimits) {
|
||||
|
||||
const auto& params = backend.GetDynamicParameters();
|
||||
EXPECT_EQ(params.MaxVertexImageUniforms, 2);
|
||||
EXPECT_EQ(params.MaxTessControlImageUniforms, 6);
|
||||
EXPECT_EQ(params.MaxTessEvaluationImageUniforms, 7);
|
||||
EXPECT_EQ(params.MaxGeometryImageUniforms, 3);
|
||||
EXPECT_EQ(params.MaxFragmentImageUniforms, 4);
|
||||
EXPECT_EQ(params.MaxComputeImageUniforms, 5);
|
||||
@@ -1095,6 +1103,8 @@ TEST(GetterSanity, PerStageImageUniformQueriesMatchShaderCompilerLimits) {
|
||||
params.MaxImageUnits = 8;
|
||||
params.MaxCombinedImageUniforms = 8;
|
||||
params.MaxVertexImageUniforms = 1;
|
||||
params.MaxTessControlImageUniforms = 5;
|
||||
params.MaxTessEvaluationImageUniforms = 6;
|
||||
params.MaxGeometryImageUniforms = 2;
|
||||
params.MaxFragmentImageUniforms = 3;
|
||||
params.MaxComputeImageUniforms = 4;
|
||||
@@ -1103,6 +1113,10 @@ TEST(GetterSanity, PerStageImageUniformQueriesMatchShaderCompilerLimits) {
|
||||
GLint reported = -1;
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &reported);
|
||||
EXPECT_EQ(reported, 1);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &reported);
|
||||
EXPECT_EQ(reported, 5);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &reported);
|
||||
EXPECT_EQ(reported, 6);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &reported);
|
||||
EXPECT_EQ(reported, 2);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &reported);
|
||||
@@ -1308,8 +1322,17 @@ TEST(GetterSanity, EveryLimitWithABuiltinAgreesWithItsQuery) {
|
||||
auto previousContext = MG_State::pGLContext.Take();
|
||||
auto previousBackend = Move(MG_Backend::pActiveBackendObject);
|
||||
MG_State::pGLContext = MakeUnique<MG_State::GLState::GLContext>();
|
||||
MG_Backend::pActiveBackendObject =
|
||||
MakeUnique<DynamicParameterBackend>(MG_Backend::DynamicBackendParameters{}, BackendType::DirectGLES);
|
||||
// Distinct non-zero image-uniform limits, so the per-stage pairs below cannot agree by both
|
||||
// falling back to the same default.
|
||||
MG_Backend::DynamicBackendParameters params;
|
||||
params.MaxVertexImageUniforms = 1;
|
||||
params.MaxTessControlImageUniforms = 2;
|
||||
params.MaxTessEvaluationImageUniforms = 3;
|
||||
params.MaxGeometryImageUniforms = 4;
|
||||
params.MaxFragmentImageUniforms = 5;
|
||||
params.MaxComputeImageUniforms = 6;
|
||||
params.MaxCombinedImageUniforms = 7;
|
||||
MG_Backend::pActiveBackendObject = MakeUnique<DynamicParameterBackend>(params, BackendType::DirectGLES);
|
||||
|
||||
struct LimitPair {
|
||||
GLenum pname;
|
||||
@@ -1330,6 +1353,13 @@ TEST(GetterSanity, EveryLimitWithABuiltinAgreesWithItsQuery) {
|
||||
{GL_MAX_FRAGMENT_INPUT_COMPONENTS, "gl_MaxFragmentInputComponents"},
|
||||
{GL_MAX_DRAW_BUFFERS, "gl_MaxDrawBuffers"},
|
||||
{GL_MAX_IMAGE_UNITS, "gl_MaxImageUnits"},
|
||||
{GL_MAX_VERTEX_IMAGE_UNIFORMS, "gl_MaxVertexImageUniforms"},
|
||||
{GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, "gl_MaxTessControlImageUniforms"},
|
||||
{GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, "gl_MaxTessEvaluationImageUniforms"},
|
||||
{GL_MAX_GEOMETRY_IMAGE_UNIFORMS, "gl_MaxGeometryImageUniforms"},
|
||||
{GL_MAX_FRAGMENT_IMAGE_UNIFORMS, "gl_MaxFragmentImageUniforms"},
|
||||
{GL_MAX_COMPUTE_IMAGE_UNIFORMS, "gl_MaxComputeImageUniforms"},
|
||||
{GL_MAX_COMBINED_IMAGE_UNIFORMS, "gl_MaxCombinedImageUniforms"},
|
||||
// The SAME token (0x8F39) under two spellings, and the two glslang fields behind them
|
||||
// must therefore carry the same value.
|
||||
{GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS, "gl_MaxCombinedImageUnitsAndFragmentOutputs"},
|
||||
|
||||
@@ -720,6 +720,9 @@ TEST_F(TranslationCacheTest, TheFrontendFingerprintMovesWithEveryFrontendLimit)
|
||||
{"params.MaxImageUnits", [](CompileEnv& e) { e.params.MaxImageUnits += 1; }},
|
||||
{"params.MaxDrawBuffers", [](CompileEnv& e) { e.params.MaxDrawBuffers += 1; }},
|
||||
{"params.MaxVertexImageUniforms", [](CompileEnv& e) { e.params.MaxVertexImageUniforms += 1; }},
|
||||
{"params.MaxTessControlImageUniforms", [](CompileEnv& e) { e.params.MaxTessControlImageUniforms += 1; }},
|
||||
{"params.MaxTessEvaluationImageUniforms",
|
||||
[](CompileEnv& e) { e.params.MaxTessEvaluationImageUniforms += 1; }},
|
||||
{"params.MaxGeometryImageUniforms", [](CompileEnv& e) { e.params.MaxGeometryImageUniforms += 1; }},
|
||||
{"params.MaxFragmentImageUniforms", [](CompileEnv& e) { e.params.MaxFragmentImageUniforms += 1; }},
|
||||
{"params.MaxComputeImageUniforms", [](CompileEnv& e) { e.params.MaxComputeImageUniforms += 1; }},
|
||||
|
||||
@@ -1398,6 +1398,8 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
GLint maxImageUnits = 8;
|
||||
GLint maxCombinedImageUniforms = 8;
|
||||
GLint maxVertexImageUniforms = 0;
|
||||
GLint maxTessControlImageUniforms = 0;
|
||||
GLint maxTessEvaluationImageUniforms = 0;
|
||||
GLint maxGeometryImageUniforms = 0;
|
||||
GLint maxFragmentImageUniforms = 8;
|
||||
GLint maxComputeImageUniforms = 8;
|
||||
@@ -1547,12 +1549,14 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
glesFuncs.glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
|
||||
glesFuncs.glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
|
||||
glesFuncs.glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
|
||||
// Geometry shaders and their image-uniform query are core only in ES 3.2. DirectGLES
|
||||
// emits ESSL 3.10 on an ES 3.1 context, so reporting zero there is both legal and an
|
||||
// accurate description of what the backend compiler can consume.
|
||||
// Geometry and tessellation shaders and their image-uniform queries are core only in
|
||||
// ES 3.2. DirectGLES emits ESSL 3.10 on an ES 3.1 context, so reporting zero there is
|
||||
// both legal and an accurate description of what the backend compiler can consume.
|
||||
if (caps.GLESVersion.Major > 3 ||
|
||||
(caps.GLESVersion.Major == 3 && caps.GLESVersion.Minor >= 2)) {
|
||||
glesFuncs.glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &maxGeometryImageUniforms);
|
||||
glesFuncs.glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &maxTessControlImageUniforms);
|
||||
glesFuncs.glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &maxTessEvaluationImageUniforms);
|
||||
}
|
||||
// Closes the bracket opened before the run: every local above now holds either the
|
||||
// driver's answer or a floor, and nothing this function asked for is left in the error
|
||||
@@ -1864,6 +1868,8 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
caps.MaxImageUnits = maxImageUnits;
|
||||
caps.MaxCombinedImageUniforms = maxCombinedImageUniforms;
|
||||
caps.MaxVertexImageUniforms = maxVertexImageUniforms;
|
||||
caps.MaxTessControlImageUniforms = maxTessControlImageUniforms;
|
||||
caps.MaxTessEvaluationImageUniforms = maxTessEvaluationImageUniforms;
|
||||
caps.MaxGeometryImageUniforms = maxGeometryImageUniforms;
|
||||
caps.MaxFragmentImageUniforms = maxFragmentImageUniforms;
|
||||
caps.MaxComputeImageUniforms = maxComputeImageUniforms;
|
||||
@@ -1962,6 +1968,8 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
MGLOG_I(" GL_MAX_IMAGE_UNITS: %d", caps.MaxImageUnits);
|
||||
MGLOG_I(" GL_MAX_COMBINED_IMAGE_UNIFORMS: %d", caps.MaxCombinedImageUniforms);
|
||||
MGLOG_I(" GL_MAX_VERTEX_IMAGE_UNIFORMS: %d", caps.MaxVertexImageUniforms);
|
||||
MGLOG_I(" GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS: %d", caps.MaxTessControlImageUniforms);
|
||||
MGLOG_I(" GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS: %d", caps.MaxTessEvaluationImageUniforms);
|
||||
MGLOG_I(" GL_MAX_GEOMETRY_IMAGE_UNIFORMS: %d", caps.MaxGeometryImageUniforms);
|
||||
MGLOG_I(" GL_MAX_FRAGMENT_IMAGE_UNIFORMS: %d", caps.MaxFragmentImageUniforms);
|
||||
MGLOG_I(" GL_MAX_COMPUTE_IMAGE_UNIFORMS: %d", caps.MaxComputeImageUniforms);
|
||||
|
||||
@@ -1364,6 +1364,8 @@ namespace MobileGL {
|
||||
Int MaxImageUnits = 8;
|
||||
Int MaxCombinedImageUniforms = 8;
|
||||
Int MaxVertexImageUniforms = 0;
|
||||
Int MaxTessControlImageUniforms = 0;
|
||||
Int MaxTessEvaluationImageUniforms = 0;
|
||||
Int MaxGeometryImageUniforms = 0;
|
||||
Int MaxFragmentImageUniforms = 8;
|
||||
Int MaxComputeImageUniforms = 8;
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace MobileGL::MG_Util::ShaderTranspiler {
|
||||
HashValue(state, env.params.MaxImageUnits);
|
||||
HashValue(state, env.params.MaxDrawBuffers);
|
||||
HashValue(state, env.params.MaxVertexImageUniforms);
|
||||
HashValue(state, env.params.MaxTessControlImageUniforms);
|
||||
HashValue(state, env.params.MaxTessEvaluationImageUniforms);
|
||||
HashValue(state, env.params.MaxGeometryImageUniforms);
|
||||
HashValue(state, env.params.MaxFragmentImageUniforms);
|
||||
HashValue(state, env.params.MaxComputeImageUniforms);
|
||||
|
||||
@@ -212,6 +212,8 @@ namespace MobileGL {
|
||||
Resources.maxCombinedShaderOutputResources =
|
||||
Resources.maxCombinedImageUnitsAndFragmentOutputs;
|
||||
Resources.maxVertexImageUniforms = dynamicParameters.MaxVertexImageUniforms;
|
||||
Resources.maxTessControlImageUniforms = dynamicParameters.MaxTessControlImageUniforms;
|
||||
Resources.maxTessEvaluationImageUniforms = dynamicParameters.MaxTessEvaluationImageUniforms;
|
||||
Resources.maxGeometryImageUniforms = dynamicParameters.MaxGeometryImageUniforms;
|
||||
Resources.maxFragmentImageUniforms = dynamicParameters.MaxFragmentImageUniforms;
|
||||
Resources.maxComputeImageUniforms = dynamicParameters.MaxComputeImageUniforms;
|
||||
|
||||
Reference in New Issue
Block a user