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
This commit is contained in:
Brian Paul 2011-01-15 10:24:08 -07:00
commit 652901e95b
33 changed files with 347 additions and 23 deletions

View File

@ -437,6 +437,7 @@ generate_vs(struct draw_llvm *llvm,
LLVMBuilderRef builder,
LLVMValueRef (*outputs)[NUM_CHANNELS],
const LLVMValueRef (*inputs)[NUM_CHANNELS],
LLVMValueRef system_values_array,
LLVMValueRef context_ptr,
struct lp_build_sampler_soa *draw_sampler)
{
@ -468,6 +469,7 @@ generate_vs(struct draw_llvm *llvm,
vs_type,
NULL /*struct lp_build_mask_context *mask*/,
consts_ptr,
system_values_array,
NULL /*pos*/,
inputs,
outputs,
@ -1118,7 +1120,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
LLVMValueRef start, end, count, stride, step, io_itr;
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
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;
struct lp_build_context bld;
struct lp_build_loop_state lp_loop;
@ -1179,6 +1183,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
lp_build_context_init(&bld, llvm->gallivm, lp_type_int(32));
system_values_array = lp_build_system_values_array(gallivm, vs_info,
instance_id, NULL);
end = lp_build_add(&bld, start, count);
step = lp_build_const_int32(gallivm, max_vertices);
@ -1233,6 +1240,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
builder,
outputs,
ptr_aos,
system_values_array,
context_ptr,
sampler);
@ -1263,8 +1271,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
/* store clipmask in vertex header and positions in data */
convert_to_aos(gallivm, io, outputs, clipmask,
draw->vs.vertex_shader->info.num_outputs,
max_vertices);
vs_info->num_outputs, max_vertices);
}
lp_build_loop_end_cond(&lp_loop, end, step, LLVMIntUGE);
@ -1315,7 +1322,9 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
LLVMValueRef fetch_elts, fetch_count, stride, step, io_itr;
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
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;
struct lp_build_context bld;
struct lp_build_loop_state lp_loop;
@ -1376,6 +1385,10 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
lp_build_context_init(&bld, gallivm, lp_type_int(32));
system_values_array = lp_build_system_values_array(gallivm, vs_info,
instance_id, NULL);
step = lp_build_const_int32(gallivm, max_vertices);
/* code generated texture sampling */
@ -1438,6 +1451,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
builder,
outputs,
ptr_aos,
system_values_array,
context_ptr,
sampler);
@ -1471,8 +1485,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
* and transformed positions in data
*/
convert_to_aos(gallivm, io, outputs, clipmask,
draw->vs.vertex_shader->info.num_outputs,
max_vertices);
vs_info->num_outputs, max_vertices);
}
lp_build_loop_end_cond(&lp_loop, fetch_count, step, LLVMIntUGE);

View File

@ -99,6 +99,12 @@ vs_exec_run_linear( struct draw_vertex_shader *shader,
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
constants, const_size);
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) {
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);

View File

@ -71,6 +71,12 @@ vs_sse_prepare( struct draw_vertex_shader *base,
struct tgsi_exec_machine *machine = shader->machine;
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;
}
}

View File

@ -180,6 +180,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
struct lp_type type,
struct lp_build_mask_context *mask,
LLVMValueRef consts_ptr,
LLVMValueRef system_values_array,
const LLVMValueRef *pos,
const LLVMValueRef (*inputs)[4],
LLVMValueRef (*outputs)[4],
@ -199,4 +200,11 @@ lp_build_tgsi_aos(struct gallivm_state *gallivm,
const struct tgsi_shader_info *info);
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 */

View File

@ -157,6 +157,8 @@ struct lp_build_tgsi_soa_context
*/
LLVMValueRef inputs_array;
LLVMValueRef system_values_array;
const struct tgsi_shader_info *info;
/** bitmask indicating which register files are accessed indirectly */
unsigned indirect_files;
@ -759,6 +761,23 @@ emit_fetch(
}
break;
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:
assert(0 && "invalid src register in emit_fetch()");
return bld->base.undef;
@ -2322,6 +2341,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
struct lp_type type,
struct lp_build_mask_context *mask,
LLVMValueRef consts_ptr,
LLVMValueRef system_values_array,
const LLVMValueRef *pos,
const LLVMValueRef (*inputs)[NUM_CHANNELS],
LLVMValueRef (*outputs)[NUM_CHANNELS],
@ -2411,6 +2431,8 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
}
}
bld.system_values_array = system_values_array;
tgsi_parse_init( &parse, tokens );
while( !tgsi_parse_end_of_tokens( &parse ) ) {
@ -2512,3 +2534,54 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
FREE( bld.instructions );
}
/**
* 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;
}

View File

@ -1038,7 +1038,6 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
break;
case TGSI_FILE_INPUT:
case TGSI_FILE_SYSTEM_VALUE:
for (i = 0; i < QUAD_SIZE; i++) {
/*
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
@ -1053,6 +1052,15 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
}
break;
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:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
@ -1907,8 +1915,7 @@ exec_declaration(struct tgsi_exec_machine *mach,
const struct tgsi_full_declaration *decl)
{
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;
first = decl->Range.First;
@ -1921,6 +1928,7 @@ exec_declaration(struct tgsi_exec_machine *mach,
* ureg code to emit the right UsageMask value (WRITEMASK_X).
* Then, we could remove the tgsi_exec_machine::Face field.
*/
/* XXX make FACE a system value */
if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
uint i;
@ -1962,8 +1970,13 @@ 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);
static void

View File

@ -31,6 +31,7 @@
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
#if defined __cplusplus
extern "C" {
@ -181,6 +182,8 @@ struct tgsi_sampler
/* The maximum total number of vertices */
#define TGSI_MAX_TOTAL_VERTICES (TGSI_MAX_PRIM_VERTICES * TGSI_MAX_PRIMITIVES * PIPE_MAX_ATTRIBS)
#define TGSI_MAX_MISC_INPUTS 8
/** function call/activation record */
struct tgsi_call_record
{
@ -228,6 +231,10 @@ struct tgsi_exec_machine
struct tgsi_exec_vector Inputs[TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS];
struct tgsi_exec_vector Outputs[TGSI_MAX_TOTAL_VERTICES];
/* System values */
unsigned SysSemanticToIndex[TGSI_SEMANTIC_COUNT];
float SystemValue[TGSI_MAX_MISC_INPUTS][4];
struct tgsi_exec_vector *Addrs;
struct tgsi_exec_vector *Predicates;

View File

@ -294,7 +294,6 @@ emit_fetch(struct gen_context *gen,
case TGSI_SWIZZLE_W:
switch (reg->Register.File) {
case TGSI_FILE_INPUT:
case TGSI_FILE_SYSTEM_VALUE:
{
int offset = (reg->Register.Index * 4 + swizzle) * 16;
int offset_reg = emit_li_offset(gen, offset);
@ -302,6 +301,9 @@ emit_fetch(struct gen_context *gen,
ppc_lvx(gen->f, dst_vec, gen->inputs_reg, offset_reg);
}
break;
case TGSI_FILE_SYSTEM_VALUE:
assert(!"unhandled system value in tgsi_ppc.c");
break;
case TGSI_FILE_TEMPORARY:
if (is_ppc_vec_temporary(reg)) {
/* use PPC vec register */

View File

@ -143,7 +143,7 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
info->file_count[file]++;
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
if (file == TGSI_FILE_INPUT || file == TGSI_FILE_SYSTEM_VALUE) {
if (file == TGSI_FILE_INPUT) {
info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
info->input_interpolate[reg] = (ubyte)fulldecl->Declaration.Interpolate;
@ -151,6 +151,23 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Declaration.CylindricalWrap;
info->num_inputs++;
}
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) {
info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;

View File

@ -51,6 +51,9 @@ struct tgsi_shader_info
ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; /**< TGSI_SEMANTIC_x */
ubyte output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
ubyte num_system_values;
ubyte system_value_semantic_name[PIPE_MAX_SHADER_INPUTS];
uint file_mask[TGSI_FILE_COUNT]; /**< bitmask of declared registers */
uint file_count[TGSI_FILE_COUNT]; /**< number of declared registers */
int file_max[TGSI_FILE_COUNT]; /**< highest index of declared registers */
@ -64,6 +67,7 @@ struct tgsi_shader_info
boolean writes_stencil; /**< does fragment shader write stencil value? */
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
boolean uses_kill; /**< KIL or KILP instruction used? */
boolean uses_instanceid;
/**
* Bitmask indicating which register files are accessed with

View File

@ -163,6 +163,14 @@ get_immediate_base( void )
reg_DX );
}
static struct x86_reg
get_system_value_base( void )
{
return x86_make_disp(
get_machine_base(),
Offset(struct tgsi_exec_machine, SystemValue) );
}
/**
* Data access helpers.
@ -228,6 +236,16 @@ get_temp(
(vec * 4 + chan) * 16 );
}
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(
unsigned vec,
@ -422,6 +440,30 @@ emit_tempf(
get_temp( vec, chan ) );
}
/**
* 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)
* \param xmm the destination xmm register
@ -1281,8 +1323,15 @@ emit_fetch(
swizzle );
break;
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(
func,
xmm,
@ -2636,8 +2685,7 @@ emit_declaration(
struct x86_function *func,
struct tgsi_full_declaration *decl )
{
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;
unsigned i, j;

View File

@ -36,6 +36,7 @@ The integer capabilities:
bound.
* ``OCCLUSION_QUERY``: Whether occlusion queries are available.
* ``TIMER_QUERY``: Whether timer queries are available.
* ``INSTANCED_DRAWING``: indicates support for instanced drawing.
* ``TEXTURE_SHADOW_MAP``: indicates whether the fragment shader hardware
can do the depth texture / Z comparison operation in TEX instructions
for shadow testing.

View File

@ -164,6 +164,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 1;
case PIPE_CAP_DEPTH_CLAMP:
return 0;
case PIPE_CAP_INSTANCED_DRAWING:
return 1;
default:
return 0;
}

View File

@ -334,7 +334,8 @@ generate_fs(struct gallivm_state *gallivm,
/* Build the actual shader */
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);
/* Alpha test */

View File

@ -123,6 +123,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 0;
case PIPE_CAP_SHADER_STENCIL_EXPORT:
return 1;
case PIPE_CAP_INSTANCED_DRAWING:
return 1;
default:
return 0;
}

View File

@ -462,6 +462,7 @@ enum pipe_cap {
PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER,
PIPE_CAP_DEPTH_CLAMP,
PIPE_CAP_SHADER_STENCIL_EXPORT,
PIPE_CAP_INSTANCED_DRAWING,
};
/* Shader caps not specific to any single stage */

View File

@ -180,6 +180,15 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
state->ARB_draw_buffers_enable = (ext_mode != extension_disable);
state->ARB_draw_buffers_warn = (ext_mode == extension_warn);
}
} 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) {
state->ARB_explicit_attrib_location_enable =
(ext_mode != extension_disable);

View File

@ -132,6 +132,8 @@ struct _mesa_glsl_parse_state {
/*@{*/
unsigned ARB_draw_buffers_enable:1;
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;
unsigned ARB_explicit_attrib_location_warn:1;
unsigned ARB_fragment_coord_conventions_enable:1;

View File

@ -225,6 +225,7 @@ enum ir_variable_mode {
ir_var_in,
ir_var_out,
ir_var_inout,
ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
ir_var_temporary /**< Temporary variable generated during compilation. */
};

View File

@ -79,6 +79,8 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len)
for (int i = 0; i < len; i++) {
if (var->mode == ir_var_in)
prog->InputsRead |= BITFIELD64_BIT(var->location + offset + i);
else if (var->mode == ir_var_system_value)
prog->SystemValuesRead |= (1 << (var->location + offset + i));
else
prog->OutputsWritten |= BITFIELD64_BIT(var->location + offset + i);
}
@ -134,7 +136,8 @@ ir_visitor_status
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);
}
@ -158,5 +161,6 @@ do_set_program_inouts(exec_list *instructions, struct gl_program *prog)
prog->InputsRead = 0;
prog->OutputsWritten = 0;
prog->SystemValuesRead = 0;
visit_list_elements(&v, instructions);
}

View File

@ -30,6 +30,11 @@ static void generate_ARB_draw_buffers_variables(exec_list *,
struct _mesa_glsl_parse_state *,
bool, _mesa_glsl_parser_targets);
static void
generate_ARB_draw_instanced_variables(exec_list *,
struct _mesa_glsl_parse_state *,
bool, _mesa_glsl_parser_targets);
static ir_variable *
add_variable(const char *name, enum ir_variable_mode mode, int slot,
const glsl_type *type, exec_list *instructions,
@ -41,6 +46,7 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot,
case ir_var_auto:
case ir_var_in:
case ir_var_uniform:
case ir_var_system_value:
var->read_only = true;
break;
case ir_var_inout:
@ -324,8 +330,13 @@ initialize_vs_variables(exec_list *instructions,
generate_130_vs_variables(instructions, state);
break;
}
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. */
static void
generate_100ES_fs_variables(exec_list *instructions,
@ -422,6 +433,27 @@ 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
generate_ARB_shader_stencil_export_variables(exec_list *instructions,
struct _mesa_glsl_parse_state *state,

View File

@ -73,6 +73,7 @@ initialize_context(struct gl_context *ctx, gl_api api)
ctx->API = api;
ctx->Extensions.ARB_draw_buffers = GL_TRUE;
ctx->Extensions.ARB_draw_instanced = GL_TRUE;
ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
ctx->Extensions.EXT_texture_array = GL_TRUE;
ctx->Extensions.NV_texture_rectangle = GL_TRUE;

View File

@ -380,6 +380,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx)
ctx->Extensions.ARB_depth_texture = GL_TRUE;
/*ctx->Extensions.ARB_draw_buffers = GL_TRUE;*/
ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE;
ctx->Extensions.ARB_draw_instanced = GL_TRUE;
ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE;
ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
#if FEATURE_ARB_fragment_program

View File

@ -1748,11 +1748,24 @@ typedef enum
PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
PROGRAM_ADDRESS, /**< machine->AddressReg */
PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */
PROGRAM_UNDEFINED, /**< Invalid/TBD value */
PROGRAM_FILE_MAX
} gl_register_file;
/**
* 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 */
struct prog_instruction;
struct gl_program_parameter_list;
@ -1775,6 +1788,7 @@ struct gl_program
GLbitfield InputsRead; /**< Bitmask of which input regs are read */
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 */
GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */

View File

@ -1462,6 +1462,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
case ir_var_in:
case ir_var_out:
case ir_var_inout:
case ir_var_system_value:
/* The linker assigns locations for varyings and attributes,
* including deprecated builtins (like gl_Color), user-assign
* generic attributes (glBindVertexLocation), and
@ -1484,6 +1485,10 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
ir->var->type->gl_type,
ir->var->location - VERT_ATTRIB_GENERIC0);
}
} else if (ir->var->mode == ir_var_system_value) {
entry = new(mem_ctx) variable_storage(ir->var,
PROGRAM_SYSTEM_VALUE,
ir->var->location);
} else {
entry = new(mem_ctx) variable_storage(ir->var,
PROGRAM_OUTPUT,

View File

@ -159,6 +159,10 @@ get_src_register_pointer(const struct prog_src_register *source,
return ZeroVec;
return prog->Parameters->ParameterValues[reg];
case PROGRAM_SYSTEM_VALUE:
assert(reg < Elements(machine->SystemValues));
return machine->SystemValues[reg];
default:
_mesa_problem(NULL,
"Invalid src register file %d in get_src_register_pointer()",

View File

@ -61,6 +61,7 @@ struct gl_program_machine
GLfloat (*EnvParams)[4]; /**< Vertex or Fragment env parameters */
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4];
GLfloat SystemValues[SYSTEM_VALUE_MAX][4];
const GLubyte *Samplers; /** Array mapping sampler var to tex unit */

View File

@ -72,6 +72,8 @@ _mesa_register_file_name(gl_register_file f)
return "ADDR";
case PROGRAM_SAMPLER:
return "SAMPLER";
case PROGRAM_SYSTEM_VALUE:
return "SYSVAL";
case PROGRAM_UNDEFINED:
return "UNDEFINED";
default:
@ -310,6 +312,9 @@ reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode,
case PROGRAM_UNIFORM: /* extension */
sprintf(str, "uniform[%s%d]", addr, index);
break;
case PROGRAM_SYSTEM_VALUE:
sprintf(str, "sysvalue[%s%d]", addr, index);
break;
case PROGRAM_STATE_VAR:
{
struct gl_program_parameter *param

View File

@ -461,4 +461,8 @@ void st_init_extensions(struct st_context *st)
if (screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) {
ctx->Extensions.ARB_shader_stencil_export = GL_TRUE;
}
if (screen->get_param(screen, PIPE_CAP_INSTANCED_DRAWING)) {
ctx->Extensions.ARB_draw_instanced = GL_TRUE;
}
}

View File

@ -72,6 +72,7 @@ struct st_translate {
struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
struct ureg_dst address[1];
struct ureg_src samplers[PIPE_MAX_SAMPLERS];
struct ureg_src systemValues[SYSTEM_VALUE_MAX];
/* Extra info for handling point size clamping in vertex shader */
struct ureg_dst pointSizeResult; /**< Actual point size output register */
@ -104,6 +105,13 @@ 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
};
/**
* Make note of a branch to a label in the TGSI code.
* After we've emitted all instructions, we'll go over the list
@ -245,6 +253,10 @@ src_register( struct st_translate *t,
case PROGRAM_ADDRESS:
return ureg_src(t->address[index]);
case PROGRAM_SYSTEM_VALUE:
assert(index < Elements(t->systemValues));
return t->systemValues[index];
default:
debug_assert( 0 );
return ureg_src_undef();
@ -1089,6 +1101,21 @@ st_translate_mesa_program(
t->address[0] = ureg_DECL_address( ureg );
}
/* 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)) {
/* If temps are accessed with indirect addressing, declare temporaries
* in sequential order. Else, we declare them on demand elsewhere.

View File

@ -527,6 +527,8 @@ typedef struct
GLubyte *block[VERT_ATTRIB_MAX];
GLuint nr_blocks;
GLuint CurInstance;
} TNLcontext;

View File

@ -453,6 +453,7 @@ void _tnl_draw_prims( struct gl_context *ctx,
*/
struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
GLuint nr_bo = 0;
GLuint inst;
for (i = 0; i < nr_prims;) {
GLuint this_nr_prims;
@ -470,15 +471,19 @@ void _tnl_draw_prims( struct gl_context *ctx,
/* Binding inputs may imply mapping some vertex buffer objects.
* They will need to be unmapped below.
*/
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);
}
i += this_nr_prims;
}

View File

@ -220,7 +220,8 @@ _tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *pr
* Initialize virtual machine state prior to executing vertex program.
*/
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)
{
/* Input registers get initialized from the current vertex attribs */
memcpy(machine->VertAttribs, ctx->Current.Attrib,
@ -256,6 +257,8 @@ init_machine(struct gl_context *ctx, struct gl_program_machine *machine)
machine->FetchTexelDeriv = NULL; /* not used by vertex programs */
machine->Samplers = ctx->VertexProgram._Current->Base.SamplerUnits;
machine->SystemValues[SYSTEM_VALUE_INSTANCE_ID][0] = (GLfloat) instID;
}
@ -341,7 +344,7 @@ run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage )
for (i = 0; i < VB->Count; i++) {
GLuint attr;
init_machine(ctx, machine);
init_machine(ctx, machine, tnl->CurInstance);
#if 0
printf("Input %d: %f, %f, %f, %f\n", i,