diff options
author | Jordan Justen <jordan.l.justen@intel.com> | 2014-10-10 08:28:24 -0700 |
---|---|---|
committer | Jordan Justen <jordan.l.justen@intel.com> | 2015-07-09 14:37:22 -0700 |
commit | 3b2a58c4890738efacf86ba25ed17441a319761d (patch) | |
tree | 90adac9ccb477f2cc4acb4ada61bfec3d1bb9e2a | |
parent | dd39d992050c51f6320b7fb1800675bdacec4186 (diff) |
glsl/cs: Lower gl_GlobalInvocationID variable
We lower this based on the extension spec formula:
gl_GlobalInvocationID =
gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID
Suggested-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
-rw-r--r-- | src/glsl/Makefile.sources | 1 | ||||
-rw-r--r-- | src/glsl/ir_optimization.h | 1 | ||||
-rw-r--r-- | src/glsl/linker.cpp | 2 | ||||
-rw-r--r-- | src/glsl/lower_cs_global_id.cpp | 178 |
4 files changed, 182 insertions, 0 deletions
diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index d784a81072..368c4845cf 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_cs_global_id.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 e6939f3fe1..f377835a72 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -134,6 +134,7 @@ void optimize_dead_builtin_variables(exec_list *instructions, enum ir_variable_mode other); bool lower_vertex_id(gl_shader *shader); +bool lower_cs_global_id(gl_shader *shader); ir_rvalue * compare_index_block(exec_list *instructions, ir_variable *index, diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index b7a783c098..0a2bf9d90e 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1825,6 +1825,8 @@ link_intrastage_shaders(void *mem_ctx, if (ctx->Const.VertexID_is_zero_based) lower_vertex_id(linked); + lower_cs_global_id(linked); + /* Make a pass over all variable declarations to ensure that arrays with * unspecified sizes have a size specified. The size is inferred from the * max_array_access field. diff --git a/src/glsl/lower_cs_global_id.cpp b/src/glsl/lower_cs_global_id.cpp new file mode 100644 index 0000000000..8a00880d2f --- /dev/null +++ b/src/glsl/lower_cs_global_id.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014 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_cs_global_id.cpp + * + * We lower this based on the extension spec formula: + * gl_GlobalInvocationID = + * gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID + */ + +#include "glsl_symbol_table.h" +#include "ir_hierarchical_visitor.h" +#include "ir.h" +#include "ir_builder.h" +#include "linker.h" +#include "program/prog_statevars.h" + +namespace { + +class lower_cs_global_id_visitor : public ir_hierarchical_visitor { +public: + explicit lower_cs_global_id_visitor(ir_function_signature *main_sig, + exec_list *ir_list) + : progress(false), GlobalInvocationID(NULL), gl_WorkGroupID(NULL), + gl_WorkGroupSize(NULL), gl_LocalInvocationID(NULL), + main_sig(main_sig), ir_list(ir_list) + { + foreach_in_list(ir_instruction, ir, ir_list) { + ir_variable *const var = ir->as_variable(); + + if (var == NULL) + continue; + + if (var->data.mode == ir_var_system_value) { + if (var->data.location == SYSTEM_VALUE_WORK_GROUP_ID) + gl_WorkGroupID = var; + if (var->data.location == SYSTEM_VALUE_LOCAL_INVOCATION_ID) + gl_LocalInvocationID = var; + } else if (gl_WorkGroupSize == NULL && + /* FIXME: Clean this up */ + /*var->data.mode == ir_var_auto && + var->data.read_only && + var->data.how_declared == ir_var_declared_implicitly &&*/ + var->name != NULL && + strcmp(var->name, "gl_WorkGroupSize") == 0) { + gl_WorkGroupSize = var; + } else + continue; + if (gl_WorkGroupID != NULL && gl_LocalInvocationID != NULL && + gl_WorkGroupSize != NULL) + break; + } + } + + virtual ir_visitor_status visit(ir_dereference_variable *); + + bool progress; + +private: + ir_variable *GlobalInvocationID; + ir_variable *gl_WorkGroupID; + ir_variable *gl_WorkGroupSize; + ir_variable *gl_LocalInvocationID; + + ir_function_signature *main_sig; + exec_list *ir_list; +}; + +} /* anonymous namespace */ + +ir_visitor_status +lower_cs_global_id_visitor::visit(ir_dereference_variable *ir) +{ + if (ir->var->data.mode != ir_var_system_value || + ir->var->data.location != SYSTEM_VALUE_GLOBAL_INVOCATION_ID) + return visit_continue; + + if (GlobalInvocationID == NULL) { + const glsl_type *const uvec3_t = glsl_type::uvec3_type; + void *const mem_ctx = ralloc_parent(ir); + + GlobalInvocationID = + new(mem_ctx) ir_variable(uvec3_t, "__GlobalInvocationID", + ir_var_temporary); + ir_list->push_head(GlobalInvocationID); + + if (gl_WorkGroupID == NULL) { + gl_WorkGroupID = new(mem_ctx) ir_variable(uvec3_t, "gl_WorkGroupID", + ir_var_system_value); + gl_WorkGroupID->data.how_declared = ir_var_declared_implicitly; + gl_WorkGroupID->data.read_only = true; + gl_WorkGroupID->data.location = SYSTEM_VALUE_GLOBAL_INVOCATION_ID; + gl_WorkGroupID->data.explicit_location = true; + gl_WorkGroupID->data.explicit_index = 0; + ir_list->push_head(gl_WorkGroupID); + } + + if (gl_WorkGroupSize == NULL) { + gl_WorkGroupSize = new(mem_ctx) ir_variable(uvec3_t, "gl_WorkGroupSize", + ir_var_auto); + gl_WorkGroupSize->data.how_declared = ir_var_declared_implicitly; + gl_WorkGroupSize->data.read_only = true; + ir_list->push_head(gl_WorkGroupSize); + } + + if (gl_LocalInvocationID == NULL) { + gl_LocalInvocationID = + new(mem_ctx) ir_variable(uvec3_t, "gl_LocalInvocationID", + ir_var_system_value); + gl_LocalInvocationID->data.how_declared = ir_var_declared_implicitly; + gl_LocalInvocationID->data.read_only = true; + gl_LocalInvocationID->data.location = SYSTEM_VALUE_LOCAL_INVOCATION_ID; + gl_LocalInvocationID->data.explicit_location = true; + gl_LocalInvocationID->data.explicit_index = 0; + ir_list->push_head(gl_LocalInvocationID); + } + + /** + * gl_GlobalInvocationID = + * gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID + */ + ir_instruction *const inst = + ir_builder::assign(GlobalInvocationID, + ir_builder::add(ir_builder::mul(gl_WorkGroupID, + gl_WorkGroupSize), + gl_LocalInvocationID)); + + main_sig->body.push_head(inst); + } + + ir->var = GlobalInvocationID; + progress = true; + + return visit_continue; +} + +bool +lower_cs_global_id(gl_shader *shader) +{ + /* gl_GlobalInvocationID only exists in the compute shader. + */ + if (shader->Stage != MESA_SHADER_COMPUTE) + return false; + + ir_function_signature *const main_sig = + link_get_main_function_signature(shader); + if (main_sig == NULL) { + assert(main_sig != NULL); + return false; + } + + lower_cs_global_id_visitor v(main_sig, shader->ir); + + v.run(shader->ir); + + return v.progress; +} |