This pass wraps sampler instructions with some logic to deal with border colors with integer formats on Gen7.5.
Fixes most of : dEQP-VK.pipeline.sampler.view_type.*.format.*int.address_modes.all_mode_clamp_to_border_* Remaining 11 failures : HSW: dEQP-VK.pipeline.sampler.view_type.*.format.b4g4r4a4_unorm_pack16.address_modes.all_mode_clamp_to_border_opaque_black dEQP-VK.pipeline.sampler.view_type.2d.format.r32_uint.address_modes.all_mode_clamp_to_border_* dEQP-VK.pipeline.sampler.view_type.2d.format.r32g32b32_uint.address_modes.all_mode_clamp_to_border_* Signed-off-by: Lionel Landwerlin <lionel.g.landwer...@intel.com> --- src/intel/vulkan/Makefile.sources | 1 + src/intel/vulkan/anv_nir.h | 3 + src/intel/vulkan/anv_nir_gen7_border_color_wa.c | 208 ++++++++++++++++++++++++ src/intel/vulkan/anv_pipeline.c | 3 + 4 files changed, 215 insertions(+) create mode 100644 src/intel/vulkan/anv_nir_gen7_border_color_wa.c diff --git a/src/intel/vulkan/Makefile.sources b/src/intel/vulkan/Makefile.sources index d81bc03..6361356 100644 --- a/src/intel/vulkan/Makefile.sources +++ b/src/intel/vulkan/Makefile.sources @@ -34,6 +34,7 @@ VULKAN_FILES := \ anv_nir.h \ anv_nir_apply_dynamic_offsets.c \ anv_nir_apply_pipeline_layout.c \ + anv_nir_gen7_border_color_wa.c \ anv_nir_lower_push_constants.c \ anv_pass.c \ anv_pipeline.c \ diff --git a/src/intel/vulkan/anv_nir.h b/src/intel/vulkan/anv_nir.h index 4fff7f4..649b5ed 100644 --- a/src/intel/vulkan/anv_nir.h +++ b/src/intel/vulkan/anv_nir.h @@ -40,6 +40,9 @@ void anv_nir_apply_pipeline_layout(struct anv_pipeline *pipeline, nir_shader *shader, struct brw_stage_prog_data *prog_data, struct anv_pipeline_bind_map *map); +void anv_nir_apply_gen7_border_color(struct anv_pipeline *pipeline, + nir_shader *shader, + struct brw_stage_prog_data *prog_data); #ifdef __cplusplus } diff --git a/src/intel/vulkan/anv_nir_gen7_border_color_wa.c b/src/intel/vulkan/anv_nir_gen7_border_color_wa.c new file mode 100644 index 0000000..d65f70f --- /dev/null +++ b/src/intel/vulkan/anv_nir_gen7_border_color_wa.c @@ -0,0 +1,208 @@ +/* + * Copyright © 2016 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. + */ + +/* + * Implements a pass replaces integer sampler accesses with some logic to work + * around broken border colors with integer formats on Ivybridge and Haswell. + */ + +#include "anv_nir.h" +#include "nir/nir_builder.h" +#include "nir/nir_opcodes.h" + +static void +wrap_tex_instr(nir_builder *b, + nir_tex_instr *tex_instr, + nir_variable *sampler, + const struct anv_descriptor_set_layout *set_layout) +{ + nir_ssa_def *zeroi = nir_imm_int(b, 0); + nir_intrinsic_instr *vk_instr = + nir_intrinsic_instr_create(b->shader, + nir_intrinsic_vulkan_resource_index); + vk_instr->num_components = 1; + vk_instr->src[0] = nir_src_for_ssa(zeroi); /* array index */ + nir_intrinsic_set_desc_set(vk_instr, 0); + nir_intrinsic_set_binding(vk_instr, set_layout->border_color_index); + nir_ssa_dest_init(&vk_instr->instr, &vk_instr->dest, 1, 32, NULL); + nir_builder_instr_insert(b, &vk_instr->instr); + + nir_intrinsic_instr *load_wrapping_instr = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_ubo); + load_wrapping_instr->num_components = 1; + load_wrapping_instr->src[0] = nir_src_for_ssa(&vk_instr->dest.ssa); + load_wrapping_instr->src[1] = /* ubo offset */ + nir_src_for_ssa(nir_imm_int(b, offsetof(struct gen7_border_color, + wrapping))); + nir_ssa_dest_init(&load_wrapping_instr->instr, &load_wrapping_instr->dest, + load_wrapping_instr->num_components, 32, NULL); + nir_builder_instr_insert(b, &load_wrapping_instr->instr); + + + + nir_ssa_def *tex_coords = + tex_instr->src[nir_tex_instr_src_index(tex_instr, + nir_tex_src_coord)].src.ssa, + *cond = NULL, + *zerof = nir_imm_float(b, 0.0f), + *onef = nir_imm_float(b, 1.0f); + uint32_t coord_components = tex_instr->coord_components; + if (glsl_sampler_type_is_array(sampler->type)) + coord_components -= 1; + for (unsigned i = 0; i < coord_components; ++i) { + nir_ssa_def *component = nir_channel(b, tex_coords, i), + *lt_def = nir_flt(b, component, zerof), + *gt_def = nir_flt(b, onef, component), + *bounds_cond = nir_ior(b, lt_def, gt_def), + *border_cond = + nir_inot(b, nir_ieq(b, nir_iand(b, &load_wrapping_instr->dest.ssa, + nir_imm_int(b, 1 << i)), + zeroi)), + *inner_cond = nir_iand(b, border_cond, bounds_cond); + + if (cond == NULL) + cond = inner_cond; + else + cond = nir_ior(b, cond, inner_cond); + } + nir_if *if_stmt = nir_if_create(b->shader); + if_stmt->condition = nir_src_for_ssa(nir_inot(b, cond)); + nir_builder_cf_insert(b, &if_stmt->cf_node); + + /* Fill out the new then-block */ + nir_instr_remove(&tex_instr->instr); + nir_instr_insert_after_cf_list(&if_stmt->then_list, &tex_instr->instr); + + /* Fill out the new else-block */ + b->cursor = nir_after_cf_list(&if_stmt->else_list); + const struct anv_descriptor_set_binding_layout *binding_layout = + &set_layout->binding[tex_instr->sampler->var->data.binding]; + uint32_t binding_offset = sizeof(struct gen7_border_color) * + binding_layout->border_color_array_index; + + /* Load border color. */ + nir_intrinsic_instr *load_color_instr = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_ubo); + load_color_instr->num_components = 4; + load_color_instr->src[0] = nir_src_for_ssa(&vk_instr->dest.ssa); + load_color_instr->src[1] = /* ubo offset */ + nir_src_for_ssa(nir_imm_int(b, binding_offset)); + nir_ssa_dest_init(&load_color_instr->instr, &load_color_instr->dest, + load_color_instr->num_components, 32, NULL); + nir_builder_instr_insert(b, &load_color_instr->instr); + + /* Load border color mask. */ + nir_intrinsic_instr *load_mask_instr = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_ubo); + load_mask_instr->num_components = 4; + load_mask_instr->src[0] = nir_src_for_ssa(&vk_instr->dest.ssa); + load_mask_instr->src[1] = /* ubo offset */ + nir_src_for_ssa(nir_imm_int(b, binding_offset + + offsetof(struct gen7_border_color, + color_mask))); + nir_ssa_dest_init(&load_mask_instr->instr, &load_mask_instr->dest, + load_mask_instr->num_components, 32, NULL); + nir_builder_instr_insert(b, &load_mask_instr->instr); + + /* Load the alpha overwrite. */ + nir_intrinsic_instr *load_alpha_instr = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_ubo); + load_alpha_instr->num_components = 1; + load_alpha_instr->src[0] = nir_src_for_ssa(&vk_instr->dest.ssa); + load_alpha_instr->src[1] = /* ubo offset */ + nir_src_for_ssa(nir_imm_int(b, binding_offset + + offsetof(struct gen7_border_color, + alpha_overwrite))); + nir_ssa_dest_init(&load_alpha_instr->instr, &load_alpha_instr->dest, + load_alpha_instr->num_components, 32, NULL); + nir_builder_instr_insert(b, &load_alpha_instr->instr); + + nir_ssa_def *masked_color = + nir_iand(b, &load_color_instr->dest.ssa, &load_mask_instr->dest.ssa); + nir_ssa_def *color_components[4] = { + nir_channel(b, masked_color, 0), + nir_channel(b, masked_color, 1), + nir_channel(b, masked_color, 2), + nir_ior(b, nir_channel(b, masked_color, 3), &load_alpha_instr->dest.ssa) + }; + nir_ssa_def *color = nir_vec(b, color_components, 4); + + /* We need a phi node to gather either values. */ + nir_phi_instr *phi = nir_phi_instr_create(b->shader); + nir_ssa_dest_init(&phi->instr, &phi->dest, + tex_instr->dest.ssa.num_components, + tex_instr->dest.ssa.bit_size, NULL); + + nir_phi_src *src1 = ralloc(phi, nir_phi_src); + struct exec_node *tnode = exec_list_get_tail(&if_stmt->then_list); + src1->pred = exec_node_data(nir_block, tnode, cf_node.node); + src1->src = nir_src_for_ssa(&tex_instr->dest.ssa); + exec_list_push_tail(&phi->srcs, &src1->node); + + nir_phi_src *src2 = ralloc(phi, nir_phi_src); + struct exec_node *enode = exec_list_get_tail(&if_stmt->else_list); + src2->pred = exec_node_data(nir_block, enode, cf_node.node); + src2->src = nir_src_for_ssa(color); + exec_list_push_tail(&phi->srcs, &src2->node); + + nir_ssa_def_rewrite_uses(&tex_instr->dest.ssa, + nir_src_for_ssa(&phi->dest.ssa)); + nir_instr_insert_after_cf(&if_stmt->cf_node, &phi->instr); +} + +void +anv_nir_apply_gen7_border_color(struct anv_pipeline *pipeline, + nir_shader *shader, + struct brw_stage_prog_data *prog_data) +{ + const struct anv_pipeline_layout *layout = pipeline->layout; + const struct anv_descriptor_set_layout *set_layout = layout->set[0].layout; + + nir_foreach_function(function, shader) { + if (!function->impl) + continue; + + nir_builder builder; + nir_builder_init(&builder, function->impl); + + nir_foreach_block(block, function->impl) { + nir_foreach_instr_safe(instr, block) { + if (instr->type != nir_instr_type_tex) + continue; + + nir_tex_instr *tex_instr = nir_instr_as_tex(instr); + if (!tex_instr->sampler || + nir_tex_instr_src_index(tex_instr, nir_tex_src_coord) == -1) + continue; + + nir_variable *sampler = tex_instr->sampler->var; + if (glsl_get_sampler_result_type(sampler->type) == GLSL_TYPE_FLOAT) { + continue; + } + + builder.cursor = nir_before_instr(instr); + wrap_tex_instr(&builder, tex_instr, sampler, set_layout); + } + } + } +} diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 2fdc9cc..0d5f801 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -316,6 +316,9 @@ anv_pipeline_compile(struct anv_pipeline *pipeline, if (nir == NULL) return NULL; + if (pipeline->device->info.is_haswell) + anv_nir_apply_gen7_border_color(pipeline, nir, prog_data); + anv_nir_lower_push_constants(nir); /* Figure out the number of parameters */ -- 2.10.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev