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:
@@ -437,6 +437,7 @@ generate_vs(struct draw_llvm *llvm,
|
|||||||
LLVMBuilderRef builder,
|
LLVMBuilderRef builder,
|
||||||
LLVMValueRef (*outputs)[NUM_CHANNELS],
|
LLVMValueRef (*outputs)[NUM_CHANNELS],
|
||||||
const LLVMValueRef (*inputs)[NUM_CHANNELS],
|
const LLVMValueRef (*inputs)[NUM_CHANNELS],
|
||||||
|
LLVMValueRef system_values_array,
|
||||||
LLVMValueRef context_ptr,
|
LLVMValueRef context_ptr,
|
||||||
struct lp_build_sampler_soa *draw_sampler)
|
struct lp_build_sampler_soa *draw_sampler)
|
||||||
{
|
{
|
||||||
@@ -468,6 +469,7 @@ generate_vs(struct draw_llvm *llvm,
|
|||||||
vs_type,
|
vs_type,
|
||||||
NULL /*struct lp_build_mask_context *mask*/,
|
NULL /*struct lp_build_mask_context *mask*/,
|
||||||
consts_ptr,
|
consts_ptr,
|
||||||
|
system_values_array,
|
||||||
NULL /*pos*/,
|
NULL /*pos*/,
|
||||||
inputs,
|
inputs,
|
||||||
outputs,
|
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 start, end, count, stride, step, io_itr;
|
||||||
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
|
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
|
||||||
LLVMValueRef instance_id;
|
LLVMValueRef instance_id;
|
||||||
|
LLVMValueRef system_values_array;
|
||||||
struct draw_context *draw = llvm->draw;
|
struct draw_context *draw = llvm->draw;
|
||||||
|
const struct tgsi_shader_info *vs_info = &draw->vs.vertex_shader->info;
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
struct lp_build_context bld;
|
struct lp_build_context bld;
|
||||||
struct lp_build_loop_state lp_loop;
|
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));
|
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);
|
end = lp_build_add(&bld, start, count);
|
||||||
|
|
||||||
step = lp_build_const_int32(gallivm, max_vertices);
|
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,
|
builder,
|
||||||
outputs,
|
outputs,
|
||||||
ptr_aos,
|
ptr_aos,
|
||||||
|
system_values_array,
|
||||||
context_ptr,
|
context_ptr,
|
||||||
sampler);
|
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 */
|
/* store clipmask in vertex header and positions in data */
|
||||||
convert_to_aos(gallivm, io, outputs, clipmask,
|
convert_to_aos(gallivm, io, outputs, clipmask,
|
||||||
draw->vs.vertex_shader->info.num_outputs,
|
vs_info->num_outputs, max_vertices);
|
||||||
max_vertices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_build_loop_end_cond(&lp_loop, end, step, LLVMIntUGE);
|
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 fetch_elts, fetch_count, stride, step, io_itr;
|
||||||
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
|
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
|
||||||
LLVMValueRef instance_id;
|
LLVMValueRef instance_id;
|
||||||
|
LLVMValueRef system_values_array;
|
||||||
struct draw_context *draw = llvm->draw;
|
struct draw_context *draw = llvm->draw;
|
||||||
|
const struct tgsi_shader_info *vs_info = &draw->vs.vertex_shader->info;
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
struct lp_build_context bld;
|
struct lp_build_context bld;
|
||||||
struct lp_build_loop_state lp_loop;
|
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));
|
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);
|
step = lp_build_const_int32(gallivm, max_vertices);
|
||||||
|
|
||||||
/* code generated texture sampling */
|
/* code generated texture sampling */
|
||||||
@@ -1438,6 +1451,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
|
|||||||
builder,
|
builder,
|
||||||
outputs,
|
outputs,
|
||||||
ptr_aos,
|
ptr_aos,
|
||||||
|
system_values_array,
|
||||||
context_ptr,
|
context_ptr,
|
||||||
sampler);
|
sampler);
|
||||||
|
|
||||||
@@ -1471,8 +1485,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
|
|||||||
* and transformed positions in data
|
* and transformed positions in data
|
||||||
*/
|
*/
|
||||||
convert_to_aos(gallivm, io, outputs, clipmask,
|
convert_to_aos(gallivm, io, outputs, clipmask,
|
||||||
draw->vs.vertex_shader->info.num_outputs,
|
vs_info->num_outputs, max_vertices);
|
||||||
max_vertices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_build_loop_end_cond(&lp_loop, fetch_count, step, LLVMIntUGE);
|
lp_build_loop_end_cond(&lp_loop, fetch_count, step, LLVMIntUGE);
|
||||||
|
@@ -99,6 +99,12 @@ vs_exec_run_linear( struct draw_vertex_shader *shader,
|
|||||||
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
|
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
|
||||||
constants, const_size);
|
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) {
|
for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
|
||||||
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
|
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
|
||||||
|
|
||||||
|
@@ -71,6 +71,12 @@ vs_sse_prepare( struct draw_vertex_shader *base,
|
|||||||
struct tgsi_exec_machine *machine = shader->machine;
|
struct tgsi_exec_machine *machine = shader->machine;
|
||||||
|
|
||||||
machine->Samplers = draw->vs.samplers;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -180,6 +180,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
|
|||||||
struct lp_type type,
|
struct lp_type type,
|
||||||
struct lp_build_mask_context *mask,
|
struct lp_build_mask_context *mask,
|
||||||
LLVMValueRef consts_ptr,
|
LLVMValueRef consts_ptr,
|
||||||
|
LLVMValueRef system_values_array,
|
||||||
const LLVMValueRef *pos,
|
const LLVMValueRef *pos,
|
||||||
const LLVMValueRef (*inputs)[4],
|
const LLVMValueRef (*inputs)[4],
|
||||||
LLVMValueRef (*outputs)[4],
|
LLVMValueRef (*outputs)[4],
|
||||||
@@ -199,4 +200,11 @@ lp_build_tgsi_aos(struct gallivm_state *gallivm,
|
|||||||
const struct tgsi_shader_info *info);
|
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 */
|
#endif /* LP_BLD_TGSI_H */
|
||||||
|
@@ -157,6 +157,8 @@ struct lp_build_tgsi_soa_context
|
|||||||
*/
|
*/
|
||||||
LLVMValueRef inputs_array;
|
LLVMValueRef inputs_array;
|
||||||
|
|
||||||
|
LLVMValueRef system_values_array;
|
||||||
|
|
||||||
const struct tgsi_shader_info *info;
|
const struct tgsi_shader_info *info;
|
||||||
/** bitmask indicating which register files are accessed indirectly */
|
/** bitmask indicating which register files are accessed indirectly */
|
||||||
unsigned indirect_files;
|
unsigned indirect_files;
|
||||||
@@ -759,6 +761,23 @@ emit_fetch(
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
assert(0 && "invalid src register in emit_fetch()");
|
assert(0 && "invalid src register in emit_fetch()");
|
||||||
return bld->base.undef;
|
return bld->base.undef;
|
||||||
@@ -2322,6 +2341,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
|
|||||||
struct lp_type type,
|
struct lp_type type,
|
||||||
struct lp_build_mask_context *mask,
|
struct lp_build_mask_context *mask,
|
||||||
LLVMValueRef consts_ptr,
|
LLVMValueRef consts_ptr,
|
||||||
|
LLVMValueRef system_values_array,
|
||||||
const LLVMValueRef *pos,
|
const LLVMValueRef *pos,
|
||||||
const LLVMValueRef (*inputs)[NUM_CHANNELS],
|
const LLVMValueRef (*inputs)[NUM_CHANNELS],
|
||||||
LLVMValueRef (*outputs)[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 );
|
tgsi_parse_init( &parse, tokens );
|
||||||
|
|
||||||
while( !tgsi_parse_end_of_tokens( &parse ) ) {
|
while( !tgsi_parse_end_of_tokens( &parse ) ) {
|
||||||
@@ -2512,3 +2534,54 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
|
|||||||
FREE( bld.instructions );
|
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;
|
||||||
|
}
|
||||||
|
@@ -1038,7 +1038,6 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TGSI_FILE_INPUT:
|
case TGSI_FILE_INPUT:
|
||||||
case TGSI_FILE_SYSTEM_VALUE:
|
|
||||||
for (i = 0; i < QUAD_SIZE; i++) {
|
for (i = 0; i < QUAD_SIZE; i++) {
|
||||||
/*
|
/*
|
||||||
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
|
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
|
||||||
@@ -1053,6 +1052,15 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case TGSI_FILE_TEMPORARY:
|
||||||
for (i = 0; i < QUAD_SIZE; i++) {
|
for (i = 0; i < QUAD_SIZE; i++) {
|
||||||
assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
|
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)
|
const struct tgsi_full_declaration *decl)
|
||||||
{
|
{
|
||||||
if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
|
if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
|
||||||
if (decl->Declaration.File == TGSI_FILE_INPUT ||
|
if (decl->Declaration.File == TGSI_FILE_INPUT) {
|
||||||
decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) {
|
|
||||||
uint first, last, mask;
|
uint first, last, mask;
|
||||||
|
|
||||||
first = decl->Range.First;
|
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).
|
* ureg code to emit the right UsageMask value (WRITEMASK_X).
|
||||||
* Then, we could remove the tgsi_exec_machine::Face field.
|
* Then, we could remove the tgsi_exec_machine::Face field.
|
||||||
*/
|
*/
|
||||||
|
/* XXX make FACE a system value */
|
||||||
if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
|
if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
|
||||||
uint i;
|
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);
|
typedef void (* micro_op)(union tgsi_exec_channel *dst);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "pipe/p_compiler.h"
|
#include "pipe/p_compiler.h"
|
||||||
#include "pipe/p_state.h"
|
#include "pipe/p_state.h"
|
||||||
|
#include "pipe/p_shader_tokens.h"
|
||||||
|
|
||||||
#if defined __cplusplus
|
#if defined __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -181,6 +182,8 @@ struct tgsi_sampler
|
|||||||
/* The maximum total number of vertices */
|
/* The maximum total number of vertices */
|
||||||
#define TGSI_MAX_TOTAL_VERTICES (TGSI_MAX_PRIM_VERTICES * TGSI_MAX_PRIMITIVES * PIPE_MAX_ATTRIBS)
|
#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 */
|
/** function call/activation record */
|
||||||
struct tgsi_call_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 Inputs[TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS];
|
||||||
struct tgsi_exec_vector Outputs[TGSI_MAX_TOTAL_VERTICES];
|
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 *Addrs;
|
||||||
struct tgsi_exec_vector *Predicates;
|
struct tgsi_exec_vector *Predicates;
|
||||||
|
|
||||||
|
@@ -294,7 +294,6 @@ emit_fetch(struct gen_context *gen,
|
|||||||
case TGSI_SWIZZLE_W:
|
case TGSI_SWIZZLE_W:
|
||||||
switch (reg->Register.File) {
|
switch (reg->Register.File) {
|
||||||
case TGSI_FILE_INPUT:
|
case TGSI_FILE_INPUT:
|
||||||
case TGSI_FILE_SYSTEM_VALUE:
|
|
||||||
{
|
{
|
||||||
int offset = (reg->Register.Index * 4 + swizzle) * 16;
|
int offset = (reg->Register.Index * 4 + swizzle) * 16;
|
||||||
int offset_reg = emit_li_offset(gen, offset);
|
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);
|
ppc_lvx(gen->f, dst_vec, gen->inputs_reg, offset_reg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TGSI_FILE_SYSTEM_VALUE:
|
||||||
|
assert(!"unhandled system value in tgsi_ppc.c");
|
||||||
|
break;
|
||||||
case TGSI_FILE_TEMPORARY:
|
case TGSI_FILE_TEMPORARY:
|
||||||
if (is_ppc_vec_temporary(reg)) {
|
if (is_ppc_vec_temporary(reg)) {
|
||||||
/* use PPC vec register */
|
/* use PPC vec register */
|
||||||
|
@@ -143,7 +143,7 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
|
|||||||
info->file_count[file]++;
|
info->file_count[file]++;
|
||||||
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
|
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_name[reg] = (ubyte)fulldecl->Semantic.Name;
|
||||||
info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
|
info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
|
||||||
info->input_interpolate[reg] = (ubyte)fulldecl->Declaration.Interpolate;
|
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->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Declaration.CylindricalWrap;
|
||||||
info->num_inputs++;
|
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) {
|
else if (file == TGSI_FILE_OUTPUT) {
|
||||||
info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
|
info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
|
||||||
info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
|
info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
|
||||||
|
@@ -51,6 +51,9 @@ struct tgsi_shader_info
|
|||||||
ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; /**< TGSI_SEMANTIC_x */
|
ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; /**< TGSI_SEMANTIC_x */
|
||||||
ubyte output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
|
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_mask[TGSI_FILE_COUNT]; /**< bitmask of declared registers */
|
||||||
uint file_count[TGSI_FILE_COUNT]; /**< number of declared registers */
|
uint file_count[TGSI_FILE_COUNT]; /**< number of declared registers */
|
||||||
int file_max[TGSI_FILE_COUNT]; /**< highest index 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_stencil; /**< does fragment shader write stencil value? */
|
||||||
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
|
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
|
||||||
boolean uses_kill; /**< KIL or KILP instruction used? */
|
boolean uses_kill; /**< KIL or KILP instruction used? */
|
||||||
|
boolean uses_instanceid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bitmask indicating which register files are accessed with
|
* Bitmask indicating which register files are accessed with
|
||||||
|
@@ -163,6 +163,14 @@ get_immediate_base( void )
|
|||||||
reg_DX );
|
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.
|
* Data access helpers.
|
||||||
@@ -228,6 +236,16 @@ get_temp(
|
|||||||
(vec * 4 + chan) * 16 );
|
(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
|
static struct x86_reg
|
||||||
get_coef(
|
get_coef(
|
||||||
unsigned vec,
|
unsigned vec,
|
||||||
@@ -422,6 +440,30 @@ emit_tempf(
|
|||||||
get_temp( vec, chan ) );
|
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)
|
* Load an xmm register with an input attrib coefficient (a0, dadx or dady)
|
||||||
* \param xmm the destination xmm register
|
* \param xmm the destination xmm register
|
||||||
@@ -1281,8 +1323,15 @@ emit_fetch(
|
|||||||
swizzle );
|
swizzle );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TGSI_FILE_INPUT:
|
|
||||||
case TGSI_FILE_SYSTEM_VALUE:
|
case TGSI_FILE_SYSTEM_VALUE:
|
||||||
|
emit_system_value(
|
||||||
|
func,
|
||||||
|
xmm,
|
||||||
|
reg->Register.Index,
|
||||||
|
swizzle );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TGSI_FILE_INPUT:
|
||||||
emit_inputf(
|
emit_inputf(
|
||||||
func,
|
func,
|
||||||
xmm,
|
xmm,
|
||||||
@@ -2636,8 +2685,7 @@ emit_declaration(
|
|||||||
struct x86_function *func,
|
struct x86_function *func,
|
||||||
struct tgsi_full_declaration *decl )
|
struct tgsi_full_declaration *decl )
|
||||||
{
|
{
|
||||||
if( decl->Declaration.File == TGSI_FILE_INPUT ||
|
if( decl->Declaration.File == TGSI_FILE_INPUT ) {
|
||||||
decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE ) {
|
|
||||||
unsigned first, last, mask;
|
unsigned first, last, mask;
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@ The integer capabilities:
|
|||||||
bound.
|
bound.
|
||||||
* ``OCCLUSION_QUERY``: Whether occlusion queries are available.
|
* ``OCCLUSION_QUERY``: Whether occlusion queries are available.
|
||||||
* ``TIMER_QUERY``: Whether timer 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
|
* ``TEXTURE_SHADOW_MAP``: indicates whether the fragment shader hardware
|
||||||
can do the depth texture / Z comparison operation in TEX instructions
|
can do the depth texture / Z comparison operation in TEX instructions
|
||||||
for shadow testing.
|
for shadow testing.
|
||||||
|
@@ -164,6 +164,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
|||||||
return 1;
|
return 1;
|
||||||
case PIPE_CAP_DEPTH_CLAMP:
|
case PIPE_CAP_DEPTH_CLAMP:
|
||||||
return 0;
|
return 0;
|
||||||
|
case PIPE_CAP_INSTANCED_DRAWING:
|
||||||
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -334,7 +334,8 @@ generate_fs(struct gallivm_state *gallivm,
|
|||||||
|
|
||||||
/* Build the actual shader */
|
/* Build the actual shader */
|
||||||
lp_build_tgsi_soa(gallivm, tokens, type, &mask,
|
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);
|
outputs, sampler, &shader->info.base);
|
||||||
|
|
||||||
/* Alpha test */
|
/* Alpha test */
|
||||||
|
@@ -123,6 +123,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
|||||||
return 0;
|
return 0;
|
||||||
case PIPE_CAP_SHADER_STENCIL_EXPORT:
|
case PIPE_CAP_SHADER_STENCIL_EXPORT:
|
||||||
return 1;
|
return 1;
|
||||||
|
case PIPE_CAP_INSTANCED_DRAWING:
|
||||||
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -462,6 +462,7 @@ enum pipe_cap {
|
|||||||
PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER,
|
PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER,
|
||||||
PIPE_CAP_DEPTH_CLAMP,
|
PIPE_CAP_DEPTH_CLAMP,
|
||||||
PIPE_CAP_SHADER_STENCIL_EXPORT,
|
PIPE_CAP_SHADER_STENCIL_EXPORT,
|
||||||
|
PIPE_CAP_INSTANCED_DRAWING,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Shader caps not specific to any single stage */
|
/* Shader caps not specific to any single stage */
|
||||||
|
@@ -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_enable = (ext_mode != extension_disable);
|
||||||
state->ARB_draw_buffers_warn = (ext_mode == extension_warn);
|
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) {
|
} else if (strcmp(name, "GL_ARB_explicit_attrib_location") == 0) {
|
||||||
state->ARB_explicit_attrib_location_enable =
|
state->ARB_explicit_attrib_location_enable =
|
||||||
(ext_mode != extension_disable);
|
(ext_mode != extension_disable);
|
||||||
|
@@ -132,6 +132,8 @@ struct _mesa_glsl_parse_state {
|
|||||||
/*@{*/
|
/*@{*/
|
||||||
unsigned ARB_draw_buffers_enable:1;
|
unsigned ARB_draw_buffers_enable:1;
|
||||||
unsigned ARB_draw_buffers_warn: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_enable:1;
|
||||||
unsigned ARB_explicit_attrib_location_warn:1;
|
unsigned ARB_explicit_attrib_location_warn:1;
|
||||||
unsigned ARB_fragment_coord_conventions_enable:1;
|
unsigned ARB_fragment_coord_conventions_enable:1;
|
||||||
|
@@ -225,6 +225,7 @@ enum ir_variable_mode {
|
|||||||
ir_var_in,
|
ir_var_in,
|
||||||
ir_var_out,
|
ir_var_out,
|
||||||
ir_var_inout,
|
ir_var_inout,
|
||||||
|
ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
|
||||||
ir_var_temporary /**< Temporary variable generated during compilation. */
|
ir_var_temporary /**< Temporary variable generated during compilation. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -79,6 +79,8 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len)
|
|||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (var->mode == ir_var_in)
|
if (var->mode == ir_var_in)
|
||||||
prog->InputsRead |= BITFIELD64_BIT(var->location + offset + i);
|
prog->InputsRead |= BITFIELD64_BIT(var->location + offset + i);
|
||||||
|
else if (var->mode == ir_var_system_value)
|
||||||
|
prog->SystemValuesRead |= (1 << (var->location + offset + i));
|
||||||
else
|
else
|
||||||
prog->OutputsWritten |= BITFIELD64_BIT(var->location + offset + i);
|
prog->OutputsWritten |= BITFIELD64_BIT(var->location + offset + i);
|
||||||
}
|
}
|
||||||
@@ -134,7 +136,8 @@ ir_visitor_status
|
|||||||
ir_set_program_inouts_visitor::visit(ir_variable *ir)
|
ir_set_program_inouts_visitor::visit(ir_variable *ir)
|
||||||
{
|
{
|
||||||
if (ir->mode == ir_var_in ||
|
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);
|
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->InputsRead = 0;
|
||||||
prog->OutputsWritten = 0;
|
prog->OutputsWritten = 0;
|
||||||
|
prog->SystemValuesRead = 0;
|
||||||
visit_list_elements(&v, instructions);
|
visit_list_elements(&v, instructions);
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,11 @@ static void generate_ARB_draw_buffers_variables(exec_list *,
|
|||||||
struct _mesa_glsl_parse_state *,
|
struct _mesa_glsl_parse_state *,
|
||||||
bool, _mesa_glsl_parser_targets);
|
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 *
|
static ir_variable *
|
||||||
add_variable(const char *name, enum ir_variable_mode mode, int slot,
|
add_variable(const char *name, enum ir_variable_mode mode, int slot,
|
||||||
const glsl_type *type, exec_list *instructions,
|
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_auto:
|
||||||
case ir_var_in:
|
case ir_var_in:
|
||||||
case ir_var_uniform:
|
case ir_var_uniform:
|
||||||
|
case ir_var_system_value:
|
||||||
var->read_only = true;
|
var->read_only = true;
|
||||||
break;
|
break;
|
||||||
case ir_var_inout:
|
case ir_var_inout:
|
||||||
@@ -324,8 +330,13 @@ initialize_vs_variables(exec_list *instructions,
|
|||||||
generate_130_vs_variables(instructions, state);
|
generate_130_vs_variables(instructions, state);
|
||||||
break;
|
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. */
|
/* This function should only be called for ES, not desktop GL. */
|
||||||
static void
|
static void
|
||||||
generate_100ES_fs_variables(exec_list *instructions,
|
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
|
static void
|
||||||
generate_ARB_shader_stencil_export_variables(exec_list *instructions,
|
generate_ARB_shader_stencil_export_variables(exec_list *instructions,
|
||||||
struct _mesa_glsl_parse_state *state,
|
struct _mesa_glsl_parse_state *state,
|
||||||
|
@@ -73,6 +73,7 @@ initialize_context(struct gl_context *ctx, gl_api api)
|
|||||||
ctx->API = api;
|
ctx->API = api;
|
||||||
|
|
||||||
ctx->Extensions.ARB_draw_buffers = GL_TRUE;
|
ctx->Extensions.ARB_draw_buffers = GL_TRUE;
|
||||||
|
ctx->Extensions.ARB_draw_instanced = GL_TRUE;
|
||||||
ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
|
ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
|
||||||
ctx->Extensions.EXT_texture_array = GL_TRUE;
|
ctx->Extensions.EXT_texture_array = GL_TRUE;
|
||||||
ctx->Extensions.NV_texture_rectangle = GL_TRUE;
|
ctx->Extensions.NV_texture_rectangle = GL_TRUE;
|
||||||
|
@@ -380,6 +380,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx)
|
|||||||
ctx->Extensions.ARB_depth_texture = GL_TRUE;
|
ctx->Extensions.ARB_depth_texture = GL_TRUE;
|
||||||
/*ctx->Extensions.ARB_draw_buffers = GL_TRUE;*/
|
/*ctx->Extensions.ARB_draw_buffers = GL_TRUE;*/
|
||||||
ctx->Extensions.ARB_draw_elements_base_vertex = 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_explicit_attrib_location = GL_TRUE;
|
||||||
ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
|
ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
|
||||||
#if FEATURE_ARB_fragment_program
|
#if FEATURE_ARB_fragment_program
|
||||||
|
@@ -1748,11 +1748,24 @@ typedef enum
|
|||||||
PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
|
PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
|
||||||
PROGRAM_ADDRESS, /**< machine->AddressReg */
|
PROGRAM_ADDRESS, /**< machine->AddressReg */
|
||||||
PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
|
PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
|
||||||
|
PROGRAM_SYSTEM_VALUE,/**< InstanceId, PrimitiveID, etc. */
|
||||||
PROGRAM_UNDEFINED, /**< Invalid/TBD value */
|
PROGRAM_UNDEFINED, /**< Invalid/TBD value */
|
||||||
PROGRAM_FILE_MAX
|
PROGRAM_FILE_MAX
|
||||||
} gl_register_file;
|
} 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 */
|
/** Vertex and fragment instructions */
|
||||||
struct prog_instruction;
|
struct prog_instruction;
|
||||||
struct gl_program_parameter_list;
|
struct gl_program_parameter_list;
|
||||||
@@ -1775,6 +1788,7 @@ struct gl_program
|
|||||||
|
|
||||||
GLbitfield InputsRead; /**< Bitmask of which input regs are read */
|
GLbitfield InputsRead; /**< Bitmask of which input regs are read */
|
||||||
GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
|
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 InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
|
||||||
GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
|
GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
|
||||||
GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */
|
GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */
|
||||||
|
@@ -1462,6 +1462,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
|
|||||||
case ir_var_in:
|
case ir_var_in:
|
||||||
case ir_var_out:
|
case ir_var_out:
|
||||||
case ir_var_inout:
|
case ir_var_inout:
|
||||||
|
case ir_var_system_value:
|
||||||
/* The linker assigns locations for varyings and attributes,
|
/* The linker assigns locations for varyings and attributes,
|
||||||
* including deprecated builtins (like gl_Color), user-assign
|
* including deprecated builtins (like gl_Color), user-assign
|
||||||
* generic attributes (glBindVertexLocation), and
|
* generic attributes (glBindVertexLocation), and
|
||||||
@@ -1484,6 +1485,10 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
|
|||||||
ir->var->type->gl_type,
|
ir->var->type->gl_type,
|
||||||
ir->var->location - VERT_ATTRIB_GENERIC0);
|
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 {
|
} else {
|
||||||
entry = new(mem_ctx) variable_storage(ir->var,
|
entry = new(mem_ctx) variable_storage(ir->var,
|
||||||
PROGRAM_OUTPUT,
|
PROGRAM_OUTPUT,
|
||||||
|
@@ -159,6 +159,10 @@ get_src_register_pointer(const struct prog_src_register *source,
|
|||||||
return ZeroVec;
|
return ZeroVec;
|
||||||
return prog->Parameters->ParameterValues[reg];
|
return prog->Parameters->ParameterValues[reg];
|
||||||
|
|
||||||
|
case PROGRAM_SYSTEM_VALUE:
|
||||||
|
assert(reg < Elements(machine->SystemValues));
|
||||||
|
return machine->SystemValues[reg];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_mesa_problem(NULL,
|
_mesa_problem(NULL,
|
||||||
"Invalid src register file %d in get_src_register_pointer()",
|
"Invalid src register file %d in get_src_register_pointer()",
|
||||||
|
@@ -61,6 +61,7 @@ struct gl_program_machine
|
|||||||
GLfloat (*EnvParams)[4]; /**< Vertex or Fragment env parameters */
|
GLfloat (*EnvParams)[4]; /**< Vertex or Fragment env parameters */
|
||||||
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
|
GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
|
||||||
GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4];
|
GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4];
|
||||||
|
GLfloat SystemValues[SYSTEM_VALUE_MAX][4];
|
||||||
|
|
||||||
const GLubyte *Samplers; /** Array mapping sampler var to tex unit */
|
const GLubyte *Samplers; /** Array mapping sampler var to tex unit */
|
||||||
|
|
||||||
|
@@ -72,6 +72,8 @@ _mesa_register_file_name(gl_register_file f)
|
|||||||
return "ADDR";
|
return "ADDR";
|
||||||
case PROGRAM_SAMPLER:
|
case PROGRAM_SAMPLER:
|
||||||
return "SAMPLER";
|
return "SAMPLER";
|
||||||
|
case PROGRAM_SYSTEM_VALUE:
|
||||||
|
return "SYSVAL";
|
||||||
case PROGRAM_UNDEFINED:
|
case PROGRAM_UNDEFINED:
|
||||||
return "UNDEFINED";
|
return "UNDEFINED";
|
||||||
default:
|
default:
|
||||||
@@ -310,6 +312,9 @@ reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode,
|
|||||||
case PROGRAM_UNIFORM: /* extension */
|
case PROGRAM_UNIFORM: /* extension */
|
||||||
sprintf(str, "uniform[%s%d]", addr, index);
|
sprintf(str, "uniform[%s%d]", addr, index);
|
||||||
break;
|
break;
|
||||||
|
case PROGRAM_SYSTEM_VALUE:
|
||||||
|
sprintf(str, "sysvalue[%s%d]", addr, index);
|
||||||
|
break;
|
||||||
case PROGRAM_STATE_VAR:
|
case PROGRAM_STATE_VAR:
|
||||||
{
|
{
|
||||||
struct gl_program_parameter *param
|
struct gl_program_parameter *param
|
||||||
|
@@ -461,4 +461,8 @@ void st_init_extensions(struct st_context *st)
|
|||||||
if (screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) {
|
if (screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) {
|
||||||
ctx->Extensions.ARB_shader_stencil_export = GL_TRUE;
|
ctx->Extensions.ARB_shader_stencil_export = GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (screen->get_param(screen, PIPE_CAP_INSTANCED_DRAWING)) {
|
||||||
|
ctx->Extensions.ARB_draw_instanced = GL_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -72,6 +72,7 @@ struct st_translate {
|
|||||||
struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
|
struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
|
||||||
struct ureg_dst address[1];
|
struct ureg_dst address[1];
|
||||||
struct ureg_src samplers[PIPE_MAX_SAMPLERS];
|
struct ureg_src samplers[PIPE_MAX_SAMPLERS];
|
||||||
|
struct ureg_src systemValues[SYSTEM_VALUE_MAX];
|
||||||
|
|
||||||
/* Extra info for handling point size clamping in vertex shader */
|
/* Extra info for handling point size clamping in vertex shader */
|
||||||
struct ureg_dst pointSizeResult; /**< Actual point size output register */
|
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.
|
* Make note of a branch to a label in the TGSI code.
|
||||||
* After we've emitted all instructions, we'll go over the list
|
* 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:
|
case PROGRAM_ADDRESS:
|
||||||
return ureg_src(t->address[index]);
|
return ureg_src(t->address[index]);
|
||||||
|
|
||||||
|
case PROGRAM_SYSTEM_VALUE:
|
||||||
|
assert(index < Elements(t->systemValues));
|
||||||
|
return t->systemValues[index];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debug_assert( 0 );
|
debug_assert( 0 );
|
||||||
return ureg_src_undef();
|
return ureg_src_undef();
|
||||||
@@ -1089,6 +1101,21 @@ st_translate_mesa_program(
|
|||||||
t->address[0] = ureg_DECL_address( ureg );
|
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 (program->IndirectRegisterFiles & (1 << PROGRAM_TEMPORARY)) {
|
||||||
/* If temps are accessed with indirect addressing, declare temporaries
|
/* If temps are accessed with indirect addressing, declare temporaries
|
||||||
* in sequential order. Else, we declare them on demand elsewhere.
|
* in sequential order. Else, we declare them on demand elsewhere.
|
||||||
|
@@ -527,6 +527,8 @@ typedef struct
|
|||||||
GLubyte *block[VERT_ATTRIB_MAX];
|
GLubyte *block[VERT_ATTRIB_MAX];
|
||||||
GLuint nr_blocks;
|
GLuint nr_blocks;
|
||||||
|
|
||||||
|
GLuint CurInstance;
|
||||||
|
|
||||||
} TNLcontext;
|
} TNLcontext;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -453,6 +453,7 @@ void _tnl_draw_prims( struct gl_context *ctx,
|
|||||||
*/
|
*/
|
||||||
struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
|
struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
|
||||||
GLuint nr_bo = 0;
|
GLuint nr_bo = 0;
|
||||||
|
GLuint inst;
|
||||||
|
|
||||||
for (i = 0; i < nr_prims;) {
|
for (i = 0; i < nr_prims;) {
|
||||||
GLuint this_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.
|
/* Binding inputs may imply mapping some vertex buffer objects.
|
||||||
* They will need to be unmapped below.
|
* They will need to be unmapped below.
|
||||||
*/
|
*/
|
||||||
|
for (inst = 0; inst < prim[i].num_instances; inst++) {
|
||||||
|
|
||||||
bind_prims(ctx, &prim[i], this_nr_prims);
|
bind_prims(ctx, &prim[i], this_nr_prims);
|
||||||
bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
|
bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
|
||||||
bo, &nr_bo);
|
bo, &nr_bo);
|
||||||
bind_indices(ctx, ib, bo, &nr_bo);
|
bind_indices(ctx, ib, bo, &nr_bo);
|
||||||
|
|
||||||
|
tnl->CurInstance = inst;
|
||||||
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
|
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
|
||||||
|
|
||||||
unmap_vbos(ctx, bo, nr_bo);
|
unmap_vbos(ctx, bo, nr_bo);
|
||||||
free_space(ctx);
|
free_space(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
i += this_nr_prims;
|
i += this_nr_prims;
|
||||||
}
|
}
|
||||||
|
@@ -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.
|
* Initialize virtual machine state prior to executing vertex program.
|
||||||
*/
|
*/
|
||||||
static void
|
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 */
|
/* Input registers get initialized from the current vertex attribs */
|
||||||
memcpy(machine->VertAttribs, ctx->Current.Attrib,
|
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->FetchTexelDeriv = NULL; /* not used by vertex programs */
|
||||||
|
|
||||||
machine->Samplers = ctx->VertexProgram._Current->Base.SamplerUnits;
|
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++) {
|
for (i = 0; i < VB->Count; i++) {
|
||||||
GLuint attr;
|
GLuint attr;
|
||||||
|
|
||||||
init_machine(ctx, machine);
|
init_machine(ctx, machine, tnl->CurInstance);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("Input %d: %f, %f, %f, %f\n", i,
|
printf("Input %d: %f, %f, %f, %f\n", i,
|
||||||
|
Reference in New Issue
Block a user