diff options
author | Brian Paul <brianp@vmware.com> | 2011-01-15 10:24:08 -0700 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2011-01-15 10:24:08 -0700 |
commit | 652901e95b4ed406293d0e1fabee857c054119b1 (patch) | |
tree | a4b40b134f7c6491cd8d9fe37590e99428d8fab5 | |
parent | 21001d2ba79be26f565a6795a907ec266564f4cd (diff) | |
parent | b7c38734c9d85f9dad1796d97690be2d9c55c397 (diff) |
Merge branch 'draw-instanced'
Conflicts:
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/glsl/ir_set_program_inouts.cpp
src/mesa/tnl/t_vb_program.c
33 files changed, 347 insertions, 23 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 943ec44bcde..41269ee869d 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -439,2 +439,3 @@ generate_vs(struct draw_llvm *llvm, const LLVMValueRef (*inputs)[NUM_CHANNELS], + LLVMValueRef system_values_array, LLVMValueRef context_ptr, @@ -470,2 +471,3 @@ generate_vs(struct draw_llvm *llvm, consts_ptr, + system_values_array, NULL /*pos*/, @@ -1120,3 +1122,5 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) LLVMValueRef instance_id; + LLVMValueRef system_values_array; struct draw_context *draw = llvm->draw; + const struct tgsi_shader_info *vs_info = &draw->vs.vertex_shader->info; unsigned i, j; @@ -1181,2 +1185,5 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) + system_values_array = lp_build_system_values_array(gallivm, vs_info, + instance_id, NULL); + end = lp_build_add(&bld, start, count); @@ -1235,2 +1242,3 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) ptr_aos, + system_values_array, context_ptr, @@ -1265,4 +1273,3 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) convert_to_aos(gallivm, io, outputs, clipmask, - draw->vs.vertex_shader->info.num_outputs, - max_vertices); + vs_info->num_outputs, max_vertices); } @@ -1317,3 +1324,5 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian LLVMValueRef instance_id; + LLVMValueRef system_values_array; struct draw_context *draw = llvm->draw; + const struct tgsi_shader_info *vs_info = &draw->vs.vertex_shader->info; unsigned i, j; @@ -1378,2 +1387,6 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian + system_values_array = lp_build_system_values_array(gallivm, vs_info, + instance_id, NULL); + + step = lp_build_const_int32(gallivm, max_vertices); @@ -1440,2 +1453,3 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian ptr_aos, + system_values_array, context_ptr, @@ -1473,4 +1487,3 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian convert_to_aos(gallivm, io, outputs, clipmask, - draw->vs.vertex_shader->info.num_outputs, - max_vertices); + vs_info->num_outputs, max_vertices); } diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index 667eb507855..c41d7c42a01 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -101,2 +101,8 @@ vs_exec_run_linear( struct draw_vertex_shader *shader, + if (shader->info.uses_instanceid) { + unsigned i = machine->SysSemanticToIndex[TGSI_SEMANTIC_INSTANCEID]; + assert(i < Elements(machine->SystemValue)); + machine->SystemValue[i][0] = shader->draw->instance_id; + } + for (i = 0; i < count; i += MAX_TGSI_VERTICES) { diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index dee7c0da9b6..d55b9b08070 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -73,2 +73,8 @@ vs_sse_prepare( struct draw_vertex_shader *base, machine->Samplers = draw->vs.samplers; + + if (base->info.uses_instanceid) { + unsigned i = machine->SysSemanticToIndex[TGSI_SEMANTIC_INSTANCEID]; + assert(i < Elements(machine->SystemValue)); + machine->SystemValue[i][0] = base->draw->instance_id; + } } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h index 40186befb9f..9713d100484 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h @@ -182,2 +182,3 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm, LLVMValueRef consts_ptr, + LLVMValueRef system_values_array, const LLVMValueRef *pos, @@ -201,2 +202,9 @@ lp_build_tgsi_aos(struct gallivm_state *gallivm, +LLVMValueRef +lp_build_system_values_array(struct gallivm_state *gallivm, + const struct tgsi_shader_info *info, + LLVMValueRef instance_id, + LLVMValueRef facing); + + #endif /* LP_BLD_TGSI_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index 1b5a8a5903b..d1585c8e2b7 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -159,2 +159,4 @@ struct lp_build_tgsi_soa_context + LLVMValueRef system_values_array; + const struct tgsi_shader_info *info; @@ -761,2 +763,19 @@ emit_fetch( + case TGSI_FILE_SYSTEM_VALUE: + assert(!reg->Register.Indirect); + { + LLVMValueRef index; /* index into the system value array */ + LLVMValueRef scalar, scalar_ptr; + + index = lp_build_const_int32(gallivm, + reg->Register.Index * 4 + swizzle); + + scalar_ptr = LLVMBuildGEP(builder, bld->system_values_array, + &index, 1, ""); + scalar = LLVMBuildLoad(builder, scalar_ptr, ""); + + res = lp_build_broadcast_scalar(&bld->base, scalar); + } + break; + default: @@ -2324,2 +2343,3 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm, LLVMValueRef consts_ptr, + LLVMValueRef system_values_array, const LLVMValueRef *pos, @@ -2413,2 +2433,4 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm, + bld.system_values_array = system_values_array; + tgsi_parse_init( &parse, tokens ); @@ -2514 +2536,52 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm, + +/** + * Build up the system values array out of individual values such as + * the instance ID, front-face, primitive ID, etc. The shader info is + * used to determine which system values are needed and where to put + * them in the system values array. + * + * XXX only instance ID is implemented at this time. + * + * The system values register file is similar to the constants buffer. + * Example declaration: + * DCL SV[0], INSTANCEID + * Example instruction: + * MOVE foo, SV[0].xxxx; + * + * \return LLVM float array (interpreted as float [][4]) + */ +LLVMValueRef +lp_build_system_values_array(struct gallivm_state *gallivm, + const struct tgsi_shader_info *info, + LLVMValueRef instance_id, + LLVMValueRef facing) +{ + LLVMValueRef size = lp_build_const_int32(gallivm, 4 * info->num_system_values); + LLVMTypeRef float_t = LLVMFloatTypeInContext(gallivm->context); + LLVMValueRef array = lp_build_array_alloca(gallivm, float_t, + size, "sysvals_array"); + unsigned i; + + for (i = 0; i < info->num_system_values; i++) { + LLVMValueRef index = lp_build_const_int32(gallivm, i * 4); + LLVMValueRef ptr, value; + + switch (info->system_value_semantic_name[i]) { + case TGSI_SEMANTIC_INSTANCEID: + /* convert instance ID from int to float */ + value = LLVMBuildSIToFP(gallivm->builder, instance_id, float_t, + "sysval_instanceid"); + break; + case TGSI_SEMANTIC_FACE: + /* fall-through */ + default: + assert(0 && "unexpected semantic in build_system_values_array()"); + } + + ptr = LLVMBuildGEP(gallivm->builder, array, &index, 1, ""); + LLVMBuildStore(gallivm->builder, value, ptr); + } + + return array; +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 7892a67f04c..35b27423513 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -1040,3 +1040,2 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach, case TGSI_FILE_INPUT: - case TGSI_FILE_SYSTEM_VALUE: for (i = 0; i < QUAD_SIZE; i++) { @@ -1055,2 +1054,11 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach, + case TGSI_FILE_SYSTEM_VALUE: + /* XXX no swizzling at this point. Will be needed if we put + * gl_FragCoord, for example, in a sys value register. + */ + for (i = 0; i < QUAD_SIZE; i++) { + chan->f[i] = mach->SystemValue[index->i[i]][0]; + } + break; + case TGSI_FILE_TEMPORARY: @@ -1909,4 +1917,3 @@ exec_declaration(struct tgsi_exec_machine *mach, if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) { - if (decl->Declaration.File == TGSI_FILE_INPUT || - decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) { + if (decl->Declaration.File == TGSI_FILE_INPUT) { uint first, last, mask; @@ -1923,2 +1930,3 @@ exec_declaration(struct tgsi_exec_machine *mach, */ + /* XXX make FACE a system value */ if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) { @@ -1964,4 +1972,9 @@ exec_declaration(struct tgsi_exec_machine *mach, } + + if (decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) { + mach->SysSemanticToIndex[decl->Declaration.Semantic] = decl->Range.First; + } } + typedef void (* micro_op)(union tgsi_exec_channel *dst); diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index b5ebbfbfaab..6c204c73714 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -33,2 +33,3 @@ #include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" @@ -183,2 +184,4 @@ struct tgsi_sampler +#define TGSI_MAX_MISC_INPUTS 8 + /** function call/activation record */ @@ -230,2 +233,6 @@ struct tgsi_exec_machine + /* System values */ + unsigned SysSemanticToIndex[TGSI_SEMANTIC_COUNT]; + float SystemValue[TGSI_MAX_MISC_INPUTS][4]; + struct tgsi_exec_vector *Addrs; diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.c b/src/gallium/auxiliary/tgsi/tgsi_ppc.c index 3521847b619..537a0f6c5e4 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ppc.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c @@ -296,3 +296,2 @@ emit_fetch(struct gen_context *gen, case TGSI_FILE_INPUT: - case TGSI_FILE_SYSTEM_VALUE: { @@ -304,2 +303,5 @@ emit_fetch(struct gen_context *gen, break; + case TGSI_FILE_SYSTEM_VALUE: + assert(!"unhandled system value in tgsi_ppc.c"); + break; case TGSI_FILE_TEMPORARY: diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c index 6585da3e838..83c6ac75e54 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.c +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c @@ -145,3 +145,3 @@ tgsi_scan_shader(const struct tgsi_token *tokens, - if (file == TGSI_FILE_INPUT || file == TGSI_FILE_SYSTEM_VALUE) { + if (file == TGSI_FILE_INPUT) { info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name; @@ -153,2 +153,19 @@ tgsi_scan_shader(const struct tgsi_token *tokens, } + else if (file == TGSI_FILE_SYSTEM_VALUE) { + unsigned index = fulldecl->Range.First; + unsigned semName = fulldecl->Semantic.Name; + + info->system_value_semantic_name[index] = semName; + info->num_system_values = MAX2(info->num_system_values, + index + 1); + + /* + info->system_value_semantic_name[info->num_system_values++] = + fulldecl->Semantic.Name; + */ + + if (fulldecl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) { + info->uses_instanceid = TRUE; + } + } else if (file == TGSI_FILE_OUTPUT) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h index 104097fbc03..53ab3d509dd 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.h +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h @@ -53,2 +53,5 @@ struct tgsi_shader_info + ubyte num_system_values; + ubyte system_value_semantic_name[PIPE_MAX_SHADER_INPUTS]; + uint file_mask[TGSI_FILE_COUNT]; /**< bitmask of declared registers */ @@ -66,2 +69,3 @@ struct tgsi_shader_info boolean uses_kill; /**< KIL or KILP instruction used? */ + boolean uses_instanceid; diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index 086d983a73a..3f2cda860e0 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -165,2 +165,10 @@ get_immediate_base( void ) +static struct x86_reg +get_system_value_base( void ) +{ + return x86_make_disp( + get_machine_base(), + Offset(struct tgsi_exec_machine, SystemValue) ); +} + @@ -231,2 +239,12 @@ get_temp( static struct x86_reg +get_system_value( + unsigned vec, + unsigned chan ) +{ + return x86_make_disp( + get_system_value_base(), /* base */ + (vec * 4 + chan) * 4 ); /* byte offset from base */ +} + +static struct x86_reg get_coef( @@ -425,2 +443,26 @@ emit_tempf( /** + * Copy a system value to xmm register + * \param xmm the destination xmm register + * \param vec the source system value register + * \param chan src channel to fetch (X, Y, Z or W) + */ +static void +emit_system_value( + struct x86_function *func, + unsigned xmm, + unsigned vec, + unsigned chan ) +{ + sse_movss( + func, + make_xmm( xmm ), + get_system_value( vec, chan ) ); + sse_shufps( + func, + make_xmm( xmm ), + make_xmm( xmm ), + SHUF( 0, 0, 0, 0 ) ); +} + +/** * Load an xmm register with an input attrib coefficient (a0, dadx or dady) @@ -1283,4 +1325,11 @@ emit_fetch( - case TGSI_FILE_INPUT: case TGSI_FILE_SYSTEM_VALUE: + emit_system_value( + func, + xmm, + reg->Register.Index, + swizzle ); + break; + + case TGSI_FILE_INPUT: emit_inputf( @@ -2638,4 +2687,3 @@ emit_declaration( { - if( decl->Declaration.File == TGSI_FILE_INPUT || - decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE ) { + if( decl->Declaration.File == TGSI_FILE_INPUT ) { unsigned first, last, mask; diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst index 09edbaa673d..ab90097add6 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -38,2 +38,3 @@ The integer capabilities: * ``TIMER_QUERY``: Whether timer queries are available. +* ``INSTANCED_DRAWING``: indicates support for instanced drawing. * ``TEXTURE_SHADOW_MAP``: indicates whether the fragment shader hardware diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 9459a3cd113..b6919a5c6d3 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -166,2 +166,4 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 0; + case PIPE_CAP_INSTANCED_DRAWING: + return 1; default: diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index ae207617cc1..1b9119eda00 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -336,3 +336,4 @@ generate_fs(struct gallivm_state *gallivm, lp_build_tgsi_soa(gallivm, tokens, type, &mask, - consts_ptr, interp->pos, interp->inputs, + consts_ptr, NULL, /* sys values array */ + interp->pos, interp->inputs, outputs, sampler, &shader->info.base); diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index cbdea19af43..e19f2e6fc7d 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -125,2 +125,4 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 1; + case PIPE_CAP_INSTANCED_DRAWING: + return 1; default: diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index f5af15ff9ff..2135c19dcfc 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -464,2 +464,3 @@ enum pipe_cap { PIPE_CAP_SHADER_STENCIL_EXPORT, + PIPE_CAP_INSTANCED_DRAWING, }; diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 8dbe66927dc..cbeacd5633f 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -182,2 +182,11 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, } + } else if (strcmp(name, "GL_ARB_draw_instanced") == 0) { + /* This extension is only supported in vertex shaders. + */ + if (state->target != vertex_shader) { + unsupported = true; + } else { + state->ARB_draw_instanced_enable = (ext_mode != extension_disable); + state->ARB_draw_instanced_warn = (ext_mode == extension_warn); + } } else if (strcmp(name, "GL_ARB_explicit_attrib_location") == 0) { diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 39c10b99e83..030d27a2627 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -134,2 +134,4 @@ struct _mesa_glsl_parse_state { unsigned ARB_draw_buffers_warn:1; + unsigned ARB_draw_instanced_enable:1; + unsigned ARB_draw_instanced_warn:1; unsigned ARB_explicit_attrib_location_enable:1; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 57e89f0f6bf..7b83c2836ee 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -227,2 +227,3 @@ enum ir_variable_mode { ir_var_inout, + ir_var_system_value, /**< Ex: front-face, instance-id, etc. */ ir_var_temporary /**< Temporary variable generated during compilation. */ diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp index 714281539ac..085456533c5 100644 --- a/src/glsl/ir_set_program_inouts.cpp +++ b/src/glsl/ir_set_program_inouts.cpp @@ -81,2 +81,4 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len) prog->InputsRead |= BITFIELD64_BIT(var->location + offset + i); + else if (var->mode == ir_var_system_value) + prog->SystemValuesRead |= (1 << (var->location + offset + i)); else @@ -136,3 +138,4 @@ ir_set_program_inouts_visitor::visit(ir_variable *ir) if (ir->mode == ir_var_in || - ir->mode == ir_var_out) { + ir->mode == ir_var_out || + ir->mode == ir_var_system_value) { hash_table_insert(this->ht, ir, ir); @@ -160,2 +163,3 @@ do_set_program_inouts(exec_list *instructions, struct gl_program *prog) prog->OutputsWritten = 0; + prog->SystemValuesRead = 0; visit_list_elements(&v, instructions); diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index 5b8281e16e3..73da28faf4f 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -32,2 +32,7 @@ static void generate_ARB_draw_buffers_variables(exec_list *, +static void +generate_ARB_draw_instanced_variables(exec_list *, + struct _mesa_glsl_parse_state *, + bool, _mesa_glsl_parser_targets); + static ir_variable * @@ -43,2 +48,3 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot, case ir_var_uniform: + case ir_var_system_value: var->read_only = true; @@ -326,4 +332,9 @@ initialize_vs_variables(exec_list *instructions, } + + if (state->ARB_draw_instanced_enable) + generate_ARB_draw_instanced_variables(instructions, state, false, + vertex_shader); } + /* This function should only be called for ES, not desktop GL. */ @@ -424,2 +435,23 @@ generate_ARB_draw_buffers_variables(exec_list *instructions, + +static void +generate_ARB_draw_instanced_variables(exec_list *instructions, + struct _mesa_glsl_parse_state *state, + bool warn, + _mesa_glsl_parser_targets target) +{ + /* gl_InstanceIDARB is only available in the vertex shader. + */ + if (target == vertex_shader) { + ir_variable *const inst = + add_variable("gl_InstanceIDARB", ir_var_system_value, + SYSTEM_VALUE_INSTANCE_ID, + glsl_type::int_type, instructions, state->symbols); + + if (warn) + inst->warn_extension = "GL_ARB_draw_instanced"; + } +} + + static void diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 2d146caca5b..9b041aafe42 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -75,2 +75,3 @@ initialize_context(struct gl_context *ctx, gl_api api) ctx->Extensions.ARB_draw_buffers = GL_TRUE; + ctx->Extensions.ARB_draw_instanced = GL_TRUE; ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index c41ae4ad2d9..24404993c69 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -382,2 +382,3 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE; + ctx->Extensions.ARB_draw_instanced = GL_TRUE; ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index f76e1eb2ee0..1522332e8a1 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1750,2 +1750,3 @@ typedef enum PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */ + PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */ PROGRAM_UNDEFINED, /**< Invalid/TBD value */ @@ -1755,2 +1756,14 @@ typedef enum +/** + * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be + * one of these values. + */ +typedef enum +{ + SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */ + SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */ + SYSTEM_VALUE_MAX /**< Number of values */ +} gl_system_value; + + /** Vertex and fragment instructions */ @@ -1777,2 +1790,3 @@ struct gl_program GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */ + GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */ diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 0929b959505..786fdfbd231 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1464,2 +1464,3 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) case ir_var_inout: + case ir_var_system_value: /* The linker assigns locations for varyings and attributes, @@ -1486,2 +1487,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) } + } else if (ir->var->mode == ir_var_system_value) { + entry = new(mem_ctx) variable_storage(ir->var, + PROGRAM_SYSTEM_VALUE, + ir->var->location); } else { diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c index dd15e9a1ccd..e7553c69dbe 100644 --- a/src/mesa/program/prog_execute.c +++ b/src/mesa/program/prog_execute.c @@ -161,2 +161,6 @@ get_src_register_pointer(const struct prog_src_register *source, + case PROGRAM_SYSTEM_VALUE: + assert(reg < Elements(machine->SystemValues)); + return machine->SystemValues[reg]; + default: diff --git a/src/mesa/program/prog_execute.h b/src/mesa/program/prog_execute.h index cefd468c36b..cdf37082a00 100644 --- a/src/mesa/program/prog_execute.h +++ b/src/mesa/program/prog_execute.h @@ -63,2 +63,3 @@ struct gl_program_machine GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4]; + GLfloat SystemValues[SYSTEM_VALUE_MAX][4]; diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index abebf392c0a..484596af760 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -74,2 +74,4 @@ _mesa_register_file_name(gl_register_file f) return "SAMPLER"; + case PROGRAM_SYSTEM_VALUE: + return "SYSVAL"; case PROGRAM_UNDEFINED: @@ -312,2 +314,5 @@ reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode, break; + case PROGRAM_SYSTEM_VALUE: + sprintf(str, "sysvalue[%s%d]", addr, index); + break; case PROGRAM_STATE_VAR: diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index d240cab1a74..df4f5cf8b5c 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -463,2 +463,6 @@ void st_init_extensions(struct st_context *st) } + + if (screen->get_param(screen, PIPE_CAP_INSTANCED_DRAWING)) { + ctx->Extensions.ARB_draw_instanced = GL_TRUE; + } } diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index f848462310e..42f1c2017f8 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -74,2 +74,3 @@ struct st_translate { struct ureg_src samplers[PIPE_MAX_SAMPLERS]; + struct ureg_src systemValues[SYSTEM_VALUE_MAX]; @@ -106,2 +107,9 @@ struct st_translate { +/** Map Mesa's SYSTEM_VALUE_x to TGSI_SEMANTIC_x */ +static unsigned mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = { + TGSI_SEMANTIC_FACE, + TGSI_SEMANTIC_INSTANCEID +}; + + /** @@ -247,2 +255,6 @@ src_register( struct st_translate *t, + case PROGRAM_SYSTEM_VALUE: + assert(index < Elements(t->systemValues)); + return t->systemValues[index]; + default: @@ -1091,2 +1103,17 @@ st_translate_mesa_program( + /* Declare misc input registers + */ + { + GLbitfield sysInputs = program->SystemValuesRead; + unsigned numSys = 0; + for (i = 0; sysInputs; i++) { + if (sysInputs & (1 << i)) { + unsigned semName = mesa_sysval_to_semantic[i]; + t->systemValues[i] = ureg_DECL_system_value(ureg, numSys, semName, 0); + numSys++; + sysInputs &= ~(1 << i); + } + } + } + if (program->IndirectRegisterFiles & (1 << PROGRAM_TEMPORARY)) { diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index bc01646247c..6a9444216c0 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -529,2 +529,4 @@ typedef struct + GLuint CurInstance; + } TNLcontext; diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index 30f1bf323cb..bdb893eba22 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -455,2 +455,3 @@ void _tnl_draw_prims( struct gl_context *ctx, GLuint nr_bo = 0; + GLuint inst; @@ -472,11 +473,15 @@ void _tnl_draw_prims( struct gl_context *ctx, */ - bind_prims(ctx, &prim[i], this_nr_prims); - bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1, - bo, &nr_bo); - bind_indices(ctx, ib, bo, &nr_bo); + for (inst = 0; inst < prim[i].num_instances; inst++) { - TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); + bind_prims(ctx, &prim[i], this_nr_prims); + bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1, + bo, &nr_bo); + bind_indices(ctx, ib, bo, &nr_bo); - unmap_vbos(ctx, bo, nr_bo); - free_space(ctx); + tnl->CurInstance = inst; + TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); + + unmap_vbos(ctx, bo, nr_bo); + free_space(ctx); + } diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index 94372bbafbc..f5d8f7477aa 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -222,3 +222,4 @@ _tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *pr static void -init_machine(struct gl_context *ctx, struct gl_program_machine *machine) +init_machine(struct gl_context *ctx, struct gl_program_machine *machine, + GLuint instID) { @@ -258,2 +259,4 @@ init_machine(struct gl_context *ctx, struct gl_program_machine *machine) machine->Samplers = ctx->VertexProgram._Current->Base.SamplerUnits; + + machine->SystemValues[SYSTEM_VALUE_INSTANCE_ID][0] = (GLfloat) instID; } @@ -343,3 +346,3 @@ run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) - init_machine(ctx, machine); + init_machine(ctx, machine, tnl->CurInstance); |