summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-08-30 15:02:25 -0500
committerJason Ekstrand <[email protected]>2018-09-06 16:07:50 -0500
commit25efd787cfd842c0b0b900f35399e44a2e01ea39 (patch)
treebe4df409f2242e2d16f10c3f8e15e6535b713769 /src/compiler
parent1285f71d3e93f200cec0c321bb6e621d4aece7b3 (diff)
compiler: Move double_inputs to gl_program::DualSlotInputs
Previously, we had two field in shader_info: double_inputs_read and double_inputs. Presumably, the one was for all double inputs that are read and the other is all that exist. However, because nir_gather_info regenerates these two values, there is a possibility, if a variable gets deleted, that the value of double_inputs could change over time. This is a problem because double_inputs is used to remap the input locations to a two-slot-per-dvec3/4 scheme for i965. If that mapping were to change between glsl_to_nir and back-end state setup, we would fall over when trying to map the NIR outputs back onto the GL location space. This commit changes the way slot re-mapping works. Instead of the double_inputs field in shader_info, it adds a DualSlotInputs bitfield to gl_program. By having it in gl_program, we more easily guarantee that NIR passes won't touch it after it's been set. It also makes more sense to put it in a GL data structure since it's really a mapping from GL slots to back-end and/or NIR slots and not really a NIR shader thing. Tested-by: Alejandro Piñeiro <[email protected]> (ARB_gl_spirv tests) Reviewed-by: Alejandro Piñeiro <[email protected]> Reviewed-by: Timothy Arceri <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/glsl/glsl_to_nir.cpp16
-rw-r--r--src/compiler/glsl/ir_set_program_inouts.cpp2
-rw-r--r--src/compiler/glsl/serialize.cpp2
-rw-r--r--src/compiler/nir/nir.c49
-rw-r--r--src/compiler/nir/nir.h6
-rw-r--r--src/compiler/nir/nir_gather_info.c6
-rw-r--r--src/compiler/shader_info.h3
7 files changed, 49 insertions, 35 deletions
diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp
index f38d280d406..d22f4a58dd4 100644
--- a/src/compiler/glsl/glsl_to_nir.cpp
+++ b/src/compiler/glsl/glsl_to_nir.cpp
@@ -149,8 +149,11 @@ glsl_to_nir(const struct gl_shader_program *shader_prog,
* two locations. For instance, if we have in the IR code a dvec3 attr0 in
* location 0 and vec4 attr1 in location 1, in NIR attr0 will use
* locations/slots 0 and 1, and attr1 will use location/slot 2 */
- if (shader->info.stage == MESA_SHADER_VERTEX)
- nir_remap_attributes(shader, options);
+ if (shader->info.stage == MESA_SHADER_VERTEX) {
+ sh->Program->DualSlotInputs = nir_get_dual_slot_attributes(shader);
+ if (options->vs_inputs_dual_locations)
+ nir_remap_dual_slot_attributes(shader, sh->Program->DualSlotInputs);
+ }
shader->info.name = ralloc_asprintf(shader, "GLSL%d", shader_prog->Name);
if (shader_prog->Label)
@@ -344,15 +347,6 @@ nir_visitor::visit(ir_variable *ir)
var->data.compact = ir->type->without_array()->is_scalar();
}
}
-
- /* Mark all the locations that require two slots */
- if (shader->info.stage == MESA_SHADER_VERTEX &&
- glsl_type_is_dual_slot(glsl_without_array(var->type))) {
- for (unsigned i = 0; i < glsl_count_attribute_slots(var->type, true); i++) {
- uint64_t bitfield = BITFIELD64_BIT(var->data.location + i);
- shader->info.vs.double_inputs |= bitfield;
- }
- }
break;
case ir_var_shader_out:
diff --git a/src/compiler/glsl/ir_set_program_inouts.cpp b/src/compiler/glsl/ir_set_program_inouts.cpp
index ba1e44167c3..a3cb19479b8 100644
--- a/src/compiler/glsl/ir_set_program_inouts.cpp
+++ b/src/compiler/glsl/ir_set_program_inouts.cpp
@@ -118,7 +118,7 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
/* double inputs read is only for vertex inputs */
if (stage == MESA_SHADER_VERTEX &&
var->type->without_array()->is_dual_slot())
- prog->info.vs.double_inputs_read |= bitfield;
+ prog->DualSlotInputs |= bitfield;
if (stage == MESA_SHADER_FRAGMENT) {
prog->info.fs.uses_sample_qualifier |= var->data.sample;
diff --git a/src/compiler/glsl/serialize.cpp b/src/compiler/glsl/serialize.cpp
index 889038fb5e2..267700e7e78 100644
--- a/src/compiler/glsl/serialize.cpp
+++ b/src/compiler/glsl/serialize.cpp
@@ -1035,6 +1035,7 @@ write_shader_metadata(struct blob *metadata, gl_linked_shader *shader)
struct gl_program *glprog = shader->Program;
unsigned i;
+ blob_write_uint64(metadata, glprog->DualSlotInputs);
blob_write_bytes(metadata, glprog->TexturesUsed,
sizeof(glprog->TexturesUsed));
blob_write_uint64(metadata, glprog->SamplersUsed);
@@ -1088,6 +1089,7 @@ read_shader_metadata(struct blob_reader *metadata,
{
unsigned i;
+ glprog->DualSlotInputs = blob_read_uint64(metadata);
blob_copy_bytes(metadata, (uint8_t *) glprog->TexturesUsed,
sizeof(glprog->TexturesUsed));
glprog->SamplersUsed = blob_read_uint64(metadata);
diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index 7ae46845191..0d8a554bd20 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -1854,23 +1854,48 @@ nir_system_value_from_intrinsic(nir_intrinsic_op intrin)
}
}
+uint64_t
+nir_get_dual_slot_attributes(nir_shader *shader)
+{
+ assert(shader->info.stage == MESA_SHADER_VERTEX);
+
+ uint64_t dual_slot = 0;
+ nir_foreach_variable(var, &shader->inputs) {
+ if (glsl_type_is_dual_slot(glsl_without_array(var->type))) {
+ unsigned slots = glsl_count_attribute_slots(var->type, true);
+ dual_slot |= BITFIELD64_MASK(slots) << var->data.location;
+ }
+ }
+
+ return dual_slot;
+}
+
/* OpenGL utility method that remaps the location attributes if they are
* doubles. Not needed for vulkan due the differences on the input location
* count for doubles on vulkan vs OpenGL
*/
void
-nir_remap_attributes(nir_shader *shader,
- const nir_shader_compiler_options *options)
-{
- if (options->vs_inputs_dual_locations) {
- nir_foreach_variable(var, &shader->inputs) {
- var->data.location +=
- _mesa_bitcount_64(shader->info.vs.double_inputs &
- BITFIELD64_MASK(var->data.location));
- }
+nir_remap_dual_slot_attributes(nir_shader *shader, uint64_t dual_slot)
+{
+ assert(shader->info.stage == MESA_SHADER_VERTEX);
+
+ nir_foreach_variable(var, &shader->inputs) {
+ var->data.location +=
+ _mesa_bitcount_64(dual_slot & BITFIELD64_MASK(var->data.location));
}
+}
- /* Once the remap is done, reset double_inputs_read, so later it will have
- * which location/slots are doubles */
- shader->info.vs.double_inputs = 0;
+/* Returns an attribute mask that has been re-compacted using the given
+ * dual_slot mask.
+ */
+uint64_t
+nir_get_single_slot_attribs_mask(uint64_t attribs, uint64_t dual_slot)
+{
+ while (dual_slot) {
+ unsigned loc = u_bit_scan64(&dual_slot);
+ /* mask of all bits up to and including loc */
+ uint64_t mask = BITFIELD64_MASK(loc + 1);
+ attribs = (attribs & mask) | ((attribs & ~mask) >> 1);
+ }
+ return attribs;
}
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 169fa1fa20d..b9393702097 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -3039,8 +3039,10 @@ bool nir_opt_conditional_discard(nir_shader *shader);
void nir_sweep(nir_shader *shader);
-void nir_remap_attributes(nir_shader *shader,
- const nir_shader_compiler_options *options);
+uint64_t nir_get_dual_slot_attributes(nir_shader *shader);
+void nir_remap_dual_slot_attributes(nir_shader *shader,
+ uint64_t dual_slot);
+uint64_t nir_get_single_slot_attribs_mask(uint64_t attribs, uint64_t dual_slot);
nir_intrinsic_op nir_intrinsic_from_system_value(gl_system_value val);
gl_system_value nir_system_value_from_intrinsic(nir_intrinsic_op intrin);
diff --git a/src/compiler/nir/nir_gather_info.c b/src/compiler/nir/nir_gather_info.c
index 4a030cb6256..de18c9bd78e 100644
--- a/src/compiler/nir/nir_gather_info.c
+++ b/src/compiler/nir/nir_gather_info.c
@@ -54,11 +54,6 @@ set_io_mask(nir_shader *shader, nir_variable *var, int offset, int len,
else
shader->info.inputs_read |= bitfield;
- /* double inputs read is only for vertex inputs */
- if (shader->info.stage == MESA_SHADER_VERTEX &&
- glsl_type_is_dual_slot(glsl_without_array(var->type)))
- shader->info.vs.double_inputs_read |= bitfield;
-
if (shader->info.stage == MESA_SHADER_FRAGMENT) {
shader->info.fs.uses_sample_qualifier |= var->data.sample;
}
@@ -417,7 +412,6 @@ nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint)
shader->info.system_values_read = 0;
if (shader->info.stage == MESA_SHADER_VERTEX) {
shader->info.vs.double_inputs = 0;
- shader->info.vs.double_inputs_read = 0;
}
if (shader->info.stage == MESA_SHADER_FRAGMENT) {
shader->info.fs.uses_sample_qualifier = false;
diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h
index dab15b58894..65bc0588d67 100644
--- a/src/compiler/shader_info.h
+++ b/src/compiler/shader_info.h
@@ -134,9 +134,6 @@ typedef struct shader_info {
struct {
/* Which inputs are doubles */
uint64_t double_inputs;
-
- /* Which inputs are actually read and are double */
- uint64_t double_inputs_read;
} vs;
struct {