From 74b83fe368eab77da4ef0ea6eaeea54514d6dfc9 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 1 Dec 2015 22:41:32 -0800 Subject: [PATCH 01/25] i965: Add the TCS/TES state upload atoms to the gen7_atoms list. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/brw_state_upload.c | 14 ++++++++++++++ src/mesa/drivers/dri/i965/gen7_ds_state.c | 15 --------------- src/mesa/drivers/dri/i965/gen7_hs_state.c | 15 --------------- 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c index 81a67d284e0..2a671a58d8c 100644 --- a/src/mesa/drivers/dri/i965/brw_state_upload.c +++ b/src/mesa/drivers/dri/i965/brw_state_upload.c @@ -196,10 +196,14 @@ static const struct brw_tracked_state *gen7_render_atoms[] = &gen7_hw_binding_tables, /* Enable hw-generated binding tables for Haswell */ &brw_vs_image_surfaces, /* Before vs push/pull constants and binding table */ + &brw_tcs_image_surfaces, /* Before tcs push/pull constants and binding table */ + &brw_tes_image_surfaces, /* Before tes push/pull constants and binding table */ &brw_gs_image_surfaces, /* Before gs push/pull constants and binding table */ &brw_wm_image_surfaces, /* Before wm push/pull constants and binding table */ &gen6_vs_push_constants, /* Before vs_state */ + &gen7_tcs_push_constants, + &gen7_tes_push_constants, &gen6_gs_push_constants, /* Before gs_state */ &gen6_wm_push_constants, /* Before wm_surfaces and constant_buffer */ @@ -209,6 +213,12 @@ static const struct brw_tracked_state *gen7_render_atoms[] = &brw_vs_pull_constants, &brw_vs_ubo_surfaces, &brw_vs_abo_surfaces, + &brw_tcs_pull_constants, + &brw_tcs_ubo_surfaces, + &brw_tcs_abo_surfaces, + &brw_tes_pull_constants, + &brw_tes_ubo_surfaces, + &brw_tes_abo_surfaces, &brw_gs_pull_constants, &brw_gs_ubo_surfaces, &brw_gs_abo_surfaces, @@ -218,11 +228,15 @@ static const struct brw_tracked_state *gen7_render_atoms[] = &gen6_renderbuffer_surfaces, &brw_texture_surfaces, &brw_vs_binding_table, + &brw_tcs_binding_table, + &brw_tes_binding_table, &brw_gs_binding_table, &brw_wm_binding_table, &brw_fs_samplers, &brw_vs_samplers, + &brw_tcs_samplers, + &brw_tes_samplers, &brw_gs_samplers, &gen6_multisample_state, diff --git a/src/mesa/drivers/dri/i965/gen7_ds_state.c b/src/mesa/drivers/dri/i965/gen7_ds_state.c index 9a697140386..2b743f6cd95 100644 --- a/src/mesa/drivers/dri/i965/gen7_ds_state.c +++ b/src/mesa/drivers/dri/i965/gen7_ds_state.c @@ -59,16 +59,6 @@ static void gen7_upload_ds_state(struct brw_context *brw) { /* Disable the DS Unit */ - BEGIN_BATCH(7); - OUT_BATCH(_3DSTATE_CONSTANT_DS << 16 | (7 - 2)); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - ADVANCE_BATCH(); - BEGIN_BATCH(6); OUT_BATCH(_3DSTATE_DS << 16 | (6 - 2)); OUT_BATCH(0); @@ -77,11 +67,6 @@ gen7_upload_ds_state(struct brw_context *brw) OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); - - BEGIN_BATCH(2); - OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_DS << 16 | (2 - 2)); - OUT_BATCH(brw->hw_bt_pool.next_offset); - ADVANCE_BATCH(); } const struct brw_tracked_state gen7_ds_state = { diff --git a/src/mesa/drivers/dri/i965/gen7_hs_state.c b/src/mesa/drivers/dri/i965/gen7_hs_state.c index 6793617b9e2..d23a4f8c2cf 100644 --- a/src/mesa/drivers/dri/i965/gen7_hs_state.c +++ b/src/mesa/drivers/dri/i965/gen7_hs_state.c @@ -61,16 +61,6 @@ static void gen7_upload_hs_state(struct brw_context *brw) { /* Disable the HS Unit */ - BEGIN_BATCH(7); - OUT_BATCH(_3DSTATE_CONSTANT_HS << 16 | (7 - 2)); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - ADVANCE_BATCH(); - BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_HS << 16 | (7 - 2)); OUT_BATCH(0); @@ -80,11 +70,6 @@ gen7_upload_hs_state(struct brw_context *brw) OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); - - BEGIN_BATCH(2); - OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_HS << 16 | (2 - 2)); - OUT_BATCH(brw->hw_bt_pool.next_offset); - ADVANCE_BATCH(); } const struct brw_tracked_state gen7_hs_state = { From 2c240b05e99abc6efb40e87ce6ea1c4ea4818acf Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 25 Nov 2015 17:12:17 -0800 Subject: [PATCH 02/25] i965: Emit a real 3DSTATE_HS on Gen7. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/gen7_hs_state.c | 58 ++++++++++++++++++----- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/src/mesa/drivers/dri/i965/gen7_hs_state.c b/src/mesa/drivers/dri/i965/gen7_hs_state.c index d23a4f8c2cf..0e2b3b2604e 100644 --- a/src/mesa/drivers/dri/i965/gen7_hs_state.c +++ b/src/mesa/drivers/dri/i965/gen7_hs_state.c @@ -60,22 +60,58 @@ const struct brw_tracked_state gen7_tcs_push_constants = { static void gen7_upload_hs_state(struct brw_context *brw) { - /* Disable the HS Unit */ - BEGIN_BATCH(7); - OUT_BATCH(_3DSTATE_HS << 16 | (7 - 2)); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - ADVANCE_BATCH(); + const struct brw_stage_state *stage_state = &brw->tcs.base; + /* BRW_NEW_TESS_PROGRAMS */ + bool active = brw->tess_eval_program; + /* BRW_NEW_TCS_PROG_DATA */ + const struct brw_vue_prog_data *prog_data = &brw->tcs.prog_data->base; + + if (active) { + BEGIN_BATCH(7); + OUT_BATCH(_3DSTATE_HS << 16 | (7 - 2)); + OUT_BATCH(SET_FIELD(DIV_ROUND_UP(stage_state->sampler_count, 4), + GEN7_HS_SAMPLER_COUNT) | + SET_FIELD(prog_data->base.binding_table.size_bytes / 4, + GEN7_HS_BINDING_TABLE_ENTRY_COUNT) | + (brw->max_hs_threads - 1)); + OUT_BATCH(GEN7_HS_ENABLE | + GEN7_HS_STATISTICS_ENABLE | + SET_FIELD(brw->tcs.prog_data->instances - 1, + GEN7_HS_INSTANCE_COUNT)); + OUT_BATCH(stage_state->prog_offset); + if (prog_data->base.total_scratch) { + OUT_RELOC(stage_state->scratch_bo, + I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, + ffs(prog_data->base.total_scratch) - 11); + } else { + OUT_BATCH(0); + } + OUT_BATCH(GEN7_HS_INCLUDE_VERTEX_HANDLES | + SET_FIELD(prog_data->base.dispatch_grf_start_reg, + GEN7_HS_DISPATCH_START_GRF)); + /* Ignore URB semaphores */ + OUT_BATCH(0); + ADVANCE_BATCH(); + } else { + BEGIN_BATCH(7); + OUT_BATCH(_3DSTATE_HS << 16 | (7 - 2)); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + } + brw->tcs.enabled = active; } const struct brw_tracked_state gen7_hs_state = { .dirty = { .mesa = 0, - .brw = BRW_NEW_CONTEXT, + .brw = BRW_NEW_BATCH | + BRW_NEW_TCS_PROG_DATA | + BRW_NEW_TESS_PROGRAMS, }, .emit = gen7_upload_hs_state, }; From 889d987904af1bcced27d1f0a8a11252e5b47fa7 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 25 Nov 2015 17:18:50 -0800 Subject: [PATCH 03/25] i965: Emit a real 3DSTATE_DS on Gen7. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/gen7_ds_state.c | 65 +++++++++++++++++++---- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/src/mesa/drivers/dri/i965/gen7_ds_state.c b/src/mesa/drivers/dri/i965/gen7_ds_state.c index 2b743f6cd95..30deabb06ed 100644 --- a/src/mesa/drivers/dri/i965/gen7_ds_state.c +++ b/src/mesa/drivers/dri/i965/gen7_ds_state.c @@ -58,21 +58,64 @@ const struct brw_tracked_state gen7_tes_push_constants = { static void gen7_upload_ds_state(struct brw_context *brw) { - /* Disable the DS Unit */ - BEGIN_BATCH(6); - OUT_BATCH(_3DSTATE_DS << 16 | (6 - 2)); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(0); - ADVANCE_BATCH(); + const struct brw_stage_state *stage_state = &brw->tes.base; + /* BRW_NEW_TESS_PROGRAMS */ + bool active = brw->tess_eval_program; + + /* BRW_NEW_TES_PROG_DATA */ + const struct brw_tes_prog_data *tes_prog_data = brw->tes.prog_data; + const struct brw_vue_prog_data *vue_prog_data = &tes_prog_data->base; + const struct brw_stage_prog_data *prog_data = &vue_prog_data->base; + + const unsigned thread_count = (brw->max_ds_threads - 1) << + (brw->is_haswell ? HSW_DS_MAX_THREADS_SHIFT : GEN7_DS_MAX_THREADS_SHIFT); + + if (active) { + BEGIN_BATCH(6); + OUT_BATCH(_3DSTATE_DS << 16 | (6 - 2)); + OUT_BATCH(stage_state->prog_offset); + OUT_BATCH(SET_FIELD(DIV_ROUND_UP(stage_state->sampler_count, 4), + GEN7_DS_SAMPLER_COUNT) | + SET_FIELD(prog_data->binding_table.size_bytes / 4, + GEN7_DS_BINDING_TABLE_ENTRY_COUNT)); + if (prog_data->total_scratch) { + OUT_RELOC(stage_state->scratch_bo, + I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, + ffs(prog_data->total_scratch) - 11); + } else { + OUT_BATCH(0); + } + OUT_BATCH(SET_FIELD(prog_data->dispatch_grf_start_reg, + GEN7_DS_DISPATCH_START_GRF) | + SET_FIELD(vue_prog_data->urb_read_length, + GEN7_DS_URB_READ_LENGTH)); + + OUT_BATCH(GEN7_DS_ENABLE | + GEN7_DS_STATISTICS_ENABLE | + thread_count | + (tes_prog_data->domain == BRW_TESS_DOMAIN_TRI ? + GEN7_DS_COMPUTE_W_COORDINATE_ENABLE : 0)); + ADVANCE_BATCH(); + } else { + BEGIN_BATCH(6); + OUT_BATCH(_3DSTATE_DS << 16 | (6 - 2)); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + } + brw->tes.enabled = active; } const struct brw_tracked_state gen7_ds_state = { .dirty = { - .mesa = 0, - .brw = BRW_NEW_CONTEXT, + .mesa = _NEW_TRANSFORM, + .brw = BRW_NEW_BATCH | + BRW_NEW_CONTEXT | + BRW_NEW_TESS_PROGRAMS | + BRW_NEW_TES_PROG_DATA, }, .emit = gen7_upload_ds_state, }; From 1245724f728915694ecb9c318a68107c01ccc808 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 17 Nov 2015 01:30:35 -0800 Subject: [PATCH 04/25] i965: Port tessellation evaluation shaders to vec4 mode. This can be used on Broadwell by setting INTEL_SCALAR_TES=0. More importantly, it will be used for Ivybridge and Haswell. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/Makefile.sources | 1 + src/mesa/drivers/dri/i965/brw_defines.h | 4 + src/mesa/drivers/dri/i965/brw_shader.cpp | 25 ++- src/mesa/drivers/dri/i965/brw_vec4.cpp | 1 + .../dri/i965/brw_vec4_dead_code_eliminate.cpp | 2 + .../drivers/dri/i965/brw_vec4_generator.cpp | 61 ++++++ src/mesa/drivers/dri/i965/brw_vec4_tes.cpp | 204 ++++++++++++++++++ src/mesa/drivers/dri/i965/brw_vec4_tes.h | 69 ++++++ 8 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 src/mesa/drivers/dri/i965/brw_vec4_tes.cpp create mode 100644 src/mesa/drivers/dri/i965/brw_vec4_tes.h diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources index 0b706de69a0..05c49ee9a12 100644 --- a/src/mesa/drivers/dri/i965/Makefile.sources +++ b/src/mesa/drivers/dri/i965/Makefile.sources @@ -76,6 +76,7 @@ i965_compiler_FILES = \ brw_vec4_surface_builder.cpp \ brw_vec4_surface_builder.h \ brw_vec4_tcs.cpp \ + brw_vec4_tes.cpp \ brw_vec4_visitor.cpp \ brw_vec4_vs_visitor.cpp \ brw_vue_map.c \ diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index cc19c06f162..61bcebdbc4b 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -1313,6 +1313,10 @@ enum opcode { TCS_OPCODE_SET_OUTPUT_URB_OFFSETS, TCS_OPCODE_GET_PRIMITIVE_ID, TCS_OPCODE_CREATE_BARRIER_HEADER, + + TES_OPCODE_GET_PRIMITIVE_ID, + TES_OPCODE_CREATE_INPUT_READ_HEADER, + TES_OPCODE_ADD_INDIRECT_URB_OFFSET, }; enum brw_urb_write_flags { diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index 5140cfb7bc6..3a36678e8d5 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -26,6 +26,7 @@ #include "brw_eu.h" #include "brw_fs.h" #include "brw_nir.h" +#include "brw_vec4_tes.h" #include "glsl/glsl_parser_extras.h" #include "main/shaderobj.h" #include "main/uniforms.h" @@ -86,7 +87,8 @@ brw_compiler_create(void *mem_ctx, const struct brw_device_info *devinfo) compiler->scalar_stage[MESA_SHADER_VERTEX] = devinfo->gen >= 8 && !(INTEL_DEBUG & DEBUG_VEC4VS); compiler->scalar_stage[MESA_SHADER_TESS_CTRL] = false; - compiler->scalar_stage[MESA_SHADER_TESS_EVAL] = true; + compiler->scalar_stage[MESA_SHADER_TESS_EVAL] = + devinfo->gen >= 8 && env_var_as_boolean("INTEL_SCALAR_TES", true); compiler->scalar_stage[MESA_SHADER_GEOMETRY] = devinfo->gen >= 8 && env_var_as_boolean("INTEL_SCALAR_GS", false); compiler->scalar_stage[MESA_SHADER_FRAGMENT] = true; @@ -566,6 +568,12 @@ brw_instruction_name(enum opcode op) return "tcs_get_primitive_id"; case TCS_OPCODE_CREATE_BARRIER_HEADER: return "tcs_create_barrier_header"; + case TES_OPCODE_CREATE_INPUT_READ_HEADER: + return "tes_create_input_read_header"; + case TES_OPCODE_ADD_INDIRECT_URB_OFFSET: + return "tes_add_indirect_urb_offset"; + case TES_OPCODE_GET_PRIMITIVE_ID: + return "tes_get_primitive_id"; } unreachable("not reached"); @@ -1400,6 +1408,19 @@ brw_compile_tes(const struct brw_compiler *compiler, return g.get_assembly(final_assembly_size); } else { - unreachable("XXX: vec4 tessellation evalation shaders not merged yet."); + brw::vec4_tes_visitor v(compiler, log_data, key, prog_data, + nir, mem_ctx, shader_time_index); + if (!v.run()) { + if (error_str) + *error_str = ralloc_strdup(mem_ctx, v.fail_msg); + return NULL; + } + + if (unlikely(INTEL_DEBUG & DEBUG_TES)) + v.dump_instructions(); + + return brw_vec4_generate_assembly(compiler, log_data, mem_ctx, nir, + &prog_data->base, v.cfg, + final_assembly_size); } } diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index 0cded0c87c6..116dd353016 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -189,6 +189,7 @@ vec4_instruction::has_source_and_destination_hazard() const switch (opcode) { case TCS_OPCODE_SET_INPUT_URB_OFFSETS: case TCS_OPCODE_SET_OUTPUT_URB_OFFSETS: + case TES_OPCODE_ADD_INDIRECT_URB_OFFSET: return true; default: return false; diff --git a/src/mesa/drivers/dri/i965/brw_vec4_dead_code_eliminate.cpp b/src/mesa/drivers/dri/i965/brw_vec4_dead_code_eliminate.cpp index c31e72def67..166bc17e1e1 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_dead_code_eliminate.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_dead_code_eliminate.cpp @@ -47,6 +47,8 @@ can_do_writemask(const struct brw_device_info *devinfo, case VS_OPCODE_SET_SIMD4X2_HEADER_GEN9: case TCS_OPCODE_SET_INPUT_URB_OFFSETS: case TCS_OPCODE_SET_OUTPUT_URB_OFFSETS: + case TES_OPCODE_CREATE_INPUT_READ_HEADER: + case TES_OPCODE_ADD_INDIRECT_URB_OFFSET: case VEC4_OPCODE_URB_READ: return false; default: diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp index 6325569956f..2541c25c6b8 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp @@ -864,6 +864,46 @@ generate_tcs_output_urb_offsets(struct brw_codegen *p, brw_pop_insn_state(p); } +static void +generate_tes_create_input_read_header(struct brw_codegen *p, + struct brw_reg dst) +{ + brw_push_insn_state(p); + brw_set_default_access_mode(p, BRW_ALIGN_1); + brw_set_default_mask_control(p, BRW_MASK_DISABLE); + + /* Initialize the register to 0 */ + brw_MOV(p, dst, brw_imm_ud(0)); + + /* Enable all the channels in m0.5 bits 15:8 */ + brw_MOV(p, get_element_ud(dst, 5), brw_imm_ud(0xff00)); + + /* Copy g1.3 (the patch URB handle) to m0.0 and m0.1. For safety, + * mask out irrelevant "Reserved" bits, as they're not marked MBZ. + */ + brw_AND(p, vec2(get_element_ud(dst, 0)), + retype(brw_vec1_grf(1, 3), BRW_REGISTER_TYPE_UD), + brw_imm_ud(0x1fff)); + brw_pop_insn_state(p); +} + +static void +generate_tes_add_indirect_urb_offset(struct brw_codegen *p, + struct brw_reg dst, + struct brw_reg header, + struct brw_reg offset) +{ + brw_push_insn_state(p); + brw_set_default_access_mode(p, BRW_ALIGN_1); + brw_set_default_mask_control(p, BRW_MASK_DISABLE); + + brw_MOV(p, dst, header); + /* m0.3-0.4: 128-bit-granular offsets into the URB from the handles */ + brw_MOV(p, vec2(get_element_ud(dst, 3)), stride(offset, 4, 1, 0)); + + brw_pop_insn_state(p); +} + static void generate_vec4_urb_read(struct brw_codegen *p, vec4_instruction *inst, @@ -889,6 +929,15 @@ generate_vec4_urb_read(struct brw_codegen *p, brw_inst_set_urb_global_offset(devinfo, send, inst->offset); } +static void +generate_tes_get_primitive_id(struct brw_codegen *p, struct brw_reg dst) +{ + brw_push_insn_state(p); + brw_set_default_access_mode(p, BRW_ALIGN_1); + brw_MOV(p, dst, retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_D)); + brw_pop_insn_state(p); +} + static void generate_tcs_get_primitive_id(struct brw_codegen *p, struct brw_reg dst) { @@ -1780,6 +1829,18 @@ generate_code(struct brw_codegen *p, generate_tcs_create_barrier_header(p, prog_data, dst); break; + case TES_OPCODE_CREATE_INPUT_READ_HEADER: + generate_tes_create_input_read_header(p, dst); + break; + + case TES_OPCODE_ADD_INDIRECT_URB_OFFSET: + generate_tes_add_indirect_urb_offset(p, dst, src[0], src[1]); + break; + + case TES_OPCODE_GET_PRIMITIVE_ID: + generate_tes_get_primitive_id(p, dst); + break; + case SHADER_OPCODE_BARRIER: brw_barrier(p, src[0]); brw_WAIT(p); diff --git a/src/mesa/drivers/dri/i965/brw_vec4_tes.cpp b/src/mesa/drivers/dri/i965/brw_vec4_tes.cpp new file mode 100644 index 00000000000..ce5fefc75a9 --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_vec4_tes.cpp @@ -0,0 +1,204 @@ +/* + * Copyright © 2013 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 brw_vec4_tes.cpp + * + * Tessellaton evaluation shader specific code derived from the vec4_visitor class. + */ + +#include "brw_vec4_tes.h" + +namespace brw { + +vec4_tes_visitor::vec4_tes_visitor(const struct brw_compiler *compiler, + void *log_data, + const struct brw_tes_prog_key *key, + struct brw_tes_prog_data *prog_data, + const nir_shader *shader, + void *mem_ctx, + int shader_time_index) + : vec4_visitor(compiler, log_data, &key->tex, &prog_data->base, + shader, mem_ctx, false, shader_time_index) +{ +} + + +dst_reg * +vec4_tes_visitor::make_reg_for_system_value(int location, const glsl_type *type) +{ + return NULL; +} + +void +vec4_tes_visitor::nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr) +{ + const struct brw_tes_prog_data *tes_prog_data = + (const struct brw_tes_prog_data *) prog_data; + + switch (instr->intrinsic) { + case nir_intrinsic_load_tess_level_outer: { + dst_reg dst(this, glsl_type::vec4_type); + nir_system_values[SYSTEM_VALUE_TESS_LEVEL_OUTER] = dst; + + dst_reg temp(this, glsl_type::vec4_type); + vec4_instruction *read = + emit(VEC4_OPCODE_URB_READ, temp, input_read_header); + read->offset = 1; + read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET; + emit(MOV(dst, swizzle(src_reg(temp), BRW_SWIZZLE_WZYX))); + break; + } + case nir_intrinsic_load_tess_level_inner: { + dst_reg dst(this, glsl_type::vec2_type); + nir_system_values[SYSTEM_VALUE_TESS_LEVEL_INNER] = dst; + + /* Set up the message header to reference the proper parts of the URB */ + dst_reg temp(this, glsl_type::vec4_type); + vec4_instruction *read = + emit(VEC4_OPCODE_URB_READ, temp, input_read_header); + read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET; + if (tes_prog_data->domain == BRW_TESS_DOMAIN_QUAD) { + emit(MOV(dst, swizzle(src_reg(temp), BRW_SWIZZLE_WZYX))); + } else { + read->offset = 1; + emit(MOV(dst, src_reg(temp))); + } + break; + } + default: + vec4_visitor::nir_setup_system_value_intrinsic(instr); + } +} + + +void +vec4_tes_visitor::setup_payload() +{ + int reg = 0; + + /* The payload always contains important data in r0 and r1, which contains + * the URB handles that are passed on to the URB write at the end + * of the thread. + */ + reg += 2; + + reg = setup_uniforms(reg); + + this->first_non_payload_grf = reg; +} + + +void +vec4_tes_visitor::emit_prolog() +{ + input_read_header = src_reg(this, glsl_type::uvec4_type); + emit(TES_OPCODE_CREATE_INPUT_READ_HEADER, dst_reg(input_read_header)); + + this->current_annotation = NULL; +} + + +void +vec4_tes_visitor::emit_urb_write_header(int mrf) +{ + /* No need to do anything for DS; an implied write to this MRF will be + * performed by VS_OPCODE_URB_WRITE. + */ + (void) mrf; +} + + +vec4_instruction * +vec4_tes_visitor::emit_urb_write_opcode(bool complete) +{ + /* For DS, the URB writes end the thread. */ + if (complete) { + if (INTEL_DEBUG & DEBUG_SHADER_TIME) + emit_shader_time_end(); + } + + vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE); + inst->urb_write_flags = complete ? + BRW_URB_WRITE_EOT_COMPLETE : BRW_URB_WRITE_NO_FLAGS; + + return inst; +} + +void +vec4_tes_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) +{ + switch (instr->intrinsic) { + case nir_intrinsic_load_tess_coord: + /* gl_TessCoord is part of the payload in g1 channels 0-2 and 4-6. */ + emit(MOV(get_nir_dest(instr->dest, BRW_REGISTER_TYPE_F), + src_reg(brw_vec8_grf(1, 0)))); + break; + case nir_intrinsic_load_primitive_id: + emit(TES_OPCODE_GET_PRIMITIVE_ID, + get_nir_dest(instr->dest, BRW_REGISTER_TYPE_UD)); + break; + + case nir_intrinsic_load_input: + case nir_intrinsic_load_per_vertex_input: { + src_reg indirect_offset = get_indirect_offset(instr); + unsigned imm_offset = instr->const_index[0]; + src_reg header = input_read_header; + + if (indirect_offset.file != BAD_FILE) { + header = src_reg(this, glsl_type::uvec4_type); + emit(TES_OPCODE_ADD_INDIRECT_URB_OFFSET, dst_reg(header), + input_read_header, indirect_offset); + } + + dst_reg temp(this, glsl_type::ivec4_type); + vec4_instruction *read = + emit(VEC4_OPCODE_URB_READ, temp, src_reg(header)); + read->offset = imm_offset; + read->urb_write_flags = BRW_URB_WRITE_PER_SLOT_OFFSET; + + /* Copy to target. We might end up with some funky writemasks landing + * in here, but we really don't want them in the above pseudo-ops. + */ + dst_reg dst = get_nir_dest(instr->dest, BRW_REGISTER_TYPE_D); + dst.writemask = brw_writemask_for_size(instr->num_components); + emit(MOV(dst, src_reg(temp))); + break; + } + default: + vec4_visitor::nir_emit_intrinsic(instr); + } +} + + +void +vec4_tes_visitor::emit_thread_end() +{ + /* For DS, we always end the thread by emitting a single vertex. + * emit_urb_write_opcode() will take care of setting the eot flag on the + * SEND instruction. + */ + emit_vertex(); +} + +} /* namespace brw */ diff --git a/src/mesa/drivers/dri/i965/brw_vec4_tes.h b/src/mesa/drivers/dri/i965/brw_vec4_tes.h new file mode 100644 index 00000000000..4b697aa592f --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_vec4_tes.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2013 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 brw_vec4_tes.h + * + * The vec4 mode tessellation evaluation shader compiler backend. + */ + +#ifndef BRW_VEC4_TES_H +#define BRW_VEC4_TES_H + +#include "brw_vec4.h" + +#ifdef __cplusplus +namespace brw { + +class vec4_tes_visitor : public vec4_visitor +{ +public: + vec4_tes_visitor(const struct brw_compiler *compiler, + void *log_data, + const struct brw_tes_prog_key *key, + struct brw_tes_prog_data *prog_data, + const nir_shader *nir, + void *mem_ctx, + int shader_time_index); + +protected: + virtual dst_reg *make_reg_for_system_value(int location, + const glsl_type *type); + virtual void nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr); + virtual void nir_emit_intrinsic(nir_intrinsic_instr *instr); + + virtual void setup_payload(); + virtual void emit_prolog(); + virtual void emit_thread_end(); + + virtual void emit_urb_write_header(int mrf); + virtual vec4_instruction *emit_urb_write_opcode(bool complete); + +private: + src_reg input_read_header; +}; + +} /* namespace brw */ +#endif /* __cplusplus */ + +#endif /* BRW_VEC4_TES_H */ From 5898cbae2479874a6206e27e6b73a3ba244a2094 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 25 Nov 2015 23:27:02 -0800 Subject: [PATCH 05/25] i965: Use proper TCS Instance ID bits for Ivybridge/Baytrail. Gen7 uses 22:16 while Gen7.5+ uses 23:17. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/brw_vec4_generator.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp index 2541c25c6b8..5d91e0f5260 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp @@ -716,6 +716,9 @@ generate_gs_set_primitive_id(struct brw_codegen *p, struct brw_reg dst) static void generate_tcs_get_instance_id(struct brw_codegen *p, struct brw_reg dst) { + const struct brw_device_info *devinfo = p->devinfo; + const bool ivb = devinfo->is_ivybridge || devinfo->is_baytrail; + /* "Instance Count" comes as part of the payload in r0.2 bits 23:17. * * Since we operate in SIMD4x2 mode, we need run half as many threads @@ -728,8 +731,8 @@ generate_tcs_get_instance_id(struct brw_codegen *p, struct brw_reg dst) brw_push_insn_state(p); brw_set_default_access_mode(p, BRW_ALIGN_1); - const int mask = INTEL_MASK(23, 17); - const int shift = 17; + const int mask = ivb ? INTEL_MASK(22, 16) : INTEL_MASK(23, 17); + const int shift = ivb ? 16 : 17; brw_AND(p, get_element_ud(dst, 0), get_element_ud(r0, 2), brw_imm_ud(mask)); brw_SHR(p, get_element_ud(dst, 0), get_element_ud(dst, 0), From 6ceabb72eae938570d9aa0ae054bab1df421d79a Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 24 Dec 2015 15:26:55 -0800 Subject: [PATCH 06/25] i965: Use proper TCS barrier ID bits for Ivybridge/Baytrail. Gen7 uses bits 15:12 while Gen7+ uses bits 16:13. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/brw_vec4_generator.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp index 5d91e0f5260..cbf8b1d0bd0 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp @@ -955,6 +955,8 @@ generate_tcs_create_barrier_header(struct brw_codegen *p, struct brw_vue_prog_data *prog_data, struct brw_reg dst) { + const struct brw_device_info *devinfo = p->devinfo; + const bool ivb = devinfo->is_ivybridge || devinfo->is_baytrail; struct brw_reg m0_2 = get_element_ud(dst, 2); unsigned instances = ((struct brw_tcs_prog_data *) prog_data)->instances; @@ -965,13 +967,13 @@ generate_tcs_create_barrier_header(struct brw_codegen *p, /* Zero the message header */ brw_MOV(p, retype(dst, BRW_REGISTER_TYPE_UD), brw_imm_ud(0u)); - /* Copy "Barrier ID" from DW0 bits 16:13 */ + /* Copy "Barrier ID" from r0.2, bits 16:13 (Gen7.5+) or 15:12 (Gen7) */ brw_AND(p, m0_2, retype(brw_vec1_grf(0, 2), BRW_REGISTER_TYPE_UD), - brw_imm_ud(0x1e000)); + brw_imm_ud(ivb ? INTEL_MASK(15, 12) : INTEL_MASK(16, 13))); - /* Shift it into place */ - brw_SHL(p, m0_2, get_element_ud(dst, 2), brw_imm_ud(11)); + /* Shift it up to bits 27:24. */ + brw_SHL(p, m0_2, get_element_ud(dst, 2), brw_imm_ud(ivb ? 12 : 11)); /* Set the Barrier Count and the enable bit */ brw_OR(p, m0_2, m0_2, brw_imm_ud(instances << 9 | (1 << 15))); From b7793783b3df94880655234bc2a9054eddf01913 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 25 Nov 2015 17:54:22 -0800 Subject: [PATCH 07/25] i965: Relase input URB Handles on Gen7/7.5 when TCS threads finish. Pre-Broadwell hardware requires us to manually release the ICP Handles by issuing URB read messages with the "Complete" bit set. We can do this in pairs to use fewer URB read messages. Based heavily on work from Chris Forbes. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/brw_defines.h | 2 + src/mesa/drivers/dri/i965/brw_shader.cpp | 5 ++ src/mesa/drivers/dri/i965/brw_vec4.cpp | 1 + .../drivers/dri/i965/brw_vec4_generator.cpp | 46 +++++++++++++++++++ src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp | 40 +++++++++++++++- 5 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index 61bcebdbc4b..d0137481c6c 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -1313,6 +1313,8 @@ enum opcode { TCS_OPCODE_SET_OUTPUT_URB_OFFSETS, TCS_OPCODE_GET_PRIMITIVE_ID, TCS_OPCODE_CREATE_BARRIER_HEADER, + TCS_OPCODE_SRC0_010_IS_ZERO, + TCS_OPCODE_RELEASE_INPUT, TES_OPCODE_GET_PRIMITIVE_ID, TES_OPCODE_CREATE_INPUT_READ_HEADER, diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index 3a36678e8d5..f692bc2de35 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -568,6 +568,10 @@ brw_instruction_name(enum opcode op) return "tcs_get_primitive_id"; case TCS_OPCODE_CREATE_BARRIER_HEADER: return "tcs_create_barrier_header"; + case TCS_OPCODE_SRC0_010_IS_ZERO: + return "tcs_src0<0,1,0>_is_zero"; + case TCS_OPCODE_RELEASE_INPUT: + return "tcs_release_input"; case TES_OPCODE_CREATE_INPUT_READ_HEADER: return "tes_create_input_read_header"; case TES_OPCODE_ADD_INDIRECT_URB_OFFSET: @@ -1009,6 +1013,7 @@ backend_instruction::has_side_effects() const case SHADER_OPCODE_URB_WRITE_SIMD8_MASKED_PER_SLOT: case FS_OPCODE_FB_WRITE: case SHADER_OPCODE_BARRIER: + case TCS_OPCODE_RELEASE_INPUT: return true; default: return false; diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index 116dd353016..f1c3d37ce1c 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -157,6 +157,7 @@ vec4_instruction::is_send_from_grf() case SHADER_OPCODE_TYPED_SURFACE_WRITE: case VEC4_OPCODE_URB_READ: case TCS_OPCODE_URB_WRITE: + case TCS_OPCODE_RELEASE_INPUT: case SHADER_OPCODE_BARRIER: return true; default: diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp index cbf8b1d0bd0..cce2b4d1f4c 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp @@ -932,6 +932,42 @@ generate_vec4_urb_read(struct brw_codegen *p, brw_inst_set_urb_global_offset(devinfo, send, inst->offset); } +static void +generate_tcs_release_input(struct brw_codegen *p, + struct brw_reg header, + struct brw_reg vertex, + struct brw_reg is_unpaired) +{ + const struct brw_device_info *devinfo = p->devinfo; + + assert(vertex.file == BRW_IMMEDIATE_VALUE); + assert(vertex.type == BRW_REGISTER_TYPE_UD); + + /* m0.0-0.1: URB handles */ + struct brw_reg urb_handles = + retype(brw_vec2_grf(1 + (vertex.ud >> 3), vertex.ud & 7), + BRW_REGISTER_TYPE_UD); + + brw_push_insn_state(p); + brw_set_default_access_mode(p, BRW_ALIGN_1); + brw_set_default_mask_control(p, BRW_MASK_DISABLE); + brw_MOV(p, header, brw_imm_ud(0)); + brw_MOV(p, vec2(get_element_ud(header, 0)), urb_handles); + brw_pop_insn_state(p); + + brw_inst *send = brw_next_insn(p, BRW_OPCODE_SEND); + brw_set_dest(p, send, brw_null_reg()); + brw_set_src0(p, send, header); + brw_set_message_descriptor(p, send, BRW_SFID_URB, + 1 /* mlen */, 0 /* rlen */, + true /* header */, false /* eot */); + brw_inst_set_urb_opcode(devinfo, send, BRW_URB_OPCODE_READ_OWORD); + brw_inst_set_urb_complete(devinfo, send, 1); + brw_inst_set_urb_swizzle_control(devinfo, send, is_unpaired.ud ? + BRW_URB_SWIZZLE_NONE : + BRW_URB_SWIZZLE_INTERLEAVE); +} + static void generate_tes_get_primitive_id(struct brw_codegen *p, struct brw_reg dst) { @@ -1846,6 +1882,16 @@ generate_code(struct brw_codegen *p, generate_tes_get_primitive_id(p, dst); break; + case TCS_OPCODE_SRC0_010_IS_ZERO: + /* If src_reg had stride like fs_reg, we wouldn't need this. */ + brw_MOV(p, brw_null_reg(), stride(src[0], 0, 1, 0)); + brw_inst_set_cond_modifier(devinfo, brw_last_inst, BRW_CONDITIONAL_Z); + break; + + case TCS_OPCODE_RELEASE_INPUT: + generate_tcs_release_input(p, dst, src[0], src[1]); + break; + case SHADER_OPCODE_BARRIER: brw_barrier(p, src[0]); brw_WAIT(p); diff --git a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp index 507db749e63..7693f095a52 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp @@ -156,16 +156,54 @@ vec4_tcs_visitor::emit_prolog() void vec4_tcs_visitor::emit_thread_end() { + vec4_instruction *inst; current_annotation = "thread end"; if (nir->info.tcs.vertices_out % 2) { emit(BRW_OPCODE_ENDIF); } + if (devinfo->gen == 7) { + struct brw_tcs_prog_data *tcs_prog_data = + (struct brw_tcs_prog_data *) prog_data; + + current_annotation = "release input vertices"; + + /* Synchronize all threads, so we know that no one is still + * using the input URB handles. + */ + if (tcs_prog_data->instances > 1) { + dst_reg header = dst_reg(this, glsl_type::uvec4_type); + emit(TCS_OPCODE_CREATE_BARRIER_HEADER, header); + emit(SHADER_OPCODE_BARRIER, dst_null_ud(), src_reg(header)); + } + + /* Make thread 0 (invocations <1, 0>) release pairs of ICP handles. + * We want to compare the bottom half of invocation_id with 0, but + * use that truth value for the top half as well. Unfortunately, + * we don't have stride in the vec4 world, nor UV immediates in + * align16, so we need an opcode to get invocation_id<0,4,0>. + */ + emit(TCS_OPCODE_SRC0_010_IS_ZERO, dst_null_d(), invocation_id); + emit(IF(BRW_PREDICATE_NORMAL)); + for (unsigned i = 0; i < key->input_vertices; i += 2) { + /* If we have an odd number of input vertices, the last will be + * unpaired. We don't want to use an interleaved URB write in + * that case. + */ + const bool is_unpaired = i == key->input_vertices - 1; + + dst_reg header(this, glsl_type::uvec4_type); + emit(TCS_OPCODE_RELEASE_INPUT, header, brw_imm_ud(i), + brw_imm_ud(is_unpaired)); + } + emit(BRW_OPCODE_ENDIF); + } + if (unlikely(INTEL_DEBUG & DEBUG_SHADER_TIME)) emit_shader_time_end(); - vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE); + inst = emit(VS_OPCODE_URB_WRITE); inst->mlen = 1; /* just the header, no data. */ inst->urb_write_flags = BRW_URB_WRITE_EOT_COMPLETE; } From bd8ab8dedb2cc557ea3cb58d507f237743b3f7f9 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 24 Dec 2015 13:09:26 -0800 Subject: [PATCH 08/25] i965: Don't set interleave or complete on TCS EOT message. Setting interleave on the TCS EOT message causes Ivybridge hardware to GPU hang like crazy. Individual tests would pass, but running even a simple test like nop.shader_test in a loop would hang within 1-3 runs. Adding sleep delays worked around the problem, somehow. Interleave doesn't make much sense given that we only have one patch URB handle, not two. Complete doesn't seem useful either. There's no reason to actually set those bits. We were just being lazy. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/brw_defines.h | 1 + src/mesa/drivers/dri/i965/brw_shader.cpp | 2 ++ src/mesa/drivers/dri/i965/brw_vec4.cpp | 1 + .../drivers/dri/i965/brw_vec4_generator.cpp | 36 +++++++++++++++++-- src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp | 6 ++-- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index d0137481c6c..10a6d39db85 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -1315,6 +1315,7 @@ enum opcode { TCS_OPCODE_CREATE_BARRIER_HEADER, TCS_OPCODE_SRC0_010_IS_ZERO, TCS_OPCODE_RELEASE_INPUT, + TCS_OPCODE_THREAD_END, TES_OPCODE_GET_PRIMITIVE_ID, TES_OPCODE_CREATE_INPUT_READ_HEADER, diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index f692bc2de35..d4b6410815e 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -572,6 +572,8 @@ brw_instruction_name(enum opcode op) return "tcs_src0<0,1,0>_is_zero"; case TCS_OPCODE_RELEASE_INPUT: return "tcs_release_input"; + case TCS_OPCODE_THREAD_END: + return "tcs_thread_end"; case TES_OPCODE_CREATE_INPUT_READ_HEADER: return "tes_create_input_read_header"; case TES_OPCODE_ADD_INDIRECT_URB_OFFSET: diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index f1c3d37ce1c..f0f18ca7768 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -276,6 +276,7 @@ vec4_visitor::implied_mrf_writes(vec4_instruction *inst) case SHADER_OPCODE_POW: return 2; case VS_OPCODE_URB_WRITE: + case TCS_OPCODE_THREAD_END: return 1; case VS_OPCODE_PULL_CONSTANT_LOAD: return 2; diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp index cce2b4d1f4c..6b03a1c3db5 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp @@ -758,8 +758,12 @@ generate_tcs_urb_write(struct brw_codegen *p, true /* header */, false /* eot */); brw_inst_set_urb_opcode(devinfo, send, BRW_URB_OPCODE_WRITE_OWORD); brw_inst_set_urb_global_offset(devinfo, send, inst->offset); - brw_inst_set_urb_per_slot_offset(devinfo, send, 1); - brw_inst_set_urb_swizzle_control(devinfo, send, BRW_URB_SWIZZLE_INTERLEAVE); + if (inst->urb_write_flags & BRW_URB_WRITE_EOT) { + brw_inst_set_eot(devinfo, send, 1); + } else { + brw_inst_set_urb_per_slot_offset(devinfo, send, 1); + brw_inst_set_urb_swizzle_control(devinfo, send, BRW_URB_SWIZZLE_INTERLEAVE); + } /* what happens to swizzles? */ } @@ -968,6 +972,30 @@ generate_tcs_release_input(struct brw_codegen *p, BRW_URB_SWIZZLE_INTERLEAVE); } +static void +generate_tcs_thread_end(struct brw_codegen *p, vec4_instruction *inst) +{ + struct brw_reg header = brw_message_reg(inst->base_mrf); + + brw_push_insn_state(p); + brw_set_default_access_mode(p, BRW_ALIGN_1); + brw_set_default_mask_control(p, BRW_MASK_DISABLE); + brw_MOV(p, header, brw_imm_ud(0)); + brw_MOV(p, get_element_ud(header, 0), + retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UD)); + brw_pop_insn_state(p); + + brw_urb_WRITE(p, + brw_null_reg(), /* dest */ + inst->base_mrf, /* starting mrf reg nr */ + header, + BRW_URB_WRITE_EOT | inst->urb_write_flags, + inst->mlen, + 0, /* response len */ + 0, /* urb destination offset */ + 0); +} + static void generate_tes_get_primitive_id(struct brw_codegen *p, struct brw_reg dst) { @@ -1892,6 +1920,10 @@ generate_code(struct brw_codegen *p, generate_tcs_release_input(p, dst, src[0], src[1]); break; + case TCS_OPCODE_THREAD_END: + generate_tcs_thread_end(p, inst); + break; + case SHADER_OPCODE_BARRIER: brw_barrier(p, src[0]); brw_WAIT(p); diff --git a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp index 7693f095a52..fb6ca8ee5f9 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp @@ -203,9 +203,9 @@ vec4_tcs_visitor::emit_thread_end() if (unlikely(INTEL_DEBUG & DEBUG_SHADER_TIME)) emit_shader_time_end(); - inst = emit(VS_OPCODE_URB_WRITE); - inst->mlen = 1; /* just the header, no data. */ - inst->urb_write_flags = BRW_URB_WRITE_EOT_COMPLETE; + inst = emit(TCS_OPCODE_THREAD_END); + inst->base_mrf = 14; + inst->mlen = 1; } From 381a89cf2a0c1e7babb0f134a3b5b662045092a2 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 25 Nov 2015 17:56:33 -0800 Subject: [PATCH 09/25] i965: Enable ARB_tessellation_shader on Gen7-7.5. We've resolved all the GPU hangs, and everything seems to be working. Signed-off-by: Kenneth Graunke Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- src/mesa/drivers/dri/i965/brw_context.c | 4 ++-- src/mesa/drivers/dri/i965/intel_extensions.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index 005c3236c88..4298252c9b7 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -374,8 +374,8 @@ brw_initialize_context_constants(struct brw_context *brw) const bool stage_exists[MESA_SHADER_STAGES] = { [MESA_SHADER_VERTEX] = true, - [MESA_SHADER_TESS_CTRL] = brw->gen >= 8, - [MESA_SHADER_TESS_EVAL] = brw->gen >= 8, + [MESA_SHADER_TESS_CTRL] = brw->gen >= 7, + [MESA_SHADER_TESS_EVAL] = brw->gen >= 7, [MESA_SHADER_GEOMETRY] = brw->gen >= 6, [MESA_SHADER_FRAGMENT] = true, [MESA_SHADER_COMPUTE] = diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c index 06672c1b4db..de16ebb0a49 100644 --- a/src/mesa/drivers/dri/i965/intel_extensions.c +++ b/src/mesa/drivers/dri/i965/intel_extensions.c @@ -333,6 +333,7 @@ intelInitExtensions(struct gl_context *ctx) ctx->Extensions.ARB_shader_image_load_store = true; ctx->Extensions.ARB_shader_image_size = true; ctx->Extensions.ARB_shader_texture_image_samples = true; + ctx->Extensions.ARB_tessellation_shader = true; ctx->Extensions.ARB_texture_compression_bptc = true; ctx->Extensions.ARB_texture_view = true; ctx->Extensions.ARB_shader_storage_buffer_object = true; @@ -362,7 +363,6 @@ intelInitExtensions(struct gl_context *ctx) if (brw->gen >= 8) { ctx->Extensions.ARB_stencil_texturing = true; - ctx->Extensions.ARB_tessellation_shader = true; } if (brw->gen >= 9) { From dfce9759abbc13f7f735ac4bf3f1a19737624ae6 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 24 Dec 2015 17:19:14 -0800 Subject: [PATCH 10/25] docs: Mark ARB_tessellation_shader as done on all i965 platforms. We now support all Intel GPUs which can do tessellation. Reviewed-by: Edward O'Callaghan Reviewed-by: Jordan Justen --- docs/GL3.txt | 2 +- docs/relnotes/11.2.0.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/GL3.txt b/docs/GL3.txt index 58aace9a13c..f12e0ba8d29 100644 --- a/docs/GL3.txt +++ b/docs/GL3.txt @@ -112,7 +112,7 @@ GL 4.0, GLSL 4.00 --- all DONE: nvc0, r600, radeonsi GL_ARB_gpu_shader_fp64 DONE (llvmpipe, softpipe) GL_ARB_sample_shading DONE (i965, nv50) GL_ARB_shader_subroutine DONE (i965, nv50, llvmpipe, softpipe) - GL_ARB_tessellation_shader DONE (i965/gen8+) + GL_ARB_tessellation_shader DONE (i965) GL_ARB_texture_buffer_object_rgb32 DONE (i965, llvmpipe, softpipe) GL_ARB_texture_cube_map_array DONE (i965, nv50, llvmpipe, softpipe) GL_ARB_texture_gather DONE (i965, nv50, llvmpipe, softpipe) diff --git a/docs/relnotes/11.2.0.html b/docs/relnotes/11.2.0.html index 6f1752cec3f..23bb31c6235 100644 --- a/docs/relnotes/11.2.0.html +++ b/docs/relnotes/11.2.0.html @@ -47,7 +47,7 @@ Note: some of the new features are only available with certain drivers.
  • GL_ARB_base_instance on freedreno/a4xx
  • GL_ARB_compute_shader on i965
  • GL_ARB_copy_image on r600
  • -
  • GL_ARB_tessellation_shader on i965/gen8+ and r600 (evergreen/cayman only)
  • +
  • GL_ARB_tessellation_shader on i965 and r600 (evergreen/cayman only)
  • GL_ARB_texture_buffer_object_rgb32 on freedreno/a4xx
  • GL_ARB_texture_buffer_range on freedreno/a4xx
  • GL_ARB_texture_query_lod on freedreno/a4xx
  • From da0e216e069bd064199ed04b52de6fb23d810806 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 22 Dec 2015 04:12:07 +0200 Subject: [PATCH 11/25] r600: fix constant buffer size programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When buffer size is less than 16, zero ends up being programmed as size, which prevents the hardware from fetching the correct values. Fix it by combining shift and align so that the value is always rounded up. Cc: "11.1 11.0 10.6" Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92229 Signed-off-by: Grazvydas Ignotas Reviewed-by: Nicolai Hähnle --- src/gallium/drivers/r600/evergreen_state.c | 2 +- src/gallium/drivers/r600/r600_state.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 1443bc0c4af..1aee7dd2da8 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -1956,7 +1956,7 @@ static void evergreen_emit_constant_buffers(struct r600_context *rctx, if (!gs_ring_buffer) { radeon_set_context_reg_flag(cs, reg_alu_constbuf_size + buffer_index * 4, - ALIGN_DIVUP(cb->buffer_size >> 4, 16), pkt_flags); + ALIGN_DIVUP(cb->buffer_size, 256), pkt_flags); radeon_set_context_reg_flag(cs, reg_alu_const_cache + buffer_index * 4, va >> 8, pkt_flags); } diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index e7ffe0dab1c..43b80742cb5 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -1768,7 +1768,7 @@ static void r600_emit_constant_buffers(struct r600_context *rctx, if (!gs_ring_buffer) { radeon_set_context_reg(cs, reg_alu_constbuf_size + buffer_index * 4, - ALIGN_DIVUP(cb->buffer_size >> 4, 16)); + ALIGN_DIVUP(cb->buffer_size, 256)); radeon_set_context_reg(cs, reg_alu_const_cache + buffer_index * 4, offset >> 8); } From 4711170239ae53c0fb06a4a0343cb3236fd882b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Mon, 21 Dec 2015 16:11:37 -0500 Subject: [PATCH 12/25] gallium/util: add DEBUG_GET_ONCE_OPTION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is analogous to the alreading existing macros for BOOL, NUM, and FLAGS. Reviewed-by: Marek Olšák --- src/gallium/auxiliary/util/u_debug.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h index 5307072fa3a..34668f844e9 100644 --- a/src/gallium/auxiliary/util/u_debug.h +++ b/src/gallium/auxiliary/util/u_debug.h @@ -404,6 +404,19 @@ debug_get_flags_option(const char *name, const struct debug_named_value *flags, uint64_t dfault); +#define DEBUG_GET_ONCE_OPTION(suffix, name, dfault) \ +static const char * \ +debug_get_option_ ## suffix (void) \ +{ \ + static boolean first = TRUE; \ + static const char * value; \ + if (first) { \ + first = FALSE; \ + value = debug_get_option(name, dfault); \ + } \ + return value; \ +} + #define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \ static boolean \ debug_get_option_ ## sufix (void) \ From 7d1fc2cf51438a649eecbe4f8e858eebd93c1757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Mon, 14 Dec 2015 19:34:45 -0500 Subject: [PATCH 13/25] radeonsi: count compilations in si_compile_llvm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This changes the count slightly (because of si_generate_gs_copy_shader), but this is only relevant for the driver-specific num-compilations query. It sets the stage for the next commit. Reviewed-by: Marek Olšák --- src/gallium/drivers/radeonsi/si_shader.c | 2 ++ src/gallium/drivers/radeonsi/si_state_shaders.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 4a672766b0f..511ed8829c6 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -3885,6 +3885,8 @@ int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader, shader->selector ? shader->selector->tokens : NULL); bool dump_ir = dump_asm && !(sscreen->b.debug_flags & DBG_NO_IR); + p_atomic_inc(&sscreen->b.num_compilations); + r = radeon_llvm_compile(mod, &shader->binary, r600_get_llvm_processor_name(sscreen->b.family), dump_ir, dump_asm, tm); if (r) diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index f0147ce2bfc..8700590435f 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -634,7 +634,6 @@ static int si_shader_select(struct pipe_context *ctx, sel->last_variant = shader; } state->current = shader; - p_atomic_inc(&sctx->screen->b.num_compilations); pipe_mutex_unlock(sel->mutex); return 0; } From 7b8db37abb1b7f08c43f20380a370766ae7923ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Mon, 14 Dec 2015 20:41:15 -0500 Subject: [PATCH 14/25] radeonsi: add RADEON_REPLACE_SHADERS debug option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This option allows replacing a single shader by a pre-compiled ELF object as generated by LLVM's llc, for example. This can be useful for debugging a deterministically occuring error in shaders (and has in fact helped find the causes of https://bugs.freedesktop.org/show_bug.cgi?id=93264). v2: drop the debug flag, use DEBUG_GET_ONCE_OPTION instead Reviewed-by: Marek Olšák --- src/gallium/drivers/radeonsi/si_debug.c | 95 ++++++++++++++++++++++++ src/gallium/drivers/radeonsi/si_pipe.h | 1 + src/gallium/drivers/radeonsi/si_shader.c | 14 ++-- 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c index c45f8c0ea50..a07b1c56579 100644 --- a/src/gallium/drivers/radeonsi/si_debug.c +++ b/src/gallium/drivers/radeonsi/si_debug.c @@ -28,8 +28,11 @@ #include "si_shader.h" #include "sid.h" #include "sid_tables.h" +#include "radeon/radeon_elf_util.h" #include "ddebug/dd_util.h" +#include "util/u_memory.h" +DEBUG_GET_ONCE_OPTION(replace_shaders, "RADEON_REPLACE_SHADERS", NULL) static void si_dump_shader(struct si_shader_ctx_state *state, const char *name, FILE *f) @@ -42,6 +45,98 @@ static void si_dump_shader(struct si_shader_ctx_state *state, const char *name, fprintf(f, "%s\n\n", state->current->binary.disasm_string); } +/** + * Shader compiles can be overridden with arbitrary ELF objects by setting + * the environment variable RADEON_REPLACE_SHADERS=num1:filename1[;num2:filename2] + */ +bool si_replace_shader(unsigned num, struct radeon_shader_binary *binary) +{ + const char *p = debug_get_option_replace_shaders(); + const char *semicolon; + char *copy = NULL; + FILE *f; + long filesize, nread; + char *buf = NULL; + bool replaced = false; + + if (!p) + return false; + + while (*p) { + unsigned long i; + char *endp; + i = strtoul(p, &endp, 0); + + p = endp; + if (*p != ':') { + fprintf(stderr, "RADEON_REPLACE_SHADERS formatted badly.\n"); + exit(1); + } + ++p; + + if (i == num) + break; + + p = strchr(p, ';'); + if (!p) + return false; + ++p; + } + if (!*p) + return false; + + semicolon = strchr(p, ';'); + if (semicolon) { + p = copy = strndup(p, semicolon - p); + if (!copy) { + fprintf(stderr, "out of memory\n"); + return false; + } + } + + fprintf(stderr, "radeonsi: replace shader %u by %s\n", num, p); + + f = fopen(p, "r"); + if (!f) { + perror("radeonsi: failed to open file"); + goto out_free; + } + + if (fseek(f, 0, SEEK_END) != 0) + goto file_error; + + filesize = ftell(f); + if (filesize < 0) + goto file_error; + + if (fseek(f, 0, SEEK_SET) != 0) + goto file_error; + + buf = MALLOC(filesize); + if (!buf) { + fprintf(stderr, "out of memory\n"); + goto out_close; + } + + nread = fread(buf, 1, filesize, f); + if (nread != filesize) + goto file_error; + + radeon_elf_read(buf, filesize, binary); + replaced = true; + +out_close: + fclose(f); +out_free: + FREE(buf); + free(copy); + return replaced; + +file_error: + perror("radeonsi: reading shader"); + goto out_close; +} + /* Parsed IBs are difficult to read without colors. Use "less -R file" to * read them, or use "aha -b -f file" to convert them to html. */ diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index 65c7e198d1d..f83cb024f0e 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -329,6 +329,7 @@ void si_init_cp_dma_functions(struct si_context *sctx); /* si_debug.c */ void si_init_debug_functions(struct si_context *sctx); void si_check_vm_faults(struct si_context *sctx); +bool si_replace_shader(unsigned num, struct radeon_shader_binary *binary); /* si_dma.c */ void si_dma_copy(struct pipe_context *ctx, diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 511ed8829c6..0e98784d51b 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -3884,13 +3884,17 @@ int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader, bool dump_asm = r600_can_dump_shader(&sscreen->b, shader->selector ? shader->selector->tokens : NULL); bool dump_ir = dump_asm && !(sscreen->b.debug_flags & DBG_NO_IR); + unsigned count = p_atomic_inc_return(&sscreen->b.num_compilations); - p_atomic_inc(&sscreen->b.num_compilations); + if (dump_ir || dump_asm) + fprintf(stderr, "radeonsi: Compiling shader %d\n", count); - r = radeon_llvm_compile(mod, &shader->binary, - r600_get_llvm_processor_name(sscreen->b.family), dump_ir, dump_asm, tm); - if (r) - return r; + if (!si_replace_shader(count, &shader->binary)) { + r = radeon_llvm_compile(mod, &shader->binary, + r600_get_llvm_processor_name(sscreen->b.family), dump_ir, dump_asm, tm); + if (r) + return r; + } r = si_shader_binary_read(sscreen, shader); From 70d8dbc9a116c32bb15ef333f5b9db4d13201b4b Mon Sep 17 00:00:00 2001 From: Aaron Watry Date: Tue, 29 Dec 2015 10:51:54 -0600 Subject: [PATCH 15/25] nir: Remove function overload in control flow test Fixes make check. Signed-off-by: Aaron Watry Reviewed-by: Jason Ekstrand --- src/glsl/nir/tests/control_flow_tests.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/glsl/nir/tests/control_flow_tests.cpp b/src/glsl/nir/tests/control_flow_tests.cpp index b9f90e66d1d..f142e443400 100644 --- a/src/glsl/nir/tests/control_flow_tests.cpp +++ b/src/glsl/nir/tests/control_flow_tests.cpp @@ -39,8 +39,7 @@ nir_cf_test::nir_cf_test() static const nir_shader_compiler_options options = { }; shader = nir_shader_create(NULL, MESA_SHADER_VERTEX, &options); nir_function *func = nir_function_create(shader, "main"); - nir_function_overload *overload = nir_function_overload_create(func); - impl = nir_function_impl_create(overload); + impl = nir_function_impl_create(func); nir_builder_init(&b, impl); } From 42dd2c028d38570d89323a110f4cbcf75481a0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Thu, 10 Dec 2015 12:06:17 -0800 Subject: [PATCH 16/25] mesa/vbo: Add draw_id field to struct _mesa_prim The drivers will need this for passing in gl_DrawIDARB. For indirect multidraw calls, we get the prim array and prim[i].draw_id == i and is redundant. But for non-indirect calls, we get one primitive at a time and need the draw_id field. Reviewed-by: Anuj Phogat Reviewed-by: Ian Romanick --- src/mesa/vbo/vbo.h | 1 + src/mesa/vbo/vbo_exec_array.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 00e843c9a0f..cef3b8cd792 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -58,6 +58,7 @@ struct _mesa_prim { GLint basevertex; GLuint num_instances; GLuint base_instance; + GLuint draw_id; GLsizeiptr indirect_offset; }; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index e27fdd90532..502b2885892 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -1341,6 +1341,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, prim[i].indexed = 1; prim[i].num_instances = 1; prim[i].base_instance = 0; + prim[i].draw_id = i; prim[i].is_indirect = 0; if (basevertex != NULL) prim[i].basevertex = basevertex[i]; @@ -1371,6 +1372,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, prim[0].indexed = 1; prim[0].num_instances = 1; prim[0].base_instance = 0; + prim[0].draw_id = i; prim[0].is_indirect = 0; if (basevertex != NULL) prim[0].basevertex = basevertex[i]; @@ -1598,6 +1600,7 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx, prim[i].mode = mode; prim[i].indirect_offset = offset; prim[i].is_indirect = 1; + prim[i].draw_id = i; } check_buffers_are_unmapped(exec->array.inputs); @@ -1684,6 +1687,7 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx, prim[i].indexed = 1; prim[i].indirect_offset = offset; prim[i].is_indirect = 1; + prim[i].draw_id = i; } check_buffers_are_unmapped(exec->array.inputs); From 1a59aeaebd24e424deae7fb4b3d76b3ad22cf360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Thu, 10 Dec 2015 12:07:43 -0800 Subject: [PATCH 17/25] mesa: Add core mesa support for GL_ARB_shader_draw_parameters Reviewed-by: Anuj Phogat --- src/glsl/builtin_variables.cpp | 5 +++++ src/glsl/glsl_parser_extras.cpp | 1 + src/glsl/glsl_parser_extras.h | 2 ++ src/glsl/nir/nir.c | 8 ++++++++ src/glsl/nir/nir_intrinsics.h | 2 ++ src/glsl/nir/shader_enums.h | 20 ++++++++++++++++++++ src/glsl/standalone_scaffolding.cpp | 1 + src/mesa/main/extensions_table.h | 1 + src/mesa/main/mtypes.h | 1 + 9 files changed, 41 insertions(+) diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp index e8eab808a19..e82c99ee3bb 100644 --- a/src/glsl/builtin_variables.cpp +++ b/src/glsl/builtin_variables.cpp @@ -951,6 +951,11 @@ builtin_variable_generator::generate_vs_special_vars() add_system_value(SYSTEM_VALUE_INSTANCE_ID, int_t, "gl_InstanceIDARB"); if (state->ARB_draw_instanced_enable || state->is_version(140, 300)) add_system_value(SYSTEM_VALUE_INSTANCE_ID, int_t, "gl_InstanceID"); + if (state->ARB_shader_draw_parameters_enable) { + add_system_value(SYSTEM_VALUE_BASE_VERTEX, int_t, "gl_BaseVertexARB"); + add_system_value(SYSTEM_VALUE_BASE_INSTANCE, int_t, "gl_BaseInstanceARB"); + add_system_value(SYSTEM_VALUE_DRAW_ID, int_t, "gl_DrawIDARB"); + } if (state->AMD_vertex_shader_layer_enable) { var = add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer"); var->data.interpolation = INTERP_QUALIFIER_FLAT; diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 29cf0c633be..8c46f147941 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -608,6 +608,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters), EXT(ARB_shader_bit_encoding, true, false, ARB_shader_bit_encoding), EXT(ARB_shader_clock, true, false, ARB_shader_clock), + EXT(ARB_shader_draw_parameters, true, false, ARB_shader_draw_parameters), EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store), EXT(ARB_shader_image_size, true, false, ARB_shader_image_size), EXT(ARB_shader_precision, true, false, ARB_shader_precision), diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index a4bda772a0f..afb99afa5cd 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -536,6 +536,8 @@ struct _mesa_glsl_parse_state { bool ARB_shader_bit_encoding_warn; bool ARB_shader_clock_enable; bool ARB_shader_clock_warn; + bool ARB_shader_draw_parameters_enable; + bool ARB_shader_draw_parameters_warn; bool ARB_shader_image_load_store_enable; bool ARB_shader_image_load_store_warn; bool ARB_shader_image_size_enable; diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c index 60395ae3ab0..21bf678c04e 100644 --- a/src/glsl/nir/nir.c +++ b/src/glsl/nir/nir.c @@ -1574,6 +1574,10 @@ nir_intrinsic_from_system_value(gl_system_value val) return nir_intrinsic_load_vertex_id; case SYSTEM_VALUE_INSTANCE_ID: return nir_intrinsic_load_instance_id; + case SYSTEM_VALUE_DRAW_ID: + return nir_intrinsic_load_draw_id; + case SYSTEM_VALUE_BASE_INSTANCE: + return nir_intrinsic_load_base_instance; case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE: return nir_intrinsic_load_vertex_id_zero_base; case SYSTEM_VALUE_BASE_VERTEX: @@ -1619,6 +1623,10 @@ nir_system_value_from_intrinsic(nir_intrinsic_op intrin) return SYSTEM_VALUE_VERTEX_ID; case nir_intrinsic_load_instance_id: return SYSTEM_VALUE_INSTANCE_ID; + case nir_intrinsic_load_draw_id: + return SYSTEM_VALUE_DRAW_ID; + case nir_intrinsic_load_base_instance: + return SYSTEM_VALUE_BASE_INSTANCE; case nir_intrinsic_load_vertex_id_zero_base: return SYSTEM_VALUE_VERTEX_ID_ZERO_BASE; case nir_intrinsic_load_base_vertex: diff --git a/src/glsl/nir/nir_intrinsics.h b/src/glsl/nir/nir_intrinsics.h index 5815dbecb68..62eead4878a 100644 --- a/src/glsl/nir/nir_intrinsics.h +++ b/src/glsl/nir/nir_intrinsics.h @@ -239,6 +239,8 @@ SYSTEM_VALUE(vertex_id, 1, 0) SYSTEM_VALUE(vertex_id_zero_base, 1, 0) SYSTEM_VALUE(base_vertex, 1, 0) SYSTEM_VALUE(instance_id, 1, 0) +SYSTEM_VALUE(base_instance, 1, 0) +SYSTEM_VALUE(draw_id, 1, 0) SYSTEM_VALUE(sample_id, 1, 0) SYSTEM_VALUE(sample_pos, 2, 0) SYSTEM_VALUE(sample_mask_in, 1, 0) diff --git a/src/glsl/nir/shader_enums.h b/src/glsl/nir/shader_enums.h index dd0e0bad806..0be217c0cf7 100644 --- a/src/glsl/nir/shader_enums.h +++ b/src/glsl/nir/shader_enums.h @@ -379,6 +379,26 @@ typedef enum * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE */ SYSTEM_VALUE_BASE_VERTEX, + + /** + * Value of \c baseinstance passed to instanced draw entry points + * + * \sa SYSTEM_VALUE_INSTANCE_ID + */ + SYSTEM_VALUE_BASE_INSTANCE, + + /** + * From _ARB_shader_draw_parameters: + * + * "Additionally, this extension adds a further built-in variable, + * gl_DrawID to the shading language. This variable contains the index + * of the draw currently being processed by a Multi* variant of a + * drawing command (such as MultiDrawElements or + * MultiDrawArraysIndirect)." + * + * If GL_ARB_multi_draw_indirect is not supported, this is always 0. + */ + SYSTEM_VALUE_DRAW_ID, /*@}*/ /** diff --git a/src/glsl/standalone_scaffolding.cpp b/src/glsl/standalone_scaffolding.cpp index 1f69d0dbd2a..e350f702099 100644 --- a/src/glsl/standalone_scaffolding.cpp +++ b/src/glsl/standalone_scaffolding.cpp @@ -149,6 +149,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.ARB_gpu_shader_fp64 = true; ctx->Extensions.ARB_sample_shading = true; ctx->Extensions.ARB_shader_bit_encoding = true; + ctx->Extensions.ARB_shader_draw_parameters = true; ctx->Extensions.ARB_shader_stencil_export = true; ctx->Extensions.ARB_shader_subroutine = true; ctx->Extensions.ARB_shader_texture_lod = true; diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h index 52a4ed63c0d..789b55a3c8d 100644 --- a/src/mesa/main/extensions_table.h +++ b/src/mesa/main/extensions_table.h @@ -96,6 +96,7 @@ EXT(ARB_separate_shader_objects , dummy_true EXT(ARB_shader_atomic_counters , ARB_shader_atomic_counters , GLL, GLC, x , x , 2011) EXT(ARB_shader_bit_encoding , ARB_shader_bit_encoding , GLL, GLC, x , x , 2010) EXT(ARB_shader_clock , ARB_shader_clock , GLL, GLC, x , x , 2015) +EXT(ARB_shader_draw_parameters , ARB_shader_draw_parameters , GLL, GLC, x , x , 2013) EXT(ARB_shader_image_load_store , ARB_shader_image_load_store , GLL, GLC, x , x , 2011) EXT(ARB_shader_image_size , ARB_shader_image_size , GLL, GLC, x , x , 2012) EXT(ARB_shader_objects , dummy_true , GLL, GLC, x , x , 2002) diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 937c8cd7e3a..5b9fce8b7cc 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -3712,6 +3712,7 @@ struct gl_extensions GLboolean ARB_shader_atomic_counters; GLboolean ARB_shader_bit_encoding; GLboolean ARB_shader_clock; + GLboolean ARB_shader_draw_parameters; GLboolean ARB_shader_image_load_store; GLboolean ARB_shader_image_size; GLboolean ARB_shader_precision; From b70616f3e7834386f96498d9a99f2ad11b292b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Thu, 10 Dec 2015 12:10:28 -0800 Subject: [PATCH 18/25] i965: Assert that SYSTEM_VALUE_VERTEX_ID gets lowered fs_visitor::emit_vs_system_value() looks like it's trying to handle SYSTEM_VALUE_VERTEX_ID, but we should never see that value in the backend. Reviewed-by: Anuj Phogat Reviewed-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index b6405cd5f0d..7036ad8b57c 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -46,6 +46,7 @@ fs_visitor::emit_vs_system_value(int location) vs_prog_data->uses_vertexid = true; break; case SYSTEM_VALUE_VERTEX_ID: + unreachable("should have been lowered"); case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE: reg->reg_offset = 2; vs_prog_data->uses_vertexid = true; From 17ebb55a14b5a9aa639845fbda9330ef9421834a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Thu, 10 Dec 2015 12:24:50 -0800 Subject: [PATCH 19/25] i965: Add support for gl_BaseVertexARB and gl_BaseInstanceARB We already have gl_BaseVertexARB in the .x component of the SGVS vec4 and plug gl_BaseInstanceARB into the last free component (.y). Reviewed-by: Anuj Phogat --- src/mesa/drivers/dri/i965/brw_compiler.h | 2 + src/mesa/drivers/dri/i965/brw_context.h | 9 ++++- src/mesa/drivers/dri/i965/brw_draw.c | 4 +- src/mesa/drivers/dri/i965/brw_draw_upload.c | 37 ++++++++++++------- src/mesa/drivers/dri/i965/brw_fs.cpp | 3 +- src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 10 ++++- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 6 ++- src/mesa/drivers/dri/i965/brw_vec4.cpp | 7 +++- src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 8 ++++ .../drivers/dri/i965/brw_vec4_vs_visitor.cpp | 6 ++- src/mesa/drivers/dri/i965/gen8_draw_upload.c | 35 +++++++++++------- 11 files changed, 89 insertions(+), 38 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_compiler.h b/src/mesa/drivers/dri/i965/brw_compiler.h index e66deb109e4..9b3bb9fe30b 100644 --- a/src/mesa/drivers/dri/i965/brw_compiler.h +++ b/src/mesa/drivers/dri/i965/brw_compiler.h @@ -595,6 +595,8 @@ struct brw_vs_prog_data { bool uses_vertexid; bool uses_instanceid; + bool uses_basevertex; + bool uses_baseinstance; }; struct brw_tcs_prog_data diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 0239b6214ae..4cbe585cd56 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -909,8 +909,13 @@ struct brw_context uint32_t pma_stall_bits; struct { - /** The value of gl_BaseVertex for the current _mesa_prim. */ - int gl_basevertex; + struct { + /** The value of gl_BaseVertex for the current _mesa_prim. */ + int gl_basevertex; + + /** The value of gl_BaseInstance for the current _mesa_prim. */ + int gl_baseinstance; + } params; /** * Buffer and offset used for GL_ARB_shader_draw_parameters diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 8398471d221..e0665d3c852 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -491,9 +491,9 @@ brw_try_draw_prims(struct gl_context *ctx, } } - brw->draw.gl_basevertex = + brw->draw.params.gl_basevertex = prims[i].indexed ? prims[i].basevertex : prims[i].start; - + brw->draw.params.gl_baseinstance = prims[i].base_instance; drm_intel_bo_unreference(brw->draw.draw_params_bo); if (prims[i].is_indirect) { diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index ea0f6f29c4f..ccf963cbd78 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -592,8 +592,10 @@ void brw_prepare_shader_draw_parameters(struct brw_context *brw) { /* For non-indirect draws, upload gl_BaseVertex. */ - if (brw->vs.prog_data->uses_vertexid && brw->draw.draw_params_bo == NULL) { - intel_upload_data(brw, &brw->draw.gl_basevertex, 4, 4, + if ((brw->vs.prog_data->uses_basevertex || + brw->vs.prog_data->uses_baseinstance) && + brw->draw.draw_params_bo == NULL) { + intel_upload_data(brw, &brw->draw.params, sizeof(brw->draw.params), 4, &brw->draw.draw_params_bo, &brw->draw.draw_params_offset); } @@ -658,7 +660,8 @@ brw_emit_vertices(struct brw_context *brw) brw_emit_query_begin(brw); unsigned nr_elements = brw->vb.nr_enabled; - if (brw->vs.prog_data->uses_vertexid || brw->vs.prog_data->uses_instanceid) + if (brw->vs.prog_data->uses_vertexid || brw->vs.prog_data->uses_instanceid || + brw->vs.prog_data->uses_basevertex || brw->vs.prog_data->uses_baseinstance) ++nr_elements; /* If the VS doesn't read any inputs (calculating vertex position from @@ -693,8 +696,10 @@ brw_emit_vertices(struct brw_context *brw) /* Now emit VB and VEP state packets. */ - unsigned nr_buffers = - brw->vb.nr_buffers + brw->vs.prog_data->uses_vertexid; + const bool uses_draw_params = + brw->vs.prog_data->uses_basevertex || + brw->vs.prog_data->uses_baseinstance; + const unsigned nr_buffers = brw->vb.nr_buffers + uses_draw_params; if (nr_buffers) { if (brw->gen >= 6) { @@ -713,7 +718,7 @@ brw_emit_vertices(struct brw_context *brw) } - if (brw->vs.prog_data->uses_vertexid) { + if (uses_draw_params) { EMIT_VERTEX_BUFFER_STATE(brw, brw->vb.nr_buffers, brw->draw.draw_params_bo, brw->draw.draw_params_bo->size - 1, @@ -790,21 +795,25 @@ brw_emit_vertices(struct brw_context *brw) ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT)); } - if (brw->vs.prog_data->uses_vertexid || brw->vs.prog_data->uses_instanceid) { + if (brw->vs.prog_data->uses_vertexid || brw->vs.prog_data->uses_instanceid || + brw->vs.prog_data->uses_basevertex || brw->vs.prog_data->uses_baseinstance) { uint32_t dw0 = 0, dw1 = 0; uint32_t comp0 = BRW_VE1_COMPONENT_STORE_0; uint32_t comp1 = BRW_VE1_COMPONENT_STORE_0; uint32_t comp2 = BRW_VE1_COMPONENT_STORE_0; uint32_t comp3 = BRW_VE1_COMPONENT_STORE_0; - if (brw->vs.prog_data->uses_vertexid) { + if (brw->vs.prog_data->uses_basevertex) comp0 = BRW_VE1_COMPONENT_STORE_SRC; - comp2 = BRW_VE1_COMPONENT_STORE_VID; - } - if (brw->vs.prog_data->uses_instanceid) { + if (brw->vs.prog_data->uses_baseinstance) + comp1 = BRW_VE1_COMPONENT_STORE_SRC; + + if (brw->vs.prog_data->uses_vertexid) + comp2 = BRW_VE1_COMPONENT_STORE_VID; + + if (brw->vs.prog_data->uses_instanceid) comp3 = BRW_VE1_COMPONENT_STORE_IID; - } dw1 = (comp0 << BRW_VE1_COMPONENT_0_SHIFT) | (comp1 << BRW_VE1_COMPONENT_1_SHIFT) | @@ -814,11 +823,11 @@ brw_emit_vertices(struct brw_context *brw) if (brw->gen >= 6) { dw0 |= GEN6_VE0_VALID | brw->vb.nr_buffers << GEN6_VE0_INDEX_SHIFT | - BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT; + BRW_SURFACEFORMAT_R32G32_UINT << BRW_VE0_FORMAT_SHIFT; } else { dw0 |= BRW_VE0_VALID | brw->vb.nr_buffers << BRW_VE0_INDEX_SHIFT | - BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT; + BRW_SURFACEFORMAT_R32G32_UINT << BRW_VE0_FORMAT_SHIFT; dw1 |= (i * 4) << BRW_VE1_DST_OFFSET_SHIFT; } diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 6ac2f857fee..8235ce76abd 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -1671,7 +1671,8 @@ fs_visitor::assign_vs_urb_setup() assert(stage == MESA_SHADER_VERTEX); int count = _mesa_bitcount_64(vs_prog_data->inputs_read); - if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid) + if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid || + vs_prog_data->uses_basevertex || vs_prog_data->uses_baseinstance) count++; /* Each attribute is 4 regs. */ diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index bb6ab53fbc5..5b901a082c6 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -222,6 +222,13 @@ emit_system_values_block(nir_block *block, void *void_visitor) *reg = *v->emit_vs_system_value(SYSTEM_VALUE_INSTANCE_ID); break; + case nir_intrinsic_load_base_instance: + assert(v->stage == MESA_SHADER_VERTEX); + reg = &v->nir_system_values[SYSTEM_VALUE_BASE_INSTANCE]; + if (reg->file == BAD_FILE) + *reg = *v->emit_vs_system_value(SYSTEM_VALUE_BASE_INSTANCE); + break; + case nir_intrinsic_load_invocation_id: assert(v->stage == MESA_SHADER_GEOMETRY); reg = &v->nir_system_values[SYSTEM_VALUE_INVOCATION_ID]; @@ -1747,7 +1754,8 @@ fs_visitor::nir_emit_vs_intrinsic(const fs_builder &bld, case nir_intrinsic_load_vertex_id_zero_base: case nir_intrinsic_load_base_vertex: - case nir_intrinsic_load_instance_id: { + case nir_intrinsic_load_instance_id: + case nir_intrinsic_load_base_instance: { gl_system_value sv = nir_system_value_from_intrinsic(instr->intrinsic); fs_reg val = nir_system_values[sv]; assert(val.file != BAD_FILE); diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 7036ad8b57c..d6941fa1daf 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -43,7 +43,11 @@ fs_visitor::emit_vs_system_value(int location) switch (location) { case SYSTEM_VALUE_BASE_VERTEX: reg->reg_offset = 0; - vs_prog_data->uses_vertexid = true; + vs_prog_data->uses_basevertex = true; + break; + case SYSTEM_VALUE_BASE_INSTANCE: + reg->reg_offset = 1; + vs_prog_data->uses_baseinstance = true; break; case SYSTEM_VALUE_VERTEX_ID: unreachable("should have been lowered"); diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index f0f18ca7768..b2a27d873e7 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -1581,7 +1581,8 @@ vec4_vs_visitor::setup_attributes(int payload_reg) * don't represent it with a flag in inputs_read, so we call it * VERT_ATTRIB_MAX. */ - if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid) { + if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid || + vs_prog_data->uses_basevertex || vs_prog_data->uses_baseinstance) { attribute_map[VERT_ATTRIB_MAX] = payload_reg + nr_attributes; } @@ -1982,7 +1983,9 @@ brw_compile_vs(const struct brw_compiler *compiler, void *log_data, * incoming vertex attribute. So, add an extra slot. */ if (shader->info.system_values_read & - (BITFIELD64_BIT(SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) | + (BITFIELD64_BIT(SYSTEM_VALUE_BASE_VERTEX) | + BITFIELD64_BIT(SYSTEM_VALUE_BASE_INSTANCE) | + BITFIELD64_BIT(SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) | BITFIELD64_BIT(SYSTEM_VALUE_INSTANCE_ID))) { nr_attributes++; } diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp index ab713047a8c..c20da9ba859 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp @@ -78,6 +78,13 @@ vec4_visitor::nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr) glsl_type::int_type); break; + case nir_intrinsic_load_base_instance: + reg = &nir_system_values[SYSTEM_VALUE_BASE_INSTANCE]; + if (reg->file == BAD_FILE) + *reg = *make_reg_for_system_value(SYSTEM_VALUE_BASE_INSTANCE, + glsl_type::int_type); + break; + default: break; } @@ -669,6 +676,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) case nir_intrinsic_load_vertex_id_zero_base: case nir_intrinsic_load_base_vertex: case nir_intrinsic_load_instance_id: + case nir_intrinsic_load_base_instance: case nir_intrinsic_load_invocation_id: case nir_intrinsic_load_tess_level_inner: case nir_intrinsic_load_tess_level_outer: { diff --git a/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp index fd8be7d972c..bd6a9a4ef7b 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp @@ -155,7 +155,11 @@ vec4_vs_visitor::make_reg_for_system_value(int location, switch (location) { case SYSTEM_VALUE_BASE_VERTEX: reg->writemask = WRITEMASK_X; - vs_prog_data->uses_vertexid = true; + vs_prog_data->uses_basevertex = true; + break; + case SYSTEM_VALUE_BASE_INSTANCE: + reg->writemask = WRITEMASK_Y; + vs_prog_data->uses_baseinstance = true; break; case SYSTEM_VALUE_VERTEX_ID: case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE: diff --git a/src/mesa/drivers/dri/i965/gen8_draw_upload.c b/src/mesa/drivers/dri/i965/gen8_draw_upload.c index 198d612c514..451cf0bd287 100644 --- a/src/mesa/drivers/dri/i965/gen8_draw_upload.c +++ b/src/mesa/drivers/dri/i965/gen8_draw_upload.c @@ -115,7 +115,11 @@ gen8_emit_vertices(struct brw_context *brw) } /* Now emit 3DSTATE_VERTEX_BUFFERS and 3DSTATE_VERTEX_ELEMENTS packets. */ - unsigned nr_buffers = brw->vb.nr_buffers + brw->vs.prog_data->uses_vertexid; + const bool uses_draw_params = + brw->vs.prog_data->uses_basevertex || + brw->vs.prog_data->uses_baseinstance; + const unsigned nr_buffers = brw->vb.nr_buffers + uses_draw_params; + if (nr_buffers) { assert(nr_buffers <= 33); @@ -135,7 +139,7 @@ gen8_emit_vertices(struct brw_context *brw) OUT_BATCH(buffer->bo->size); } - if (brw->vs.prog_data->uses_vertexid) { + if (uses_draw_params) { OUT_BATCH(brw->vb.nr_buffers << GEN6_VB0_INDEX_SHIFT | GEN7_VB0_ADDRESS_MODIFYENABLE | mocs_wb << 16); @@ -148,16 +152,18 @@ gen8_emit_vertices(struct brw_context *brw) /* Normally we don't need an element for the SGVS attribute because the * 3DSTATE_VF_SGVS instruction lets you store the generated attribute in an - * element that is past the list in 3DSTATE_VERTEX_ELEMENTS. However if the - * vertex ID is used then it needs an element for the base vertex buffer. - * Additionally if there is an edge flag element then the SGVS can't be - * inserted past that so we need a dummy element to ensure that the edge - * flag is the last one. + * element that is past the list in 3DSTATE_VERTEX_ELEMENTS. However if + * we're using draw parameters then we need an element for the those + * values. Additionally if there is an edge flag element then the SGVS + * can't be inserted past that so we need a dummy element to ensure that + * the edge flag is the last one. */ - bool needs_sgvs_element = (brw->vs.prog_data->uses_vertexid || - (brw->vs.prog_data->uses_instanceid && - uses_edge_flag)); - unsigned nr_elements = brw->vb.nr_enabled + needs_sgvs_element; + const bool needs_sgvs_element = (brw->vs.prog_data->uses_basevertex || + brw->vs.prog_data->uses_baseinstance || + ((brw->vs.prog_data->uses_instanceid || + brw->vs.prog_data->uses_vertexid) && + uses_edge_flag)); + const unsigned nr_elements = brw->vb.nr_enabled + needs_sgvs_element; /* The hardware allows one more VERTEX_ELEMENTS than VERTEX_BUFFERS, * presumably for VertexID/InstanceID. @@ -212,12 +218,13 @@ gen8_emit_vertices(struct brw_context *brw) } if (needs_sgvs_element) { - if (brw->vs.prog_data->uses_vertexid) { + if (brw->vs.prog_data->uses_basevertex || + brw->vs.prog_data->uses_baseinstance) { OUT_BATCH(GEN6_VE0_VALID | brw->vb.nr_buffers << GEN6_VE0_INDEX_SHIFT | - BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT); + BRW_SURFACEFORMAT_R32G32_UINT << BRW_VE0_FORMAT_SHIFT); OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) | - (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | + (BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_1_SHIFT) | (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT)); } else { From cddfc2cefa93b884c40329dcb193fe4fb22143ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Thu, 10 Dec 2015 12:27:38 -0800 Subject: [PATCH 20/25] i965: Add support for gl_DrawIDARB and enable extension We have to break open a new vec4 for gl_DrawIDARB. We've used up all space in the vec4 we use for SGVS and gl_DrawIDARB has to come from its own separate vertex buffer anyway. This is because we point the vb for base vertex and base instance into the draw parameter BO for indirect draw calls, but the draw id is generated by mesa in a different buffer. Reviewed-by: Anuj Phogat --- src/mesa/drivers/dri/i965/brw_compiler.h | 1 + src/mesa/drivers/dri/i965/brw_context.h | 9 ++++ src/mesa/drivers/dri/i965/brw_draw.c | 12 +++++ src/mesa/drivers/dri/i965/brw_draw_upload.c | 45 ++++++++++++++++++- src/mesa/drivers/dri/i965/brw_fs.cpp | 2 + src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 10 ++++- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 10 +++++ src/mesa/drivers/dri/i965/brw_vec4.cpp | 13 +++++- src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 8 ++++ .../drivers/dri/i965/brw_vec4_vs_visitor.cpp | 5 +++ src/mesa/drivers/dri/i965/gen8_draw_upload.c | 34 +++++++++++++- src/mesa/drivers/dri/i965/intel_extensions.c | 1 + 12 files changed, 145 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_compiler.h b/src/mesa/drivers/dri/i965/brw_compiler.h index 9b3bb9fe30b..224ddb14ed1 100644 --- a/src/mesa/drivers/dri/i965/brw_compiler.h +++ b/src/mesa/drivers/dri/i965/brw_compiler.h @@ -597,6 +597,7 @@ struct brw_vs_prog_data { bool uses_instanceid; bool uses_basevertex; bool uses_baseinstance; + bool uses_drawid; }; struct brw_tcs_prog_data diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 4cbe585cd56..7b0340fc2ab 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -923,6 +923,15 @@ struct brw_context */ drm_intel_bo *draw_params_bo; uint32_t draw_params_offset; + + /** + * The value of gl_DrawID for the current _mesa_prim. This always comes + * in from it's own vertex buffer since it's not part of the indirect + * draw parameters. + */ + int gl_drawid; + drm_intel_bo *draw_id_bo; + uint32_t draw_id_offset; } draw; struct { diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index e0665d3c852..b0a162aa0b6 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -511,6 +511,18 @@ brw_try_draw_prims(struct gl_context *ctx, brw->draw.draw_params_offset = 0; } + /* gl_DrawID always needs its own vertex buffer since it's not part of + * the indirect parameter buffer. If the program uses gl_DrawID we need + * to flag BRW_NEW_VERTICES. For the first iteration, we don't have + * valid brw->vs.prog_data, but we always flag BRW_NEW_VERTICES before + * the loop. + */ + brw->draw.gl_drawid = prims[i].draw_id; + drm_intel_bo_unreference(brw->draw.draw_id_bo); + brw->draw.draw_id_bo = NULL; + if (i > 0 && brw->vs.prog_data->uses_drawid) + brw->ctx.NewDriverState |= BRW_NEW_VERTICES; + if (brw->gen < 6) brw_set_prim(brw, &prims[i]); else diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index ccf963cbd78..f781d8ba72d 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -599,6 +599,12 @@ brw_prepare_shader_draw_parameters(struct brw_context *brw) &brw->draw.draw_params_bo, &brw->draw.draw_params_offset); } + + if (brw->vs.prog_data->uses_drawid) { + intel_upload_data(brw, &brw->draw.gl_drawid, sizeof(brw->draw.gl_drawid), 4, + &brw->draw.draw_id_bo, + &brw->draw.draw_id_offset); + } } /** @@ -663,6 +669,8 @@ brw_emit_vertices(struct brw_context *brw) if (brw->vs.prog_data->uses_vertexid || brw->vs.prog_data->uses_instanceid || brw->vs.prog_data->uses_basevertex || brw->vs.prog_data->uses_baseinstance) ++nr_elements; + if (brw->vs.prog_data->uses_drawid) + nr_elements++; /* If the VS doesn't read any inputs (calculating vertex position from * a state variable for some reason, for example), emit a single pad @@ -699,7 +707,8 @@ brw_emit_vertices(struct brw_context *brw) const bool uses_draw_params = brw->vs.prog_data->uses_basevertex || brw->vs.prog_data->uses_baseinstance; - const unsigned nr_buffers = brw->vb.nr_buffers + uses_draw_params; + const unsigned nr_buffers = brw->vb.nr_buffers + + uses_draw_params + brw->vs.prog_data->uses_drawid; if (nr_buffers) { if (brw->gen >= 6) { @@ -726,6 +735,16 @@ brw_emit_vertices(struct brw_context *brw) 0, /* stride */ 0); /* step rate */ } + + if (brw->vs.prog_data->uses_drawid) { + EMIT_VERTEX_BUFFER_STATE(brw, brw->vb.nr_buffers + 1, + brw->draw.draw_id_bo, + brw->draw.draw_id_bo->size - 1, + brw->draw.draw_id_offset, + 0, /* stride */ + 0); /* step rate */ + } + ADVANCE_BATCH(); } @@ -839,6 +858,30 @@ brw_emit_vertices(struct brw_context *brw) OUT_BATCH(dw1); } + if (brw->vs.prog_data->uses_drawid) { + uint32_t dw0 = 0, dw1 = 0; + + dw1 = (BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT); + + if (brw->gen >= 6) { + dw0 |= GEN6_VE0_VALID | + ((brw->vb.nr_buffers + 1) << GEN6_VE0_INDEX_SHIFT) | + (BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT); + } else { + dw0 |= BRW_VE0_VALID | + ((brw->vb.nr_buffers + 1) << BRW_VE0_INDEX_SHIFT) | + (BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT); + + dw1 |= (i * 4) << BRW_VE1_DST_OFFSET_SHIFT; + } + + OUT_BATCH(dw0); + OUT_BATCH(dw1); + } + if (brw->gen >= 6 && gen6_edgeflag_input) { uint32_t format = brw_get_vertex_surface_type(brw, gen6_edgeflag_input->glarray); diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 8235ce76abd..286ee0ed4e7 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -1674,6 +1674,8 @@ fs_visitor::assign_vs_urb_setup() if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid || vs_prog_data->uses_basevertex || vs_prog_data->uses_baseinstance) count++; + if (vs_prog_data->uses_drawid) + count++; /* Each attribute is 4 regs. */ this->first_non_payload_grf += 4 * vs_prog_data->nr_attributes; diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 5b901a082c6..827dbeeb7b6 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -229,6 +229,13 @@ emit_system_values_block(nir_block *block, void *void_visitor) *reg = *v->emit_vs_system_value(SYSTEM_VALUE_BASE_INSTANCE); break; + case nir_intrinsic_load_draw_id: + assert(v->stage == MESA_SHADER_VERTEX); + reg = &v->nir_system_values[SYSTEM_VALUE_DRAW_ID]; + if (reg->file == BAD_FILE) + *reg = *v->emit_vs_system_value(SYSTEM_VALUE_DRAW_ID); + break; + case nir_intrinsic_load_invocation_id: assert(v->stage == MESA_SHADER_GEOMETRY); reg = &v->nir_system_values[SYSTEM_VALUE_INVOCATION_ID]; @@ -1755,7 +1762,8 @@ fs_visitor::nir_emit_vs_intrinsic(const fs_builder &bld, case nir_intrinsic_load_vertex_id_zero_base: case nir_intrinsic_load_base_vertex: case nir_intrinsic_load_instance_id: - case nir_intrinsic_load_base_instance: { + case nir_intrinsic_load_base_instance: + case nir_intrinsic_load_draw_id: { gl_system_value sv = nir_system_value_from_intrinsic(instr->intrinsic); fs_reg val = nir_system_values[sv]; assert(val.file != BAD_FILE); diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index d6941fa1daf..25240ad65fa 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -59,6 +59,16 @@ fs_visitor::emit_vs_system_value(int location) reg->reg_offset = 3; vs_prog_data->uses_instanceid = true; break; + case SYSTEM_VALUE_DRAW_ID: + if (nir->info.system_values_read & + (BITFIELD64_BIT(SYSTEM_VALUE_BASE_VERTEX) | + BITFIELD64_BIT(SYSTEM_VALUE_BASE_INSTANCE) | + BITFIELD64_BIT(SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) | + BITFIELD64_BIT(SYSTEM_VALUE_INSTANCE_ID))) + reg->nr += 4; + reg->reg_offset = 0; + vs_prog_data->uses_drawid = true; + break; default: unreachable("not reached"); } diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index b2a27d873e7..dd223985d1c 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -1566,7 +1566,7 @@ int vec4_vs_visitor::setup_attributes(int payload_reg) { int nr_attributes; - int attribute_map[VERT_ATTRIB_MAX + 1]; + int attribute_map[VERT_ATTRIB_MAX + 2]; memset(attribute_map, 0, sizeof(attribute_map)); nr_attributes = 0; @@ -1577,6 +1577,11 @@ vec4_vs_visitor::setup_attributes(int payload_reg) } } + if (vs_prog_data->uses_drawid) { + attribute_map[VERT_ATTRIB_MAX + 1] = payload_reg + nr_attributes; + nr_attributes++; + } + /* VertexID is stored by the VF as the last vertex element, but we * don't represent it with a flag in inputs_read, so we call it * VERT_ATTRIB_MAX. @@ -1584,6 +1589,7 @@ vec4_vs_visitor::setup_attributes(int payload_reg) if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid || vs_prog_data->uses_basevertex || vs_prog_data->uses_baseinstance) { attribute_map[VERT_ATTRIB_MAX] = payload_reg + nr_attributes; + nr_attributes++; } lower_attributes_to_hw_regs(attribute_map, false /* interleaved */); @@ -1990,6 +1996,11 @@ brw_compile_vs(const struct brw_compiler *compiler, void *log_data, nr_attributes++; } + /* gl_DrawID has its very own vec4 */ + if (shader->info.system_values_read & BITFIELD64_BIT(SYSTEM_VALUE_DRAW_ID)) { + nr_attributes++; + } + /* The 3DSTATE_VS documentation lists the lower bound on "Vertex URB Entry * Read Length" as 1 in vec4 mode, and 0 in SIMD8 mode. Empirically, in * vec4 mode, the hardware appears to wedge unless we read something. diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp index c20da9ba859..a3bdbc35b49 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp @@ -85,6 +85,13 @@ vec4_visitor::nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr) glsl_type::int_type); break; + case nir_intrinsic_load_draw_id: + reg = &nir_system_values[SYSTEM_VALUE_DRAW_ID]; + if (reg->file == BAD_FILE) + *reg = *make_reg_for_system_value(SYSTEM_VALUE_DRAW_ID, + glsl_type::int_type); + break; + default: break; } @@ -677,6 +684,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) case nir_intrinsic_load_base_vertex: case nir_intrinsic_load_instance_id: case nir_intrinsic_load_base_instance: + case nir_intrinsic_load_draw_id: case nir_intrinsic_load_invocation_id: case nir_intrinsic_load_tess_level_inner: case nir_intrinsic_load_tess_level_outer: { diff --git a/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp index bd6a9a4ef7b..1d6914902b3 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp @@ -170,6 +170,11 @@ vec4_vs_visitor::make_reg_for_system_value(int location, reg->writemask = WRITEMASK_W; vs_prog_data->uses_instanceid = true; break; + case SYSTEM_VALUE_DRAW_ID: + reg = new(mem_ctx) dst_reg(ATTR, VERT_ATTRIB_MAX + 1); + reg->writemask = WRITEMASK_X; + vs_prog_data->uses_drawid = true; + break; default: unreachable("not reached"); } diff --git a/src/mesa/drivers/dri/i965/gen8_draw_upload.c b/src/mesa/drivers/dri/i965/gen8_draw_upload.c index 451cf0bd287..ff89e5f240d 100644 --- a/src/mesa/drivers/dri/i965/gen8_draw_upload.c +++ b/src/mesa/drivers/dri/i965/gen8_draw_upload.c @@ -118,7 +118,8 @@ gen8_emit_vertices(struct brw_context *brw) const bool uses_draw_params = brw->vs.prog_data->uses_basevertex || brw->vs.prog_data->uses_baseinstance; - const unsigned nr_buffers = brw->vb.nr_buffers + uses_draw_params; + const unsigned nr_buffers = brw->vb.nr_buffers + + uses_draw_params + brw->vs.prog_data->uses_drawid; if (nr_buffers) { assert(nr_buffers <= 33); @@ -147,6 +148,15 @@ gen8_emit_vertices(struct brw_context *brw) brw->draw.draw_params_offset); OUT_BATCH(brw->draw.draw_params_bo->size); } + + if (brw->vs.prog_data->uses_drawid) { + OUT_BATCH((brw->vb.nr_buffers + 1) << GEN6_VB0_INDEX_SHIFT | + GEN7_VB0_ADDRESS_MODIFYENABLE | + mocs_wb << 16); + OUT_RELOC64(brw->draw.draw_id_bo, I915_GEM_DOMAIN_VERTEX, 0, + brw->draw.draw_id_offset); + OUT_BATCH(brw->draw.draw_id_bo->size); + } ADVANCE_BATCH(); } @@ -163,7 +173,8 @@ gen8_emit_vertices(struct brw_context *brw) ((brw->vs.prog_data->uses_instanceid || brw->vs.prog_data->uses_vertexid) && uses_edge_flag)); - const unsigned nr_elements = brw->vb.nr_enabled + needs_sgvs_element; + const unsigned nr_elements = + brw->vb.nr_enabled + needs_sgvs_element + brw->vs.prog_data->uses_drawid; /* The hardware allows one more VERTEX_ELEMENTS than VERTEX_BUFFERS, * presumably for VertexID/InstanceID. @@ -236,6 +247,16 @@ gen8_emit_vertices(struct brw_context *brw) } } + if (brw->vs.prog_data->uses_drawid) { + OUT_BATCH(GEN6_VE0_VALID | + ((brw->vb.nr_buffers + 1) << GEN6_VE0_INDEX_SHIFT) | + (BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT)); + OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT)); + } + if (gen6_edgeflag_input) { uint32_t format = brw_get_vertex_surface_type(brw, gen6_edgeflag_input->glarray); @@ -273,6 +294,15 @@ gen8_emit_vertices(struct brw_context *brw) OUT_BATCH(buffer->step_rate); ADVANCE_BATCH(); } + + if (brw->vs.prog_data->uses_drawid) { + const unsigned element = brw->vb.nr_enabled + needs_sgvs_element; + BEGIN_BATCH(3); + OUT_BATCH(_3DSTATE_VF_INSTANCING << 16 | (3 - 2)); + OUT_BATCH(element); + OUT_BATCH(0); + ADVANCE_BATCH(); + } } const struct brw_tracked_state gen8_vertices = { diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c index de16ebb0a49..e1338e92e15 100644 --- a/src/mesa/drivers/dri/i965/intel_extensions.c +++ b/src/mesa/drivers/dri/i965/intel_extensions.c @@ -203,6 +203,7 @@ intelInitExtensions(struct gl_context *ctx) ctx->Extensions.ARB_point_sprite = true; ctx->Extensions.ARB_seamless_cube_map = true; ctx->Extensions.ARB_shader_bit_encoding = true; + ctx->Extensions.ARB_shader_draw_parameters = true; ctx->Extensions.ARB_shader_texture_lod = true; ctx->Extensions.ARB_shadow = true; ctx->Extensions.ARB_sync = true; From f9283f2668bb1a64303d73b663464a8556fe3f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Mon, 14 Dec 2015 17:44:23 -0800 Subject: [PATCH 21/25] nir: Teach nir_opt_algebraic about adding and subtracting the same thing This optimizes a + b - b to just a. Modest shader-db results (BDW): total instructions in shared programs: 7842452 -> 7841862 (-0.01%) instructions in affected programs: 61938 -> 61348 (-0.95%) total loops in shared programs: 2131 -> 2131 (0.00%) helped: 263 HURT: 0 GAINED: 0 LOST: 0 but the optimization turns gl_VertexID - gl_BaseVertexARB into just a reference to SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, which the i965 hardware supports natively. That means we can avoid using the internal vertex buffer for gl_BaseVertexARB in this case. Reviewed-by: Eduardo Lima Mitev Reviewed-by: Ian Romanick Reviewed-by: Matt Turner --- src/glsl/nir/nir_opt_algebraic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/glsl/nir/nir_opt_algebraic.py b/src/glsl/nir/nir_opt_algebraic.py index cb715c0b2c1..1fdad3d78a6 100644 --- a/src/glsl/nir/nir_opt_algebraic.py +++ b/src/glsl/nir/nir_opt_algebraic.py @@ -62,6 +62,10 @@ optimizations = [ (('iadd', ('imul', a, b), ('imul', a, c)), ('imul', a, ('iadd', b, c))), (('fadd', ('fneg', a), a), 0.0), (('iadd', ('ineg', a), a), 0), + (('iadd', ('ineg', a), ('iadd', a, b)), b), + (('iadd', a, ('iadd', ('ineg', a), b)), b), + (('fadd', ('fneg', a), ('fadd', a, b)), b), + (('fadd', a, ('fadd', ('fneg', a), b)), b), (('fmul', a, 0.0), 0.0), (('imul', a, 0), 0), (('umul_unorm_4x8', a, 0), 0), From 581f81860e7409a60c869f76e503cbb865dd68b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Mon, 14 Dec 2015 23:36:06 -0800 Subject: [PATCH 22/25] i965: Reemit vertex state between indirect multi draws If we're doing an indirect draw, prims[i].basevertex is always 0 and the real base vertex value is in the indirect parameter buffer. We try to avoid flagging BRW_NEW_VERTICES if prims[i].basevertex doesn't change, which then breaks down for indirect draws. Thus, if a program uses base vertex or base instance, and the draw call is indirect, always flag BRW_NEW_VERTICES. A new piglit test, spec/ARB_shader_draw_parameters/drawid-indirect-vertexid tests this. Reviewed-by: Anuj Phogat --- src/mesa/drivers/dri/i965/brw_draw.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index b0a162aa0b6..8737c6468e5 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -491,9 +491,29 @@ brw_try_draw_prims(struct gl_context *ctx, } } - brw->draw.params.gl_basevertex = + /* Determine if we need to flag BRW_NEW_VERTICES for updating the + * gl_BaseVertexARB or gl_BaseInstanceARB values. For indirect draw, we + * always flag if the shader uses one of the values. For direct draws, + * we only flag if the values change. + */ + const int new_basevertex = prims[i].indexed ? prims[i].basevertex : prims[i].start; - brw->draw.params.gl_baseinstance = prims[i].base_instance; + const int new_baseinstance = prims[i].base_instance; + if (i > 0) { + const bool uses_draw_parameters = + brw->vs.prog_data->uses_basevertex || + brw->vs.prog_data->uses_baseinstance; + + if ((uses_draw_parameters && prims[i].is_indirect) || + (brw->vs.prog_data->uses_basevertex && + brw->draw.params.gl_basevertex != new_basevertex) || + (brw->vs.prog_data->uses_baseinstance && + brw->draw.params.gl_baseinstance != new_baseinstance)) + brw->ctx.NewDriverState |= BRW_NEW_VERTICES; + } + + brw->draw.params.gl_basevertex = new_basevertex; + brw->draw.params.gl_baseinstance = new_baseinstance; drm_intel_bo_unreference(brw->draw.draw_params_bo); if (prims[i].is_indirect) { From 724134f68322087ef88bc590febd0011167ae367 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Tue, 29 Dec 2015 15:05:34 -0500 Subject: [PATCH 23/25] nv50/ir: float(s32 & 0xff) = float(u8), not s8 Make sure to make conversion unsigned when we're ANDing the high bits away. Fixes corruption in dolphin. Signed-off-by: Ilia Mirkin Cc: "11.0 11.1" --- src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp index 022626ccb8f..c2842c2186f 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp @@ -1889,6 +1889,9 @@ AlgebraicOpt::handleCVT_EXTBF(Instruction *cvt) arg = shift->getSrc(0); offset = imm.reg.data.u32; } + // We just AND'd the high bits away, which means this is effectively an + // unsigned value. + cvt->sType = TYPE_U32; } else if (insn->op == OP_SHR && insn->sType == cvt->sType && insn->src(1).getImmediate(imm)) { From 55ca5b0e74dff2b2f7df57af332b73e2a1b7d081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg=20Kristensen?= Date: Tue, 29 Dec 2015 11:14:07 -0800 Subject: [PATCH 24/25] mesa/st: Pad out _mesa_sysval_to_semantic for new SYSTEM_VALUE_* enums GL_ARB_shader_draw_parameters added two new system values. This gets us back to mapping mesa system values to the right TGSI semantics. Reviewed-by: Ilia Mirkin --- src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 89ad6cd8c28..5a6be08185f 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -4328,6 +4328,8 @@ const unsigned _mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = { TGSI_SEMANTIC_INSTANCEID, TGSI_SEMANTIC_VERTEXID_NOBASE, TGSI_SEMANTIC_BASEVERTEX, + 0, /* SYSTEM_VALUE_BASE_INSTANCE */ + 0, /* SYSTEM_VALUE_DRAW_ID */ /* Geometry shader */ From 0119773ffca586c9e51fa19248c3dfaab0500b25 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 29 Dec 2015 09:56:44 -0800 Subject: [PATCH 25/25] nir/builder: Add an init function that creates a simple shader for you A hugely common case when using nir_builder is to have a shader with a single function called main. This adds a helper that gives you just that. This commit also makes us use it in the NIR control-flow unit tests as well as tgsi_to_nir and prog_to_nir. Reviewed-by: Eric Anholt Reviewed-by: Connor Abbott Acked-by: Kenneth Graunke --- src/gallium/auxiliary/nir/tgsi_to_nir.c | 12 ++++------- src/glsl/nir/nir_builder.h | 11 ++++++++++ src/glsl/nir/tests/control_flow_tests.cpp | 26 +++++++++-------------- src/mesa/program/prog_to_nir.c | 13 +++--------- 4 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c index 01426e86e61..94d992b0031 100644 --- a/src/gallium/auxiliary/nir/tgsi_to_nir.c +++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c @@ -1968,14 +1968,10 @@ tgsi_to_nir(const void *tgsi_tokens, tgsi_scan_shader(tgsi_tokens, &scan); c->scan = &scan; - s = nir_shader_create(NULL, tgsi_processor_to_shader_stage(scan.processor), - options); - - nir_function *func = nir_function_create(s, "main"); - nir_function_impl *impl = nir_function_impl_create(func); - - nir_builder_init(&c->build, impl); - c->build.cursor = nir_after_cf_list(&impl->body); + nir_builder_init_simple_shader(&c->build, NULL, + tgsi_processor_to_shader_stage(scan.processor), + options); + s = c->build.shader; s->num_inputs = scan.file_max[TGSI_FILE_INPUT] + 1; s->num_uniforms = scan.const_file_max[0] + 1; diff --git a/src/glsl/nir/nir_builder.h b/src/glsl/nir/nir_builder.h index ee6131a089f..cfaaf8e03e3 100644 --- a/src/glsl/nir/nir_builder.h +++ b/src/glsl/nir/nir_builder.h @@ -43,6 +43,17 @@ nir_builder_init(nir_builder *build, nir_function_impl *impl) build->shader = impl->function->shader; } +static inline void +nir_builder_init_simple_shader(nir_builder *build, void *mem_ctx, + gl_shader_stage stage, + const nir_shader_compiler_options *options) +{ + build->shader = nir_shader_create(mem_ctx, stage, options); + nir_function *func = nir_function_create(build->shader, "main"); + build->impl = nir_function_impl_create(func); + build->cursor = nir_after_cf_list(&build->impl->body); +} + static inline void nir_builder_instr_insert(nir_builder *build, nir_instr *instr) { diff --git a/src/glsl/nir/tests/control_flow_tests.cpp b/src/glsl/nir/tests/control_flow_tests.cpp index f142e443400..b9379ef3b06 100644 --- a/src/glsl/nir/tests/control_flow_tests.cpp +++ b/src/glsl/nir/tests/control_flow_tests.cpp @@ -30,23 +30,17 @@ protected: ~nir_cf_test(); nir_builder b; - nir_shader *shader; - nir_function_impl *impl; }; nir_cf_test::nir_cf_test() { static const nir_shader_compiler_options options = { }; - shader = nir_shader_create(NULL, MESA_SHADER_VERTEX, &options); - nir_function *func = nir_function_create(shader, "main"); - impl = nir_function_impl_create(func); - - nir_builder_init(&b, impl); + nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, &options); } nir_cf_test::~nir_cf_test() { - ralloc_free(shader); + ralloc_free(b.shader); } TEST_F(nir_cf_test, delete_break_in_loop) @@ -55,12 +49,12 @@ TEST_F(nir_cf_test, delete_break_in_loop) * * while (...) { break; } */ - nir_loop *loop = nir_loop_create(shader); - nir_cf_node_insert(nir_after_cf_list(&impl->body), &loop->cf_node); + nir_loop *loop = nir_loop_create(b.shader); + nir_cf_node_insert(nir_after_cf_list(&b.impl->body), &loop->cf_node); b.cursor = nir_after_cf_list(&loop->body); - nir_jump_instr *jump = nir_jump_instr_create(shader, nir_jump_break); + nir_jump_instr *jump = nir_jump_instr_create(b.shader, nir_jump_break); nir_builder_instr_insert(&b, &jump->instr); /* At this point, we should have: @@ -81,10 +75,10 @@ TEST_F(nir_cf_test, delete_break_in_loop) * block block_3: * } */ - nir_block *block_0 = nir_start_block(impl); + nir_block *block_0 = nir_start_block(b.impl); nir_block *block_1 = nir_cf_node_as_block(nir_loop_first_cf_node(loop)); nir_block *block_2 = nir_cf_node_as_block(nir_cf_node_next(&loop->cf_node)); - nir_block *block_3 = impl->end_block; + nir_block *block_3 = b.impl->end_block; ASSERT_EQ(nir_cf_node_block, block_0->cf_node.type); ASSERT_EQ(nir_cf_node_block, block_1->cf_node.type); ASSERT_EQ(nir_cf_node_block, block_2->cf_node.type); @@ -107,12 +101,12 @@ TEST_F(nir_cf_test, delete_break_in_loop) EXPECT_TRUE(_mesa_set_search(block_2->predecessors, block_1)); EXPECT_TRUE(_mesa_set_search(block_3->predecessors, block_2)); - nir_print_shader(shader, stderr); + nir_print_shader(b.shader, stderr); /* Now remove the break. */ nir_instr_remove(&jump->instr); - nir_print_shader(shader, stderr); + nir_print_shader(b.shader, stderr); /* At this point, we should have: * @@ -150,5 +144,5 @@ TEST_F(nir_cf_test, delete_break_in_loop) EXPECT_TRUE(_mesa_set_search(block_2->predecessors, block_1)); EXPECT_TRUE(_mesa_set_search(block_3->predecessors, block_2)); - nir_metadata_require(impl, nir_metadata_dominance); + nir_metadata_require(b.impl, nir_metadata_dominance); } diff --git a/src/mesa/program/prog_to_nir.c b/src/mesa/program/prog_to_nir.c index c5d4f273fc8..ce6f6997d2f 100644 --- a/src/mesa/program/prog_to_nir.c +++ b/src/mesa/program/prog_to_nir.c @@ -1082,11 +1082,11 @@ prog_to_nir(const struct gl_program *prog, c = rzalloc(NULL, struct ptn_compile); if (!c) return NULL; - s = nir_shader_create(NULL, stage, options); - if (!s) - goto fail; c->prog = prog; + nir_builder_init_simple_shader(&c->build, NULL, stage, options); + s = c->build.shader; + if (prog->Parameters->NumParameters > 0) { c->parameters = rzalloc(s, nir_variable); c->parameters->type = @@ -1097,13 +1097,6 @@ prog_to_nir(const struct gl_program *prog, exec_list_push_tail(&s->uniforms, &c->parameters->node); } - nir_function *func = nir_function_create(s, "main"); - nir_function_impl *impl = nir_function_impl_create(func); - - c->build.shader = s; - c->build.impl = impl; - c->build.cursor = nir_after_cf_list(&impl->body); - setup_registers_and_variables(c); if (unlikely(c->error)) goto fail;