X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fir_set_program_inouts.cpp;h=c9b8a38384ff924c6841253b669e73b256b12390;hb=1fc39dae22843d6faf3ec43eab90c7d06f9f6f7b;hp=ab23538c341ef2d6997fde0b8840a7b492a2e9df;hpb=36e25ccd29056d965612523f82d973b43b85313e;p=mesa.git diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp index ab23538c341..c9b8a38384f 100644 --- a/src/glsl/ir_set_program_inouts.cpp +++ b/src/glsl/ir_set_program_inouts.cpp @@ -27,7 +27,7 @@ * Sets the InputsRead and OutputsWritten of Mesa programs. * * Additionally, for fragment shaders, sets the InterpQualifier array, the - * IsCentroid bitfield, and the UsesDFdy flag. + * IsCentroid and IsSample bitfields, and the UsesDFdy flag. * * Mesa programs (gl_program, not gl_shader_program) have a set of * flags indicating which varyings are read and written. Computing @@ -46,10 +46,11 @@ namespace { class ir_set_program_inouts_visitor : public ir_hierarchical_visitor { public: - ir_set_program_inouts_visitor(struct gl_program *prog, GLenum shader_type) + ir_set_program_inouts_visitor(struct gl_program *prog, + gl_shader_stage shader_stage) { this->prog = prog; - this->shader_type = shader_type; + this->shader_stage = shader_stage; } ~ir_set_program_inouts_visitor() { @@ -67,7 +68,7 @@ private: bool try_mark_partial_variable(ir_variable *var, ir_rvalue *index); struct gl_program *prog; - GLenum shader_type; + gl_shader_stage shader_stage; }; } /* anonymous namespace */ @@ -75,14 +76,14 @@ private: static inline bool is_shader_inout(ir_variable *var) { - return var->mode == ir_var_shader_in || - var->mode == ir_var_shader_out || - var->mode == ir_var_system_value; + return var->data.mode == ir_var_shader_in || + var->data.mode == ir_var_shader_out || + var->data.mode == ir_var_system_value; } static void mark(struct gl_program *prog, ir_variable *var, int offset, int len, - bool is_fragment_shader) + gl_shader_stage stage) { /* As of GLSL 1.20, varyings can only be floats, floating-point * vectors or matrices, or arrays of them. For Mesa programs using @@ -93,21 +94,49 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, */ for (int i = 0; i < len; i++) { - GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i); - if (var->mode == ir_var_shader_in) { - prog->InputsRead |= bitfield; - if (is_fragment_shader) { + int idx = var->data.location + var->data.index + offset + i; + bool is_patch_generic = var->data.patch && + idx != VARYING_SLOT_TESS_LEVEL_INNER && + idx != VARYING_SLOT_TESS_LEVEL_OUTER; + GLbitfield64 bitfield; + + if (is_patch_generic) { + assert(idx >= VARYING_SLOT_PATCH0 && idx < VARYING_SLOT_TESS_MAX); + bitfield = BITFIELD64_BIT(idx - VARYING_SLOT_PATCH0); + } + else { + assert(idx < VARYING_SLOT_MAX); + bitfield = BITFIELD64_BIT(idx); + } + + if (var->data.mode == ir_var_shader_in) { + if (is_patch_generic) + prog->PatchInputsRead |= bitfield; + else + prog->InputsRead |= bitfield; + + /* double inputs read is only for vertex inputs */ + if (stage == MESA_SHADER_VERTEX && + var->type->without_array()->is_dual_slot_double()) + prog->DoubleInputsRead |= bitfield; + + if (stage == MESA_SHADER_FRAGMENT) { gl_fragment_program *fprog = (gl_fragment_program *) prog; - fprog->InterpQualifier[var->location + var->index + offset + i] = - (glsl_interp_qualifier) var->interpolation; - if (var->centroid) + fprog->InterpQualifier[idx] = + (glsl_interp_qualifier) var->data.interpolation; + if (var->data.centroid) fprog->IsCentroid |= bitfield; + if (var->data.sample) + fprog->IsSample |= bitfield; } - } else if (var->mode == ir_var_system_value) { + } else if (var->data.mode == ir_var_system_value) { prog->SystemValuesRead |= bitfield; } else { - assert(var->mode == ir_var_shader_out); - prog->OutputsWritten |= bitfield; + assert(var->data.mode == ir_var_shader_out); + if (is_patch_generic) + prog->PatchOutputsWritten |= bitfield; + else + prog->OutputsWritten |= bitfield; } } } @@ -120,13 +149,36 @@ void ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var) { const glsl_type *type = var->type; - if (this->shader_type == GL_GEOMETRY_SHADER && - var->mode == ir_var_shader_in && type->is_array()) { + bool vertex_input = false; + if (this->shader_stage == MESA_SHADER_GEOMETRY && + var->data.mode == ir_var_shader_in && type->is_array()) { + type = type->fields.array; + } + + if (this->shader_stage == MESA_SHADER_TESS_CTRL && + var->data.mode == ir_var_shader_in) { + assert(type->is_array()); + type = type->fields.array; + } + + if (this->shader_stage == MESA_SHADER_TESS_CTRL && + var->data.mode == ir_var_shader_out && !var->data.patch) { + assert(type->is_array()); + type = type->fields.array; + } + + if (this->shader_stage == MESA_SHADER_TESS_EVAL && + var->data.mode == ir_var_shader_in && !var->data.patch) { + assert(type->is_array()); type = type->fields.array; } - mark(this->prog, var, 0, type->count_attribute_slots(), - this->shader_type == GL_FRAGMENT_SHADER); + if (this->shader_stage == MESA_SHADER_VERTEX && + var->data.mode == ir_var_shader_in) + vertex_input = true; + + mark(this->prog, var, 0, type->count_attribute_slots(vertex_input), + this->shader_stage); } /* Default handler: Mark all the locations in the variable as used. */ @@ -150,6 +202,9 @@ ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir) * * *Except gl_PrimitiveIDIn, as noted below. * + * For tessellation control shaders all inputs and non-patch outputs are + * arrays. For tessellation evaluation shaders non-patch inputs are arrays. + * * If the index can't be interpreted as a constant, or some other problem * occurs, then nothing will be marked and false will be returned. */ @@ -159,8 +214,8 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, { const glsl_type *type = var->type; - if (this->shader_type == GL_GEOMETRY_SHADER && - var->mode == ir_var_shader_in) { + if (this->shader_stage == MESA_SHADER_GEOMETRY && + var->data.mode == ir_var_shader_in) { /* The only geometry shader input that is not an array is * gl_PrimitiveIDIn, and in that case, this code will never be reached, * because gl_PrimitiveIDIn can't be indexed into in array fashion. @@ -169,6 +224,30 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, type = type->fields.array; } + if (this->shader_stage == MESA_SHADER_TESS_CTRL && + var->data.mode == ir_var_shader_in) { + assert(type->is_array()); + type = type->fields.array; + } + + if (this->shader_stage == MESA_SHADER_TESS_CTRL && + var->data.mode == ir_var_shader_out && !var->data.patch) { + assert(type->is_array()); + type = type->fields.array; + } + + if (this->shader_stage == MESA_SHADER_TESS_EVAL && + var->data.mode == ir_var_shader_in && !var->data.patch) { + assert(type->is_array()); + type = type->fields.array; + } + + /* TODO: implement proper arrays of arrays support + * for now let the caller mark whole variable as used. + */ + if (type->is_array() && type->fields.array->is_array()) + return false; + /* The code below only handles: * * - Indexing into matrices @@ -223,10 +302,26 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, } mark(this->prog, var, index_as_constant->value.u[0] * elem_width, - elem_width, this->shader_type == GL_FRAGMENT_SHADER); + elem_width, this->shader_stage); return true; } +static bool +is_multiple_vertices(gl_shader_stage stage, ir_variable *var) +{ + if (var->data.patch) + return false; + + if (var->data.mode == ir_var_shader_in) + return stage == MESA_SHADER_GEOMETRY || + stage == MESA_SHADER_TESS_CTRL || + stage == MESA_SHADER_TESS_EVAL; + if (var->data.mode == ir_var_shader_out) + return stage == MESA_SHADER_TESS_CTRL; + + return false; +} + ir_visitor_status ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) { @@ -241,10 +336,9 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) */ if (ir_dereference_variable * const deref_var = inner_array->array->as_dereference_variable()) { - if (this->shader_type == GL_GEOMETRY_SHADER && - deref_var->var->mode == ir_var_shader_in) { - /* foo is a geometry shader input, so i is the vertex, and j the - * part of the input we're accessing. + if (is_multiple_vertices(this->shader_stage, deref_var->var)) { + /* foo is a geometry or tessellation shader input, so i is + * the vertex, and j the part of the input we're accessing. */ if (try_mark_partial_variable(deref_var->var, ir->array_index)) { @@ -260,10 +354,9 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) } else if (ir_dereference_variable * const deref_var = ir->array->as_dereference_variable()) { /* ir => foo[i], where foo is a variable. */ - if (this->shader_type == GL_GEOMETRY_SHADER && - deref_var->var->mode == ir_var_shader_in) { - /* foo is a geometry shader input, so i is the vertex, and we're - * accessing the entire input. + if (is_multiple_vertices(this->shader_stage, deref_var->var)) { + /* foo is a geometry or tessellation shader input, so i is + * the vertex, and we're accessing the entire input. */ mark_whole_variable(deref_var->var); /* We've now taken care of foo, but i might contain a subexpression @@ -300,8 +393,10 @@ ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir) ir_visitor_status ir_set_program_inouts_visitor::visit_enter(ir_expression *ir) { - if (this->shader_type == GL_FRAGMENT_SHADER && - ir->operation == ir_unop_dFdy) { + if (this->shader_stage == MESA_SHADER_FRAGMENT && + (ir->operation == ir_unop_dFdy || + ir->operation == ir_unop_dFdy_coarse || + ir->operation == ir_unop_dFdy_fine)) { gl_fragment_program *fprog = (gl_fragment_program *) prog; fprog->UsesDFdy = true; } @@ -312,7 +407,7 @@ ir_visitor_status ir_set_program_inouts_visitor::visit_enter(ir_discard *) { /* discards are only allowed in fragment shaders. */ - assert(this->shader_type == GL_FRAGMENT_SHADER); + assert(this->shader_stage == MESA_SHADER_FRAGMENT); gl_fragment_program *fprog = (gl_fragment_program *) prog; fprog->UsesKill = true; @@ -330,17 +425,20 @@ ir_set_program_inouts_visitor::visit_enter(ir_texture *ir) void do_set_program_inouts(exec_list *instructions, struct gl_program *prog, - GLenum shader_type) + gl_shader_stage shader_stage) { - ir_set_program_inouts_visitor v(prog, shader_type); + ir_set_program_inouts_visitor v(prog, shader_stage); prog->InputsRead = 0; prog->OutputsWritten = 0; + prog->PatchInputsRead = 0; + prog->PatchOutputsWritten = 0; prog->SystemValuesRead = 0; - if (shader_type == GL_FRAGMENT_SHADER) { + if (shader_stage == MESA_SHADER_FRAGMENT) { gl_fragment_program *fprog = (gl_fragment_program *) prog; memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier)); fprog->IsCentroid = 0; + fprog->IsSample = 0; fprog->UsesDFdy = false; fprog->UsesKill = false; }