glsl: Parse and propagate derivative_group to shader_info
NV_compute_shader_derivatives allow selecting between two possible arrangements (quads and linear) when calculating derivatives and certain subgroup operations in case of Vulkan. So parse and propagate those up to shader_info.h. v2: Do not fail when ARB_compute_variable_group_size is being used, since we are still clarifying what is the right thing to do here. Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
@@ -654,6 +654,11 @@ struct ast_type_qualifier {
|
|||||||
/** \{ */
|
/** \{ */
|
||||||
unsigned non_coherent:1;
|
unsigned non_coherent:1;
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/** \name Layout qualifiers for NV_compute_shader_derivatives */
|
||||||
|
/** \{ */
|
||||||
|
unsigned derivative_group:1;
|
||||||
|
/** \} */
|
||||||
}
|
}
|
||||||
/** \brief Set of flags, accessed by name. */
|
/** \brief Set of flags, accessed by name. */
|
||||||
q;
|
q;
|
||||||
@@ -766,6 +771,12 @@ struct ast_type_qualifier {
|
|||||||
*/
|
*/
|
||||||
GLenum image_format;
|
GLenum image_format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arrangement of invocations used to calculate derivatives in a compute
|
||||||
|
* shader. From NV_compute_shader_derivatives.
|
||||||
|
*/
|
||||||
|
enum gl_derivative_group derivative_group;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base type of the data read from or written to this image. Only
|
* Base type of the data read from or written to this image. Only
|
||||||
* the following enumerants are allowed: GLSL_TYPE_UINT,
|
* the following enumerants are allowed: GLSL_TYPE_UINT,
|
||||||
|
@@ -444,6 +444,11 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
|
|||||||
if (q.flags.q.bound_image)
|
if (q.flags.q.bound_image)
|
||||||
this->flags.q.bound_image = true;
|
this->flags.q.bound_image = true;
|
||||||
|
|
||||||
|
if (q.flags.q.derivative_group) {
|
||||||
|
this->flags.q.derivative_group = true;
|
||||||
|
this->derivative_group = q.derivative_group;
|
||||||
|
}
|
||||||
|
|
||||||
this->flags.i |= q.flags.i;
|
this->flags.i |= q.flags.i;
|
||||||
|
|
||||||
if (this->flags.q.in &&
|
if (this->flags.q.in &&
|
||||||
@@ -645,6 +650,7 @@ ast_type_qualifier::validate_in_qualifier(YYLTYPE *loc,
|
|||||||
case MESA_SHADER_COMPUTE:
|
case MESA_SHADER_COMPUTE:
|
||||||
valid_in_mask.flags.q.local_size = 7;
|
valid_in_mask.flags.q.local_size = 7;
|
||||||
valid_in_mask.flags.q.local_size_variable = 1;
|
valid_in_mask.flags.q.local_size_variable = 1;
|
||||||
|
valid_in_mask.flags.q.derivative_group = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
r = false;
|
r = false;
|
||||||
@@ -741,6 +747,19 @@ ast_type_qualifier::merge_into_in_qualifier(YYLTYPE *loc,
|
|||||||
r = false;
|
r = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->in_qualifier->flags.q.derivative_group) {
|
||||||
|
if (state->cs_derivative_group != DERIVATIVE_GROUP_NONE) {
|
||||||
|
if (state->in_qualifier->derivative_group != DERIVATIVE_GROUP_NONE &&
|
||||||
|
state->cs_derivative_group != state->in_qualifier->derivative_group) {
|
||||||
|
_mesa_glsl_error(loc, state,
|
||||||
|
"conflicting derivative groups.");
|
||||||
|
r = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state->cs_derivative_group = state->in_qualifier->derivative_group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We allow the creation of multiple cs_input_layout nodes. Coherence among
|
/* We allow the creation of multiple cs_input_layout nodes. Coherence among
|
||||||
* all existing nodes is checked later, when the AST node is transformed
|
* all existing nodes is checked later, when the AST node is transformed
|
||||||
* into HIR.
|
* into HIR.
|
||||||
|
@@ -1655,6 +1655,37 @@ layout_qualifier_id:
|
|||||||
$$.flags.q.non_coherent = 1;
|
$$.flags.q.non_coherent = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Layout qualifiers for NV_compute_shader_derivatives.
|
||||||
|
if (!$$.flags.i) {
|
||||||
|
if (match_layout_qualifier($1, "derivative_group_quadsNV", state) == 0) {
|
||||||
|
$$.flags.q.derivative_group = 1;
|
||||||
|
$$.derivative_group = DERIVATIVE_GROUP_QUADS;
|
||||||
|
} else if (match_layout_qualifier($1, "derivative_group_linearNV", state) == 0) {
|
||||||
|
$$.flags.q.derivative_group = 1;
|
||||||
|
$$.derivative_group = DERIVATIVE_GROUP_LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($$.flags.i) {
|
||||||
|
if (!state->has_compute_shader()) {
|
||||||
|
_mesa_glsl_error(& @1, state,
|
||||||
|
"qualifier `%s' requires "
|
||||||
|
"a compute shader", $1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state->NV_compute_shader_derivatives_enable) {
|
||||||
|
_mesa_glsl_error(& @1, state,
|
||||||
|
"qualifier `%s' requires "
|
||||||
|
"NV_compute_shader_derivatives", $1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->NV_compute_shader_derivatives_warn) {
|
||||||
|
_mesa_glsl_warning(& @1, state,
|
||||||
|
"NV_compute_shader_derivatives layout "
|
||||||
|
"qualifier `%s' used", $1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!$$.flags.i) {
|
if (!$$.flags.i) {
|
||||||
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
|
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
|
||||||
"`%s'", $1);
|
"`%s'", $1);
|
||||||
|
@@ -1717,7 +1717,8 @@ set_shader_inout_layout(struct gl_shader *shader,
|
|||||||
{
|
{
|
||||||
/* Should have been prevented by the parser. */
|
/* Should have been prevented by the parser. */
|
||||||
if (shader->Stage != MESA_SHADER_GEOMETRY &&
|
if (shader->Stage != MESA_SHADER_GEOMETRY &&
|
||||||
shader->Stage != MESA_SHADER_TESS_EVAL) {
|
shader->Stage != MESA_SHADER_TESS_EVAL &&
|
||||||
|
shader->Stage != MESA_SHADER_COMPUTE) {
|
||||||
assert(!state->in_qualifier->flags.i);
|
assert(!state->in_qualifier->flags.i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1725,6 +1726,7 @@ set_shader_inout_layout(struct gl_shader *shader,
|
|||||||
/* Should have been prevented by the parser. */
|
/* Should have been prevented by the parser. */
|
||||||
assert(!state->cs_input_local_size_specified);
|
assert(!state->cs_input_local_size_specified);
|
||||||
assert(!state->cs_input_local_size_variable_specified);
|
assert(!state->cs_input_local_size_variable_specified);
|
||||||
|
assert(state->cs_derivative_group == DERIVATIVE_GROUP_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader->Stage != MESA_SHADER_FRAGMENT) {
|
if (shader->Stage != MESA_SHADER_FRAGMENT) {
|
||||||
@@ -1849,6 +1851,36 @@ set_shader_inout_layout(struct gl_shader *shader,
|
|||||||
|
|
||||||
shader->info.Comp.LocalSizeVariable =
|
shader->info.Comp.LocalSizeVariable =
|
||||||
state->cs_input_local_size_variable_specified;
|
state->cs_input_local_size_variable_specified;
|
||||||
|
|
||||||
|
shader->info.Comp.DerivativeGroup = state->cs_derivative_group;
|
||||||
|
|
||||||
|
if (state->NV_compute_shader_derivatives_enable) {
|
||||||
|
/* We allow multiple cs_input_layout nodes, but do not store them in
|
||||||
|
* a convenient place, so for now live with an empty location error.
|
||||||
|
*/
|
||||||
|
YYLTYPE loc = {0};
|
||||||
|
if (shader->info.Comp.DerivativeGroup == DERIVATIVE_GROUP_QUADS) {
|
||||||
|
if (shader->info.Comp.LocalSize[0] % 2 != 0) {
|
||||||
|
_mesa_glsl_error(&loc, state, "derivative_group_quadsNV must be used with a "
|
||||||
|
"local group size whose first dimension "
|
||||||
|
"is a multiple of 2\n");
|
||||||
|
}
|
||||||
|
if (shader->info.Comp.LocalSize[1] % 2 != 0) {
|
||||||
|
_mesa_glsl_error(&loc, state, "derivative_group_quadsNV must be used with a "
|
||||||
|
"local group size whose second dimension "
|
||||||
|
"is a multiple of 2\n");
|
||||||
|
}
|
||||||
|
} else if (shader->info.Comp.DerivativeGroup == DERIVATIVE_GROUP_LINEAR) {
|
||||||
|
if ((shader->info.Comp.LocalSize[0] *
|
||||||
|
shader->info.Comp.LocalSize[1] *
|
||||||
|
shader->info.Comp.LocalSize[2]) % 4 != 0) {
|
||||||
|
_mesa_glsl_error(&loc, state, "derivative_group_linearNV must be used with a "
|
||||||
|
"local group size whose total number of invocations "
|
||||||
|
"is a multiple of 4\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MESA_SHADER_FRAGMENT:
|
case MESA_SHADER_FRAGMENT:
|
||||||
|
@@ -445,6 +445,12 @@ struct _mesa_glsl_parse_state {
|
|||||||
*/
|
*/
|
||||||
bool cs_input_local_size_variable_specified;
|
bool cs_input_local_size_variable_specified;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arrangement of invocations used to calculate derivatives in a compute
|
||||||
|
* shader. From NV_compute_shader_derivatives.
|
||||||
|
*/
|
||||||
|
enum gl_derivative_group cs_derivative_group;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if a shader declare bindless_sampler/bindless_image, and
|
* True if a shader declare bindless_sampler/bindless_image, and
|
||||||
* respectively bound_sampler/bound_image at global scope as specified by
|
* respectively bound_sampler/bound_image at global scope as specified by
|
||||||
|
@@ -2170,9 +2170,9 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform cross-validation of compute shader local_size_{x,y,z} layout
|
* Perform cross-validation of compute shader local_size_{x,y,z} layout and
|
||||||
* qualifiers for the attached compute shaders, and propagate them to the
|
* derivative arrangement qualifiers for the attached compute shaders, and
|
||||||
* linked CS and linked shader program.
|
* propagate them to the linked CS and linked shader program.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
link_cs_input_layout_qualifiers(struct gl_shader_program *prog,
|
link_cs_input_layout_qualifiers(struct gl_shader_program *prog,
|
||||||
@@ -2191,6 +2191,8 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog,
|
|||||||
|
|
||||||
gl_prog->info.cs.local_size_variable = false;
|
gl_prog->info.cs.local_size_variable = false;
|
||||||
|
|
||||||
|
gl_prog->info.cs.derivative_group = DERIVATIVE_GROUP_NONE;
|
||||||
|
|
||||||
/* From the ARB_compute_shader spec, in the section describing local size
|
/* From the ARB_compute_shader spec, in the section describing local size
|
||||||
* declarations:
|
* declarations:
|
||||||
*
|
*
|
||||||
@@ -2234,6 +2236,17 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog,
|
|||||||
}
|
}
|
||||||
gl_prog->info.cs.local_size_variable = true;
|
gl_prog->info.cs.local_size_variable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum gl_derivative_group group = shader->info.Comp.DerivativeGroup;
|
||||||
|
if (group != DERIVATIVE_GROUP_NONE) {
|
||||||
|
if (gl_prog->info.cs.derivative_group != DERIVATIVE_GROUP_NONE &&
|
||||||
|
gl_prog->info.cs.derivative_group != group) {
|
||||||
|
linker_error(prog, "compute shader defined with conflicting "
|
||||||
|
"derivative groups\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gl_prog->info.cs.derivative_group = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just do the intrastage -> interstage propagation right now,
|
/* Just do the intrastage -> interstage propagation right now,
|
||||||
@@ -2246,6 +2259,30 @@ link_cs_input_layout_qualifiers(struct gl_shader_program *prog,
|
|||||||
"local group size\n");
|
"local group size\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gl_prog->info.cs.derivative_group == DERIVATIVE_GROUP_QUADS) {
|
||||||
|
if (gl_prog->info.cs.local_size[0] % 2 != 0) {
|
||||||
|
linker_error(prog, "derivative_group_quadsNV must be used with a "
|
||||||
|
"local group size whose first dimension "
|
||||||
|
"is a multiple of 2\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gl_prog->info.cs.local_size[1] % 2 != 0) {
|
||||||
|
linker_error(prog, "derivative_group_quadsNV must be used with a local"
|
||||||
|
"group size whose second dimension "
|
||||||
|
"is a multiple of 2\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (gl_prog->info.cs.derivative_group == DERIVATIVE_GROUP_LINEAR) {
|
||||||
|
if ((gl_prog->info.cs.local_size[0] *
|
||||||
|
gl_prog->info.cs.local_size[1] *
|
||||||
|
gl_prog->info.cs.local_size[2]) % 4 != 0) {
|
||||||
|
linker_error(prog, "derivative_group_linearNV must be used with a "
|
||||||
|
"local group size whose total number of invocations "
|
||||||
|
"is a multiple of 4\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -772,6 +772,47 @@ enum compare_func
|
|||||||
COMPARE_FUNC_ALWAYS,
|
COMPARE_FUNC_ALWAYS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arrangements for grouping invocations from NV_compute_shader_derivatives.
|
||||||
|
*
|
||||||
|
* The extension provides new layout qualifiers that support two different
|
||||||
|
* arrangements of compute shader invocations for the purpose of derivative
|
||||||
|
* computation. When specifying
|
||||||
|
*
|
||||||
|
* layout(derivative_group_quadsNV) in;
|
||||||
|
*
|
||||||
|
* compute shader invocations are grouped into 2x2x1 arrays whose four local
|
||||||
|
* invocation ID values follow the pattern:
|
||||||
|
*
|
||||||
|
* +-----------------+------------------+
|
||||||
|
* | (2x+0, 2y+0, z) | (2x+1, 2y+0, z) |
|
||||||
|
* +-----------------+------------------+
|
||||||
|
* | (2x+0, 2y+1, z) | (2x+1, 2y+1, z) |
|
||||||
|
* +-----------------+------------------+
|
||||||
|
*
|
||||||
|
* where Y increases from bottom to top. When specifying
|
||||||
|
*
|
||||||
|
* layout(derivative_group_linearNV) in;
|
||||||
|
*
|
||||||
|
* compute shader invocations are grouped into 2x2x1 arrays whose four local
|
||||||
|
* invocation index values follow the pattern:
|
||||||
|
*
|
||||||
|
* +------+------+
|
||||||
|
* | 4n+0 | 4n+1 |
|
||||||
|
* +------+------+
|
||||||
|
* | 4n+2 | 4n+3 |
|
||||||
|
* +------+------+
|
||||||
|
*
|
||||||
|
* If neither layout qualifier is specified, derivatives in compute shaders
|
||||||
|
* return zero, which is consistent with the handling of built-in texture
|
||||||
|
* functions like texture() in GLSL 4.50 compute shaders.
|
||||||
|
*/
|
||||||
|
enum gl_derivative_group {
|
||||||
|
DERIVATIVE_GROUP_NONE = 0,
|
||||||
|
DERIVATIVE_GROUP_QUADS,
|
||||||
|
DERIVATIVE_GROUP_LINEAR,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
@@ -252,6 +252,12 @@ typedef struct shader_info {
|
|||||||
* AddressingModelPhysical64: 64
|
* AddressingModelPhysical64: 64
|
||||||
*/
|
*/
|
||||||
unsigned ptr_size;
|
unsigned ptr_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arrangement of invocations used to calculate derivatives in a compute
|
||||||
|
* shader. From NV_compute_shader_derivatives.
|
||||||
|
*/
|
||||||
|
enum gl_derivative_group derivative_group;
|
||||||
} cs;
|
} cs;
|
||||||
|
|
||||||
/* Applies to both TCS and TES. */
|
/* Applies to both TCS and TES. */
|
||||||
|
@@ -2516,6 +2516,12 @@ struct gl_shader_info
|
|||||||
* ARB_compute_variable_group_size.
|
* ARB_compute_variable_group_size.
|
||||||
*/
|
*/
|
||||||
bool LocalSizeVariable;
|
bool LocalSizeVariable;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arrangement of invocations used to calculate derivatives in a compute
|
||||||
|
* shader. From NV_compute_shader_derivatives.
|
||||||
|
*/
|
||||||
|
enum gl_derivative_group DerivativeGroup;
|
||||||
} Comp;
|
} Comp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user