diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vulkan/Makefile.am | 1 | ||||
-rw-r--r-- | src/vulkan/anv_nir.h | 2 | ||||
-rw-r--r-- | src/vulkan/anv_nir_lower_push_constants.c | 107 | ||||
-rw-r--r-- | src/vulkan/anv_pipeline.c | 16 |
4 files changed, 113 insertions, 13 deletions
diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am index 475fa4f2ad2..0d6c9df6b67 100644 --- a/src/vulkan/Makefile.am +++ b/src/vulkan/Makefile.am @@ -69,6 +69,7 @@ VULKAN_SOURCES = \ anv_meta.c \ anv_nir_apply_dynamic_offsets.c \ anv_nir_apply_pipeline_layout.c \ + anv_nir_lower_push_constants.c \ anv_pass.c \ anv_pipeline.c \ anv_private.h \ diff --git a/src/vulkan/anv_nir.h b/src/vulkan/anv_nir.h index af95e3a8849..b164ae581e1 100644 --- a/src/vulkan/anv_nir.h +++ b/src/vulkan/anv_nir.h @@ -37,6 +37,8 @@ anv_vk_shader_stage_for_mesa_stage(gl_shader_stage stage) return (VkShaderStage)(int)stage; } +void anv_nir_lower_push_constants(nir_shader *shader, bool is_scalar); + void anv_nir_apply_dynamic_offsets(struct anv_pipeline *pipeline, nir_shader *shader, struct brw_stage_prog_data *prog_data); diff --git a/src/vulkan/anv_nir_lower_push_constants.c b/src/vulkan/anv_nir_lower_push_constants.c new file mode 100644 index 00000000000..af48470522a --- /dev/null +++ b/src/vulkan/anv_nir_lower_push_constants.c @@ -0,0 +1,107 @@ +/* + * Copyright © 2015 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. + */ + +#include "anv_nir.h" + +struct lower_push_constants_state { + nir_shader *shader; + bool is_scalar; +}; + +static bool +lower_push_constants_block(nir_block *block, void *void_state) +{ + struct lower_push_constants_state *state = void_state; + + nir_foreach_instr(block, instr) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + + /* TODO: Handle indirect push constants */ + if (intrin->intrinsic != nir_intrinsic_load_push_constant) + continue; + + assert(intrin->const_index[0] % 4 == 0); + unsigned dword_offset = intrin->const_index[0] / 4; + + /* We just turn them into uniform loads with the appropreate offset */ + intrin->intrinsic = nir_intrinsic_load_uniform; + intrin->const_index[0] = 0; + if (state->is_scalar) { + intrin->const_index[1] = dword_offset; + } else { + unsigned shift = dword_offset % 4; + /* Can't cross the vec4 boundary */ + assert(shift + intrin->num_components <= 4); + + /* vec4 shifts are in units of vec4's */ + intrin->const_index[1] = dword_offset / 4; + + if (shift) { + /* If there's a non-zero shift then we need to load a whole vec4 + * and use a move to swizzle it into place. + */ + assert(intrin->dest.is_ssa); + nir_alu_instr *mov = nir_alu_instr_create(state->shader, + nir_op_imov); + mov->src[0].src = nir_src_for_ssa(&intrin->dest.ssa); + for (unsigned i = 0; i < intrin->num_components; i++) + mov->src[0].swizzle[i] = i + shift; + mov->dest.write_mask = (1 << intrin->num_components) - 1; + nir_ssa_dest_init(&intrin->instr, &intrin->dest, + intrin->num_components, NULL); + + nir_ssa_def_rewrite_uses(&intrin->dest.ssa, + nir_src_for_ssa(&mov->dest.dest.ssa)); + nir_instr_insert_after(&intrin->instr, &mov->instr); + + /* Stomp the number of components to 4 */ + intrin->num_components = 4; + } + } + } + + return true; +} + +void +anv_nir_lower_push_constants(nir_shader *shader, bool is_scalar) +{ + struct lower_push_constants_state state = { + .shader = shader, + .is_scalar = is_scalar, + }; + + nir_foreach_overload(shader, overload) { + if (overload->impl) + nir_foreach_block(overload->impl, lower_push_constants_block, &state); + } + + assert(shader->num_uniforms % 4 == 0); + if (is_scalar) + shader->num_uniforms /= 4; + else + shader->num_uniforms = DIV_ROUND_UP(shader->num_uniforms, 16); +} diff --git a/src/vulkan/anv_pipeline.c b/src/vulkan/anv_pipeline.c index 59f304f55df..9fb5ddba20b 100644 --- a/src/vulkan/anv_pipeline.c +++ b/src/vulkan/anv_pipeline.c @@ -357,22 +357,12 @@ anv_pipeline_compile(struct anv_pipeline *pipeline, if (nir == NULL) return NULL; - bool have_push_constants = false; - nir_foreach_variable(var, &nir->uniforms) { - const struct glsl_type *type = var->type; - if (glsl_type_is_array(type)) - type = glsl_get_array_element(type); - - if (!glsl_type_is_sampler(type)) { - have_push_constants = true; - break; - } - } + anv_nir_lower_push_constants(nir, is_scalar_shader_stage(compiler, stage)); /* Figure out the number of parameters */ prog_data->nr_params = 0; - if (have_push_constants) { + if (nir->num_uniforms > 0) { /* If the shader uses any push constants at all, we'll just give * them the maximum possible number */ @@ -394,7 +384,7 @@ anv_pipeline_compile(struct anv_pipeline *pipeline, * params array, it doesn't really matter what we put here. */ struct anv_push_constants *null_data = NULL; - if (have_push_constants) { + if (nir->num_uniforms > 0) { /* Fill out the push constants section of the param array */ for (unsigned i = 0; i < MAX_PUSH_CONSTANTS_SIZE / sizeof(float); i++) prog_data->param[i] = (const gl_constant_value *) |