Tobias Klausmann
2015-May-24 17:57 UTC
[Nouveau] [RFC PATCH 00/11] Implement ARB_cull_distance
This patch series adds the needed support for this extension to the various parts of mesa to finally enable it for nvc0. Dave Airlie (1): glsl: lower cull_distance into cull_distance_mesa Tobias Klausmann (10): glapi: add GL_ARB_cull_distance mesa/main: add support for GL_ARB_cull_distance mesa/prog: Add varyings for arb_cull_distance mesa/st: add support for GL_ARB_cull_distance glsl: Add a helper to see if an array was unsize in the shader glsl: Add arb_cull_distance support i965: rename UsesClipDistanceOut to UsesClipCullDistanceOut gallium: add support for arb_cull_distance nouveau/codegen: sort in galliums cull_distance semantic into the drivers bitmask nouveau/nvc0: implement cull_distance as a special form of clip distance docs/GL3.txt | 2 +- docs/relnotes/10.7.0.html | 4 +- src/gallium/auxiliary/cso_cache/cso_context.c | 3 + src/gallium/drivers/freedreno/freedreno_screen.c | 1 + src/gallium/drivers/i915/i915_screen.c | 1 + src/gallium/drivers/ilo/ilo_screen.c | 1 + src/gallium/drivers/llvmpipe/lp_screen.c | 2 + .../drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp | 5 + src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 + src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 + src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 6 +- src/gallium/drivers/nouveau/nvc0/nvc0_program.h | 1 + src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 + .../drivers/nouveau/nvc0/nvc0_state_validate.c | 1 + src/gallium/drivers/r300/r300_screen.c | 1 + src/gallium/drivers/r600/r600_pipe.c | 1 + src/gallium/drivers/radeonsi/si_pipe.c | 1 + src/gallium/drivers/softpipe/sp_screen.c | 2 + src/gallium/drivers/svga/svga_screen.c | 1 + src/gallium/drivers/vc4/vc4_screen.c | 1 + src/gallium/include/pipe/p_defines.h | 1 + src/glsl/Makefile.sources | 1 + 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/glsl_types.cpp | 8 +- src/glsl/glsl_types.h | 10 +- src/glsl/ir_optimization.h | 1 + src/glsl/link_varyings.cpp | 17 +- src/glsl/link_varyings.h | 3 +- src/glsl/linker.cpp | 124 +++-- src/glsl/lower_cull_distance.cpp | 549 +++++++++++++++++++++ src/glsl/standalone_scaffolding.cpp | 1 + src/glsl/tests/varyings_test.cpp | 27 + src/mapi/glapi/gen/gl_API.xml | 7 +- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 2 +- src/mesa/drivers/dri/i965/brw_gs.c | 2 +- src/mesa/drivers/dri/i965/brw_vec4.cpp | 2 +- src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 2 +- src/mesa/drivers/dri/i965/brw_vs.c | 2 +- src/mesa/main/extensions.c | 1 + src/mesa/main/get.c | 26 + src/mesa/main/get_hash_params.py | 4 + src/mesa/main/mtypes.h | 22 +- src/mesa/main/shaderapi.c | 4 +- src/mesa/main/tests/enum_strings.cpp | 2 + src/mesa/program/prog_print.c | 4 + src/mesa/state_tracker/st_extensions.c | 4 + src/mesa/state_tracker/st_program.c | 34 ++ 51 files changed, 859 insertions(+), 72 deletions(-) create mode 100644 src/glsl/lower_cull_distance.cpp -- 2.4.1
Tobias Klausmann
2015-May-24 17:57 UTC
[Nouveau] [PATCH 01/11] glapi: add GL_ARB_cull_distance
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/mapi/glapi/gen/gl_API.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml index 3090b9f..a792056 100644 --- a/src/mapi/glapi/gen/gl_API.xml +++ b/src/mapi/glapi/gen/gl_API.xml @@ -8247,7 +8247,12 @@ <enum name="QUERY_BY_REGION_NO_WAIT_INVERTED" value="0x8E1A"/> </category> -<!-- ARB extensions 162 - 163 --> +<category name="ARB_cull_distance" number="162"> + <enum name="MAX_CULL_DISTANCES" value="0x82F9"/> + <enum name="MAX_COMBINED_CLIP_AND_CULL_DISTANCES" value="0x82FA"/> +</category> + +<!-- ARB extensions 163 --> <xi:include href="ARB_direct_state_access.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 02/11] mesa/main: add support for GL_ARB_cull_distance
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/mesa/main/extensions.c | 1 + src/mesa/main/get.c | 26 ++++++++++++++++++++++++++ src/mesa/main/get_hash_params.py | 4 ++++ src/mesa/main/mtypes.h | 22 +++++++++++++--------- src/mesa/main/shaderapi.c | 4 ++-- src/mesa/main/tests/enum_strings.cpp | 2 ++ 6 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index c82416a..2145502 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -99,6 +99,7 @@ static const struct extension extension_table[] = { { "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 }, { "GL_ARB_copy_image", o(ARB_copy_image), GL, 2012 }, { "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 }, + { "GL_ARB_cull_distance", o(ARB_cull_distance), GL, 2014 }, { "GL_ARB_debug_output", o(dummy_true), GL, 2009 }, { "GL_ARB_depth_buffer_float", o(ARB_depth_buffer_float), GL, 2008 }, { "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 }, diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 8a6c81a..1dcfcc9 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -143,6 +143,8 @@ enum value_extra { EXTRA_VALID_DRAW_BUFFER, EXTRA_VALID_TEXTURE_UNIT, EXTRA_VALID_CLIP_DISTANCE, + EXTRA_VALID_CULL_DISTANCE, + EXTRA_VALID_CULL_AND_CLIP_DISTANCE, EXTRA_FLUSH_CURRENT, EXTRA_GLSL_130, EXTRA_EXT_UBO_GS4, @@ -267,6 +269,13 @@ static const int extra_valid_clip_distance[] = { EXTRA_END }; +static const int extra_valid_clip_and_cull_distance[] = { + EXTRA_VALID_CLIP_DISTANCE, + EXTRA_VALID_CULL_DISTANCE, + EXTRA_VALID_CULL_AND_CLIP_DISTANCE, + EXTRA_END +}; + static const int extra_flush_current_valid_texture_unit[] = { EXTRA_FLUSH_CURRENT, EXTRA_VALID_TEXTURE_UNIT, @@ -393,6 +402,7 @@ EXTRA_EXT(INTEL_performance_query); EXTRA_EXT(ARB_explicit_uniform_location); EXTRA_EXT(ARB_clip_control); EXTRA_EXT(EXT_polygon_offset_clamp); +EXTRA_EXT(ARB_cull_distance); static const int extra_ARB_color_buffer_float_or_glcore[] = { @@ -1116,6 +1126,22 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d return GL_FALSE; } break; + case EXTRA_VALID_CULL_DISTANCE: + if (d->pname - GL_MAX_CULL_DISTANCES >= ctx->Const.MaxClipPlanes) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(cull distance %u)", + func, d->pname - GL_MAX_CULL_DISTANCES); + return GL_FALSE; + } + break; + case EXTRA_VALID_CULL_AND_CLIP_DISTANCE: + if (d->pname - GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES >+ ctx->Const.MaxClipPlanes) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(combined clip and cull distance %u)", func, + d->pname - GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES); + return GL_FALSE; + } + break; case EXTRA_GLSL_130: api_check = GL_TRUE; if (ctx->Const.GLSLVersion >= 130) diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index 41cb2c1..a63aba7 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -798,6 +798,10 @@ descriptor=[ [ "MIN_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MinFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], [ "MAX_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MaxFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], [ "FRAGMENT_INTERPOLATION_OFFSET_BITS", "CONST(FRAGMENT_INTERPOLATION_OFFSET_BITS), extra_ARB_gpu_shader5" ], + +# GL_ARB_cull_distance + [ "MAX_CULL_DISTANCES", "CONTEXT_INT(Const.MaxClipPlanes), extra_ARB_cull_distance" ], + [ "MAX_COMBINED_CLIP_AND_CULL_DISTANCES", "CONTEXT_INT(Const.MaxClipPlanes), extra_ARB_cull_distance" ], ]}, # Enums restricted to OpenGL Core profile diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 8342517..6425c06 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -236,6 +236,8 @@ typedef enum VARYING_SLOT_CLIP_VERTEX, /* Does not appear in FS */ VARYING_SLOT_CLIP_DIST0, VARYING_SLOT_CLIP_DIST1, + VARYING_SLOT_CULL_DIST0, + VARYING_SLOT_CULL_DIST1, VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */ VARYING_SLOT_LAYER, /* Appears as VS or GS output */ VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */ @@ -272,6 +274,8 @@ typedef enum #define VARYING_BIT_CLIP_VERTEX BITFIELD64_BIT(VARYING_SLOT_CLIP_VERTEX) #define VARYING_BIT_CLIP_DIST0 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0) #define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1) +#define VARYING_BIT_CULL_DIST0 BITFIELD64_BIT(VARYING_SLOT_CULL_DIST0) +#define VARYING_BIT_CULL_DIST1 BITFIELD64_BIT(VARYING_SLOT_CULL_DIST1) #define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID) #define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER) #define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT) @@ -2111,8 +2115,7 @@ struct gl_program * For vertex and geometry shaders, true if the program uses the * gl_ClipDistance output. Ignored for fragment shaders. */ - GLboolean UsesClipDistanceOut; - + GLboolean UsesClipCullDistanceOut; /** Named parameters, constants, etc. from program text */ struct gl_program_parameter_list *Parameters; @@ -2697,9 +2700,9 @@ struct gl_shader_program * True if gl_ClipDistance is written to. Copied into * gl_geometry_program by _mesa_copy_linked_program_data(). */ - GLboolean UsesClipDistance; - GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or - 0 if not present. */ + GLboolean UsesClipCullDistance; + GLuint ClipCullDistanceArraySize; /**< Size of the gl_ClipDistance array, + or 0 if not present. */ bool UsesEndPrimitive; bool UsesStreams; } Geom; @@ -2710,9 +2713,9 @@ struct gl_shader_program * True if gl_ClipDistance is written to. Copied into gl_vertex_program * by _mesa_copy_linked_program_data(). */ - GLboolean UsesClipDistance; - GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or - 0 if not present. */ + GLboolean UsesClipCullDistance; + GLuint ClipCullDistanceArraySize; /**< Size of the gl_ClipDistance array, + or 0 if not present. */ } Vert; /** @@ -2744,7 +2747,7 @@ struct gl_shader_program * Size of the gl_ClipDistance array that is output from the last pipeline * stage before the fragment shader. */ - unsigned LastClipDistanceArraySize; + unsigned LastClipCullDistanceArraySize; unsigned NumUniformBlocks; struct gl_uniform_block *UniformBlocks; @@ -3617,6 +3620,7 @@ struct gl_extensions GLboolean ARB_conditional_render_inverted; GLboolean ARB_conservative_depth; GLboolean ARB_copy_image; + GLboolean ARB_cull_distance; GLboolean ARB_depth_buffer_float; GLboolean ARB_depth_clamp; GLboolean ARB_depth_texture; diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index a04b287..7b26173 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -1942,7 +1942,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, { switch (type) { case MESA_SHADER_VERTEX: - dst->UsesClipDistanceOut = src->Vert.UsesClipDistance; + dst->UsesClipCullDistanceOut = src->Vert.UsesClipCullDistance; break; case MESA_SHADER_GEOMETRY: { struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst; @@ -1951,7 +1951,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, dst_gp->Invocations = src->Geom.Invocations; dst_gp->InputType = src->Geom.InputType; dst_gp->OutputType = src->Geom.OutputType; - dst->UsesClipDistanceOut = src->Geom.UsesClipDistance; + dst->UsesClipCullDistanceOut = src->Geom.UsesClipCullDistance; dst_gp->UsesEndPrimitive = src->Geom.UsesEndPrimitive; dst_gp->UsesStreams = src->Geom.UsesStreams; } diff --git a/src/mesa/main/tests/enum_strings.cpp b/src/mesa/main/tests/enum_strings.cpp index dc5fe75..959db15 100644 --- a/src/mesa/main/tests/enum_strings.cpp +++ b/src/mesa/main/tests/enum_strings.cpp @@ -789,6 +789,8 @@ const struct enum_info everything[] = { { 0x8261, "GL_NO_RESET_NOTIFICATION_ARB" }, { 0x826E, "GL_MAX_UNIFORM_LOCATIONS" }, { 0x82DF, "GL_TEXTURE_IMMUTABLE_LEVELS" }, + { 0x82F9, "GL_MAX_CULL_DISTANCES" }, + { 0x82FA, "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES" }, { 0x8362, "GL_UNSIGNED_BYTE_2_3_3_REV" }, { 0x8363, "GL_UNSIGNED_SHORT_5_6_5" }, { 0x8364, "GL_UNSIGNED_SHORT_5_6_5_REV" }, -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 03/11] mesa/prog: Add varyings for arb_cull_distance
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/mesa/program/prog_print.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index d588d07..e8855cd 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -147,6 +147,8 @@ arb_input_attrib_string(GLuint index, GLenum progType) "fragment.(twenty-one)", /* VARYING_SLOT_VIEWPORT */ "fragment.(twenty-two)", /* VARYING_SLOT_FACE */ "fragment.(twenty-three)", /* VARYING_SLOT_PNTC */ + "fragment.(twenty-four)", /* VARYING_SLOT_CULL_DIST0 */ + "fragment.(twenty-five)", /* VARYING_SLOT_CULL_DIST1 */ "fragment.varying[0]", "fragment.varying[1]", "fragment.varying[2]", @@ -272,6 +274,8 @@ arb_output_attrib_string(GLuint index, GLenum progType) "result.(twenty-one)", /* VARYING_SLOT_VIEWPORT */ "result.(twenty-two)", /* VARYING_SLOT_FACE */ "result.(twenty-three)", /* VARYING_SLOT_PNTC */ + "result.(twenty-four)", /* VARYING_SLOT_CULL_DIST0 */ + "result.(twenty-five)", /* VARYING_SLOT_CULL_DIST1 */ "result.varying[0]", "result.varying[1]", "result.varying[2]", -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 04/11] mesa/st: add support for GL_ARB_cull_distance
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/mesa/state_tracker/st_extensions.c | 4 ++++ src/mesa/state_tracker/st_program.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 23a4588..63f3334 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -466,6 +466,7 @@ void st_init_extensions(struct pipe_screen *screen, { o(ARB_conditional_render_inverted), PIPE_CAP_CONDITIONAL_RENDER_INVERTED }, { o(ARB_texture_view), PIPE_CAP_SAMPLER_VIEW_TARGET }, { o(ARB_clip_control), PIPE_CAP_CLIP_HALFZ }, + { o(ARB_cull_distance), PIPE_CAP_CULL_DISTANCE }, { o(EXT_polygon_offset_clamp), PIPE_CAP_POLYGON_OFFSET_CLAMP }, }; @@ -678,6 +679,9 @@ void st_init_extensions(struct pipe_screen *screen, if (glsl_feature_level >= 410) extensions->ARB_shader_precision = GL_TRUE; + if (glsl_feature_level >= 130) + extensions->ARB_cull_distance = GL_TRUE; + /* This extension needs full OpenGL 3.2, but we don't know if that's * supported at this point. Only check the GLSL version. */ if (consts->GLSLVersion >= 150 && diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index a9110d3..79e8ad7 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -253,6 +253,14 @@ st_prepare_vertex_program(struct gl_context *ctx, stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; stvp->output_semantic_index[slot] = 1; break; + case VARYING_SLOT_CULL_DIST0: + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + stvp->output_semantic_index[slot] = 0; + break; + case VARYING_SLOT_CULL_DIST1: + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + stvp->output_semantic_index[slot] = 1; + break; case VARYING_SLOT_EDGE: assert(0); break; @@ -606,6 +614,16 @@ st_translate_fragment_program(struct st_context *st, input_semantic_index[slot] = 1; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; + case VARYING_SLOT_CULL_DIST0: + input_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + break; + case VARYING_SLOT_CULL_DIST1: + input_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + input_semantic_index[slot] = 1; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + break; /* In most cases, there is nothing special about these * inputs, so adopt a convention to use the generic * semantic name and the mesa VARYING_SLOT_ number as the @@ -941,6 +959,14 @@ st_translate_geometry_program(struct st_context *st, input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 1; break; + case VARYING_SLOT_CULL_DIST0: + input_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + input_semantic_index[slot] = 0; + break; + case VARYING_SLOT_CULL_DIST1: + input_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + input_semantic_index[slot] = 1; + break; case VARYING_SLOT_PSIZ: input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; input_semantic_index[slot] = 0; @@ -1028,6 +1054,14 @@ st_translate_geometry_program(struct st_context *st, gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; gs_output_semantic_index[slot] = 1; break; + case VARYING_SLOT_CULL_DIST0: + gs_output_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + gs_output_semantic_index[slot] = 0; + break; + case VARYING_SLOT_CULL_DIST1: + gs_output_semantic_name[slot] = TGSI_SEMANTIC_CULLDIST; + gs_output_semantic_index[slot] = 1; + break; case VARYING_SLOT_LAYER: gs_output_semantic_name[slot] = TGSI_SEMANTIC_LAYER; gs_output_semantic_index[slot] = 0; -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 05/11] glsl: Add a helper to see if an array was unsize in the shader
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/glsl/glsl_types.cpp | 8 ++++---- src/glsl/glsl_types.h | 10 ++++++++-- src/glsl/linker.cpp | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp index f675e90..4bc7324 100644 --- a/src/glsl/glsl_types.cpp +++ b/src/glsl/glsl_types.cpp @@ -340,12 +340,12 @@ _mesa_glsl_release_types(void) } -glsl_type::glsl_type(const glsl_type *array, unsigned length) : +glsl_type::glsl_type(const glsl_type *array, unsigned length, bool was_unsized) : base_type(GLSL_TYPE_ARRAY), sampler_dimensionality(0), sampler_shadow(0), sampler_array(0), sampler_type(0), interface_packing(0), vector_elements(0), matrix_columns(0), - length(length), name(NULL) + length(length), name(NULL), was_unsized(was_unsized) { this->fields.array = array; /* Inherit the gl type of the base. The GL type is used for @@ -635,7 +635,7 @@ glsl_type::get_sampler_instance(enum glsl_sampler_dim dim, } const glsl_type * -glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) +glsl_type::get_array_instance(const glsl_type *base, unsigned array_size, bool was_unsized) { /* Generate a name using the base type pointer in the key. This is * done because the name of the base type may not be unique across @@ -656,7 +656,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size) if (t == NULL) { mtx_unlock(&glsl_type::mutex); - t = new glsl_type(base, array_size); + t = new glsl_type(base, array_size, was_unsized); mtx_lock(&glsl_type::mutex); hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key)); diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h index f54a939..d6ad450 100644 --- a/src/glsl/glsl_types.h +++ b/src/glsl/glsl_types.h @@ -183,6 +183,12 @@ struct glsl_type { } fields; /** + * For \c GLSL_TYPE_ARRAY this determines if an array was unsized and + * got changed to a sized array. + */ + bool was_unsized; + + /** * \name Pointers to various public type singletons */ /*@{*/ @@ -246,7 +252,7 @@ struct glsl_type { * Get the instance of an array type */ static const glsl_type *get_array_instance(const glsl_type *base, - unsigned elements); + unsigned elements, bool was_unsized = false); /** * Get the instance of a record type @@ -677,7 +683,7 @@ private: enum glsl_interface_packing packing, const char *name); /** Constructor for array types */ - glsl_type(const glsl_type *array, unsigned length); + glsl_type(const glsl_type *array, unsigned length, bool was_unsized); /** Hash table containing the known array types. */ static struct hash_table *array_types; diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 9798afe..8eace14 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1261,7 +1261,7 @@ private: { if ((*type)->is_unsized_array()) { *type = glsl_type::get_array_instance((*type)->fields.array, - max_array_access + 1); + max_array_access + 1, true); assert(*type != NULL); } } -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 06/11] glsl: lower cull_distance into cull_distance_mesa
From: Dave Airlie <airlied at redhat.com> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/glsl/Makefile.sources | 1 + src/glsl/ir_optimization.h | 1 + src/glsl/link_varyings.cpp | 15 +- src/glsl/link_varyings.h | 3 +- src/glsl/linker.cpp | 1 + src/glsl/lower_cull_distance.cpp | 549 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 565 insertions(+), 5 deletions(-) create mode 100644 src/glsl/lower_cull_distance.cpp diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index d784a81..502b6ca 100644 --- a/src/glsl/Makefile.sources +++ b/src/glsl/Makefile.sources @@ -143,6 +143,7 @@ LIBGLSL_FILES = \ loop_unroll.cpp \ lower_clip_distance.cpp \ lower_const_arrays_to_uniforms.cpp \ + lower_cull_distance.cpp \ lower_discard.cpp \ lower_discard_flow.cpp \ lower_if_to_cond_assign.cpp \ diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index e6939f3..1220df6 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -119,6 +119,7 @@ bool lower_variable_index_to_cond_assign(exec_list *instructions, bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz); bool lower_const_arrays_to_uniforms(exec_list *instructions); bool lower_clip_distance(gl_shader *shader); +bool lower_cull_distance(gl_shader *shader); void lower_output_reads(exec_list *instructions); bool lower_packing_builtins(exec_list *instructions, int op_mask); void lower_ubo_reference(struct gl_shader *shader, exec_list *instructions); diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp index 7b2d4bd..46f84c6 100644 --- a/src/glsl/link_varyings.cpp +++ b/src/glsl/link_varyings.cpp @@ -301,6 +301,7 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx, this->location = -1; this->orig_name = input; this->is_clip_distance_mesa = false; + this->is_cull_distance_mesa = false; this->skip_components = 0; this->next_buffer_separator = false; this->matched_candidate = NULL; @@ -351,6 +352,10 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx, strcmp(this->var_name, "gl_ClipDistance") == 0) { this->is_clip_distance_mesa = true; } + if (ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance && + strcmp(this->var_name, "gl_CullDistance") == 0) { + this->is_cull_distance_mesa = true; + } } @@ -397,7 +402,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, this->matched_candidate->type->fields.array->matrix_columns; const unsigned vector_elements this->matched_candidate->type->fields.array->vector_elements; - unsigned actual_array_size = this->is_clip_distance_mesa ? + unsigned actual_array_size + (this->is_clip_distance_mesa || this->is_cull_distance_mesa) ? prog->LastClipDistanceArraySize : this->matched_candidate->type->array_size(); @@ -410,7 +416,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, actual_array_size); return false; } - unsigned array_elem_size = this->is_clip_distance_mesa ? + unsigned array_elem_size + (this->is_clip_distance_mesa || this->is_cull_distance_mesa) ? 1 : vector_elements * matrix_cols; fine_location += array_elem_size * this->array_subscript; this->size = 1; @@ -419,7 +426,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, } this->vector_elements = vector_elements; this->matrix_columns = matrix_cols; - if (this->is_clip_distance_mesa) + if (this->is_clip_distance_mesa || this->is_cull_distance_mesa) this->type = GL_FLOAT; else this->type = this->matched_candidate->type->fields.array->gl_type; @@ -542,7 +549,7 @@ const tfeedback_candidate * tfeedback_decl::find_candidate(gl_shader_program *prog, hash_table *tfeedback_candidates) { - const char *name = this->is_clip_distance_mesa + const char *name = this->is_cull_distance_mesa ? "gl_CullDistanceMESA" : this->is_clip_distance_mesa ? "gl_ClipDistanceMESA" : this->var_name; this->matched_candidate = (const tfeedback_candidate *) hash_table_find(tfeedback_candidates, name); diff --git a/src/glsl/link_varyings.h b/src/glsl/link_varyings.h index afc16a8..842ab7c 100644 --- a/src/glsl/link_varyings.h +++ b/src/glsl/link_varyings.h @@ -128,7 +128,7 @@ public: */ unsigned num_components() const { - if (this->is_clip_distance_mesa) + if (this->is_clip_distance_mesa || this->is_cull_distance_mesa) return this->size; else return this->vector_elements * this->matrix_columns * this->size; @@ -165,6 +165,7 @@ private: * gl_ClipDistance to gl_ClipDistanceMESA. */ bool is_clip_distance_mesa; + bool is_cull_distance_mesa; /** * The vertex shader output location that the linker assigned for this diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 8eace14..e616520 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -2938,6 +2938,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (ctx->Const.ShaderCompilerOptions[i].LowerClipDistance) { lower_clip_distance(prog->_LinkedShaders[i]); + lower_cull_distance(prog->_LinkedShaders[i]); } while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, diff --git a/src/glsl/lower_cull_distance.cpp b/src/glsl/lower_cull_distance.cpp new file mode 100644 index 0000000..d3b9592 --- /dev/null +++ b/src/glsl/lower_cull_distance.cpp @@ -0,0 +1,549 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file lower_cull_distance.cpp + * + * This pass accounts for the difference between the way + * gl_CullDistance is declared in standard GLSL (as an array of + * floats), and the way it is frequently implemented in hardware (as + * a pair of vec4s, with four cull distances packed into each). + * + * The declaration of gl_CullDistance is replaced with a declaration + * of gl_CullDistanceMESA, and any references to gl_CullDistance are + * translated to refer to gl_CullDistanceMESA with the appropriate + * swizzling of array indices. For instance: + * + * gl_CullDistance[i] + * + * is translated into: + * + * gl_CullDistanceMESA[i>>2][i&3] + * + * Since some hardware may not internally represent gl_CullDistance as a pair + * of vec4's, this lowering pass is optional. To enable it, set the + * LowerCullDistance flag in gl_shader_compiler_options to true. + */ + +#include "glsl_symbol_table.h" +#include "ir_rvalue_visitor.h" +#include "ir.h" +#include "program/prog_instruction.h" /* For WRITEMASK_* */ + +namespace { + +class lower_cull_distance_visitor : public ir_rvalue_visitor { +public: + explicit lower_cull_distance_visitor(gl_shader_stage shader_stage) + : progress(false), old_cull_distance_1d_var(NULL), + old_cull_distance_2d_var(NULL), new_cull_distance_1d_var(NULL), + new_cull_distance_2d_var(NULL), shader_stage(shader_stage) + { + } + + virtual ir_visitor_status visit(ir_variable *); + void create_indices(ir_rvalue*, ir_rvalue *&, ir_rvalue *&); + bool is_cull_distance_vec8(ir_rvalue *ir); + ir_rvalue *lower_cull_distance_vec8(ir_rvalue *ir); + virtual ir_visitor_status visit_leave(ir_assignment *); + void visit_new_assignment(ir_assignment *ir); + virtual ir_visitor_status visit_leave(ir_call *); + + virtual void handle_rvalue(ir_rvalue **rvalue); + + void fix_lhs(ir_assignment *); + + bool progress; + + /** + * Pointer to the declaration of gl_CullDistance, if found. + * + * Note: + * + * - the 2d_var is for geometry shader input only. + * + * - since gl_CullDistance is available in geometry shaders as both an + * input and an output, it's possible for both old_cull_distance_1d_var + * and old_cull_distance_2d_var to be non-null. + */ + ir_variable *old_cull_distance_1d_var; + ir_variable *old_cull_distance_2d_var; + + /** + * Pointer to the newly-created gl_CullDistanceMESA variable. + */ + ir_variable *new_cull_distance_1d_var; + ir_variable *new_cull_distance_2d_var; + + /** + * Type of shader we are compiling (e.g. MESA_SHADER_VERTEX) + */ + const gl_shader_stage shader_stage; +}; + +} /* anonymous namespace */ + +/** + * Replace any declaration of gl_CullDistance as an array of floats with a + * declaration of gl_CullDistanceMESA as an array of vec4's. + */ +ir_visitor_status +lower_cull_distance_visitor::visit(ir_variable *ir) +{ + if (!ir->name || strcmp(ir->name, "gl_CullDistance") != 0) + return visit_continue; + assert (ir->type->is_array()); + + if (!ir->type->fields.array->is_array()) { + /* 1D gl_CullDistance (used for vertex and geometry output, and fragment + * input). + */ + if (this->old_cull_distance_1d_var) + return visit_continue; + + this->progress = true; + this->old_cull_distance_1d_var = ir; + assert (ir->type->fields.array == glsl_type::float_type); + unsigned new_size = (ir->type->array_size() + 3) / 4; + + /* Clone the old var so that we inherit all of its properties */ + this->new_cull_distance_1d_var = ir->clone(ralloc_parent(ir), NULL); + + /* And change the properties that we need to change */ + this->new_cull_distance_1d_var->name + = ralloc_strdup(this->new_cull_distance_1d_var, + "gl_CullDistanceMESA"); + this->new_cull_distance_1d_var->type + = glsl_type::get_array_instance(glsl_type::vec4_type, new_size); + this->new_cull_distance_1d_var->data.max_array_access + = ir->data.max_array_access / 4; + + ir->replace_with(this->new_cull_distance_1d_var); + } else { + /* 2D gl_CullDistance (used for geometry input). */ + assert(ir->data.mode == ir_var_shader_in && + this->shader_stage == MESA_SHADER_GEOMETRY); + if (this->old_cull_distance_2d_var) + return visit_continue; + + this->progress = true; + this->old_cull_distance_2d_var = ir; + assert (ir->type->fields.array->fields.array == glsl_type::float_type); + unsigned new_size = (ir->type->fields.array->array_size() + 3) / 4; + + /* Clone the old var so that we inherit all of its properties */ + this->new_cull_distance_2d_var = ir->clone(ralloc_parent(ir), NULL); + + /* And change the properties that we need to change */ + this->new_cull_distance_2d_var->name + = ralloc_strdup(this->new_cull_distance_2d_var, "gl_CullDistanceMESA"); + this->new_cull_distance_2d_var->type = glsl_type::get_array_instance( + glsl_type::get_array_instance(glsl_type::vec4_type, + new_size), + ir->type->array_size()); + this->new_cull_distance_2d_var->data.max_array_access + = ir->data.max_array_access / 4; + + ir->replace_with(this->new_cull_distance_2d_var); + } + return visit_continue; +} + + +/** + * Create the necessary GLSL rvalues to index into gl_CullDistanceMESA based + * on the rvalue previously used to index into gl_CullDistance. + * + * \param array_index Selects one of the vec4's in gl_CullDistanceMESA + * \param swizzle_index Selects a component within the vec4 selected by + * array_index. + */ +void +lower_cull_distance_visitor::create_indices(ir_rvalue *old_index, + ir_rvalue *&array_index, + ir_rvalue *&swizzle_index) +{ + void *ctx = ralloc_parent(old_index); + + /* Make sure old_index is a signed int so that the bitwise "shift" and + * "and" operations below type check properly. + */ + if (old_index->type != glsl_type::int_type) { + assert (old_index->type == glsl_type::uint_type); + old_index = new(ctx) ir_expression(ir_unop_u2i, old_index); + } + + ir_constant *old_index_constant = old_index->constant_expression_value(); + if (old_index_constant) { + /* gl_CullDistance is being accessed via a constant index. Don't bother + * creating expressions to calculate the lowered indices. Just create + * constants. + */ + int const_val = old_index_constant->get_int_component(0); + array_index = new(ctx) ir_constant(const_val / 4); + swizzle_index = new(ctx) ir_constant(const_val % 4); + } else { + /* Create a variable to hold the value of old_index (so that we + * don't compute it twice). + */ + ir_variable *old_index_var = new(ctx) ir_variable( + glsl_type::int_type, "cull_distance_index", ir_var_temporary); + this->base_ir->insert_before(old_index_var); + this->base_ir->insert_before(new(ctx) ir_assignment( + new(ctx) ir_dereference_variable(old_index_var), old_index)); + + /* Create the expression cull_distance_index / 4. Do this as a bit + * shift because that's likely to be more efficient. + */ + array_index = new(ctx) ir_expression( + ir_binop_rshift, new(ctx) ir_dereference_variable(old_index_var), + new(ctx) ir_constant(2)); + + /* Create the expression cull_distance_index % 4. Do this as a bitwise + * AND because that's likely to be more efficient. + */ + swizzle_index = new(ctx) ir_expression( + ir_binop_bit_and, new(ctx) ir_dereference_variable(old_index_var), + new(ctx) ir_constant(3)); + } +} + + +/** + * Determine whether the given rvalue describes an array of 8 floats that + * needs to be lowered to an array of 2 vec4's; that is, determine whether it + * matches one of the following patterns: + * + * - gl_CullDistance (if gl_CullDistance is 1D) + * - gl_CullDistance[i] (if gl_CullDistance is 2D) + */ +bool +lower_cull_distance_visitor::is_cull_distance_vec8(ir_rvalue *ir) +{ + /* Note that geometry shaders contain gl_CullDistance both as an input + * (which is a 2D array) and an output (which is a 1D array), so it's + * possible for both this->old_cull_distance_1d_var and + * this->old_cull_distance_2d_var to be non-NULL in the same shader. + */ + + if (this->old_cull_distance_1d_var) { + ir_dereference_variable *var_ref = ir->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_cull_distance_1d_var) + return true; + } + if (this->old_cull_distance_2d_var) { + /* 2D cull distance is only possible as a geometry input */ + assert(this->shader_stage == MESA_SHADER_GEOMETRY); + + ir_dereference_array *array_ref = ir->as_dereference_array(); + if (array_ref) { + ir_dereference_variable *var_ref + array_ref->array->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_cull_distance_2d_var) + return true; + } + } + return false; +} + + +/** + * If the given ir satisfies is_cull_distance_vec8(), return new ir + * representing its lowered equivalent. That is, map: + * + * - gl_CullDistance => gl_CullDistanceMESA (if gl_CullDistance is 1D) + * - gl_CullDistance[i] => gl_CullDistanceMESA[i] (if gl_CullDistance is 2D) + * + * Otherwise return NULL. + */ +ir_rvalue * +lower_cull_distance_visitor::lower_cull_distance_vec8(ir_rvalue *ir) +{ + if (this->old_cull_distance_1d_var) { + ir_dereference_variable *var_ref = ir->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_cull_distance_1d_var) { + return new(ralloc_parent(ir)) + ir_dereference_variable(this->new_cull_distance_1d_var); + } + } + if (this->old_cull_distance_2d_var) { + /* 2D cull distance is only possible as a geometry input */ + assert(this->shader_stage == MESA_SHADER_GEOMETRY); + + ir_dereference_array *array_ref = ir->as_dereference_array(); + if (array_ref) { + ir_dereference_variable *var_ref + array_ref->array->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_cull_distance_2d_var) { + return new(ralloc_parent(ir)) + ir_dereference_array(this->new_cull_distance_2d_var, + array_ref->array_index); + } + } + } + return NULL; +} + + +void +lower_cull_distance_visitor::handle_rvalue(ir_rvalue **rv) +{ + if (*rv == NULL) + return; + + ir_dereference_array *const array_deref = (*rv)->as_dereference_array(); + if (array_deref == NULL) + return; + + /* Replace any expression that indexes one of the floats in gl_CullDistance + * with an expression that indexes into one of the vec4's in + * gl_CullDistanceMESA and accesses the appropriate component. + */ + ir_rvalue *lowered_vec8 + this->lower_cull_distance_vec8(array_deref->array); + if (lowered_vec8 != NULL) { + this->progress = true; + ir_rvalue *array_index; + ir_rvalue *swizzle_index; + this->create_indices(array_deref->array_index, array_index, swizzle_index); + void *mem_ctx = ralloc_parent(array_deref); + + ir_dereference_array *const new_array_deref + new(mem_ctx) ir_dereference_array(lowered_vec8, array_index); + + ir_expression *const expr + new(mem_ctx) ir_expression(ir_binop_vector_extract, + new_array_deref, + swizzle_index); + + *rv = expr; + } +} + +void +lower_cull_distance_visitor::fix_lhs(ir_assignment *ir) +{ + if (ir->lhs->ir_type == ir_type_expression) { + void *mem_ctx = ralloc_parent(ir); + ir_expression *const expr = (ir_expression *) ir->lhs; + + /* The expression must be of the form: + * + * (vector_extract gl_CullDistanceMESA[i], j). + */ + assert(expr->operation == ir_binop_vector_extract); + assert(expr->operands[0]->ir_type == ir_type_dereference_array); + assert(expr->operands[0]->type == glsl_type::vec4_type); + + ir_dereference *const new_lhs = (ir_dereference *) expr->operands[0]; + ir->rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert, + glsl_type::vec4_type, + new_lhs->clone(mem_ctx, NULL), + ir->rhs, + expr->operands[1]); + ir->set_lhs(new_lhs); + ir->write_mask = WRITEMASK_XYZW; + } +} + +/** + * Replace any assignment having the 1D gl_CullDistance (undereferenced) as + * its LHS or RHS with a sequence of assignments, one for each component of + * the array. Each of these assignments is lowered to refer to + * gl_CullDistanceMESA as appropriate. + * + * We need to do a similar replacement for 2D gl_CullDistance, however since + * it's an input, the only case we need to address is where a 1D slice of it + * is the entire RHS of an assignment, e.g.: + * + * foo = gl_in[i].gl_CullDistance + */ +ir_visitor_status +lower_cull_distance_visitor::visit_leave(ir_assignment *ir) +{ + /* First invoke the base class visitor. This causes handle_rvalue() to be + * called on ir->rhs and ir->condition. + */ + ir_rvalue_visitor::visit_leave(ir); + + if (this->is_cull_distance_vec8(ir->lhs) || + this->is_cull_distance_vec8(ir->rhs)) { + /* LHS or RHS of the assignment is the entire 1D gl_CullDistance array + * (or a 1D slice of a 2D gl_CullDistance input array). Since we are + * reshaping gl_CullDistance from an array of floats to an array of + * vec4's, this isn't going to work as a bulk assignment anymore, so + * unroll it to element-by-element assignments and lower each of them. + * + * Note: to unroll into element-by-element assignments, we need to make + * clones of the LHS and RHS. This is safe because expressions and + * l-values are side-effect free. + */ + void *ctx = ralloc_parent(ir); + int array_size = ir->lhs->type->array_size(); + for (int i = 0; i < array_size; ++i) { + ir_dereference_array *new_lhs = new(ctx) ir_dereference_array( + ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i)); + ir_dereference_array *new_rhs = new(ctx) ir_dereference_array( + ir->rhs->clone(ctx, NULL), new(ctx) ir_constant(i)); + this->handle_rvalue((ir_rvalue **) &new_rhs); + + /* Handle the LHS after creating the new assignment. This must + * happen in this order because handle_rvalue may replace the old LHS + * with an ir_expression of ir_binop_vector_extract. Since this is + * not a valide l-value, this will cause an assertion in the + * ir_assignment constructor to fail. + * + * If this occurs, replace the mangled LHS with a dereference of the + * vector, and replace the RHS with an ir_triop_vector_insert. + */ + ir_assignment *const assign = new(ctx) ir_assignment(new_lhs, new_rhs); + this->handle_rvalue((ir_rvalue **) &assign->lhs); + this->fix_lhs(assign); + + this->base_ir->insert_before(assign); + } + ir->remove(); + + return visit_continue; + } + + /* Handle the LHS as if it were an r-value. Normally + * rvalue_visit(ir_assignment *) only visits the RHS, but we need to lower + * expressions in the LHS as well. + * + * This may cause the LHS to get replaced with an ir_expression of + * ir_binop_vector_extract. If this occurs, replace it with a dereference + * of the vector, and replace the RHS with an ir_triop_vector_insert. + */ + handle_rvalue((ir_rvalue **)&ir->lhs); + this->fix_lhs(ir); + + return rvalue_visit(ir); +} + + +/** + * Set up base_ir properly and call visit_leave() on a newly created + * ir_assignment node. This is used in cases where we have to insert an + * ir_assignment in a place where we know the hierarchical visitor won't see + * it. + */ +void +lower_cull_distance_visitor::visit_new_assignment(ir_assignment *ir) +{ + ir_instruction *old_base_ir = this->base_ir; + this->base_ir = ir; + ir->accept(this); + this->base_ir = old_base_ir; +} + + +/** + * If a 1D gl_CullDistance variable appears as an argument in an ir_call + * expression, replace it with a temporary variable, and make sure the ir_call + * is preceded and/or followed by assignments that copy the contents of the + * temporary variable to and/or from gl_CullDistance. Each of these + * assignments is then lowered to refer to gl_CullDistanceMESA. + * + * We need to do a similar replacement for 2D gl_CullDistance, however since + * it's an input, the only case we need to address is where a 1D slice of it + * is passed as an "in" parameter to an ir_call, e.g.: + * + * foo(gl_in[i].gl_CullDistance) + */ +ir_visitor_status +lower_cull_distance_visitor::visit_leave(ir_call *ir) +{ + void *ctx = ralloc_parent(ir); + + const exec_node *formal_param_node = ir->callee->parameters.head; + const exec_node *actual_param_node = ir->actual_parameters.head; + while (!actual_param_node->is_tail_sentinel()) { + ir_variable *formal_param = (ir_variable *) formal_param_node; + ir_rvalue *actual_param = (ir_rvalue *) actual_param_node; + + /* Advance formal_param_node and actual_param_node now so that we can + * safely replace actual_param with another node, if necessary, below. + */ + formal_param_node = formal_param_node->next; + actual_param_node = actual_param_node->next; + + if (this->is_cull_distance_vec8(actual_param)) { + /* User is trying to pass the whole 1D gl_CullDistance array (or a 1D + * slice of a 2D gl_CullDistance array) to a function call. Since we + * are reshaping gl_CullDistance from an array of floats to an array + * of vec4's, this isn't going to work anymore, so use a temporary + * array instead. + */ + ir_variable *temp_cull_distance = new(ctx) ir_variable( + actual_param->type, "temp_cull_distance", ir_var_temporary); + this->base_ir->insert_before(temp_cull_distance); + actual_param->replace_with( + new(ctx) ir_dereference_variable(temp_cull_distance)); + if (formal_param->data.mode == ir_var_function_in + || formal_param->data.mode == ir_var_function_inout) { + /* Copy from gl_CullDistance to the temporary before the call. + * Since we are going to insert this copy before the current + * instruction, we need to visit it afterwards to make sure it + * gets lowered. + */ + ir_assignment *new_assignment = new(ctx) ir_assignment( + new(ctx) ir_dereference_variable(temp_cull_distance), + actual_param->clone(ctx, NULL)); + this->base_ir->insert_before(new_assignment); + this->visit_new_assignment(new_assignment); + } + if (formal_param->data.mode == ir_var_function_out + || formal_param->data.mode == ir_var_function_inout) { + /* Copy from the temporary to gl_CullDistance after the call. + * Since visit_list_elements() has already decided which + * instruction it's going to visit next, we need to visit + * afterwards to make sure it gets lowered. + */ + ir_assignment *new_assignment = new(ctx) ir_assignment( + actual_param->clone(ctx, NULL), + new(ctx) ir_dereference_variable(temp_cull_distance)); + this->base_ir->insert_after(new_assignment); + this->visit_new_assignment(new_assignment); + } + } + } + + return rvalue_visit(ir); +} + + +bool +lower_cull_distance(gl_shader *shader) +{ + lower_cull_distance_visitor v(shader->Stage); + + visit_list_elements(&v, shader->ir); + + if (v.new_cull_distance_1d_var) + shader->symbols->add_variable(v.new_cull_distance_1d_var); + if (v.new_cull_distance_2d_var) + shader->symbols->add_variable(v.new_cull_distance_2d_var); + + return v.progress; +} -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 07/11] glsl: Add arb_cull_distance support
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at 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
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 08/11] i965: rename UsesClipDistanceOut to UsesClipCullDistanceOut
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 2 +- src/mesa/drivers/dri/i965/brw_gs.c | 2 +- src/mesa/drivers/dri/i965/brw_vec4.cpp | 2 +- src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 2 +- src/mesa/drivers/dri/i965/brw_vs.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index ead7768..c4439fd 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -3912,7 +3912,7 @@ fs_visitor::emit_urb_writes() fs_reg sources[8]; /* Lower legacy ff and ClipVertex clipping to clip distances */ - if (key->base.userclip_active && !prog->UsesClipDistanceOut) + if (key->base.userclip_active && !prog->UsesClipCullDistanceOut) compute_clip_distance(); /* If we don't have any valid slots to write, just do a minimal urb write diff --git a/src/mesa/drivers/dri/i965/brw_gs.c b/src/mesa/drivers/dri/i965/brw_gs.c index 52c7303..2cb3fe2 100644 --- a/src/mesa/drivers/dri/i965/brw_gs.c +++ b/src/mesa/drivers/dri/i965/brw_gs.c @@ -314,7 +314,7 @@ brw_gs_populate_key(struct brw_context *brw, key->base.program_string_id = gp->id; brw_setup_vue_key_clip_info(brw, &key->base, - gp->program.Base.UsesClipDistanceOut); + gp->program.Base.UsesClipCullDistanceOut); /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count, diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index e9681b7..d99dcd0 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -1730,7 +1730,7 @@ vec4_visitor::run() } base_ir = NULL; - if (key->userclip_active && !prog->UsesClipDistanceOut) + if (key->userclip_active && !prog->UsesClipCullDistanceOut) setup_uniform_clipplane_values(); emit_thread_end(); diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index 5a60fe4..0401171 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -3250,7 +3250,7 @@ vec4_visitor::emit_vertex() } /* Lower legacy ff and ClipVertex clipping to clip distances */ - if (key->userclip_active && !prog->UsesClipDistanceOut) { + if (key->userclip_active && !prog->UsesClipCullDistanceOut) { current_annotation = "user clip distances"; output_reg[VARYING_SLOT_CLIP_DIST0] = dst_reg(this, glsl_type::vec4_type); diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c index d03567e..eb69cc7 100644 --- a/src/mesa/drivers/dri/i965/brw_vs.c +++ b/src/mesa/drivers/dri/i965/brw_vs.c @@ -435,7 +435,7 @@ brw_vs_populate_key(struct brw_context *brw, */ key->base.program_string_id = vp->id; brw_setup_vue_key_clip_info(brw, &key->base, - vp->program.Base.UsesClipDistanceOut); + vp->program.Base.UsesClipCullDistanceOut); /* _NEW_POLYGON */ if (brw->gen < 6) { -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 09/11] gallium: add support for arb_cull_distance
Add another pipe cap so we can savely enable of disable this extension Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/gallium/auxiliary/cso_cache/cso_context.c | 3 +++ src/gallium/drivers/freedreno/freedreno_screen.c | 1 + src/gallium/drivers/i915/i915_screen.c | 1 + src/gallium/drivers/ilo/ilo_screen.c | 1 + src/gallium/drivers/llvmpipe/lp_screen.c | 2 ++ src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 + src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 + src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 + src/gallium/drivers/r300/r300_screen.c | 1 + src/gallium/drivers/r600/r600_pipe.c | 1 + src/gallium/drivers/radeonsi/si_pipe.c | 1 + src/gallium/drivers/softpipe/sp_screen.c | 2 ++ src/gallium/drivers/svga/svga_screen.c | 1 + src/gallium/drivers/vc4/vc4_screen.c | 1 + src/gallium/include/pipe/p_defines.h | 1 + 15 files changed, 19 insertions(+) diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 744b00c..7612b43 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -119,6 +119,9 @@ struct cso_context { struct pipe_clip_state clip; struct pipe_clip_state clip_saved; + struct pipe_clip_state cull; + struct pipe_clip_state cull_saved; + struct pipe_framebuffer_state fb, fb_saved; struct pipe_viewport_state vp, vp_saved; struct pipe_blend_color blend_color; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index c596d03..986a942 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -221,6 +221,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_MAX_VIEWPORTS: diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index 03fecd1..678347d 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -242,6 +242,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: diff --git a/src/gallium/drivers/ilo/ilo_screen.c b/src/gallium/drivers/ilo/ilo_screen.c index b0fed73..f92d5de 100644 --- a/src/gallium/drivers/ilo/ilo_screen.c +++ b/src/gallium/drivers/ilo/ilo_screen.c @@ -459,6 +459,7 @@ ilo_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 09ac9af..c90c405 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -293,6 +293,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: return 0; + case PIPE_CAP_CULL_DISTANCE: + return 0; } /* should only get here on unhandled cases */ debug_printf("Unexpected PIPE_CAP %d query\n", param); diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c index bb79ccc..fc33ddf 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c @@ -162,6 +162,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c index f455a7f..d8efd75 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c @@ -210,6 +210,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: /* potentially supported on some hw */ case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index 1ca997a..c942dda 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -194,6 +194,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 8e1d710..00bb6dd 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -191,6 +191,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; /* SWTCL-only features. */ diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 5a8eb06..87f556b 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -333,6 +333,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_SAMPLER_VIEW_TARGET: case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; /* Stream output. */ diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 9d60ef1..7ec9758 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -294,6 +294,7 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_SAMPLER_VIEW_TARGET: case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index a688d31..c0d7d86 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -243,6 +243,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: return 0; + case PIPE_CAP_CULL_DISTANCE: + return 0; } /* should only get here on unhandled cases */ debug_printf("Unexpected PIPE_CAP %d query\n", param); diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index 549a89a..6e5a3da 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -285,6 +285,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_POLYGON_OFFSET_CLAMP: case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: + case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: return 64; diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c index 134d644..565f0c4 100644 --- a/src/gallium/drivers/vc4/vc4_screen.c +++ b/src/gallium/drivers/vc4/vc4_screen.c @@ -176,6 +176,7 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: + case PIPE_CAP_CULL_DISTANCE: return 0; /* Stream output. */ diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 8fabf5e..50f9cfe 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -605,6 +605,7 @@ enum pipe_cap PIPE_CAP_MULTISAMPLE_Z_RESOLVE = 114, PIPE_CAP_RESOURCE_FROM_USER_MEMORY = 115, PIPE_CAP_DEVICE_RESET_STATUS_QUERY = 116, + PIPE_CAP_CULL_DISTANCE = 117, }; #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0) -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 10/11] nouveau/codegen: sort in galliums cull_distance semantic into the drivers bitmask
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp index ecd115f..381a958 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp @@ -1063,6 +1063,11 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl) decl->Declaration.UsageMask << (si * 4); info->io.genUserClip = -1; break; + case TGSI_SEMANTIC_CULLDIST: + info->io.cullDistanceMask |+ decl->Declaration.UsageMask << (si * 4); + info->io.genUserClip = -1; + break; case TGSI_SEMANTIC_SAMPLEMASK: info->io.sampleMask = i; break; -- 2.4.1
Tobias Klausmann
2015-May-24 17:58 UTC
[Nouveau] [PATCH 11/11] nouveau/nvc0: implement cull_distance as a special form of clip distance
This enables ARB_cull_distance. Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> --- docs/GL3.txt | 2 +- docs/relnotes/10.7.0.html | 4 +++- src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 6 +++++- src/gallium/drivers/nouveau/nvc0/nvc0_program.h | 1 + src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 2 +- src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c | 1 + 6 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/GL3.txt b/docs/GL3.txt index 9d56ee5..ebdae38 100644 --- a/docs/GL3.txt +++ b/docs/GL3.txt @@ -190,7 +190,7 @@ GL 4.5, GLSL 4.50: GL_ARB_ES3_1_compatibility not started GL_ARB_clip_control DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe) GL_ARB_conditional_render_inverted DONE (i965, nv50, nvc0, llvmpipe, softpipe) - GL_ARB_cull_distance not started + GL_ARB_cull_distance DONE (nvc0) GL_ARB_derivative_control DONE (i965, nv50, nvc0, r600) GL_ARB_direct_state_access DONE (all drivers) - Transform Feedback object DONE diff --git a/docs/relnotes/10.7.0.html b/docs/relnotes/10.7.0.html index 6206716..12e6b5b 100644 --- a/docs/relnotes/10.7.0.html +++ b/docs/relnotes/10.7.0.html @@ -43,7 +43,9 @@ TBD. Note: some of the new features are only available with certain drivers. </p> -TBD. +<ul> +<li>GL_ARB_cull_distance on nvc0</li> +</ul> <h2>Bug fixes</h2> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c index 4a47cb2..aa3b751 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c @@ -46,6 +46,7 @@ nvc0_shader_input_address(unsigned sn, unsigned si, unsigned ubase) case TGSI_SEMANTIC_BCOLOR: return 0x2a0 + si * 0x10; case NV50_SEMANTIC_CLIPDISTANCE: return 0x2c0 + si * 0x4; case TGSI_SEMANTIC_CLIPDIST: return 0x2c0 + si * 0x10; + case TGSI_SEMANTIC_CULLDIST: return 0x2c0 + si * 0x10; case TGSI_SEMANTIC_CLIPVERTEX: return 0x270; case TGSI_SEMANTIC_PCOORD: return 0x2e0; case NV50_SEMANTIC_TESSCOORD: return 0x2f0; @@ -75,6 +76,7 @@ nvc0_shader_output_address(unsigned sn, unsigned si, unsigned ubase) case TGSI_SEMANTIC_BCOLOR: return 0x2a0 + si * 0x10; case NV50_SEMANTIC_CLIPDISTANCE: return 0x2c0 + si * 0x4; case TGSI_SEMANTIC_CLIPDIST: return 0x2c0 + si * 0x10; + case TGSI_SEMANTIC_CULLDIST: return 0x2c0 + si * 0x10; case TGSI_SEMANTIC_CLIPVERTEX: return 0x270; case TGSI_SEMANTIC_TEXCOORD: return 0x300 + si * 0x10; case TGSI_SEMANTIC_EDGEFLAG: return ~0; @@ -255,11 +257,13 @@ nvc0_vtgp_gen_header(struct nvc0_program *vp, struct nv50_ir_prog_info *info) } } - vp->vp.clip_enable = info->io.clipDistanceMask; for (i = 0; i < 8; ++i) if (info->io.cullDistanceMask & (1 << i)) vp->vp.clip_mode |= 1 << (i * 4); + vp->vp.clip_enable = info->io.clipDistanceMask; + vp->vp.cull_enable = info->io.cullDistanceMask; + if (info->io.genUserClip < 0) vp->vp.num_ucps = PIPE_MAX_CLIP_PLANES + 1; /* prevent rebuilding */ diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.h b/src/gallium/drivers/nouveau/nvc0/nvc0_program.h index 3fd9d21..b8b1a5a 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.h @@ -39,6 +39,7 @@ struct nvc0_program { struct { uint32_t clip_mode; /* clip/cull selection */ uint8_t clip_enable; /* mask of defined clip planes */ + uint8_t cull_enable; /* mask of defined cull planes */ uint8_t num_ucps; /* also set to max if ClipDistance is used */ uint8_t edgeflag; /* attribute index of edgeflag input */ boolean need_vertex_id; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index c942dda..56d22a0 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -174,6 +174,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_CLIP_HALFZ: case PIPE_CAP_POLYGON_OFFSET_CLAMP: case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: + case PIPE_CAP_CULL_DISTANCE: return 1; case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: return (class_3d >= NVE4_3D_CLASS) ? 1 : 0; @@ -194,7 +195,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: - case PIPE_CAP_CULL_DISTANCE: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c index d3ad81d..abb1c0e 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c @@ -372,6 +372,7 @@ nvc0_validate_clip(struct nvc0_context *nvc0) nvc0_upload_uclip_planes(nvc0, stage); clip_enable &= vp->vp.clip_enable; + clip_enable |= vp->vp.cull_enable; if (nvc0->state.clip_enable != clip_enable) { nvc0->state.clip_enable = clip_enable; -- 2.4.1
Marek Olšák
2015-May-24 18:09 UTC
[Nouveau] [Mesa-dev] [PATCH 06/11] glsl: lower cull_distance into cull_distance_mesa
Would it be possible to modify lower_clip_distance to add support for cull distances instead of duplicating it? Marek On Sun, May 24, 2015 at 7:58 PM, Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> wrote:> From: Dave Airlie <airlied at redhat.com> > > Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> > --- > src/glsl/Makefile.sources | 1 + > src/glsl/ir_optimization.h | 1 + > src/glsl/link_varyings.cpp | 15 +- > src/glsl/link_varyings.h | 3 +- > src/glsl/linker.cpp | 1 + > src/glsl/lower_cull_distance.cpp | 549 +++++++++++++++++++++++++++++++++++++++ > 6 files changed, 565 insertions(+), 5 deletions(-) > create mode 100644 src/glsl/lower_cull_distance.cpp > > diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources > index d784a81..502b6ca 100644 > --- a/src/glsl/Makefile.sources > +++ b/src/glsl/Makefile.sources > @@ -143,6 +143,7 @@ LIBGLSL_FILES = \ > loop_unroll.cpp \ > lower_clip_distance.cpp \ > lower_const_arrays_to_uniforms.cpp \ > + lower_cull_distance.cpp \ > lower_discard.cpp \ > lower_discard_flow.cpp \ > lower_if_to_cond_assign.cpp \ > diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h > index e6939f3..1220df6 100644 > --- a/src/glsl/ir_optimization.h > +++ b/src/glsl/ir_optimization.h > @@ -119,6 +119,7 @@ bool lower_variable_index_to_cond_assign(exec_list *instructions, > bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz); > bool lower_const_arrays_to_uniforms(exec_list *instructions); > bool lower_clip_distance(gl_shader *shader); > +bool lower_cull_distance(gl_shader *shader); > void lower_output_reads(exec_list *instructions); > bool lower_packing_builtins(exec_list *instructions, int op_mask); > void lower_ubo_reference(struct gl_shader *shader, exec_list *instructions); > diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp > index 7b2d4bd..46f84c6 100644 > --- a/src/glsl/link_varyings.cpp > +++ b/src/glsl/link_varyings.cpp > @@ -301,6 +301,7 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx, > this->location = -1; > this->orig_name = input; > this->is_clip_distance_mesa = false; > + this->is_cull_distance_mesa = false; > this->skip_components = 0; > this->next_buffer_separator = false; > this->matched_candidate = NULL; > @@ -351,6 +352,10 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx, > strcmp(this->var_name, "gl_ClipDistance") == 0) { > this->is_clip_distance_mesa = true; > } > + if (ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance && > + strcmp(this->var_name, "gl_CullDistance") == 0) { > + this->is_cull_distance_mesa = true; > + } > } > > > @@ -397,7 +402,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, > this->matched_candidate->type->fields.array->matrix_columns; > const unsigned vector_elements > this->matched_candidate->type->fields.array->vector_elements; > - unsigned actual_array_size = this->is_clip_distance_mesa ? > + unsigned actual_array_size > + (this->is_clip_distance_mesa || this->is_cull_distance_mesa) ? > prog->LastClipDistanceArraySize : > this->matched_candidate->type->array_size(); > > @@ -410,7 +416,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, > actual_array_size); > return false; > } > - unsigned array_elem_size = this->is_clip_distance_mesa ? > + unsigned array_elem_size > + (this->is_clip_distance_mesa || this->is_cull_distance_mesa) ? > 1 : vector_elements * matrix_cols; > fine_location += array_elem_size * this->array_subscript; > this->size = 1; > @@ -419,7 +426,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, > } > this->vector_elements = vector_elements; > this->matrix_columns = matrix_cols; > - if (this->is_clip_distance_mesa) > + if (this->is_clip_distance_mesa || this->is_cull_distance_mesa) > this->type = GL_FLOAT; > else > this->type = this->matched_candidate->type->fields.array->gl_type; > @@ -542,7 +549,7 @@ const tfeedback_candidate * > tfeedback_decl::find_candidate(gl_shader_program *prog, > hash_table *tfeedback_candidates) > { > - const char *name = this->is_clip_distance_mesa > + const char *name = this->is_cull_distance_mesa ? "gl_CullDistanceMESA" : this->is_clip_distance_mesa > ? "gl_ClipDistanceMESA" : this->var_name; > this->matched_candidate = (const tfeedback_candidate *) > hash_table_find(tfeedback_candidates, name); > diff --git a/src/glsl/link_varyings.h b/src/glsl/link_varyings.h > index afc16a8..842ab7c 100644 > --- a/src/glsl/link_varyings.h > +++ b/src/glsl/link_varyings.h > @@ -128,7 +128,7 @@ public: > */ > unsigned num_components() const > { > - if (this->is_clip_distance_mesa) > + if (this->is_clip_distance_mesa || this->is_cull_distance_mesa) > return this->size; > else > return this->vector_elements * this->matrix_columns * this->size; > @@ -165,6 +165,7 @@ private: > * gl_ClipDistance to gl_ClipDistanceMESA. > */ > bool is_clip_distance_mesa; > + bool is_cull_distance_mesa; > > /** > * The vertex shader output location that the linker assigned for this > diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp > index 8eace14..e616520 100644 > --- a/src/glsl/linker.cpp > +++ b/src/glsl/linker.cpp > @@ -2938,6 +2938,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) > > if (ctx->Const.ShaderCompilerOptions[i].LowerClipDistance) { > lower_clip_distance(prog->_LinkedShaders[i]); > + lower_cull_distance(prog->_LinkedShaders[i]); > } > > while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, > diff --git a/src/glsl/lower_cull_distance.cpp b/src/glsl/lower_cull_distance.cpp > new file mode 100644 > index 0000000..d3b9592 > --- /dev/null > +++ b/src/glsl/lower_cull_distance.cpp > @@ -0,0 +1,549 @@ > +/* > + * Copyright © 2011 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE SOFTWARE. > + */ > + > +/** > + * \file lower_cull_distance.cpp > + * > + * This pass accounts for the difference between the way > + * gl_CullDistance is declared in standard GLSL (as an array of > + * floats), and the way it is frequently implemented in hardware (as > + * a pair of vec4s, with four cull distances packed into each). > + * > + * The declaration of gl_CullDistance is replaced with a declaration > + * of gl_CullDistanceMESA, and any references to gl_CullDistance are > + * translated to refer to gl_CullDistanceMESA with the appropriate > + * swizzling of array indices. For instance: > + * > + * gl_CullDistance[i] > + * > + * is translated into: > + * > + * gl_CullDistanceMESA[i>>2][i&3] > + * > + * Since some hardware may not internally represent gl_CullDistance as a pair > + * of vec4's, this lowering pass is optional. To enable it, set the > + * LowerCullDistance flag in gl_shader_compiler_options to true. > + */ > + > +#include "glsl_symbol_table.h" > +#include "ir_rvalue_visitor.h" > +#include "ir.h" > +#include "program/prog_instruction.h" /* For WRITEMASK_* */ > + > +namespace { > + > +class lower_cull_distance_visitor : public ir_rvalue_visitor { > +public: > + explicit lower_cull_distance_visitor(gl_shader_stage shader_stage) > + : progress(false), old_cull_distance_1d_var(NULL), > + old_cull_distance_2d_var(NULL), new_cull_distance_1d_var(NULL), > + new_cull_distance_2d_var(NULL), shader_stage(shader_stage) > + { > + } > + > + virtual ir_visitor_status visit(ir_variable *); > + void create_indices(ir_rvalue*, ir_rvalue *&, ir_rvalue *&); > + bool is_cull_distance_vec8(ir_rvalue *ir); > + ir_rvalue *lower_cull_distance_vec8(ir_rvalue *ir); > + virtual ir_visitor_status visit_leave(ir_assignment *); > + void visit_new_assignment(ir_assignment *ir); > + virtual ir_visitor_status visit_leave(ir_call *); > + > + virtual void handle_rvalue(ir_rvalue **rvalue); > + > + void fix_lhs(ir_assignment *); > + > + bool progress; > + > + /** > + * Pointer to the declaration of gl_CullDistance, if found. > + * > + * Note: > + * > + * - the 2d_var is for geometry shader input only. > + * > + * - since gl_CullDistance is available in geometry shaders as both an > + * input and an output, it's possible for both old_cull_distance_1d_var > + * and old_cull_distance_2d_var to be non-null. > + */ > + ir_variable *old_cull_distance_1d_var; > + ir_variable *old_cull_distance_2d_var; > + > + /** > + * Pointer to the newly-created gl_CullDistanceMESA variable. > + */ > + ir_variable *new_cull_distance_1d_var; > + ir_variable *new_cull_distance_2d_var; > + > + /** > + * Type of shader we are compiling (e.g. MESA_SHADER_VERTEX) > + */ > + const gl_shader_stage shader_stage; > +}; > + > +} /* anonymous namespace */ > + > +/** > + * Replace any declaration of gl_CullDistance as an array of floats with a > + * declaration of gl_CullDistanceMESA as an array of vec4's. > + */ > +ir_visitor_status > +lower_cull_distance_visitor::visit(ir_variable *ir) > +{ > + if (!ir->name || strcmp(ir->name, "gl_CullDistance") != 0) > + return visit_continue; > + assert (ir->type->is_array()); > + > + if (!ir->type->fields.array->is_array()) { > + /* 1D gl_CullDistance (used for vertex and geometry output, and fragment > + * input). > + */ > + if (this->old_cull_distance_1d_var) > + return visit_continue; > + > + this->progress = true; > + this->old_cull_distance_1d_var = ir; > + assert (ir->type->fields.array == glsl_type::float_type); > + unsigned new_size = (ir->type->array_size() + 3) / 4; > + > + /* Clone the old var so that we inherit all of its properties */ > + this->new_cull_distance_1d_var = ir->clone(ralloc_parent(ir), NULL); > + > + /* And change the properties that we need to change */ > + this->new_cull_distance_1d_var->name > + = ralloc_strdup(this->new_cull_distance_1d_var, > + "gl_CullDistanceMESA"); > + this->new_cull_distance_1d_var->type > + = glsl_type::get_array_instance(glsl_type::vec4_type, new_size); > + this->new_cull_distance_1d_var->data.max_array_access > + = ir->data.max_array_access / 4; > + > + ir->replace_with(this->new_cull_distance_1d_var); > + } else { > + /* 2D gl_CullDistance (used for geometry input). */ > + assert(ir->data.mode == ir_var_shader_in && > + this->shader_stage == MESA_SHADER_GEOMETRY); > + if (this->old_cull_distance_2d_var) > + return visit_continue; > + > + this->progress = true; > + this->old_cull_distance_2d_var = ir; > + assert (ir->type->fields.array->fields.array == glsl_type::float_type); > + unsigned new_size = (ir->type->fields.array->array_size() + 3) / 4; > + > + /* Clone the old var so that we inherit all of its properties */ > + this->new_cull_distance_2d_var = ir->clone(ralloc_parent(ir), NULL); > + > + /* And change the properties that we need to change */ > + this->new_cull_distance_2d_var->name > + = ralloc_strdup(this->new_cull_distance_2d_var, "gl_CullDistanceMESA"); > + this->new_cull_distance_2d_var->type = glsl_type::get_array_instance( > + glsl_type::get_array_instance(glsl_type::vec4_type, > + new_size), > + ir->type->array_size()); > + this->new_cull_distance_2d_var->data.max_array_access > + = ir->data.max_array_access / 4; > + > + ir->replace_with(this->new_cull_distance_2d_var); > + } > + return visit_continue; > +} > + > + > +/** > + * Create the necessary GLSL rvalues to index into gl_CullDistanceMESA based > + * on the rvalue previously used to index into gl_CullDistance. > + * > + * \param array_index Selects one of the vec4's in gl_CullDistanceMESA > + * \param swizzle_index Selects a component within the vec4 selected by > + * array_index. > + */ > +void > +lower_cull_distance_visitor::create_indices(ir_rvalue *old_index, > + ir_rvalue *&array_index, > + ir_rvalue *&swizzle_index) > +{ > + void *ctx = ralloc_parent(old_index); > + > + /* Make sure old_index is a signed int so that the bitwise "shift" and > + * "and" operations below type check properly. > + */ > + if (old_index->type != glsl_type::int_type) { > + assert (old_index->type == glsl_type::uint_type); > + old_index = new(ctx) ir_expression(ir_unop_u2i, old_index); > + } > + > + ir_constant *old_index_constant = old_index->constant_expression_value(); > + if (old_index_constant) { > + /* gl_CullDistance is being accessed via a constant index. Don't bother > + * creating expressions to calculate the lowered indices. Just create > + * constants. > + */ > + int const_val = old_index_constant->get_int_component(0); > + array_index = new(ctx) ir_constant(const_val / 4); > + swizzle_index = new(ctx) ir_constant(const_val % 4); > + } else { > + /* Create a variable to hold the value of old_index (so that we > + * don't compute it twice). > + */ > + ir_variable *old_index_var = new(ctx) ir_variable( > + glsl_type::int_type, "cull_distance_index", ir_var_temporary); > + this->base_ir->insert_before(old_index_var); > + this->base_ir->insert_before(new(ctx) ir_assignment( > + new(ctx) ir_dereference_variable(old_index_var), old_index)); > + > + /* Create the expression cull_distance_index / 4. Do this as a bit > + * shift because that's likely to be more efficient. > + */ > + array_index = new(ctx) ir_expression( > + ir_binop_rshift, new(ctx) ir_dereference_variable(old_index_var), > + new(ctx) ir_constant(2)); > + > + /* Create the expression cull_distance_index % 4. Do this as a bitwise > + * AND because that's likely to be more efficient. > + */ > + swizzle_index = new(ctx) ir_expression( > + ir_binop_bit_and, new(ctx) ir_dereference_variable(old_index_var), > + new(ctx) ir_constant(3)); > + } > +} > + > + > +/** > + * Determine whether the given rvalue describes an array of 8 floats that > + * needs to be lowered to an array of 2 vec4's; that is, determine whether it > + * matches one of the following patterns: > + * > + * - gl_CullDistance (if gl_CullDistance is 1D) > + * - gl_CullDistance[i] (if gl_CullDistance is 2D) > + */ > +bool > +lower_cull_distance_visitor::is_cull_distance_vec8(ir_rvalue *ir) > +{ > + /* Note that geometry shaders contain gl_CullDistance both as an input > + * (which is a 2D array) and an output (which is a 1D array), so it's > + * possible for both this->old_cull_distance_1d_var and > + * this->old_cull_distance_2d_var to be non-NULL in the same shader. > + */ > + > + if (this->old_cull_distance_1d_var) { > + ir_dereference_variable *var_ref = ir->as_dereference_variable(); > + if (var_ref && var_ref->var == this->old_cull_distance_1d_var) > + return true; > + } > + if (this->old_cull_distance_2d_var) { > + /* 2D cull distance is only possible as a geometry input */ > + assert(this->shader_stage == MESA_SHADER_GEOMETRY); > + > + ir_dereference_array *array_ref = ir->as_dereference_array(); > + if (array_ref) { > + ir_dereference_variable *var_ref > + array_ref->array->as_dereference_variable(); > + if (var_ref && var_ref->var == this->old_cull_distance_2d_var) > + return true; > + } > + } > + return false; > +} > + > + > +/** > + * If the given ir satisfies is_cull_distance_vec8(), return new ir > + * representing its lowered equivalent. That is, map: > + * > + * - gl_CullDistance => gl_CullDistanceMESA (if gl_CullDistance is 1D) > + * - gl_CullDistance[i] => gl_CullDistanceMESA[i] (if gl_CullDistance is 2D) > + * > + * Otherwise return NULL. > + */ > +ir_rvalue * > +lower_cull_distance_visitor::lower_cull_distance_vec8(ir_rvalue *ir) > +{ > + if (this->old_cull_distance_1d_var) { > + ir_dereference_variable *var_ref = ir->as_dereference_variable(); > + if (var_ref && var_ref->var == this->old_cull_distance_1d_var) { > + return new(ralloc_parent(ir)) > + ir_dereference_variable(this->new_cull_distance_1d_var); > + } > + } > + if (this->old_cull_distance_2d_var) { > + /* 2D cull distance is only possible as a geometry input */ > + assert(this->shader_stage == MESA_SHADER_GEOMETRY); > + > + ir_dereference_array *array_ref = ir->as_dereference_array(); > + if (array_ref) { > + ir_dereference_variable *var_ref > + array_ref->array->as_dereference_variable(); > + if (var_ref && var_ref->var == this->old_cull_distance_2d_var) { > + return new(ralloc_parent(ir)) > + ir_dereference_array(this->new_cull_distance_2d_var, > + array_ref->array_index); > + } > + } > + } > + return NULL; > +} > + > + > +void > +lower_cull_distance_visitor::handle_rvalue(ir_rvalue **rv) > +{ > + if (*rv == NULL) > + return; > + > + ir_dereference_array *const array_deref = (*rv)->as_dereference_array(); > + if (array_deref == NULL) > + return; > + > + /* Replace any expression that indexes one of the floats in gl_CullDistance > + * with an expression that indexes into one of the vec4's in > + * gl_CullDistanceMESA and accesses the appropriate component. > + */ > + ir_rvalue *lowered_vec8 > + this->lower_cull_distance_vec8(array_deref->array); > + if (lowered_vec8 != NULL) { > + this->progress = true; > + ir_rvalue *array_index; > + ir_rvalue *swizzle_index; > + this->create_indices(array_deref->array_index, array_index, swizzle_index); > + void *mem_ctx = ralloc_parent(array_deref); > + > + ir_dereference_array *const new_array_deref > + new(mem_ctx) ir_dereference_array(lowered_vec8, array_index); > + > + ir_expression *const expr > + new(mem_ctx) ir_expression(ir_binop_vector_extract, > + new_array_deref, > + swizzle_index); > + > + *rv = expr; > + } > +} > + > +void > +lower_cull_distance_visitor::fix_lhs(ir_assignment *ir) > +{ > + if (ir->lhs->ir_type == ir_type_expression) { > + void *mem_ctx = ralloc_parent(ir); > + ir_expression *const expr = (ir_expression *) ir->lhs; > + > + /* The expression must be of the form: > + * > + * (vector_extract gl_CullDistanceMESA[i], j). > + */ > + assert(expr->operation == ir_binop_vector_extract); > + assert(expr->operands[0]->ir_type == ir_type_dereference_array); > + assert(expr->operands[0]->type == glsl_type::vec4_type); > + > + ir_dereference *const new_lhs = (ir_dereference *) expr->operands[0]; > + ir->rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert, > + glsl_type::vec4_type, > + new_lhs->clone(mem_ctx, NULL), > + ir->rhs, > + expr->operands[1]); > + ir->set_lhs(new_lhs); > + ir->write_mask = WRITEMASK_XYZW; > + } > +} > + > +/** > + * Replace any assignment having the 1D gl_CullDistance (undereferenced) as > + * its LHS or RHS with a sequence of assignments, one for each component of > + * the array. Each of these assignments is lowered to refer to > + * gl_CullDistanceMESA as appropriate. > + * > + * We need to do a similar replacement for 2D gl_CullDistance, however since > + * it's an input, the only case we need to address is where a 1D slice of it > + * is the entire RHS of an assignment, e.g.: > + * > + * foo = gl_in[i].gl_CullDistance > + */ > +ir_visitor_status > +lower_cull_distance_visitor::visit_leave(ir_assignment *ir) > +{ > + /* First invoke the base class visitor. This causes handle_rvalue() to be > + * called on ir->rhs and ir->condition. > + */ > + ir_rvalue_visitor::visit_leave(ir); > + > + if (this->is_cull_distance_vec8(ir->lhs) || > + this->is_cull_distance_vec8(ir->rhs)) { > + /* LHS or RHS of the assignment is the entire 1D gl_CullDistance array > + * (or a 1D slice of a 2D gl_CullDistance input array). Since we are > + * reshaping gl_CullDistance from an array of floats to an array of > + * vec4's, this isn't going to work as a bulk assignment anymore, so > + * unroll it to element-by-element assignments and lower each of them. > + * > + * Note: to unroll into element-by-element assignments, we need to make > + * clones of the LHS and RHS. This is safe because expressions and > + * l-values are side-effect free. > + */ > + void *ctx = ralloc_parent(ir); > + int array_size = ir->lhs->type->array_size(); > + for (int i = 0; i < array_size; ++i) { > + ir_dereference_array *new_lhs = new(ctx) ir_dereference_array( > + ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i)); > + ir_dereference_array *new_rhs = new(ctx) ir_dereference_array( > + ir->rhs->clone(ctx, NULL), new(ctx) ir_constant(i)); > + this->handle_rvalue((ir_rvalue **) &new_rhs); > + > + /* Handle the LHS after creating the new assignment. This must > + * happen in this order because handle_rvalue may replace the old LHS > + * with an ir_expression of ir_binop_vector_extract. Since this is > + * not a valide l-value, this will cause an assertion in the > + * ir_assignment constructor to fail. > + * > + * If this occurs, replace the mangled LHS with a dereference of the > + * vector, and replace the RHS with an ir_triop_vector_insert. > + */ > + ir_assignment *const assign = new(ctx) ir_assignment(new_lhs, new_rhs); > + this->handle_rvalue((ir_rvalue **) &assign->lhs); > + this->fix_lhs(assign); > + > + this->base_ir->insert_before(assign); > + } > + ir->remove(); > + > + return visit_continue; > + } > + > + /* Handle the LHS as if it were an r-value. Normally > + * rvalue_visit(ir_assignment *) only visits the RHS, but we need to lower > + * expressions in the LHS as well. > + * > + * This may cause the LHS to get replaced with an ir_expression of > + * ir_binop_vector_extract. If this occurs, replace it with a dereference > + * of the vector, and replace the RHS with an ir_triop_vector_insert. > + */ > + handle_rvalue((ir_rvalue **)&ir->lhs); > + this->fix_lhs(ir); > + > + return rvalue_visit(ir); > +} > + > + > +/** > + * Set up base_ir properly and call visit_leave() on a newly created > + * ir_assignment node. This is used in cases where we have to insert an > + * ir_assignment in a place where we know the hierarchical visitor won't see > + * it. > + */ > +void > +lower_cull_distance_visitor::visit_new_assignment(ir_assignment *ir) > +{ > + ir_instruction *old_base_ir = this->base_ir; > + this->base_ir = ir; > + ir->accept(this); > + this->base_ir = old_base_ir; > +} > + > + > +/** > + * If a 1D gl_CullDistance variable appears as an argument in an ir_call > + * expression, replace it with a temporary variable, and make sure the ir_call > + * is preceded and/or followed by assignments that copy the contents of the > + * temporary variable to and/or from gl_CullDistance. Each of these > + * assignments is then lowered to refer to gl_CullDistanceMESA. > + * > + * We need to do a similar replacement for 2D gl_CullDistance, however since > + * it's an input, the only case we need to address is where a 1D slice of it > + * is passed as an "in" parameter to an ir_call, e.g.: > + * > + * foo(gl_in[i].gl_CullDistance) > + */ > +ir_visitor_status > +lower_cull_distance_visitor::visit_leave(ir_call *ir) > +{ > + void *ctx = ralloc_parent(ir); > + > + const exec_node *formal_param_node = ir->callee->parameters.head; > + const exec_node *actual_param_node = ir->actual_parameters.head; > + while (!actual_param_node->is_tail_sentinel()) { > + ir_variable *formal_param = (ir_variable *) formal_param_node; > + ir_rvalue *actual_param = (ir_rvalue *) actual_param_node; > + > + /* Advance formal_param_node and actual_param_node now so that we can > + * safely replace actual_param with another node, if necessary, below. > + */ > + formal_param_node = formal_param_node->next; > + actual_param_node = actual_param_node->next; > + > + if (this->is_cull_distance_vec8(actual_param)) { > + /* User is trying to pass the whole 1D gl_CullDistance array (or a 1D > + * slice of a 2D gl_CullDistance array) to a function call. Since we > + * are reshaping gl_CullDistance from an array of floats to an array > + * of vec4's, this isn't going to work anymore, so use a temporary > + * array instead. > + */ > + ir_variable *temp_cull_distance = new(ctx) ir_variable( > + actual_param->type, "temp_cull_distance", ir_var_temporary); > + this->base_ir->insert_before(temp_cull_distance); > + actual_param->replace_with( > + new(ctx) ir_dereference_variable(temp_cull_distance)); > + if (formal_param->data.mode == ir_var_function_in > + || formal_param->data.mode == ir_var_function_inout) { > + /* Copy from gl_CullDistance to the temporary before the call. > + * Since we are going to insert this copy before the current > + * instruction, we need to visit it afterwards to make sure it > + * gets lowered. > + */ > + ir_assignment *new_assignment = new(ctx) ir_assignment( > + new(ctx) ir_dereference_variable(temp_cull_distance), > + actual_param->clone(ctx, NULL)); > + this->base_ir->insert_before(new_assignment); > + this->visit_new_assignment(new_assignment); > + } > + if (formal_param->data.mode == ir_var_function_out > + || formal_param->data.mode == ir_var_function_inout) { > + /* Copy from the temporary to gl_CullDistance after the call. > + * Since visit_list_elements() has already decided which > + * instruction it's going to visit next, we need to visit > + * afterwards to make sure it gets lowered. > + */ > + ir_assignment *new_assignment = new(ctx) ir_assignment( > + actual_param->clone(ctx, NULL), > + new(ctx) ir_dereference_variable(temp_cull_distance)); > + this->base_ir->insert_after(new_assignment); > + this->visit_new_assignment(new_assignment); > + } > + } > + } > + > + return rvalue_visit(ir); > +} > + > + > +bool > +lower_cull_distance(gl_shader *shader) > +{ > + lower_cull_distance_visitor v(shader->Stage); > + > + visit_list_elements(&v, shader->ir); > + > + if (v.new_cull_distance_1d_var) > + shader->symbols->add_variable(v.new_cull_distance_1d_var); > + if (v.new_cull_distance_2d_var) > + shader->symbols->add_variable(v.new_cull_distance_2d_var); > + > + return v.progress; > +} > -- > 2.4.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev
Ilia Mirkin
2015-May-24 18:11 UTC
[Nouveau] [PATCH 02/11] mesa/main: add support for GL_ARB_cull_distance
On Sun, May 24, 2015 at 1:58 PM, Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> wrote:> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> > --- > src/mesa/main/extensions.c | 1 + > src/mesa/main/get.c | 26 ++++++++++++++++++++++++++ > src/mesa/main/get_hash_params.py | 4 ++++ > src/mesa/main/mtypes.h | 22 +++++++++++++--------- > src/mesa/main/shaderapi.c | 4 ++-- > src/mesa/main/tests/enum_strings.cpp | 2 ++ > 6 files changed, 48 insertions(+), 11 deletions(-) > > diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c > index c82416a..2145502 100644 > --- a/src/mesa/main/extensions.c > +++ b/src/mesa/main/extensions.c > @@ -99,6 +99,7 @@ static const struct extension extension_table[] = { > { "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 }, > { "GL_ARB_copy_image", o(ARB_copy_image), GL, 2012 }, > { "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 }, > + { "GL_ARB_cull_distance", o(ARB_cull_distance), GL, 2014 }, > { "GL_ARB_debug_output", o(dummy_true), GL, 2009 }, > { "GL_ARB_depth_buffer_float", o(ARB_depth_buffer_float), GL, 2008 }, > { "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 }, > diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c > index 8a6c81a..1dcfcc9 100644 > --- a/src/mesa/main/get.c > +++ b/src/mesa/main/get.c > @@ -143,6 +143,8 @@ enum value_extra { > EXTRA_VALID_DRAW_BUFFER, > EXTRA_VALID_TEXTURE_UNIT, > EXTRA_VALID_CLIP_DISTANCE, > + EXTRA_VALID_CULL_DISTANCE, > + EXTRA_VALID_CULL_AND_CLIP_DISTANCE, > EXTRA_FLUSH_CURRENT, > EXTRA_GLSL_130, > EXTRA_EXT_UBO_GS4, > @@ -267,6 +269,13 @@ static const int extra_valid_clip_distance[] = { > EXTRA_END > }; > > +static const int extra_valid_clip_and_cull_distance[] = { > + EXTRA_VALID_CLIP_DISTANCE, > + EXTRA_VALID_CULL_DISTANCE, > + EXTRA_VALID_CULL_AND_CLIP_DISTANCE, > + EXTRA_END > +}; > + > static const int extra_flush_current_valid_texture_unit[] = { > EXTRA_FLUSH_CURRENT, > EXTRA_VALID_TEXTURE_UNIT, > @@ -393,6 +402,7 @@ EXTRA_EXT(INTEL_performance_query); > EXTRA_EXT(ARB_explicit_uniform_location); > EXTRA_EXT(ARB_clip_control); > EXTRA_EXT(EXT_polygon_offset_clamp); > +EXTRA_EXT(ARB_cull_distance); > > static const int > extra_ARB_color_buffer_float_or_glcore[] = { > @@ -1116,6 +1126,22 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d > return GL_FALSE; > } > break; > + case EXTRA_VALID_CULL_DISTANCE: > + if (d->pname - GL_MAX_CULL_DISTANCES >= ctx->Const.MaxClipPlanes) { > + _mesa_error(ctx, GL_INVALID_ENUM, "%s(cull distance %u)", > + func, d->pname - GL_MAX_CULL_DISTANCES); > + return GL_FALSE; > + } > + break; > + case EXTRA_VALID_CULL_AND_CLIP_DISTANCE: > + if (d->pname - GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES >> + ctx->Const.MaxClipPlanes) { > + _mesa_error(ctx, GL_INVALID_ENUM, > + "%s(combined clip and cull distance %u)", func, > + d->pname - GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES); > + return GL_FALSE; > + }huh? I guess you were copying EXTRA_VALID_CLIP_DISTANCE? That's for validating GL_CLIP_DISTANCE0..7 all in one go (and erroring out for ones that are too high). That doesn't seem to apply here. You don't appear to use extra_valid_clip_and_cull_distance either, so I guess that makes sense... should remove the whole lot.> + break; > case EXTRA_GLSL_130: > api_check = GL_TRUE; > if (ctx->Const.GLSLVersion >= 130) > diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py > index 41cb2c1..a63aba7 100644 > --- a/src/mesa/main/get_hash_params.py > +++ b/src/mesa/main/get_hash_params.py > @@ -798,6 +798,10 @@ descriptor=[ > [ "MIN_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MinFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], > [ "MAX_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MaxFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], > [ "FRAGMENT_INTERPOLATION_OFFSET_BITS", "CONST(FRAGMENT_INTERPOLATION_OFFSET_BITS), extra_ARB_gpu_shader5" ], > + > +# GL_ARB_cull_distance > + [ "MAX_CULL_DISTANCES", "CONTEXT_INT(Const.MaxClipPlanes), extra_ARB_cull_distance" ], > + [ "MAX_COMBINED_CLIP_AND_CULL_DISTANCES", "CONTEXT_INT(Const.MaxClipPlanes), extra_ARB_cull_distance" ], > ]}, > > # Enums restricted to OpenGL Core profile > diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h > index 8342517..6425c06 100644 > --- a/src/mesa/main/mtypes.h > +++ b/src/mesa/main/mtypes.h > @@ -236,6 +236,8 @@ typedef enum > VARYING_SLOT_CLIP_VERTEX, /* Does not appear in FS */ > VARYING_SLOT_CLIP_DIST0, > VARYING_SLOT_CLIP_DIST1, > + VARYING_SLOT_CULL_DIST0, > + VARYING_SLOT_CULL_DIST1, > VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */ > VARYING_SLOT_LAYER, /* Appears as VS or GS output */ > VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */ > @@ -272,6 +274,8 @@ typedef enum > #define VARYING_BIT_CLIP_VERTEX BITFIELD64_BIT(VARYING_SLOT_CLIP_VERTEX) > #define VARYING_BIT_CLIP_DIST0 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0) > #define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1) > +#define VARYING_BIT_CULL_DIST0 BITFIELD64_BIT(VARYING_SLOT_CULL_DIST0) > +#define VARYING_BIT_CULL_DIST1 BITFIELD64_BIT(VARYING_SLOT_CULL_DIST1) > #define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID) > #define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER) > #define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT) > @@ -2111,8 +2115,7 @@ struct gl_program > * For vertex and geometry shaders, true if the program uses the > * gl_ClipDistance output. Ignored for fragment shaders. > */ > - GLboolean UsesClipDistanceOut; > - > + GLboolean UsesClipCullDistanceOut; > > /** Named parameters, constants, etc. from program text */ > struct gl_program_parameter_list *Parameters; > @@ -2697,9 +2700,9 @@ struct gl_shader_program > * True if gl_ClipDistance is written to. Copied into > * gl_geometry_program by _mesa_copy_linked_program_data(). > */ > - GLboolean UsesClipDistance; > - GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or > - 0 if not present. */ > + GLboolean UsesClipCullDistance; > + GLuint ClipCullDistanceArraySize; /**< Size of the gl_ClipDistance array, > + or 0 if not present. */ > bool UsesEndPrimitive; > bool UsesStreams; > } Geom; > @@ -2710,9 +2713,9 @@ struct gl_shader_program > * True if gl_ClipDistance is written to. Copied into gl_vertex_program > * by _mesa_copy_linked_program_data(). > */ > - GLboolean UsesClipDistance; > - GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or > - 0 if not present. */ > + GLboolean UsesClipCullDistance; > + GLuint ClipCullDistanceArraySize; /**< Size of the gl_ClipDistance array, > + or 0 if not present. */ > } Vert; > > /** > @@ -2744,7 +2747,7 @@ struct gl_shader_program > * Size of the gl_ClipDistance array that is output from the last pipeline > * stage before the fragment shader. > */ > - unsigned LastClipDistanceArraySize; > + unsigned LastClipCullDistanceArraySize; > > unsigned NumUniformBlocks; > struct gl_uniform_block *UniformBlocks; > @@ -3617,6 +3620,7 @@ struct gl_extensions > GLboolean ARB_conditional_render_inverted; > GLboolean ARB_conservative_depth; > GLboolean ARB_copy_image; > + GLboolean ARB_cull_distance; > GLboolean ARB_depth_buffer_float; > GLboolean ARB_depth_clamp; > GLboolean ARB_depth_texture; > diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c > index a04b287..7b26173 100644 > --- a/src/mesa/main/shaderapi.c > +++ b/src/mesa/main/shaderapi.c > @@ -1942,7 +1942,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, > { > switch (type) { > case MESA_SHADER_VERTEX: > - dst->UsesClipDistanceOut = src->Vert.UsesClipDistance; > + dst->UsesClipCullDistanceOut = src->Vert.UsesClipCullDistance; > break; > case MESA_SHADER_GEOMETRY: { > struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst; > @@ -1951,7 +1951,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, > dst_gp->Invocations = src->Geom.Invocations; > dst_gp->InputType = src->Geom.InputType; > dst_gp->OutputType = src->Geom.OutputType; > - dst->UsesClipDistanceOut = src->Geom.UsesClipDistance; > + dst->UsesClipCullDistanceOut = src->Geom.UsesClipCullDistance; > dst_gp->UsesEndPrimitive = src->Geom.UsesEndPrimitive; > dst_gp->UsesStreams = src->Geom.UsesStreams; > } > diff --git a/src/mesa/main/tests/enum_strings.cpp b/src/mesa/main/tests/enum_strings.cpp > index dc5fe75..959db15 100644 > --- a/src/mesa/main/tests/enum_strings.cpp > +++ b/src/mesa/main/tests/enum_strings.cpp > @@ -789,6 +789,8 @@ const struct enum_info everything[] = { > { 0x8261, "GL_NO_RESET_NOTIFICATION_ARB" }, > { 0x826E, "GL_MAX_UNIFORM_LOCATIONS" }, > { 0x82DF, "GL_TEXTURE_IMMUTABLE_LEVELS" }, > + { 0x82F9, "GL_MAX_CULL_DISTANCES" }, > + { 0x82FA, "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES" }, > { 0x8362, "GL_UNSIGNED_BYTE_2_3_3_REV" }, > { 0x8363, "GL_UNSIGNED_SHORT_5_6_5" }, > { 0x8364, "GL_UNSIGNED_SHORT_5_6_5_REV" }, > -- > 2.4.1 > > _______________________________________________ > Nouveau mailing list > Nouveau at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/nouveau
Marek Olšák
2015-May-24 18:12 UTC
[Nouveau] [Mesa-dev] [PATCH 04/11] mesa/st: add support for GL_ARB_cull_distance
On Sun, May 24, 2015 at 7:58 PM, Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> wrote:> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> > --- > src/mesa/state_tracker/st_extensions.c | 4 ++++ > src/mesa/state_tracker/st_program.c | 34 ++++++++++++++++++++++++++++++++++ > 2 files changed, 38 insertions(+) > > diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c > index 23a4588..63f3334 100644 > --- a/src/mesa/state_tracker/st_extensions.c > +++ b/src/mesa/state_tracker/st_extensions.c > @@ -466,6 +466,7 @@ void st_init_extensions(struct pipe_screen *screen, > { o(ARB_conditional_render_inverted), PIPE_CAP_CONDITIONAL_RENDER_INVERTED }, > { o(ARB_texture_view), PIPE_CAP_SAMPLER_VIEW_TARGET }, > { o(ARB_clip_control), PIPE_CAP_CLIP_HALFZ }, > + { o(ARB_cull_distance), PIPE_CAP_CULL_DISTANCE }, > { o(EXT_polygon_offset_clamp), PIPE_CAP_POLYGON_OFFSET_CLAMP }, > }; > > @@ -678,6 +679,9 @@ void st_init_extensions(struct pipe_screen *screen, > if (glsl_feature_level >= 410) > extensions->ARB_shader_precision = GL_TRUE; > > + if (glsl_feature_level >= 130) > + extensions->ARB_cull_distance = GL_TRUE; > +This hunk is wrong and seems to be completely unnecessary. Also, the patch which adds PIPE_CAP_CULL_DISTANCE should be before this patch. Marek
I'm having a bit of trouble tracing through this. What happens if I have a shader that just does: gl_ClipDistance[0] = 1; gl_CullDistance[0] = 1; what does the resulting TGSI look like? (Assuming that clip plane 0 is enabled.) What about the generated nvc0 code (for the vertex shader)? On Sun, May 24, 2015 at 1:57 PM, Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> wrote:> This patch series adds the needed support for this extension to the various > parts of mesa to finally enable it for nvc0. > > Dave Airlie (1): > glsl: lower cull_distance into cull_distance_mesa > > Tobias Klausmann (10): > glapi: add GL_ARB_cull_distance > mesa/main: add support for GL_ARB_cull_distance > mesa/prog: Add varyings for arb_cull_distance > mesa/st: add support for GL_ARB_cull_distance > glsl: Add a helper to see if an array was unsize in the shader > glsl: Add arb_cull_distance support > i965: rename UsesClipDistanceOut to UsesClipCullDistanceOut > gallium: add support for arb_cull_distance > nouveau/codegen: sort in galliums cull_distance semantic into the > drivers bitmask > nouveau/nvc0: implement cull_distance as a special form of clip > distance > > docs/GL3.txt | 2 +- > docs/relnotes/10.7.0.html | 4 +- > src/gallium/auxiliary/cso_cache/cso_context.c | 3 + > src/gallium/drivers/freedreno/freedreno_screen.c | 1 + > src/gallium/drivers/i915/i915_screen.c | 1 + > src/gallium/drivers/ilo/ilo_screen.c | 1 + > src/gallium/drivers/llvmpipe/lp_screen.c | 2 + > .../drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp | 5 + > src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 + > src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 + > src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 6 +- > src/gallium/drivers/nouveau/nvc0/nvc0_program.h | 1 + > src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 + > .../drivers/nouveau/nvc0/nvc0_state_validate.c | 1 + > src/gallium/drivers/r300/r300_screen.c | 1 + > src/gallium/drivers/r600/r600_pipe.c | 1 + > src/gallium/drivers/radeonsi/si_pipe.c | 1 + > src/gallium/drivers/softpipe/sp_screen.c | 2 + > src/gallium/drivers/svga/svga_screen.c | 1 + > src/gallium/drivers/vc4/vc4_screen.c | 1 + > src/gallium/include/pipe/p_defines.h | 1 + > src/glsl/Makefile.sources | 1 + > 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/glsl_types.cpp | 8 +- > src/glsl/glsl_types.h | 10 +- > src/glsl/ir_optimization.h | 1 + > src/glsl/link_varyings.cpp | 17 +- > src/glsl/link_varyings.h | 3 +- > src/glsl/linker.cpp | 124 +++-- > src/glsl/lower_cull_distance.cpp | 549 +++++++++++++++++++++ > src/glsl/standalone_scaffolding.cpp | 1 + > src/glsl/tests/varyings_test.cpp | 27 + > src/mapi/glapi/gen/gl_API.xml | 7 +- > src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 2 +- > src/mesa/drivers/dri/i965/brw_gs.c | 2 +- > src/mesa/drivers/dri/i965/brw_vec4.cpp | 2 +- > src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 2 +- > src/mesa/drivers/dri/i965/brw_vs.c | 2 +- > src/mesa/main/extensions.c | 1 + > src/mesa/main/get.c | 26 + > src/mesa/main/get_hash_params.py | 4 + > src/mesa/main/mtypes.h | 22 +- > src/mesa/main/shaderapi.c | 4 +- > src/mesa/main/tests/enum_strings.cpp | 2 + > src/mesa/program/prog_print.c | 4 + > src/mesa/state_tracker/st_extensions.c | 4 + > src/mesa/state_tracker/st_program.c | 34 ++ > 51 files changed, 859 insertions(+), 72 deletions(-) > create mode 100644 src/glsl/lower_cull_distance.cpp > > -- > 2.4.1 > > _______________________________________________ > Nouveau mailing list > Nouveau at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/nouveau
Tobias Klausmann
2015-May-24 19:30 UTC
[Nouveau] [RFC PATCH 00/11] Implement ARB_cull_distance
On 24.05.2015 20:25, Ilia Mirkin wrote:> I'm having a bit of trouble tracing through this. What happens if I > have a shader that just does: > > gl_ClipDistance[0] = 1; > gl_CullDistance[0] = 1; > > what does the resulting TGSI look like? (Assuming that clip plane 0 is > enabled.) What about the generated nvc0 code (for the vertex shader)?(hack up a patch for this, run it without DRI_PRIME=1, see i pass and forget to check it again) yeah those are equal, sorry for wasting your time on this :/> > On Sun, May 24, 2015 at 1:57 PM, Tobias Klausmann > <tobias.johannes.klausmann at mni.thm.de> wrote: >> This patch series adds the needed support for this extension to the various >> parts of mesa to finally enable it for nvc0. >> >> Dave Airlie (1): >> glsl: lower cull_distance into cull_distance_mesa >> >> Tobias Klausmann (10): >> glapi: add GL_ARB_cull_distance >> mesa/main: add support for GL_ARB_cull_distance >> mesa/prog: Add varyings for arb_cull_distance >> mesa/st: add support for GL_ARB_cull_distance >> glsl: Add a helper to see if an array was unsize in the shader >> glsl: Add arb_cull_distance support >> i965: rename UsesClipDistanceOut to UsesClipCullDistanceOut >> gallium: add support for arb_cull_distance >> nouveau/codegen: sort in galliums cull_distance semantic into the >> drivers bitmask >> nouveau/nvc0: implement cull_distance as a special form of clip >> distance >> >> docs/GL3.txt | 2 +- >> docs/relnotes/10.7.0.html | 4 +- >> src/gallium/auxiliary/cso_cache/cso_context.c | 3 + >> src/gallium/drivers/freedreno/freedreno_screen.c | 1 + >> src/gallium/drivers/i915/i915_screen.c | 1 + >> src/gallium/drivers/ilo/ilo_screen.c | 1 + >> src/gallium/drivers/llvmpipe/lp_screen.c | 2 + >> .../drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp | 5 + >> src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 + >> src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 + >> src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 6 +- >> src/gallium/drivers/nouveau/nvc0/nvc0_program.h | 1 + >> src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 + >> .../drivers/nouveau/nvc0/nvc0_state_validate.c | 1 + >> src/gallium/drivers/r300/r300_screen.c | 1 + >> src/gallium/drivers/r600/r600_pipe.c | 1 + >> src/gallium/drivers/radeonsi/si_pipe.c | 1 + >> src/gallium/drivers/softpipe/sp_screen.c | 2 + >> src/gallium/drivers/svga/svga_screen.c | 1 + >> src/gallium/drivers/vc4/vc4_screen.c | 1 + >> src/gallium/include/pipe/p_defines.h | 1 + >> src/glsl/Makefile.sources | 1 + >> 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/glsl_types.cpp | 8 +- >> src/glsl/glsl_types.h | 10 +- >> src/glsl/ir_optimization.h | 1 + >> src/glsl/link_varyings.cpp | 17 +- >> src/glsl/link_varyings.h | 3 +- >> src/glsl/linker.cpp | 124 +++-- >> src/glsl/lower_cull_distance.cpp | 549 +++++++++++++++++++++ >> src/glsl/standalone_scaffolding.cpp | 1 + >> src/glsl/tests/varyings_test.cpp | 27 + >> src/mapi/glapi/gen/gl_API.xml | 7 +- >> src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 2 +- >> src/mesa/drivers/dri/i965/brw_gs.c | 2 +- >> src/mesa/drivers/dri/i965/brw_vec4.cpp | 2 +- >> src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 2 +- >> src/mesa/drivers/dri/i965/brw_vs.c | 2 +- >> src/mesa/main/extensions.c | 1 + >> src/mesa/main/get.c | 26 + >> src/mesa/main/get_hash_params.py | 4 + >> src/mesa/main/mtypes.h | 22 +- >> src/mesa/main/shaderapi.c | 4 +- >> src/mesa/main/tests/enum_strings.cpp | 2 + >> src/mesa/program/prog_print.c | 4 + >> src/mesa/state_tracker/st_extensions.c | 4 + >> src/mesa/state_tracker/st_program.c | 34 ++ >> 51 files changed, 859 insertions(+), 72 deletions(-) >> create mode 100644 src/glsl/lower_cull_distance.cpp >> >> -- >> 2.4.1 >> >> _______________________________________________ >> Nouveau mailing list >> Nouveau at lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/nouveau
Ilia Mirkin
2015-May-24 19:38 UTC
[Nouveau] [Mesa-dev] [PATCH 10/11] nouveau/codegen: sort in galliums cull_distance semantic into the drivers bitmask
For when you resend, I tend to name things like this "nv50/ir" or "nvc0/ir". In this case, I would have chosen "nv50/ir" since it applies to both nvc0 and nv50. When it's a driver change, I just call it "nv50: " or "nvc0: " (even if it might include small codegen changes). On Sun, May 24, 2015 at 1:58 PM, Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> wrote:> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> > --- > src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp > index ecd115f..381a958 100644 > --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp > +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp > @@ -1063,6 +1063,11 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl) > decl->Declaration.UsageMask << (si * 4); > info->io.genUserClip = -1; > break; > + case TGSI_SEMANTIC_CULLDIST: > + info->io.cullDistanceMask |> + decl->Declaration.UsageMask << (si * 4); > + info->io.genUserClip = -1; > + break; > case TGSI_SEMANTIC_SAMPLEMASK: > info->io.sampleMask = i; > break; > -- > 2.4.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev
Timothy Arceri
2015-May-24 22:34 UTC
[Nouveau] [Mesa-dev] [PATCH 07/11] glsl: Add arb_cull_distance support
On Sun, 2015-05-24 at 19:58 +0200, Tobias Klausmann wrote:> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at 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;How come this needs to be done for former unsized arrays?> + > + /* 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 =
Roland Scheidegger
2015-May-25 18:36 UTC
[Nouveau] [Mesa-dev] [PATCH 09/11] gallium: add support for arb_cull_distance
This doesn't really do what the commit message claims - it just adds a cap bit, not actual support for arb_cull_distance (which was already there), so the log should be changed accordingly. Apart from what was already mentioned (that is, the cap bit isn't used by st/mesa which instead mistakenly uses glsl13), it would be nice if you could test softpipe/llvmpipe with this enabled, as it should already work (at least for llvmpipe, I'm not entirely sure for softpipe) if not there's some unaccounted difference somewhere how we'd thought of how this should work for dx10 vs. opengl). Roland Am 24.05.2015 um 19:58 schrieb Tobias Klausmann:> Add another pipe cap so we can savely enable of disable this extension > > Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> > --- > src/gallium/auxiliary/cso_cache/cso_context.c | 3 +++ > src/gallium/drivers/freedreno/freedreno_screen.c | 1 + > src/gallium/drivers/i915/i915_screen.c | 1 + > src/gallium/drivers/ilo/ilo_screen.c | 1 + > src/gallium/drivers/llvmpipe/lp_screen.c | 2 ++ > src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 + > src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 + > src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 + > src/gallium/drivers/r300/r300_screen.c | 1 + > src/gallium/drivers/r600/r600_pipe.c | 1 + > src/gallium/drivers/radeonsi/si_pipe.c | 1 + > src/gallium/drivers/softpipe/sp_screen.c | 2 ++ > src/gallium/drivers/svga/svga_screen.c | 1 + > src/gallium/drivers/vc4/vc4_screen.c | 1 + > src/gallium/include/pipe/p_defines.h | 1 + > 15 files changed, 19 insertions(+) > > diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c > index 744b00c..7612b43 100644 > --- a/src/gallium/auxiliary/cso_cache/cso_context.c > +++ b/src/gallium/auxiliary/cso_cache/cso_context.c > @@ -119,6 +119,9 @@ struct cso_context { > struct pipe_clip_state clip; > struct pipe_clip_state clip_saved; > > + struct pipe_clip_state cull; > + struct pipe_clip_state cull_saved; > + > struct pipe_framebuffer_state fb, fb_saved; > struct pipe_viewport_state vp, vp_saved; > struct pipe_blend_color blend_color; > diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c > index c596d03..986a942 100644 > --- a/src/gallium/drivers/freedreno/freedreno_screen.c > +++ b/src/gallium/drivers/freedreno/freedreno_screen.c > @@ -221,6 +221,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > case PIPE_CAP_MAX_VIEWPORTS: > diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c > index 03fecd1..678347d 100644 > --- a/src/gallium/drivers/i915/i915_screen.c > +++ b/src/gallium/drivers/i915/i915_screen.c > @@ -242,6 +242,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: > diff --git a/src/gallium/drivers/ilo/ilo_screen.c b/src/gallium/drivers/ilo/ilo_screen.c > index b0fed73..f92d5de 100644 > --- a/src/gallium/drivers/ilo/ilo_screen.c > +++ b/src/gallium/drivers/ilo/ilo_screen.c > @@ -459,6 +459,7 @@ ilo_get_param(struct pipe_screen *screen, enum pipe_cap param) > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > case PIPE_CAP_VENDOR_ID: > diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c > index 09ac9af..c90c405 100644 > --- a/src/gallium/drivers/llvmpipe/lp_screen.c > +++ b/src/gallium/drivers/llvmpipe/lp_screen.c > @@ -293,6 +293,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > return 0; > + case PIPE_CAP_CULL_DISTANCE: > + return 0; > } > /* should only get here on unhandled cases */ > debug_printf("Unexpected PIPE_CAP %d query\n", param); > diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c > index bb79ccc..fc33ddf 100644 > --- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c > +++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c > @@ -162,6 +162,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > case PIPE_CAP_VENDOR_ID: > diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c > index f455a7f..d8efd75 100644 > --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c > +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c > @@ -210,6 +210,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: /* potentially supported on some hw */ > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > case PIPE_CAP_VENDOR_ID: > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c > index 1ca997a..c942dda 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c > @@ -194,6 +194,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) > case PIPE_CAP_VERTEXID_NOBASE: > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > case PIPE_CAP_VENDOR_ID: > diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c > index 8e1d710..00bb6dd 100644 > --- a/src/gallium/drivers/r300/r300_screen.c > +++ b/src/gallium/drivers/r300/r300_screen.c > @@ -191,6 +191,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > /* SWTCL-only features. */ > diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c > index 5a8eb06..87f556b 100644 > --- a/src/gallium/drivers/r600/r600_pipe.c > +++ b/src/gallium/drivers/r600/r600_pipe.c > @@ -333,6 +333,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) > case PIPE_CAP_SAMPLER_VIEW_TARGET: > case PIPE_CAP_VERTEXID_NOBASE: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > /* Stream output. */ > diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c > index 9d60ef1..7ec9758 100644 > --- a/src/gallium/drivers/radeonsi/si_pipe.c > +++ b/src/gallium/drivers/radeonsi/si_pipe.c > @@ -294,6 +294,7 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param) > case PIPE_CAP_SAMPLER_VIEW_TARGET: > case PIPE_CAP_VERTEXID_NOBASE: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: > diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c > index a688d31..c0d7d86 100644 > --- a/src/gallium/drivers/softpipe/sp_screen.c > +++ b/src/gallium/drivers/softpipe/sp_screen.c > @@ -243,6 +243,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > return 0; > + case PIPE_CAP_CULL_DISTANCE: > + return 0; > } > /* should only get here on unhandled cases */ > debug_printf("Unexpected PIPE_CAP %d query\n", param); > diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c > index 549a89a..6e5a3da 100644 > --- a/src/gallium/drivers/svga/svga_screen.c > +++ b/src/gallium/drivers/svga/svga_screen.c > @@ -285,6 +285,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param) > case PIPE_CAP_VERTEXID_NOBASE: > case PIPE_CAP_POLYGON_OFFSET_CLAMP: > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: > return 64; > diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c > index 134d644..565f0c4 100644 > --- a/src/gallium/drivers/vc4/vc4_screen.c > +++ b/src/gallium/drivers/vc4/vc4_screen.c > @@ -176,6 +176,7 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) > case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: > case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: > case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: > + case PIPE_CAP_CULL_DISTANCE: > return 0; > > /* Stream output. */ > diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h > index 8fabf5e..50f9cfe 100644 > --- a/src/gallium/include/pipe/p_defines.h > +++ b/src/gallium/include/pipe/p_defines.h > @@ -605,6 +605,7 @@ enum pipe_cap > PIPE_CAP_MULTISAMPLE_Z_RESOLVE = 114, > PIPE_CAP_RESOURCE_FROM_USER_MEMORY = 115, > PIPE_CAP_DEVICE_RESET_STATUS_QUERY = 116, > + PIPE_CAP_CULL_DISTANCE = 117, > }; > > #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0) >