Skip to content

Commit 3510039

Browse files
committed
Validate varying count when compiling shaders
This avoids crashing on devices when a number of varyings greater than the device limit is used. For now this accurately prints an error when compiling the shader, but the error text only pops up in the editor if the number of user varyings is above the limit.
1 parent 296de7d commit 3510039

17 files changed

+92
-27
lines changed

drivers/d3d12/rendering_device_driver_d3d12.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6234,6 +6234,8 @@ uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
62346234
case LIMIT_VRS_MAX_FRAGMENT_WIDTH:
62356235
case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
62366236
return vrs_capabilities.ss_max_fragment_size;
6237+
case LIMIT_MAX_SHADER_VARYINGS:
6238+
return MIN(D3D12_VS_OUTPUT_REGISTER_COUNT, D3D12_PS_INPUT_REGISTER_COUNT);
62376239
default: {
62386240
#ifdef DEV_ENABLED
62396241
WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");

drivers/gles3/storage/config.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ Config::Config() {
110110
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
111111
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
112112
glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
113+
GLint max_vertex_output;
114+
glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &max_vertex_output);
115+
GLint max_fragment_input;
116+
glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &max_fragment_input);
117+
max_shader_varyings = (uint32_t)MIN(max_vertex_output, max_fragment_input) / 4;
113118

114119
// sanity clamp buffer size to 16K..1MB
115120
max_uniform_buffer_size = CLAMP(max_uniform_buffer_size, 16384, 1048576);

drivers/gles3/storage/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class Config {
6262
GLint max_texture_size = 0;
6363
GLint max_viewport_size[2] = { 0, 0 };
6464
GLint64 max_uniform_buffer_size = 0;
65+
uint32_t max_shader_varyings = 0;
6566

6667
int64_t max_renderable_elements = 0;
6768
int64_t max_renderable_lights = 0;

drivers/gles3/storage/utilities.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,4 +465,16 @@ Size2i Utilities::get_maximum_viewport_size() const {
465465
return Size2i(config->max_viewport_size[0], config->max_viewport_size[1]);
466466
}
467467

468+
uint32_t Utilities::get_maximum_shader_varyings() const {
469+
Config *config = Config::get_singleton();
470+
ERR_FAIL_NULL_V(config, 31);
471+
return config->max_shader_varyings;
472+
}
473+
474+
uint64_t Utilities::get_maximum_uniform_buffer_size() const {
475+
Config *config = Config::get_singleton();
476+
ERR_FAIL_NULL_V(config, 65536);
477+
return uint64_t(config->max_uniform_buffer_size);
478+
}
479+
468480
#endif // GLES3_ENABLED

drivers/gles3/storage/utilities.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ class Utilities : public RendererUtilities {
226226
virtual String get_video_adapter_api_version() const override;
227227

228228
virtual Size2i get_maximum_viewport_size() const override;
229+
virtual uint32_t get_maximum_shader_varyings() const override;
230+
virtual uint64_t get_maximum_uniform_buffer_size() const override;
229231
};
230232

231233
} // namespace GLES3

drivers/metal/metal_device_properties.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct MetalLimits {
124124
uint32_t maxVertexInputBindings;
125125
uint32_t maxVertexInputBindingStride;
126126
uint32_t maxDrawIndexedIndexValue;
127+
uint32_t maxShaderVaryings;
127128

128129
double temporalScalerInputContentMinScale;
129130
double temporalScalerInputContentMaxScale;

drivers/metal/metal_device_properties.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@
303303
limits.maxVertexInputAttributes = 31;
304304
limits.maxVertexInputBindings = 31;
305305
limits.maxVertexInputBindingStride = (2 * KIBI);
306+
limits.maxShaderVaryings = 31; // Accurate on Apple4 and above. See: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
306307

307308
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
308309
limits.minUniformBufferOffsetAlignment = 64;

drivers/metal/rendering_device_driver_metal.mm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3999,6 +3999,8 @@ bool isArrayTexture(MTLTextureType p_type) {
39993999
return (uint64_t)((1.0 / limits.temporalScalerInputContentMaxScale) * 1000'000);
40004000
case LIMIT_METALFX_TEMPORAL_SCALER_MAX_SCALE:
40014001
return (uint64_t)((1.0 / limits.temporalScalerInputContentMinScale) * 1000'000);
4002+
case LIMIT_MAX_SHADER_VARYINGS:
4003+
return limits.maxShaderVaryings;
40024004
UNKNOWN(LIMIT_VRS_TEXEL_WIDTH);
40034005
UNKNOWN(LIMIT_VRS_TEXEL_HEIGHT);
40044006
UNKNOWN(LIMIT_VRS_MAX_FRAGMENT_WIDTH);

drivers/vulkan/rendering_device_driver_vulkan.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5886,6 +5886,10 @@ uint64_t RenderingDeviceDriverVulkan::limit_get(Limit p_limit) {
58865886
return vrs_capabilities.max_fragment_size.x;
58875887
case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
58885888
return vrs_capabilities.max_fragment_size.y;
5889+
case LIMIT_MAX_SHADER_VARYINGS:
5890+
// The Vulkan spec states that built in varyings like gl_FragCoord should count against this, but in
5891+
// practice, that doesn't seem to be the case. The validation layers don't even complain.
5892+
return MIN(limits.maxVertexOutputComponents / 4, limits.maxFragmentInputComponents / 4);
58895893
default:
58905894
ERR_FAIL_V(0);
58915895
}

servers/rendering/dummy/storage/utilities.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class Utilities : public RendererUtilities {
9494
virtual String get_video_adapter_api_version() const override { return String(); }
9595

9696
virtual Size2i get_maximum_viewport_size() const override { return Size2i(); }
97+
virtual uint32_t get_maximum_shader_varyings() const override { return 31; } // Fair assumption for everything except old OpenGL-only phones.
98+
virtual uint64_t get_maximum_uniform_buffer_size() const override { return 65536; } // Fair assumption for all devices.
9799
};
98100

99101
} // namespace RendererDummy

0 commit comments

Comments
 (0)