Signed-off-by: Tobias Klausmann <tobias.johannes.klausm...@mni.thm.de> --- src/glsl/ast_to_hir.cpp | 14 +++++ src/glsl/builtin_variables.cpp | 13 +++- src/glsl/glcpp/glcpp-parse.y | 3 + src/glsl/glsl_parser_extras.cpp | 1 + src/glsl/glsl_parser_extras.h | 3 + src/glsl/link_varyings.cpp | 2 +- src/glsl/linker.cpp | 121 +++++++++++++++++++++++++----------- src/glsl/standalone_scaffolding.cpp | 1 + src/glsl/tests/varyings_test.cpp | 27 ++++++++ 9 files changed, 145 insertions(+), 40 deletions(-)
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 8aebb13..4db2b2e 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -1045,6 +1045,20 @@ check_builtin_array_max_size(const char *name, unsigned size, _mesa_glsl_error(&loc, state, "`gl_ClipDistance' array size cannot " "be larger than gl_MaxClipDistances (%u)", state->Const.MaxClipPlanes); + } else if (strcmp("gl_CullDistance", name) == 0 + && size > state->Const.MaxClipPlanes) { + /* From the ARB_cull_distance spec: + * + * "The gl_CullDistance array is predeclared as unsized and + * must be sized by the shader either redeclaring it with + * a size or indexing it only with integral constant + * expressions. The size determines the number and set of + * enabled cull distances and can be at most + * gl_MaxCullDistances." + */ + _mesa_glsl_error(&loc, state, "`gl_CullDistance' array size cannot " + "be larger than gl_MaxCullDistances (%u)", + state->Const.MaxClipPlanes); } } diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp index 6806aa1..78c8db2 100644 --- a/src/glsl/builtin_variables.cpp +++ b/src/glsl/builtin_variables.cpp @@ -298,7 +298,7 @@ public: const glsl_type *construct_interface_instance() const; private: - glsl_struct_field fields[10]; + glsl_struct_field fields[11]; unsigned num_fields; }; @@ -600,6 +600,12 @@ builtin_variable_generator::generate_constants() add_const("gl_MaxVaryingComponents", state->ctx->Const.MaxVarying * 4); } + if (state->is_version(450, 0) || state->ARB_cull_distance_enable) { + add_const("gl_MaxCullDistances", state->Const.MaxClipPlanes); + add_const("gl_MaxCombinedClipAndCullDistances", + state->Const.MaxClipPlanes); + } + if (state->is_version(150, 0)) { add_const("gl_MaxVertexOutputComponents", state->Const.MaxVertexOutputComponents); @@ -1029,6 +1035,11 @@ builtin_variable_generator::generate_varyings() "gl_ClipDistance"); } + if (state->is_version(450, 0) || state->ARB_cull_distance_enable) { + ADD_VARYING(VARYING_SLOT_CULL_DIST0, array(float_t, 0), + "gl_CullDistance"); + } + if (compatibility) { ADD_VARYING(VARYING_SLOT_TEX0, array(vec4_t, 0), "gl_TexCoord"); ADD_VARYING(VARYING_SLOT_FOGC, float_t, "gl_FogFragCoord"); diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y index a11b6b2..536c17f 100644 --- a/src/glsl/glcpp/glcpp-parse.y +++ b/src/glsl/glcpp/glcpp-parse.y @@ -2483,6 +2483,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->ARB_shader_precision) add_builtin_define(parser, "GL_ARB_shader_precision", 1); + + if (extensions->ARB_cull_distance) + add_builtin_define(parser, "GL_ARB_cull_distance", 1); } } diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 046d5d7..d1cd8ff 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -554,6 +554,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_arrays_of_arrays, true, false, ARB_arrays_of_arrays), EXT(ARB_compute_shader, true, false, ARB_compute_shader), EXT(ARB_conservative_depth, true, false, ARB_conservative_depth), + EXT(ARB_cull_distance, true, false, ARB_cull_distance), EXT(ARB_derivative_control, true, false, ARB_derivative_control), EXT(ARB_draw_buffers, true, false, dummy_true), EXT(ARB_draw_instanced, true, false, ARB_draw_instanced), diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 9a0c24e..8572905 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -378,6 +378,7 @@ struct _mesa_glsl_parse_state { /* ARB_viewport_array */ unsigned MaxViewports; + } Const; /** @@ -430,6 +431,8 @@ struct _mesa_glsl_parse_state { bool ARB_compute_shader_warn; bool ARB_conservative_depth_enable; bool ARB_conservative_depth_warn; + bool ARB_cull_distance_enable; + bool ARB_cull_distance_warn; bool ARB_derivative_control_enable; bool ARB_derivative_control_warn; bool ARB_draw_buffers_enable; diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp index 46f84c6..81c0dac 100644 --- a/src/glsl/link_varyings.cpp +++ b/src/glsl/link_varyings.cpp @@ -404,7 +404,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, this->matched_candidate->type->fields.array->vector_elements; unsigned actual_array_size = (this->is_clip_distance_mesa || this->is_cull_distance_mesa) ? - prog->LastClipDistanceArraySize : + prog->LastClipCullDistanceArraySize : this->matched_candidate->type->array_size(); if (this->is_subscripted) { diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index e616520..8bb1a5c 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -474,49 +474,94 @@ link_invalidate_variable_locations(exec_list *ir) } + /** - * Set UsesClipDistance and ClipDistanceArraySize based on the given shader. + * Set UsesClipCullDistance and ClipCullDistanceArraySize based on the given + * shader. * - * Also check for errors based on incorrect usage of gl_ClipVertex and - * gl_ClipDistance. + * Also check for errors based on incorrect usage of gl_ClipVertex, + * gl_ClipDistance and gl_CullDistance. + * + * Additionally test whether the arrays gl_ClipDistance and gl_CullDistance + * exceed the maximum size defined by gl_MaxCombinedClipAndCullDistances. * * Return false if an error was reported. */ static void -analyze_clip_usage(struct gl_shader_program *prog, - struct gl_shader *shader, GLboolean *UsesClipDistance, - GLuint *ClipDistanceArraySize) +analyze_clip_cull_usage(struct gl_shader_program *prog, + struct gl_shader *shader, + struct gl_context *ctx, + GLboolean *UsesClipCullDistance, + GLuint *ClipCullDistanceArraySize) { - *ClipDistanceArraySize = 0; + *ClipCullDistanceArraySize = 0; - if (!prog->IsES && prog->Version >= 130) { - /* From section 7.1 (Vertex Shader Special Variables) of the - * GLSL 1.30 spec: - * - * "It is an error for a shader to statically write both - * gl_ClipVertex and gl_ClipDistance." - * - * This does not apply to GLSL ES shaders, since GLSL ES defines neither - * gl_ClipVertex nor gl_ClipDistance. - */ + if (prog->IsES && prog->Version < 130) { + *UsesClipCullDistance = false; + } else { find_assignment_visitor clip_vertex("gl_ClipVertex"); find_assignment_visitor clip_distance("gl_ClipDistance"); + find_assignment_visitor cull_distance("gl_CullDistance"); clip_vertex.run(shader->ir); clip_distance.run(shader->ir); + cull_distance.run(shader->ir); + + /* From the ARB_cull_distance spec: + * + * It is a compile-time or link-time error for the set of shaders forming + * a program to statically read or write both gl_ClipVertex and either + * gl_ClipDistance or gl_CullDistance. + * + * This does not apply to GLSL ES shaders, since GLSL ES defines neither + * gl_ClipVertex, gl_ClipDistance or gl_CullDistance. + */ if (clip_vertex.variable_found() && clip_distance.variable_found()) { linker_error(prog, "%s shader writes to both `gl_ClipVertex' " "and `gl_ClipDistance'\n", _mesa_shader_stage_to_string(shader->Stage)); return; } - *UsesClipDistance = clip_distance.variable_found(); + if (clip_vertex.variable_found() && cull_distance.variable_found()) { + linker_error(prog, "%s shader writes to both `gl_ClipVertex' " + "and `gl_CullDistance'\n", + _mesa_shader_stage_to_string(shader->Stage)); + return; + } + + *UsesClipCullDistance = clip_distance.variable_found() | + cull_distance.variable_found(); + ir_variable *clip_distance_var = shader->symbols->get_variable("gl_ClipDistance"); + ir_variable *cull_distance_var = + shader->symbols->get_variable("gl_CullDistance"); + if (clip_distance_var) - *ClipDistanceArraySize = clip_distance_var->type->length; - } else { - *UsesClipDistance = false; + *ClipCullDistanceArraySize = clip_distance_var->type->was_unsized ? + clip_distance_var->type->length -1 : + clip_distance_var->type->length; + + if (cull_distance_var) + *ClipCullDistanceArraySize+= cull_distance_var->type->was_unsized ? + cull_distance_var->type->length -1 : + cull_distance_var->type->length; + + /* From the ARB_cull_distance spec: + * + * It is a compile-time or link-time error for the set of shaders forming + * a program to have the sum of the sizes of the gl_ClipDistance and + * gl_CullDistance arrays to be larger than + * gl_MaxCombinedClipAndCullDistances. + */ + if (*ClipCullDistanceArraySize > ctx->Const.MaxClipPlanes) { + linker_error(prog, "%s shader: the combined size of " + "'gl_ClipDistance' and 'gl_CullDistance' size cannot " + "be larger than " + "gl_MaxCombinedClipAndCullDistances (%u)", + _mesa_shader_stage_to_string(shader->Stage), + ctx->Const.MaxClipPlanes); + } } } @@ -524,14 +569,14 @@ analyze_clip_usage(struct gl_shader_program *prog, /** * Verify that a vertex shader executable meets all semantic requirements. * - * Also sets prog->Vert.UsesClipDistance and prog->Vert.ClipDistanceArraySize - * as a side effect. + * Also sets prog->Vert.UsesClipCullDistance and + * prog->Vert.ClipCullDistanceArraySize as a side effect. * * \param shader Vertex shader executable to be verified */ void validate_vertex_shader_executable(struct gl_shader_program *prog, - struct gl_shader *shader) + struct gl_shader *shader, struct gl_context *ctx) { if (shader == NULL) return; @@ -578,8 +623,8 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, } } - analyze_clip_usage(prog, shader, &prog->Vert.UsesClipDistance, - &prog->Vert.ClipDistanceArraySize); + analyze_clip_cull_usage(prog, shader, ctx, &prog->Vert.UsesClipCullDistance, + &prog->Vert.ClipCullDistanceArraySize); } @@ -590,7 +635,7 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, */ void validate_fragment_shader_executable(struct gl_shader_program *prog, - struct gl_shader *shader) + struct gl_shader *shader, struct gl_context *ctx) { if (shader == NULL) return; @@ -610,14 +655,14 @@ validate_fragment_shader_executable(struct gl_shader_program *prog, /** * Verify that a geometry shader executable meets all semantic requirements * - * Also sets prog->Geom.VerticesIn, prog->Geom.UsesClipDistance, and - * prog->Geom.ClipDistanceArraySize as a side effect. + * Also sets prog->Geom.VerticesIn, prog->Geom.UsesClipCullDistance, and + * prog->Geom.ClipCullDistanceArraySize as a side effect. * * \param shader Geometry shader executable to be verified */ void validate_geometry_shader_executable(struct gl_shader_program *prog, - struct gl_shader *shader) + struct gl_shader *shader, struct gl_context *ctx) { if (shader == NULL) return; @@ -625,8 +670,8 @@ validate_geometry_shader_executable(struct gl_shader_program *prog, unsigned num_vertices = vertices_per_prim(prog->Geom.InputType); prog->Geom.VerticesIn = num_vertices; - analyze_clip_usage(prog, shader, &prog->Geom.UsesClipDistance, - &prog->Geom.ClipDistanceArraySize); + analyze_clip_cull_usage(prog, shader, ctx, &prog->Geom.UsesClipCullDistance, + &prog->Geom.ClipCullDistanceArraySize); } /** @@ -2834,13 +2879,13 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) switch (stage) { case MESA_SHADER_VERTEX: - validate_vertex_shader_executable(prog, sh); + validate_vertex_shader_executable(prog, sh, ctx); break; case MESA_SHADER_GEOMETRY: - validate_geometry_shader_executable(prog, sh); + validate_geometry_shader_executable(prog, sh, ctx); break; case MESA_SHADER_FRAGMENT: - validate_fragment_shader_executable(prog, sh); + validate_fragment_shader_executable(prog, sh, ctx); break; } if (!prog->LinkStatus) @@ -2851,11 +2896,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } if (num_shaders[MESA_SHADER_GEOMETRY] > 0) - prog->LastClipDistanceArraySize = prog->Geom.ClipDistanceArraySize; + prog->LastClipCullDistanceArraySize = prog->Geom.ClipCullDistanceArraySize; else if (num_shaders[MESA_SHADER_VERTEX] > 0) - prog->LastClipDistanceArraySize = prog->Vert.ClipDistanceArraySize; + prog->LastClipCullDistanceArraySize = prog->Vert.ClipCullDistanceArraySize; else - prog->LastClipDistanceArraySize = 0; /* Not used */ + prog->LastClipCullDistanceArraySize = 0; /* Not used */ /* Here begins the inter-stage linking phase. Some initial validation is * performed, then locations are assigned for uniforms, attributes, and diff --git a/src/glsl/standalone_scaffolding.cpp b/src/glsl/standalone_scaffolding.cpp index a109c4e..0ac16bb 100644 --- a/src/glsl/standalone_scaffolding.cpp +++ b/src/glsl/standalone_scaffolding.cpp @@ -142,6 +142,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.ARB_texture_query_lod = true; ctx->Extensions.ARB_uniform_buffer_object = true; ctx->Extensions.ARB_viewport_array = true; + ctx->Extensions.ARB_cull_distance = true; ctx->Extensions.OES_EGL_image_external = true; ctx->Extensions.OES_standard_derivatives = true; diff --git a/src/glsl/tests/varyings_test.cpp b/src/glsl/tests/varyings_test.cpp index 4573529..7a962c5 100644 --- a/src/glsl/tests/varyings_test.cpp +++ b/src/glsl/tests/varyings_test.cpp @@ -202,6 +202,33 @@ TEST_F(link_varyings, gl_ClipDistance) EXPECT_TRUE(is_empty(consumer_interface_inputs)); } +TEST_F(link_varyings, gl_CullDistance) +{ + const glsl_type *const array_8_of_float = + glsl_type::get_array_instance(glsl_type::vec(1), 8); + + ir_variable *const culldistance = + new(mem_ctx) ir_variable(array_8_of_float, + "gl_CullDistance", + ir_var_shader_in); + + culldistance->data.explicit_location = true; + culldistance->data.location = VARYING_SLOT_CULL_DIST0; + culldistance->data.explicit_index = 0; + + ir.push_tail(culldistance); + + ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); + + EXPECT_EQ(culldistance, junk[VARYING_SLOT_CULL_DIST0]); + EXPECT_TRUE(is_empty(consumer_inputs)); + EXPECT_TRUE(is_empty(consumer_interface_inputs)); +} + TEST_F(link_varyings, single_interface_input) { ir_variable *const v = -- 2.4.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev