[Mesa-dev] [PATCH v3 3/8] glsl: Add support for the new builtins that EXT_blend_func_extended provides.
Ilia Mirkin
imirkin at alum.mit.edu
Fri Nov 6 11:20:38 PST 2015
On Fri, Nov 6, 2015 at 1:10 PM, Ian Romanick <idr at freedesktop.org> wrote:
> On 11/05/2015 06:47 PM, Ryan Houdek wrote:
>> gl_MaxDualSourceDrawBuffersEXT - Maximum DS draw buffers supported
>>
>> Only for ESSL 1.0 it provides two builtins since you can't have user-defined
>> color output variables
>> gl_SecondaryFragColorEXT and gl_SecondaryFragDataEXT[MaxDSDrawBuffers]
>> ---
>> src/glsl/ast_to_hir.cpp | 16 +++++++++++
>> src/glsl/builtin_variables.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 78 insertions(+)
>>
>> diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
>> index 0306530..9ac7d80 100644
>> --- a/src/glsl/ast_to_hir.cpp
>> +++ b/src/glsl/ast_to_hir.cpp
>> @@ -6973,6 +6973,8 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
>> {
>> bool gl_FragColor_assigned = false;
>> bool gl_FragData_assigned = false;
>> + bool gl_FragSecondaryColor_assigned = false;
>> + bool gl_FragSecondaryData_assigned = false;
>> bool user_defined_fs_output_assigned = false;
>> ir_variable *user_defined_fs_output = NULL;
>>
>> @@ -6990,6 +6992,10 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
>> gl_FragColor_assigned = true;
>> else if (strcmp(var->name, "gl_FragData") == 0)
>> gl_FragData_assigned = true;
>> + else if (strcmp(var->name, "gl_SecondaryFragColorEXT") == 0)
>> + gl_FragSecondaryColor_assigned = true;
>> + else if (strcmp(var->name, "gl_SecondaryFragDataEXT") == 0)
>> + gl_FragSecondaryData_assigned = true;
>> else if (!is_gl_identifier(var->name)) {
>> if (state->stage == MESA_SHADER_FRAGMENT &&
>> var->data.mode == ir_var_shader_out) {
>> @@ -7021,11 +7027,21 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
>> _mesa_glsl_error(&loc, state, "fragment shader writes to both "
>> "`gl_FragColor' and `%s'",
>> user_defined_fs_output->name);
>> + } else if (gl_FragSecondaryColor_assigned && gl_FragSecondaryData_assigned) {
>> + _mesa_glsl_error(&loc, state, "fragment shader writes to both "
>> + "`gl_FragSecondaryColorEXT' and"
>> + " `gl_FragSecondaryDataEXT'");
>> } else if (gl_FragData_assigned && user_defined_fs_output_assigned) {
>> _mesa_glsl_error(&loc, state, "fragment shader writes to both "
>> "`gl_FragData' and `%s'",
>> user_defined_fs_output->name);
>> }
>> +
>> + if ((gl_FragSecondaryColor_assigned || gl_FragSecondaryData_assigned) &&
>> + !state->EXT_blend_func_extended_enable) {
>> + _mesa_glsl_error(&loc, state,
>> + "Dual source blending requires EXT_blend_func_extended");
>> + }
>
> The spec doesn't seem to provide any guidance about a shader like:
>
> #extension GL_EXT_blend_func_extended: require
> void main() {
> gl_FragData[0] = vec4(0);
> glSecondaryFragColorEXT = vec4(0);
> }
>
> What does NVIDIA's implementation do? We should mimic that behavior,
It says "GL_EXT_blend_func_extended not supported" :) Why would the
above be problematic though?
> and have a comment here justifying it. Something like
>
> /* The EXT_blend_func_extended spec doesn't say what to do if
> * gl_FragData and glSecondaryFragColorEXT (or gl_FragColor and
> * glSecondaryFragDataEXT) are written together. NVIDIA's XXX.YY
> * driver [say what it does], so we mimic that.
> */
>
> We should also have piglit tests that exercise it.
>
>> }
>>
>>
>> diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp
>> index c30fb92..4933c8a 100644
>> --- a/src/glsl/builtin_variables.cpp
>> +++ b/src/glsl/builtin_variables.cpp
>> @@ -376,6 +376,11 @@ private:
>> return add_variable(name, type, ir_var_shader_out, slot);
>> }
>>
>> + ir_variable *add_index_output(int slot, int index, const glsl_type *type, const char *name)
>> + {
>> + return add_index_variable(name, type, ir_var_shader_out, slot, index);
>> + }
>> +
>> ir_variable *add_system_value(int slot, const glsl_type *type,
>> const char *name)
>> {
>> @@ -384,6 +389,8 @@ private:
>>
>> ir_variable *add_variable(const char *name, const glsl_type *type,
>> enum ir_variable_mode mode, int slot);
>> + ir_variable *add_index_variable(const char *name, const glsl_type *type,
>> + enum ir_variable_mode mode, int slot, int index);
>> ir_variable *add_uniform(const glsl_type *type, const char *name);
>> ir_variable *add_const(const char *name, int value);
>> ir_variable *add_const_ivec3(const char *name, int x, int y, int z);
>> @@ -429,6 +436,46 @@ builtin_variable_generator::builtin_variable_generator(
>> {
>> }
>>
>> +ir_variable *
>> +builtin_variable_generator::add_index_variable(const char *name,
>> + const glsl_type *type,
>> + enum ir_variable_mode mode, int slot, int index)
>> +{
>> + ir_variable *var = new(symtab) ir_variable(type, name, mode);
>> + var->data.how_declared = ir_var_declared_implicitly;
>> +
>> + switch (var->data.mode) {
>> + case ir_var_auto:
>> + case ir_var_shader_in:
>> + case ir_var_uniform:
>> + case ir_var_system_value:
>> + var->data.read_only = true;
>> + break;
>> + case ir_var_shader_out:
>> + case ir_var_shader_storage:
>> + break;
>> + default:
>> + /* The only variables that are added using this function should be
>> + * uniforms, shader storage, shader inputs, and shader outputs, constants
>> + * (which use ir_var_auto), and system values.
>> + */
>> + assert(0);
>> + break;
>> + }
>> +
>> + var->data.location = slot;
>> + var->data.explicit_location = (slot >= 0);
>> + var->data.explicit_index = 1;
>> + var->data.index = index;
>> +
>> + /* Once the variable is created an initialized, add it to the symbol table
>> + * and add the declaration to the IR stream.
>> + */
>> + instructions->push_tail(var);
>> +
>> + symtab->add_variable(var);
>> + return var;
>> +}
>>
>> ir_variable *
>> builtin_variable_generator::add_variable(const char *name,
>> @@ -580,6 +627,14 @@ builtin_variable_generator::generate_constants()
>> add_const("gl_MaxVaryingVectors",
>> state->ctx->Const.MaxVarying);
>> }
>> +
>> + /* EXT_blend_func_extended brings a built in constant
>> + * for determining number of dual source draw buffers
>> + */
>> + if (state->EXT_blend_func_extended_enable) {
>> + add_const("gl_MaxDualSourceDrawBuffersEXT",
>> + state->Const.MaxDualSourceDrawBuffers);
>> + }
>> } else {
>> add_const("gl_MaxVertexUniformComponents",
>> state->Const.MaxVertexUniformComponents);
>> @@ -1016,6 +1071,13 @@ builtin_variable_generator::generate_fs_special_vars()
>> array(vec4_t, state->Const.MaxDrawBuffers), "gl_FragData");
>> }
>>
>> + if (state->es_shader && state->language_version == 100 && state->EXT_blend_func_extended_enable) {
>> + add_index_output(FRAG_RESULT_DATA0, 1, vec4_t, "gl_SecondaryFragColorEXT");
>> + add_index_output(FRAG_RESULT_DATA0, 1,
>> + array(vec4_t, state->Const.MaxDualSourceDrawBuffers),
>> + "gl_SecondaryFragDataEXT");
>> + }
>> +
>> /* gl_FragDepth has always been in desktop GLSL, but did not appear in GLSL
>> * ES 1.00.
>> */
>>
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list