Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4357 → Rev 4358

/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_build.c
0,0 → 1,1343
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "pipe/p_format.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi_build.h"
#include "tgsi_parse.h"
 
 
/*
* header
*/
 
struct tgsi_header
tgsi_build_header( void )
{
struct tgsi_header header;
 
header.HeaderSize = 1;
header.BodySize = 0;
 
return header;
}
 
static void
header_headersize_grow( struct tgsi_header *header )
{
assert( header->HeaderSize < 0xFF );
assert( header->BodySize == 0 );
 
header->HeaderSize++;
}
 
static void
header_bodysize_grow( struct tgsi_header *header )
{
assert( header->BodySize < 0xFFFFFF );
 
header->BodySize++;
}
 
struct tgsi_processor
tgsi_build_processor(
unsigned type,
struct tgsi_header *header )
{
struct tgsi_processor processor;
 
processor.Processor = type;
processor.Padding = 0;
 
header_headersize_grow( header );
 
return processor;
}
 
/*
* declaration
*/
 
static void
declaration_grow(
struct tgsi_declaration *declaration,
struct tgsi_header *header )
{
assert( declaration->NrTokens < 0xFF );
 
declaration->NrTokens++;
 
header_bodysize_grow( header );
}
 
static struct tgsi_declaration
tgsi_default_declaration( void )
{
struct tgsi_declaration declaration;
 
declaration.Type = TGSI_TOKEN_TYPE_DECLARATION;
declaration.NrTokens = 1;
declaration.File = TGSI_FILE_NULL;
declaration.UsageMask = TGSI_WRITEMASK_XYZW;
declaration.Interpolate = 0;
declaration.Dimension = 0;
declaration.Semantic = 0;
declaration.Invariant = 0;
declaration.Local = 0;
declaration.Array = 0;
declaration.Padding = 0;
 
return declaration;
}
 
static struct tgsi_declaration
tgsi_build_declaration(
unsigned file,
unsigned usage_mask,
unsigned interpolate,
unsigned dimension,
unsigned semantic,
unsigned invariant,
unsigned local,
struct tgsi_header *header )
{
struct tgsi_declaration declaration;
 
assert( file < TGSI_FILE_COUNT );
assert( interpolate < TGSI_INTERPOLATE_COUNT );
 
declaration = tgsi_default_declaration();
declaration.File = file;
declaration.UsageMask = usage_mask;
declaration.Interpolate = interpolate;
declaration.Dimension = dimension;
declaration.Semantic = semantic;
declaration.Invariant = invariant;
declaration.Local = local;
 
header_bodysize_grow( header );
 
return declaration;
}
 
static struct tgsi_declaration_range
tgsi_default_declaration_range( void )
{
struct tgsi_declaration_range dr;
 
dr.First = 0;
dr.Last = 0;
 
return dr;
}
 
static struct tgsi_declaration_range
tgsi_build_declaration_range(
unsigned first,
unsigned last,
struct tgsi_declaration *declaration,
struct tgsi_header *header )
{
struct tgsi_declaration_range declaration_range;
 
assert( last >= first );
assert( last <= 0xFFFF );
 
declaration_range.First = first;
declaration_range.Last = last;
 
declaration_grow( declaration, header );
 
return declaration_range;
}
 
static struct tgsi_declaration_dimension
tgsi_build_declaration_dimension(unsigned index_2d,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_dimension dd;
 
assert(index_2d <= 0xFFFF);
 
dd.Index2D = index_2d;
dd.Padding = 0;
 
declaration_grow(declaration, header);
 
return dd;
}
 
static struct tgsi_declaration_interp
tgsi_default_declaration_interp( void )
{
struct tgsi_declaration_interp di;
 
di.Interpolate = TGSI_INTERPOLATE_CONSTANT;
di.Centroid = 0;
di.CylindricalWrap = 0;
di.Padding = 0;
 
return di;
}
 
static struct tgsi_declaration_interp
tgsi_build_declaration_interp(unsigned interpolate,
unsigned centroid,
unsigned cylindrical_wrap,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_interp di;
 
di.Interpolate = interpolate;
di.Centroid = centroid;
di.CylindricalWrap = cylindrical_wrap;
di.Padding = 0;
 
declaration_grow(declaration, header);
 
return di;
}
 
static struct tgsi_declaration_semantic
tgsi_default_declaration_semantic( void )
{
struct tgsi_declaration_semantic ds;
 
ds.Name = TGSI_SEMANTIC_POSITION;
ds.Index = 0;
ds.Padding = 0;
 
return ds;
}
 
static struct tgsi_declaration_semantic
tgsi_build_declaration_semantic(
unsigned semantic_name,
unsigned semantic_index,
struct tgsi_declaration *declaration,
struct tgsi_header *header )
{
struct tgsi_declaration_semantic ds;
 
assert( semantic_name <= TGSI_SEMANTIC_COUNT );
assert( semantic_index <= 0xFFFF );
 
ds.Name = semantic_name;
ds.Index = semantic_index;
ds.Padding = 0;
 
declaration_grow( declaration, header );
 
return ds;
}
 
static struct tgsi_declaration_resource
tgsi_default_declaration_resource(void)
{
struct tgsi_declaration_resource dr;
 
dr.Resource = TGSI_TEXTURE_BUFFER;
dr.Raw = 0;
dr.Writable = 0;
dr.Padding = 0;
 
return dr;
}
 
static struct tgsi_declaration_resource
tgsi_build_declaration_resource(unsigned texture,
unsigned raw,
unsigned writable,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_resource dr;
 
dr = tgsi_default_declaration_resource();
dr.Resource = texture;
dr.Raw = raw;
dr.Writable = writable;
 
declaration_grow(declaration, header);
 
return dr;
}
 
static struct tgsi_declaration_sampler_view
tgsi_default_declaration_sampler_view(void)
{
struct tgsi_declaration_sampler_view dsv;
 
dsv.Resource = TGSI_TEXTURE_BUFFER;
dsv.ReturnTypeX = PIPE_TYPE_UNORM;
dsv.ReturnTypeY = PIPE_TYPE_UNORM;
dsv.ReturnTypeZ = PIPE_TYPE_UNORM;
dsv.ReturnTypeW = PIPE_TYPE_UNORM;
 
return dsv;
}
 
static struct tgsi_declaration_sampler_view
tgsi_build_declaration_sampler_view(unsigned texture,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_sampler_view dsv;
 
dsv = tgsi_default_declaration_sampler_view();
dsv.Resource = texture;
dsv.ReturnTypeX = return_type_x;
dsv.ReturnTypeY = return_type_y;
dsv.ReturnTypeZ = return_type_z;
dsv.ReturnTypeW = return_type_w;
 
declaration_grow(declaration, header);
 
return dsv;
}
 
 
static struct tgsi_declaration_array
tgsi_default_declaration_array( void )
{
struct tgsi_declaration_array a;
 
a.ArrayID = 0;
a.Padding = 0;
 
return a;
}
 
struct tgsi_full_declaration
tgsi_default_full_declaration( void )
{
struct tgsi_full_declaration full_declaration;
 
full_declaration.Declaration = tgsi_default_declaration();
full_declaration.Range = tgsi_default_declaration_range();
full_declaration.Semantic = tgsi_default_declaration_semantic();
full_declaration.Interp = tgsi_default_declaration_interp();
full_declaration.Resource = tgsi_default_declaration_resource();
full_declaration.SamplerView = tgsi_default_declaration_sampler_view();
full_declaration.Array = tgsi_default_declaration_array();
 
return full_declaration;
}
 
unsigned
tgsi_build_full_declaration(
const struct tgsi_full_declaration *full_decl,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0;
struct tgsi_declaration *declaration;
struct tgsi_declaration_range *dr;
 
if( maxsize <= size )
return 0;
declaration = (struct tgsi_declaration *) &tokens[size];
size++;
 
*declaration = tgsi_build_declaration(
full_decl->Declaration.File,
full_decl->Declaration.UsageMask,
full_decl->Declaration.Interpolate,
full_decl->Declaration.Dimension,
full_decl->Declaration.Semantic,
full_decl->Declaration.Invariant,
full_decl->Declaration.Local,
header );
 
if (maxsize <= size)
return 0;
dr = (struct tgsi_declaration_range *) &tokens[size];
size++;
 
*dr = tgsi_build_declaration_range(
full_decl->Range.First,
full_decl->Range.Last,
declaration,
header );
 
if (full_decl->Declaration.Dimension) {
struct tgsi_declaration_dimension *dd;
 
if (maxsize <= size) {
return 0;
}
dd = (struct tgsi_declaration_dimension *)&tokens[size];
size++;
 
*dd = tgsi_build_declaration_dimension(full_decl->Dim.Index2D,
declaration,
header);
}
 
if (full_decl->Declaration.Interpolate) {
struct tgsi_declaration_interp *di;
 
if (maxsize <= size) {
return 0;
}
di = (struct tgsi_declaration_interp *)&tokens[size];
size++;
 
*di = tgsi_build_declaration_interp(full_decl->Interp.Interpolate,
full_decl->Interp.Centroid,
full_decl->Interp.CylindricalWrap,
declaration,
header);
}
 
if( full_decl->Declaration.Semantic ) {
struct tgsi_declaration_semantic *ds;
 
if( maxsize <= size )
return 0;
ds = (struct tgsi_declaration_semantic *) &tokens[size];
size++;
 
*ds = tgsi_build_declaration_semantic(
full_decl->Semantic.Name,
full_decl->Semantic.Index,
declaration,
header );
}
 
if (full_decl->Declaration.File == TGSI_FILE_RESOURCE) {
struct tgsi_declaration_resource *dr;
 
if (maxsize <= size) {
return 0;
}
dr = (struct tgsi_declaration_resource *)&tokens[size];
size++;
 
*dr = tgsi_build_declaration_resource(full_decl->Resource.Resource,
full_decl->Resource.Raw,
full_decl->Resource.Writable,
declaration,
header);
}
 
if (full_decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
struct tgsi_declaration_sampler_view *dsv;
 
if (maxsize <= size) {
return 0;
}
dsv = (struct tgsi_declaration_sampler_view *)&tokens[size];
size++;
 
*dsv = tgsi_build_declaration_sampler_view(
full_decl->SamplerView.Resource,
full_decl->SamplerView.ReturnTypeX,
full_decl->SamplerView.ReturnTypeY,
full_decl->SamplerView.ReturnTypeZ,
full_decl->SamplerView.ReturnTypeW,
declaration,
header);
}
 
return size;
}
 
/*
* immediate
*/
 
static struct tgsi_immediate
tgsi_default_immediate( void )
{
struct tgsi_immediate immediate;
 
immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
immediate.NrTokens = 1;
immediate.DataType = TGSI_IMM_FLOAT32;
immediate.Padding = 0;
 
return immediate;
}
 
static struct tgsi_immediate
tgsi_build_immediate(
struct tgsi_header *header,
unsigned type )
{
struct tgsi_immediate immediate;
 
immediate = tgsi_default_immediate();
immediate.DataType = type;
 
header_bodysize_grow( header );
 
return immediate;
}
 
struct tgsi_full_immediate
tgsi_default_full_immediate( void )
{
struct tgsi_full_immediate fullimm;
 
fullimm.Immediate = tgsi_default_immediate();
fullimm.u[0].Float = 0.0f;
fullimm.u[1].Float = 0.0f;
fullimm.u[2].Float = 0.0f;
fullimm.u[3].Float = 0.0f;
 
return fullimm;
}
 
static void
immediate_grow(
struct tgsi_immediate *immediate,
struct tgsi_header *header )
{
assert( immediate->NrTokens < 0xFF );
 
immediate->NrTokens++;
 
header_bodysize_grow( header );
}
 
unsigned
tgsi_build_full_immediate(
const struct tgsi_full_immediate *full_imm,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0, i;
struct tgsi_immediate *immediate;
 
if( maxsize <= size )
return 0;
immediate = (struct tgsi_immediate *) &tokens[size];
size++;
 
*immediate = tgsi_build_immediate( header, full_imm->Immediate.DataType );
 
assert( full_imm->Immediate.NrTokens <= 4 + 1 );
 
for( i = 0; i < full_imm->Immediate.NrTokens - 1; i++ ) {
union tgsi_immediate_data *data;
 
if( maxsize <= size )
return 0;
 
data = (union tgsi_immediate_data *) &tokens[size];
*data = full_imm->u[i];
 
immediate_grow( immediate, header );
size++;
}
 
return size;
}
 
/*
* instruction
*/
 
struct tgsi_instruction
tgsi_default_instruction( void )
{
struct tgsi_instruction instruction;
 
instruction.Type = TGSI_TOKEN_TYPE_INSTRUCTION;
instruction.NrTokens = 0;
instruction.Opcode = TGSI_OPCODE_MOV;
instruction.Saturate = TGSI_SAT_NONE;
instruction.Predicate = 0;
instruction.NumDstRegs = 1;
instruction.NumSrcRegs = 1;
instruction.Label = 0;
instruction.Texture = 0;
instruction.Padding = 0;
 
return instruction;
}
 
static struct tgsi_instruction
tgsi_build_instruction(unsigned opcode,
unsigned saturate,
unsigned predicate,
unsigned num_dst_regs,
unsigned num_src_regs,
struct tgsi_header *header)
{
struct tgsi_instruction instruction;
 
assert (opcode <= TGSI_OPCODE_LAST);
assert (saturate <= TGSI_SAT_MINUS_PLUS_ONE);
assert (num_dst_regs <= 3);
assert (num_src_regs <= 15);
 
instruction = tgsi_default_instruction();
instruction.Opcode = opcode;
instruction.Saturate = saturate;
instruction.Predicate = predicate;
instruction.NumDstRegs = num_dst_regs;
instruction.NumSrcRegs = num_src_regs;
 
header_bodysize_grow( header );
 
return instruction;
}
 
static void
instruction_grow(
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
assert (instruction->NrTokens < 0xFF);
 
instruction->NrTokens++;
 
header_bodysize_grow( header );
}
 
struct tgsi_instruction_predicate
tgsi_default_instruction_predicate(void)
{
struct tgsi_instruction_predicate instruction_predicate;
 
instruction_predicate.SwizzleX = TGSI_SWIZZLE_X;
instruction_predicate.SwizzleY = TGSI_SWIZZLE_Y;
instruction_predicate.SwizzleZ = TGSI_SWIZZLE_Z;
instruction_predicate.SwizzleW = TGSI_SWIZZLE_W;
instruction_predicate.Negate = 0;
instruction_predicate.Index = 0;
instruction_predicate.Padding = 0;
 
return instruction_predicate;
}
 
static struct tgsi_instruction_predicate
tgsi_build_instruction_predicate(int index,
unsigned negate,
unsigned swizzleX,
unsigned swizzleY,
unsigned swizzleZ,
unsigned swizzleW,
struct tgsi_instruction *instruction,
struct tgsi_header *header)
{
struct tgsi_instruction_predicate instruction_predicate;
 
instruction_predicate = tgsi_default_instruction_predicate();
instruction_predicate.SwizzleX = swizzleX;
instruction_predicate.SwizzleY = swizzleY;
instruction_predicate.SwizzleZ = swizzleZ;
instruction_predicate.SwizzleW = swizzleW;
instruction_predicate.Negate = negate;
instruction_predicate.Index = index;
 
instruction_grow(instruction, header);
 
return instruction_predicate;
}
 
static struct tgsi_instruction_label
tgsi_default_instruction_label( void )
{
struct tgsi_instruction_label instruction_label;
 
instruction_label.Label = 0;
instruction_label.Padding = 0;
 
return instruction_label;
}
 
static struct tgsi_instruction_label
tgsi_build_instruction_label(
unsigned label,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_instruction_label instruction_label;
 
instruction_label.Label = label;
instruction_label.Padding = 0;
instruction->Label = 1;
 
instruction_grow( instruction, header );
 
return instruction_label;
}
 
static struct tgsi_instruction_texture
tgsi_default_instruction_texture( void )
{
struct tgsi_instruction_texture instruction_texture;
 
instruction_texture.Texture = TGSI_TEXTURE_UNKNOWN;
instruction_texture.NumOffsets = 0;
instruction_texture.Padding = 0;
 
return instruction_texture;
}
 
static struct tgsi_instruction_texture
tgsi_build_instruction_texture(
unsigned texture,
unsigned num_offsets,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_instruction_texture instruction_texture;
 
instruction_texture.Texture = texture;
instruction_texture.NumOffsets = num_offsets;
instruction_texture.Padding = 0;
instruction->Texture = 1;
 
instruction_grow( instruction, header );
 
return instruction_texture;
}
 
 
static struct tgsi_texture_offset
tgsi_default_texture_offset( void )
{
struct tgsi_texture_offset texture_offset;
 
texture_offset.Index = 0;
texture_offset.File = 0;
texture_offset.SwizzleX = 0;
texture_offset.SwizzleY = 0;
texture_offset.SwizzleZ = 0;
texture_offset.Padding = 0;
 
return texture_offset;
}
 
static struct tgsi_texture_offset
tgsi_build_texture_offset(
int index, int file, int swizzle_x, int swizzle_y, int swizzle_z,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_texture_offset texture_offset;
 
texture_offset.Index = index;
texture_offset.File = file;
texture_offset.SwizzleX = swizzle_x;
texture_offset.SwizzleY = swizzle_y;
texture_offset.SwizzleZ = swizzle_z;
texture_offset.Padding = 0;
 
instruction_grow( instruction, header );
 
return texture_offset;
}
 
static struct tgsi_src_register
tgsi_default_src_register( void )
{
struct tgsi_src_register src_register;
 
src_register.File = TGSI_FILE_NULL;
src_register.SwizzleX = TGSI_SWIZZLE_X;
src_register.SwizzleY = TGSI_SWIZZLE_Y;
src_register.SwizzleZ = TGSI_SWIZZLE_Z;
src_register.SwizzleW = TGSI_SWIZZLE_W;
src_register.Negate = 0;
src_register.Absolute = 0;
src_register.Indirect = 0;
src_register.Dimension = 0;
src_register.Index = 0;
 
return src_register;
}
 
static struct tgsi_src_register
tgsi_build_src_register(
unsigned file,
unsigned swizzle_x,
unsigned swizzle_y,
unsigned swizzle_z,
unsigned swizzle_w,
unsigned negate,
unsigned absolute,
unsigned indirect,
unsigned dimension,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_src_register src_register;
 
assert( file < TGSI_FILE_COUNT );
assert( swizzle_x <= TGSI_SWIZZLE_W );
assert( swizzle_y <= TGSI_SWIZZLE_W );
assert( swizzle_z <= TGSI_SWIZZLE_W );
assert( swizzle_w <= TGSI_SWIZZLE_W );
assert( negate <= 1 );
assert( index >= -0x8000 && index <= 0x7FFF );
 
src_register.File = file;
src_register.SwizzleX = swizzle_x;
src_register.SwizzleY = swizzle_y;
src_register.SwizzleZ = swizzle_z;
src_register.SwizzleW = swizzle_w;
src_register.Negate = negate;
src_register.Absolute = absolute;
src_register.Indirect = indirect;
src_register.Dimension = dimension;
src_register.Index = index;
 
instruction_grow( instruction, header );
 
return src_register;
}
 
static struct tgsi_ind_register
tgsi_default_ind_register( void )
{
struct tgsi_ind_register ind_register;
 
ind_register.File = TGSI_FILE_NULL;
ind_register.Index = 0;
ind_register.Swizzle = TGSI_SWIZZLE_X;
ind_register.ArrayID = 0;
 
return ind_register;
}
 
static struct tgsi_ind_register
tgsi_build_ind_register(
unsigned file,
unsigned swizzle,
unsigned arrayid,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_ind_register ind_register;
 
assert( file < TGSI_FILE_COUNT );
assert( swizzle <= TGSI_SWIZZLE_W );
assert( index >= -0x8000 && index <= 0x7FFF );
 
ind_register.File = file;
ind_register.Swizzle = swizzle;
ind_register.Index = index;
ind_register.ArrayID = arrayid;
 
instruction_grow( instruction, header );
 
return ind_register;
}
 
static struct tgsi_dimension
tgsi_default_dimension( void )
{
struct tgsi_dimension dimension;
 
dimension.Indirect = 0;
dimension.Dimension = 0;
dimension.Padding = 0;
dimension.Index = 0;
 
return dimension;
}
 
static struct tgsi_full_src_register
tgsi_default_full_src_register( void )
{
struct tgsi_full_src_register full_src_register;
 
full_src_register.Register = tgsi_default_src_register();
full_src_register.Indirect = tgsi_default_ind_register();
full_src_register.Dimension = tgsi_default_dimension();
full_src_register.DimIndirect = tgsi_default_ind_register();
 
return full_src_register;
}
 
static struct tgsi_dimension
tgsi_build_dimension(
unsigned indirect,
unsigned index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_dimension dimension;
 
dimension.Indirect = indirect;
dimension.Dimension = 0;
dimension.Padding = 0;
dimension.Index = index;
 
instruction_grow( instruction, header );
 
return dimension;
}
 
static struct tgsi_dst_register
tgsi_default_dst_register( void )
{
struct tgsi_dst_register dst_register;
 
dst_register.File = TGSI_FILE_NULL;
dst_register.WriteMask = TGSI_WRITEMASK_XYZW;
dst_register.Indirect = 0;
dst_register.Dimension = 0;
dst_register.Index = 0;
dst_register.Padding = 0;
 
return dst_register;
}
 
static struct tgsi_dst_register
tgsi_build_dst_register(
unsigned file,
unsigned mask,
unsigned indirect,
unsigned dimension,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_dst_register dst_register;
 
assert( file < TGSI_FILE_COUNT );
assert( mask <= TGSI_WRITEMASK_XYZW );
assert( index >= -32768 && index <= 32767 );
 
dst_register.File = file;
dst_register.WriteMask = mask;
dst_register.Indirect = indirect;
dst_register.Dimension = dimension;
dst_register.Index = index;
dst_register.Padding = 0;
 
instruction_grow( instruction, header );
 
return dst_register;
}
 
static struct tgsi_full_dst_register
tgsi_default_full_dst_register( void )
{
struct tgsi_full_dst_register full_dst_register;
 
full_dst_register.Register = tgsi_default_dst_register();
full_dst_register.Indirect = tgsi_default_ind_register();
full_dst_register.Dimension = tgsi_default_dimension();
full_dst_register.DimIndirect = tgsi_default_ind_register();
 
return full_dst_register;
}
 
struct tgsi_full_instruction
tgsi_default_full_instruction( void )
{
struct tgsi_full_instruction full_instruction;
unsigned i;
 
full_instruction.Instruction = tgsi_default_instruction();
full_instruction.Predicate = tgsi_default_instruction_predicate();
full_instruction.Label = tgsi_default_instruction_label();
full_instruction.Texture = tgsi_default_instruction_texture();
for( i = 0; i < TGSI_FULL_MAX_TEX_OFFSETS; i++ ) {
full_instruction.TexOffsets[i] = tgsi_default_texture_offset();
}
for( i = 0; i < TGSI_FULL_MAX_DST_REGISTERS; i++ ) {
full_instruction.Dst[i] = tgsi_default_full_dst_register();
}
for( i = 0; i < TGSI_FULL_MAX_SRC_REGISTERS; i++ ) {
full_instruction.Src[i] = tgsi_default_full_src_register();
}
 
return full_instruction;
}
 
unsigned
tgsi_build_full_instruction(
const struct tgsi_full_instruction *full_inst,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0;
unsigned i;
struct tgsi_instruction *instruction;
struct tgsi_token *prev_token;
 
if( maxsize <= size )
return 0;
instruction = (struct tgsi_instruction *) &tokens[size];
size++;
 
*instruction = tgsi_build_instruction(full_inst->Instruction.Opcode,
full_inst->Instruction.Saturate,
full_inst->Instruction.Predicate,
full_inst->Instruction.NumDstRegs,
full_inst->Instruction.NumSrcRegs,
header);
prev_token = (struct tgsi_token *) instruction;
 
if (full_inst->Instruction.Predicate) {
struct tgsi_instruction_predicate *instruction_predicate;
 
if (maxsize <= size) {
return 0;
}
instruction_predicate = (struct tgsi_instruction_predicate *)&tokens[size];
size++;
 
*instruction_predicate =
tgsi_build_instruction_predicate(full_inst->Predicate.Index,
full_inst->Predicate.Negate,
full_inst->Predicate.SwizzleX,
full_inst->Predicate.SwizzleY,
full_inst->Predicate.SwizzleZ,
full_inst->Predicate.SwizzleW,
instruction,
header);
}
 
if (full_inst->Instruction.Label) {
struct tgsi_instruction_label *instruction_label;
 
if( maxsize <= size )
return 0;
instruction_label =
(struct tgsi_instruction_label *) &tokens[size];
size++;
 
*instruction_label = tgsi_build_instruction_label(
full_inst->Label.Label,
prev_token,
instruction,
header );
prev_token = (struct tgsi_token *) instruction_label;
}
 
if (full_inst->Instruction.Texture) {
struct tgsi_instruction_texture *instruction_texture;
 
if( maxsize <= size )
return 0;
instruction_texture =
(struct tgsi_instruction_texture *) &tokens[size];
size++;
 
*instruction_texture = tgsi_build_instruction_texture(
full_inst->Texture.Texture,
full_inst->Texture.NumOffsets,
prev_token,
instruction,
header );
prev_token = (struct tgsi_token *) instruction_texture;
 
for (i = 0; i < full_inst->Texture.NumOffsets; i++) {
struct tgsi_texture_offset *texture_offset;
if ( maxsize <= size )
return 0;
texture_offset = (struct tgsi_texture_offset *)&tokens[size];
size++;
*texture_offset = tgsi_build_texture_offset(
full_inst->TexOffsets[i].Index,
full_inst->TexOffsets[i].File,
full_inst->TexOffsets[i].SwizzleX,
full_inst->TexOffsets[i].SwizzleY,
full_inst->TexOffsets[i].SwizzleZ,
prev_token,
instruction,
header);
prev_token = (struct tgsi_token *) texture_offset;
}
}
for( i = 0; i < full_inst->Instruction.NumDstRegs; i++ ) {
const struct tgsi_full_dst_register *reg = &full_inst->Dst[i];
struct tgsi_dst_register *dst_register;
 
if( maxsize <= size )
return 0;
dst_register = (struct tgsi_dst_register *) &tokens[size];
size++;
 
*dst_register = tgsi_build_dst_register(
reg->Register.File,
reg->Register.WriteMask,
reg->Register.Indirect,
reg->Register.Dimension,
reg->Register.Index,
instruction,
header );
 
if( reg->Register.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->Indirect.File,
reg->Indirect.Swizzle,
reg->Indirect.Index,
reg->Indirect.ArrayID,
instruction,
header );
}
 
if( reg->Register.Dimension ) {
struct tgsi_dimension *dim;
 
assert( !reg->Dimension.Dimension );
 
if( maxsize <= size )
return 0;
dim = (struct tgsi_dimension *) &tokens[size];
size++;
 
*dim = tgsi_build_dimension(
reg->Dimension.Indirect,
reg->Dimension.Index,
instruction,
header );
 
if( reg->Dimension.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->DimIndirect.File,
reg->DimIndirect.Swizzle,
reg->DimIndirect.Index,
reg->DimIndirect.ArrayID,
instruction,
header );
}
}
}
 
for( i = 0; i < full_inst->Instruction.NumSrcRegs; i++ ) {
const struct tgsi_full_src_register *reg = &full_inst->Src[i];
struct tgsi_src_register *src_register;
 
if( maxsize <= size )
return 0;
src_register = (struct tgsi_src_register *) &tokens[size];
size++;
 
*src_register = tgsi_build_src_register(
reg->Register.File,
reg->Register.SwizzleX,
reg->Register.SwizzleY,
reg->Register.SwizzleZ,
reg->Register.SwizzleW,
reg->Register.Negate,
reg->Register.Absolute,
reg->Register.Indirect,
reg->Register.Dimension,
reg->Register.Index,
instruction,
header );
 
if( reg->Register.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->Indirect.File,
reg->Indirect.Swizzle,
reg->Indirect.Index,
reg->Indirect.ArrayID,
instruction,
header );
}
 
if( reg->Register.Dimension ) {
struct tgsi_dimension *dim;
 
assert( !reg->Dimension.Dimension );
 
if( maxsize <= size )
return 0;
dim = (struct tgsi_dimension *) &tokens[size];
size++;
 
*dim = tgsi_build_dimension(
reg->Dimension.Indirect,
reg->Dimension.Index,
instruction,
header );
 
if( reg->Dimension.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->DimIndirect.File,
reg->DimIndirect.Swizzle,
reg->DimIndirect.Index,
reg->DimIndirect.ArrayID,
instruction,
header );
}
}
}
 
return size;
}
 
static struct tgsi_property
tgsi_default_property( void )
{
struct tgsi_property property;
 
property.Type = TGSI_TOKEN_TYPE_PROPERTY;
property.NrTokens = 1;
property.PropertyName = TGSI_PROPERTY_GS_INPUT_PRIM;
property.Padding = 0;
 
return property;
}
 
static struct tgsi_property
tgsi_build_property(unsigned property_name,
struct tgsi_header *header)
{
struct tgsi_property property;
 
property = tgsi_default_property();
property.PropertyName = property_name;
 
header_bodysize_grow( header );
 
return property;
}
 
 
struct tgsi_full_property
tgsi_default_full_property( void )
{
struct tgsi_full_property full_property;
 
full_property.Property = tgsi_default_property();
memset(full_property.u, 0,
sizeof(struct tgsi_property_data) * 8);
 
return full_property;
}
 
static void
property_grow(
struct tgsi_property *property,
struct tgsi_header *header )
{
assert( property->NrTokens < 0xFF );
 
property->NrTokens++;
 
header_bodysize_grow( header );
}
 
static struct tgsi_property_data
tgsi_build_property_data(
unsigned value,
struct tgsi_property *property,
struct tgsi_header *header )
{
struct tgsi_property_data property_data;
 
property_data.Data = value;
 
property_grow( property, header );
 
return property_data;
}
 
unsigned
tgsi_build_full_property(
const struct tgsi_full_property *full_prop,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0, i;
struct tgsi_property *property;
 
if( maxsize <= size )
return 0;
property = (struct tgsi_property *) &tokens[size];
size++;
 
*property = tgsi_build_property(
full_prop->Property.PropertyName,
header );
 
assert( full_prop->Property.NrTokens <= 8 + 1 );
 
for( i = 0; i < full_prop->Property.NrTokens - 1; i++ ) {
struct tgsi_property_data *data;
 
if( maxsize <= size )
return 0;
data = (struct tgsi_property_data *) &tokens[size];
size++;
 
*data = tgsi_build_property_data(
full_prop->u[i].Data,
property,
header );
}
 
return size;
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_build.h
0,0 → 1,118
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_BUILD_H
#define TGSI_BUILD_H
 
 
struct tgsi_token;
 
 
#if defined __cplusplus
extern "C" {
#endif
 
 
/*
* header
*/
 
struct tgsi_header
tgsi_build_header( void );
 
struct tgsi_processor
tgsi_build_processor(
unsigned processor,
struct tgsi_header *header );
 
/*
* declaration
*/
 
struct tgsi_full_declaration
tgsi_default_full_declaration( void );
 
unsigned
tgsi_build_full_declaration(
const struct tgsi_full_declaration *full_decl,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
/*
* immediate
*/
 
struct tgsi_full_immediate
tgsi_default_full_immediate( void );
 
unsigned
tgsi_build_full_immediate(
const struct tgsi_full_immediate *full_imm,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
/*
* properties
*/
 
struct tgsi_full_property
tgsi_default_full_property( void );
 
unsigned
tgsi_build_full_property(
const struct tgsi_full_property *full_prop,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
/*
* instruction
*/
 
struct tgsi_instruction
tgsi_default_instruction( void );
 
struct tgsi_full_instruction
tgsi_default_full_instruction( void );
 
unsigned
tgsi_build_full_instruction(
const struct tgsi_full_instruction *full_inst,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
struct tgsi_instruction_predicate
tgsi_default_instruction_predicate(void);
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_BUILD_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_dump.c
0,0 → 1,723
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_string.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi_dump.h"
#include "tgsi_info.h"
#include "tgsi_iterate.h"
#include "tgsi_strings.h"
 
 
/** Number of spaces to indent for IF/LOOP/etc */
static const int indent_spaces = 3;
 
 
struct dump_ctx
{
struct tgsi_iterate_context iter;
 
uint instno;
uint immno;
int indent;
uint indentation;
 
void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...);
};
 
static void
dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
{
va_list ap;
(void)ctx;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
}
 
static void
dump_enum(
struct dump_ctx *ctx,
uint e,
const char **enums,
uint enum_count )
{
if (e >= enum_count)
ctx->dump_printf( ctx, "%u", e );
else
ctx->dump_printf( ctx, "%s", enums[e] );
}
 
#define EOL() ctx->dump_printf( ctx, "\n" )
#define TXT(S) ctx->dump_printf( ctx, "%s", S )
#define CHR(C) ctx->dump_printf( ctx, "%c", C )
#define UIX(I) ctx->dump_printf( ctx, "0x%x", I )
#define UID(I) ctx->dump_printf( ctx, "%u", I )
#define INSTID(I) ctx->dump_printf( ctx, "% 3u", I )
#define SID(I) ctx->dump_printf( ctx, "%d", I )
#define FLT(F) ctx->dump_printf( ctx, "%10.4f", F )
#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
 
const char *
tgsi_swizzle_names[4] =
{
"x",
"y",
"z",
"w"
};
 
static void
_dump_register_src(
struct dump_ctx *ctx,
const struct tgsi_full_src_register *src )
{
TXT(tgsi_file_name(src->Register.File));
if (src->Register.Dimension) {
if (src->Dimension.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(src->DimIndirect.File));
CHR( '[' );
SID( src->DimIndirect.Index );
TXT( "]." );
ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names );
if (src->Dimension.Index != 0) {
if (src->Dimension.Index > 0)
CHR( '+' );
SID( src->Dimension.Index );
}
CHR( ']' );
if (src->DimIndirect.ArrayID) {
CHR( '(' );
SID( src->DimIndirect.ArrayID );
CHR( ')' );
}
} else {
CHR('[');
SID(src->Dimension.Index);
CHR(']');
}
}
if (src->Register.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(src->Indirect.File));
CHR( '[' );
SID( src->Indirect.Index );
TXT( "]." );
ENM( src->Indirect.Swizzle, tgsi_swizzle_names );
if (src->Register.Index != 0) {
if (src->Register.Index > 0)
CHR( '+' );
SID( src->Register.Index );
}
CHR( ']' );
if (src->Indirect.ArrayID) {
CHR( '(' );
SID( src->Indirect.ArrayID );
CHR( ')' );
}
} else {
CHR( '[' );
SID( src->Register.Index );
CHR( ']' );
}
}
 
 
static void
_dump_register_dst(
struct dump_ctx *ctx,
const struct tgsi_full_dst_register *dst )
{
TXT(tgsi_file_name(dst->Register.File));
if (dst->Register.Dimension) {
if (dst->Dimension.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(dst->DimIndirect.File));
CHR( '[' );
SID( dst->DimIndirect.Index );
TXT( "]." );
ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names );
if (dst->Dimension.Index != 0) {
if (dst->Dimension.Index > 0)
CHR( '+' );
SID( dst->Dimension.Index );
}
CHR( ']' );
if (dst->DimIndirect.ArrayID) {
CHR( '(' );
SID( dst->DimIndirect.ArrayID );
CHR( ')' );
}
} else {
CHR('[');
SID(dst->Dimension.Index);
CHR(']');
}
}
if (dst->Register.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(dst->Indirect.File));
CHR( '[' );
SID( dst->Indirect.Index );
TXT( "]." );
ENM( dst->Indirect.Swizzle, tgsi_swizzle_names );
if (dst->Register.Index != 0) {
if (dst->Register.Index > 0)
CHR( '+' );
SID( dst->Register.Index );
}
CHR( ']' );
if (dst->Indirect.ArrayID) {
CHR( '(' );
SID( dst->Indirect.ArrayID );
CHR( ')' );
}
} else {
CHR( '[' );
SID( dst->Register.Index );
CHR( ']' );
}
}
static void
_dump_writemask(
struct dump_ctx *ctx,
uint writemask )
{
if (writemask != TGSI_WRITEMASK_XYZW) {
CHR( '.' );
if (writemask & TGSI_WRITEMASK_X)
CHR( 'x' );
if (writemask & TGSI_WRITEMASK_Y)
CHR( 'y' );
if (writemask & TGSI_WRITEMASK_Z)
CHR( 'z' );
if (writemask & TGSI_WRITEMASK_W)
CHR( 'w' );
}
}
 
static void
dump_imm_data(struct tgsi_iterate_context *iter,
union tgsi_immediate_data *data,
unsigned num_tokens,
unsigned data_type)
{
struct dump_ctx *ctx = (struct dump_ctx *)iter;
unsigned i ;
 
TXT( " {" );
 
assert( num_tokens <= 4 );
for (i = 0; i < num_tokens; i++) {
switch (data_type) {
case TGSI_IMM_FLOAT32:
FLT( data[i].Float );
break;
case TGSI_IMM_UINT32:
UID(data[i].Uint);
break;
case TGSI_IMM_INT32:
SID(data[i].Int);
break;
default:
assert( 0 );
}
 
if (i < num_tokens - 1)
TXT( ", " );
}
TXT( "}" );
}
 
static boolean
iter_declaration(
struct tgsi_iterate_context *iter,
struct tgsi_full_declaration *decl )
{
struct dump_ctx *ctx = (struct dump_ctx *)iter;
 
TXT( "DCL " );
 
TXT(tgsi_file_name(decl->Declaration.File));
 
/* all geometry shader inputs are two dimensional */
if (decl->Declaration.File == TGSI_FILE_INPUT &&
iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
TXT("[]");
}
 
if (decl->Declaration.Dimension) {
CHR('[');
SID(decl->Dim.Index2D);
CHR(']');
}
 
CHR('[');
SID(decl->Range.First);
if (decl->Range.First != decl->Range.Last) {
TXT("..");
SID(decl->Range.Last);
}
CHR(']');
 
_dump_writemask(
ctx,
decl->Declaration.UsageMask );
 
if (decl->Declaration.Array) {
TXT( ", ARRAY(" );
SID(decl->Array.ArrayID);
CHR(')');
}
 
if (decl->Declaration.Local)
TXT( ", LOCAL" );
 
if (decl->Declaration.Semantic) {
TXT( ", " );
ENM( decl->Semantic.Name, tgsi_semantic_names );
if (decl->Semantic.Index != 0 ||
decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
CHR( '[' );
UID( decl->Semantic.Index );
CHR( ']' );
}
}
 
if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
TXT(", ");
ENM(decl->Resource.Resource, tgsi_texture_names);
if (decl->Resource.Writable)
TXT(", WR");
if (decl->Resource.Raw)
TXT(", RAW");
}
 
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
TXT(", ");
ENM(decl->SamplerView.Resource, tgsi_texture_names);
TXT(", ");
if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) &&
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) &&
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) {
ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
} else {
ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
TXT(", ");
ENM(decl->SamplerView.ReturnTypeY, tgsi_type_names);
TXT(", ");
ENM(decl->SamplerView.ReturnTypeZ, tgsi_type_names);
TXT(", ");
ENM(decl->SamplerView.ReturnTypeW, tgsi_type_names);
}
}
 
if (decl->Declaration.Interpolate) {
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
decl->Declaration.File == TGSI_FILE_INPUT)
{
TXT( ", " );
ENM( decl->Interp.Interpolate, tgsi_interpolate_names );
}
 
if (decl->Interp.Centroid) {
TXT( ", CENTROID" );
}
 
if (decl->Interp.CylindricalWrap) {
TXT(", CYLWRAP_");
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
CHR('X');
}
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
CHR('Y');
}
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
CHR('Z');
}
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
CHR('W');
}
}
}
 
if (decl->Declaration.Invariant) {
TXT( ", INVARIANT" );
}
 
EOL();
 
return TRUE;
}
 
void
tgsi_dump_declaration(
const struct tgsi_full_declaration *decl )
{
struct dump_ctx ctx;
 
ctx.dump_printf = dump_ctx_printf;
 
iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
}
 
static boolean
iter_property(
struct tgsi_iterate_context *iter,
struct tgsi_full_property *prop )
{
unsigned i;
struct dump_ctx *ctx = (struct dump_ctx *)iter;
 
TXT( "PROPERTY " );
ENM(prop->Property.PropertyName, tgsi_property_names);
 
if (prop->Property.NrTokens > 1)
TXT(" ");
 
for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
switch (prop->Property.PropertyName) {
case TGSI_PROPERTY_GS_INPUT_PRIM:
case TGSI_PROPERTY_GS_OUTPUT_PRIM:
ENM(prop->u[i].Data, tgsi_primitive_names);
break;
case TGSI_PROPERTY_FS_COORD_ORIGIN:
ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
break;
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
break;
default:
SID( prop->u[i].Data );
break;
}
if (i < prop->Property.NrTokens - 2)
TXT( ", " );
}
EOL();
 
return TRUE;
}
 
void tgsi_dump_property(
const struct tgsi_full_property *prop )
{
struct dump_ctx ctx;
 
ctx.dump_printf = dump_ctx_printf;
 
iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
}
 
static boolean
iter_immediate(
struct tgsi_iterate_context *iter,
struct tgsi_full_immediate *imm )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
 
TXT( "IMM[" );
SID( ctx->immno++ );
TXT( "] " );
ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
 
dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
imm->Immediate.DataType);
 
EOL();
 
return TRUE;
}
 
void
tgsi_dump_immediate(
const struct tgsi_full_immediate *imm )
{
struct dump_ctx ctx;
 
ctx.dump_printf = dump_ctx_printf;
 
iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
}
 
static boolean
iter_instruction(
struct tgsi_iterate_context *iter,
struct tgsi_full_instruction *inst )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
uint instno = ctx->instno++;
const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
uint i;
boolean first_reg = TRUE;
 
INSTID( instno );
TXT( ": " );
 
ctx->indent -= info->pre_dedent;
for(i = 0; (int)i < ctx->indent; ++i)
TXT( " " );
ctx->indent += info->post_indent;
 
if (inst->Instruction.Predicate) {
CHR( '(' );
 
if (inst->Predicate.Negate)
CHR( '!' );
 
TXT( "PRED[" );
SID( inst->Predicate.Index );
CHR( ']' );
 
if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X ||
inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y ||
inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z ||
inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) {
CHR( '.' );
ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names );
ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names );
ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names );
ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names );
}
 
TXT( ") " );
}
 
TXT( info->mnemonic );
 
switch (inst->Instruction.Saturate) {
case TGSI_SAT_NONE:
break;
case TGSI_SAT_ZERO_ONE:
TXT( "_SAT" );
break;
case TGSI_SAT_MINUS_PLUS_ONE:
TXT( "_SATNV" );
break;
default:
assert( 0 );
}
 
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
const struct tgsi_full_dst_register *dst = &inst->Dst[i];
 
if (!first_reg)
CHR( ',' );
CHR( ' ' );
 
_dump_register_dst( ctx, dst );
_dump_writemask( ctx, dst->Register.WriteMask );
 
first_reg = FALSE;
}
 
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *src = &inst->Src[i];
 
if (!first_reg)
CHR( ',' );
CHR( ' ' );
 
if (src->Register.Negate)
CHR( '-' );
if (src->Register.Absolute)
CHR( '|' );
 
_dump_register_src(ctx, src);
 
if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
src->Register.SwizzleW != TGSI_SWIZZLE_W) {
CHR( '.' );
ENM( src->Register.SwizzleX, tgsi_swizzle_names );
ENM( src->Register.SwizzleY, tgsi_swizzle_names );
ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
ENM( src->Register.SwizzleW, tgsi_swizzle_names );
}
 
if (src->Register.Absolute)
CHR( '|' );
 
first_reg = FALSE;
}
 
if (inst->Instruction.Texture) {
TXT( ", " );
ENM( inst->Texture.Texture, tgsi_texture_names );
for (i = 0; i < inst->Texture.NumOffsets; i++) {
TXT( ", " );
TXT(tgsi_file_name(inst->TexOffsets[i].File));
CHR( '[' );
SID( inst->TexOffsets[i].Index );
CHR( ']' );
CHR( '.' );
ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
}
}
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_IF:
case TGSI_OPCODE_UIF:
case TGSI_OPCODE_ELSE:
case TGSI_OPCODE_BGNLOOP:
case TGSI_OPCODE_ENDLOOP:
case TGSI_OPCODE_CAL:
TXT( " :" );
UID( inst->Label.Label );
break;
}
 
/* update indentation */
if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
ctx->indentation += indent_spaces;
}
 
EOL();
 
return TRUE;
}
 
void
tgsi_dump_instruction(
const struct tgsi_full_instruction *inst,
uint instno )
{
struct dump_ctx ctx;
 
ctx.instno = instno;
ctx.immno = instno;
ctx.indent = 0;
ctx.dump_printf = dump_ctx_printf;
ctx.indentation = 0;
 
iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
}
 
static boolean
prolog(
struct tgsi_iterate_context *iter )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
ENM( iter->processor.Processor, tgsi_processor_type_names );
EOL();
return TRUE;
}
 
void
tgsi_dump(
const struct tgsi_token *tokens,
uint flags )
{
struct dump_ctx ctx;
 
ctx.iter.prolog = prolog;
ctx.iter.iterate_instruction = iter_instruction;
ctx.iter.iterate_declaration = iter_declaration;
ctx.iter.iterate_immediate = iter_immediate;
ctx.iter.iterate_property = iter_property;
ctx.iter.epilog = NULL;
 
ctx.instno = 0;
ctx.immno = 0;
ctx.indent = 0;
ctx.dump_printf = dump_ctx_printf;
ctx.indentation = 0;
 
tgsi_iterate_shader( tokens, &ctx.iter );
}
 
struct str_dump_ctx
{
struct dump_ctx base;
char *str;
char *ptr;
int left;
};
 
static void
str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
{
struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
if(sctx->left > 1) {
int written;
va_list ap;
va_start(ap, format);
written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
va_end(ap);
 
/* Some complicated logic needed to handle the return value of
* vsnprintf:
*/
if (written > 0) {
written = MIN2(sctx->left, written);
sctx->ptr += written;
sctx->left -= written;
}
}
}
 
void
tgsi_dump_str(
const struct tgsi_token *tokens,
uint flags,
char *str,
size_t size)
{
struct str_dump_ctx ctx;
 
ctx.base.iter.prolog = prolog;
ctx.base.iter.iterate_instruction = iter_instruction;
ctx.base.iter.iterate_declaration = iter_declaration;
ctx.base.iter.iterate_immediate = iter_immediate;
ctx.base.iter.iterate_property = iter_property;
ctx.base.iter.epilog = NULL;
 
ctx.base.instno = 0;
ctx.base.immno = 0;
ctx.base.indent = 0;
ctx.base.dump_printf = &str_dump_ctx_printf;
ctx.base.indentation = 0;
 
ctx.str = str;
ctx.str[0] = 0;
ctx.ptr = str;
ctx.left = (int)size;
 
tgsi_iterate_shader( tokens, &ctx.base.iter );
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_dump.h
0,0 → 1,77
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_DUMP_H
#define TGSI_DUMP_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
void
tgsi_dump_str(
const struct tgsi_token *tokens,
uint flags,
char *str,
size_t size);
 
void
tgsi_dump(
const struct tgsi_token *tokens,
uint flags );
 
struct tgsi_full_immediate;
struct tgsi_full_instruction;
struct tgsi_full_declaration;
struct tgsi_full_property;
 
void
tgsi_dump_immediate(
const struct tgsi_full_immediate *imm );
 
void
tgsi_dump_instruction(
const struct tgsi_full_instruction *inst,
uint instno );
 
void
tgsi_dump_declaration(
const struct tgsi_full_declaration *decl );
 
void
tgsi_dump_property(
const struct tgsi_full_property *prop );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_DUMP_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_exec.c
0,0 → 1,4430
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009-2010 VMware, Inc. All rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* TGSI interpreter/executor.
*
* Flow control information:
*
* Since we operate on 'quads' (4 pixels or 4 vertices in parallel)
* flow control statements (IF/ELSE/ENDIF, LOOP/ENDLOOP) require special
* care since a condition may be true for some quad components but false
* for other components.
*
* We basically execute all statements (even if they're in the part of
* an IF/ELSE clause that's "not taken") and use a special mask to
* control writing to destination registers. This is the ExecMask.
* See store_dest().
*
* The ExecMask is computed from three other masks (CondMask, LoopMask and
* ContMask) which are controlled by the flow control instructions (namely:
* (IF/ELSE/ENDIF, LOOP/ENDLOOP and CONT).
*
*
* Authors:
* Michal Krol
* Brian Paul
*/
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi_exec.h"
#include "util/u_memory.h"
#include "util/u_math.h"
 
 
#define DEBUG_EXECUTION 0
 
 
#define FAST_MATH 0
 
#define TILE_TOP_LEFT 0
#define TILE_TOP_RIGHT 1
#define TILE_BOTTOM_LEFT 2
#define TILE_BOTTOM_RIGHT 3
 
static void
micro_abs(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = fabsf(src->f[0]);
dst->f[1] = fabsf(src->f[1]);
dst->f[2] = fabsf(src->f[2]);
dst->f[3] = fabsf(src->f[3]);
}
 
static void
micro_arl(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = (int)floorf(src->f[0]);
dst->i[1] = (int)floorf(src->f[1]);
dst->i[2] = (int)floorf(src->f[2]);
dst->i[3] = (int)floorf(src->f[3]);
}
 
static void
micro_arr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = (int)floorf(src->f[0] + 0.5f);
dst->i[1] = (int)floorf(src->f[1] + 0.5f);
dst->i[2] = (int)floorf(src->f[2] + 0.5f);
dst->i[3] = (int)floorf(src->f[3] + 0.5f);
}
 
static void
micro_ceil(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = ceilf(src->f[0]);
dst->f[1] = ceilf(src->f[1]);
dst->f[2] = ceilf(src->f[2]);
dst->f[3] = ceilf(src->f[3]);
}
 
static void
micro_clamp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] < src1->f[0] ? src1->f[0] : src0->f[0] > src2->f[0] ? src2->f[0] : src0->f[0];
dst->f[1] = src0->f[1] < src1->f[1] ? src1->f[1] : src0->f[1] > src2->f[1] ? src2->f[1] : src0->f[1];
dst->f[2] = src0->f[2] < src1->f[2] ? src1->f[2] : src0->f[2] > src2->f[2] ? src2->f[2] : src0->f[2];
dst->f[3] = src0->f[3] < src1->f[3] ? src1->f[3] : src0->f[3] > src2->f[3] ? src2->f[3] : src0->f[3];
}
 
static void
micro_cmp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] < 0.0f ? src1->f[0] : src2->f[0];
dst->f[1] = src0->f[1] < 0.0f ? src1->f[1] : src2->f[1];
dst->f[2] = src0->f[2] < 0.0f ? src1->f[2] : src2->f[2];
dst->f[3] = src0->f[3] < 0.0f ? src1->f[3] : src2->f[3];
}
 
static void
micro_cnd(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src2->f[0] > 0.5f ? src0->f[0] : src1->f[0];
dst->f[1] = src2->f[1] > 0.5f ? src0->f[1] : src1->f[1];
dst->f[2] = src2->f[2] > 0.5f ? src0->f[2] : src1->f[2];
dst->f[3] = src2->f[3] > 0.5f ? src0->f[3] : src1->f[3];
}
 
static void
micro_cos(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = cosf(src->f[0]);
dst->f[1] = cosf(src->f[1]);
dst->f[2] = cosf(src->f[2]);
dst->f[3] = cosf(src->f[3]);
}
 
static void
micro_ddx(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] =
dst->f[1] =
dst->f[2] =
dst->f[3] = src->f[TILE_BOTTOM_RIGHT] - src->f[TILE_BOTTOM_LEFT];
}
 
static void
micro_ddy(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] =
dst->f[1] =
dst->f[2] =
dst->f[3] = src->f[TILE_BOTTOM_LEFT] - src->f[TILE_TOP_LEFT];
}
 
static void
micro_exp2(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if FAST_MATH
dst->f[0] = util_fast_exp2(src->f[0]);
dst->f[1] = util_fast_exp2(src->f[1]);
dst->f[2] = util_fast_exp2(src->f[2]);
dst->f[3] = util_fast_exp2(src->f[3]);
#else
#if DEBUG
/* Inf is okay for this instruction, so clamp it to silence assertions. */
uint i;
union tgsi_exec_channel clamped;
 
for (i = 0; i < 4; i++) {
if (src->f[i] > 127.99999f) {
clamped.f[i] = 127.99999f;
} else if (src->f[i] < -126.99999f) {
clamped.f[i] = -126.99999f;
} else {
clamped.f[i] = src->f[i];
}
}
src = &clamped;
#endif /* DEBUG */
 
dst->f[0] = powf(2.0f, src->f[0]);
dst->f[1] = powf(2.0f, src->f[1]);
dst->f[2] = powf(2.0f, src->f[2]);
dst->f[3] = powf(2.0f, src->f[3]);
#endif /* FAST_MATH */
}
 
static void
micro_flr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = floorf(src->f[0]);
dst->f[1] = floorf(src->f[1]);
dst->f[2] = floorf(src->f[2]);
dst->f[3] = floorf(src->f[3]);
}
 
static void
micro_frc(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = src->f[0] - floorf(src->f[0]);
dst->f[1] = src->f[1] - floorf(src->f[1]);
dst->f[2] = src->f[2] - floorf(src->f[2]);
dst->f[3] = src->f[3] - floorf(src->f[3]);
}
 
static void
micro_iabs(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = src->i[0] >= 0 ? src->i[0] : -src->i[0];
dst->i[1] = src->i[1] >= 0 ? src->i[1] : -src->i[1];
dst->i[2] = src->i[2] >= 0 ? src->i[2] : -src->i[2];
dst->i[3] = src->i[3] >= 0 ? src->i[3] : -src->i[3];
}
 
static void
micro_ineg(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = -src->i[0];
dst->i[1] = -src->i[1];
dst->i[2] = -src->i[2];
dst->i[3] = -src->i[3];
}
 
static void
micro_lg2(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if FAST_MATH
dst->f[0] = util_fast_log2(src->f[0]);
dst->f[1] = util_fast_log2(src->f[1]);
dst->f[2] = util_fast_log2(src->f[2]);
dst->f[3] = util_fast_log2(src->f[3]);
#else
dst->f[0] = logf(src->f[0]) * 1.442695f;
dst->f[1] = logf(src->f[1]) * 1.442695f;
dst->f[2] = logf(src->f[2]) * 1.442695f;
dst->f[3] = logf(src->f[3]) * 1.442695f;
#endif
}
 
static void
micro_lrp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] * (src1->f[0] - src2->f[0]) + src2->f[0];
dst->f[1] = src0->f[1] * (src1->f[1] - src2->f[1]) + src2->f[1];
dst->f[2] = src0->f[2] * (src1->f[2] - src2->f[2]) + src2->f[2];
dst->f[3] = src0->f[3] * (src1->f[3] - src2->f[3]) + src2->f[3];
}
 
static void
micro_mad(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] * src1->f[0] + src2->f[0];
dst->f[1] = src0->f[1] * src1->f[1] + src2->f[1];
dst->f[2] = src0->f[2] * src1->f[2] + src2->f[2];
dst->f[3] = src0->f[3] * src1->f[3] + src2->f[3];
}
 
static void
micro_mov(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->u[0] = src->u[0];
dst->u[1] = src->u[1];
dst->u[2] = src->u[2];
dst->u[3] = src->u[3];
}
 
static void
micro_rcp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if 0 /* for debugging */
assert(src->f[0] != 0.0f);
assert(src->f[1] != 0.0f);
assert(src->f[2] != 0.0f);
assert(src->f[3] != 0.0f);
#endif
dst->f[0] = 1.0f / src->f[0];
dst->f[1] = 1.0f / src->f[1];
dst->f[2] = 1.0f / src->f[2];
dst->f[3] = 1.0f / src->f[3];
}
 
static void
micro_rnd(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = floorf(src->f[0] + 0.5f);
dst->f[1] = floorf(src->f[1] + 0.5f);
dst->f[2] = floorf(src->f[2] + 0.5f);
dst->f[3] = floorf(src->f[3] + 0.5f);
}
 
static void
micro_rsq(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if 0 /* for debugging */
assert(src->f[0] != 0.0f);
assert(src->f[1] != 0.0f);
assert(src->f[2] != 0.0f);
assert(src->f[3] != 0.0f);
#endif
dst->f[0] = 1.0f / sqrtf(src->f[0]);
dst->f[1] = 1.0f / sqrtf(src->f[1]);
dst->f[2] = 1.0f / sqrtf(src->f[2]);
dst->f[3] = 1.0f / sqrtf(src->f[3]);
}
 
static void
micro_sqrt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = sqrtf(src->f[0]);
dst->f[1] = sqrtf(src->f[1]);
dst->f[2] = sqrtf(src->f[2]);
dst->f[3] = sqrtf(src->f[3]);
}
 
static void
micro_seq(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] == src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] == src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] == src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] == src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sge(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] >= src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] >= src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] >= src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] >= src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sgn(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = src->f[0] < 0.0f ? -1.0f : src->f[0] > 0.0f ? 1.0f : 0.0f;
dst->f[1] = src->f[1] < 0.0f ? -1.0f : src->f[1] > 0.0f ? 1.0f : 0.0f;
dst->f[2] = src->f[2] < 0.0f ? -1.0f : src->f[2] > 0.0f ? 1.0f : 0.0f;
dst->f[3] = src->f[3] < 0.0f ? -1.0f : src->f[3] > 0.0f ? 1.0f : 0.0f;
}
 
static void
micro_isgn(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = src->i[0] < 0 ? -1 : src->i[0] > 0 ? 1 : 0;
dst->i[1] = src->i[1] < 0 ? -1 : src->i[1] > 0 ? 1 : 0;
dst->i[2] = src->i[2] < 0 ? -1 : src->i[2] > 0 ? 1 : 0;
dst->i[3] = src->i[3] < 0 ? -1 : src->i[3] > 0 ? 1 : 0;
}
 
static void
micro_sgt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] > src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] > src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] > src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] > src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sin(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = sinf(src->f[0]);
dst->f[1] = sinf(src->f[1]);
dst->f[2] = sinf(src->f[2]);
dst->f[3] = sinf(src->f[3]);
}
 
static void
micro_sle(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] <= src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] <= src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] <= src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] <= src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_slt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] < src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] < src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] < src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] < src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sne(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] != src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] != src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] != src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] != src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sfl(union tgsi_exec_channel *dst)
{
dst->f[0] = 0.0f;
dst->f[1] = 0.0f;
dst->f[2] = 0.0f;
dst->f[3] = 0.0f;
}
 
static void
micro_str(union tgsi_exec_channel *dst)
{
dst->f[0] = 1.0f;
dst->f[1] = 1.0f;
dst->f[2] = 1.0f;
dst->f[3] = 1.0f;
}
 
static void
micro_trunc(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = (float)(int)src->f[0];
dst->f[1] = (float)(int)src->f[1];
dst->f[2] = (float)(int)src->f[2];
dst->f[3] = (float)(int)src->f[3];
}
 
 
enum tgsi_exec_datatype {
TGSI_EXEC_DATA_FLOAT,
TGSI_EXEC_DATA_INT,
TGSI_EXEC_DATA_UINT
};
 
/*
* Shorthand locations of various utility registers (_I = Index, _C = Channel)
*/
#define TEMP_KILMASK_I TGSI_EXEC_TEMP_KILMASK_I
#define TEMP_KILMASK_C TGSI_EXEC_TEMP_KILMASK_C
#define TEMP_OUTPUT_I TGSI_EXEC_TEMP_OUTPUT_I
#define TEMP_OUTPUT_C TGSI_EXEC_TEMP_OUTPUT_C
#define TEMP_PRIMITIVE_I TGSI_EXEC_TEMP_PRIMITIVE_I
#define TEMP_PRIMITIVE_C TGSI_EXEC_TEMP_PRIMITIVE_C
 
 
/** The execution mask depends on the conditional mask and the loop mask */
#define UPDATE_EXEC_MASK(MACH) \
MACH->ExecMask = MACH->CondMask & MACH->LoopMask & MACH->ContMask & MACH->Switch.mask & MACH->FuncMask
 
 
static const union tgsi_exec_channel ZeroVec =
{ { 0.0, 0.0, 0.0, 0.0 } };
 
static const union tgsi_exec_channel OneVec = {
{1.0f, 1.0f, 1.0f, 1.0f}
};
 
static const union tgsi_exec_channel P128Vec = {
{128.0f, 128.0f, 128.0f, 128.0f}
};
 
static const union tgsi_exec_channel M128Vec = {
{-128.0f, -128.0f, -128.0f, -128.0f}
};
 
 
/**
* Assert that none of the float values in 'chan' are infinite or NaN.
* NaN and Inf may occur normally during program execution and should
* not lead to crashes, etc. But when debugging, it's helpful to catch
* them.
*/
static INLINE void
check_inf_or_nan(const union tgsi_exec_channel *chan)
{
assert(!util_is_inf_or_nan((chan)->f[0]));
assert(!util_is_inf_or_nan((chan)->f[1]));
assert(!util_is_inf_or_nan((chan)->f[2]));
assert(!util_is_inf_or_nan((chan)->f[3]));
}
 
 
#ifdef DEBUG
static void
print_chan(const char *msg, const union tgsi_exec_channel *chan)
{
debug_printf("%s = {%f, %f, %f, %f}\n",
msg, chan->f[0], chan->f[1], chan->f[2], chan->f[3]);
}
#endif
 
 
#ifdef DEBUG
static void
print_temp(const struct tgsi_exec_machine *mach, uint index)
{
const struct tgsi_exec_vector *tmp = &mach->Temps[index];
int i;
debug_printf("Temp[%u] =\n", index);
for (i = 0; i < 4; i++) {
debug_printf(" %c: { %f, %f, %f, %f }\n",
"XYZW"[i],
tmp->xyzw[i].f[0],
tmp->xyzw[i].f[1],
tmp->xyzw[i].f[2],
tmp->xyzw[i].f[3]);
}
}
#endif
 
 
void
tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
unsigned num_bufs,
const void **bufs,
const unsigned *buf_sizes)
{
unsigned i;
 
for (i = 0; i < num_bufs; i++) {
mach->Consts[i] = bufs[i];
mach->ConstsSize[i] = buf_sizes[i];
}
}
 
 
/**
* Check if there's a potential src/dst register data dependency when
* using SOA execution.
* Example:
* MOV T, T.yxwz;
* This would expand into:
* MOV t0, t1;
* MOV t1, t0;
* MOV t2, t3;
* MOV t3, t2;
* The second instruction will have the wrong value for t0 if executed as-is.
*/
boolean
tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst)
{
uint i, chan;
 
uint writemask = inst->Dst[0].Register.WriteMask;
if (writemask == TGSI_WRITEMASK_X ||
writemask == TGSI_WRITEMASK_Y ||
writemask == TGSI_WRITEMASK_Z ||
writemask == TGSI_WRITEMASK_W ||
writemask == TGSI_WRITEMASK_NONE) {
/* no chance of data dependency */
return FALSE;
}
 
/* loop over src regs */
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
if ((inst->Src[i].Register.File ==
inst->Dst[0].Register.File) &&
((inst->Src[i].Register.Index ==
inst->Dst[0].Register.Index) ||
inst->Src[i].Register.Indirect ||
inst->Dst[0].Register.Indirect)) {
/* loop over dest channels */
uint channelsWritten = 0x0;
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
/* check if we're reading a channel that's been written */
uint swizzle = tgsi_util_get_full_src_register_swizzle(&inst->Src[i], chan);
if (channelsWritten & (1 << swizzle)) {
return TRUE;
}
 
channelsWritten |= (1 << chan);
}
}
}
}
return FALSE;
}
 
 
/**
* Initialize machine state by expanding tokens to full instructions,
* allocating temporary storage, setting up constants, etc.
* After this, we can call tgsi_exec_machine_run() many times.
*/
void
tgsi_exec_machine_bind_shader(
struct tgsi_exec_machine *mach,
const struct tgsi_token *tokens,
struct tgsi_sampler *sampler)
{
uint k;
struct tgsi_parse_context parse;
struct tgsi_full_instruction *instructions;
struct tgsi_full_declaration *declarations;
uint maxInstructions = 10, numInstructions = 0;
uint maxDeclarations = 10, numDeclarations = 0;
 
#if 0
tgsi_dump(tokens, 0);
#endif
 
util_init_math();
 
 
mach->Tokens = tokens;
mach->Sampler = sampler;
 
if (!tokens) {
/* unbind and free all */
FREE(mach->Declarations);
mach->Declarations = NULL;
mach->NumDeclarations = 0;
 
FREE(mach->Instructions);
mach->Instructions = NULL;
mach->NumInstructions = 0;
 
return;
}
 
k = tgsi_parse_init (&parse, mach->Tokens);
if (k != TGSI_PARSE_OK) {
debug_printf( "Problem parsing!\n" );
return;
}
 
mach->Processor = parse.FullHeader.Processor.Processor;
mach->ImmLimit = 0;
mach->NumOutputs = 0;
 
if (mach->Processor == TGSI_PROCESSOR_GEOMETRY &&
!mach->UsedGeometryShader) {
struct tgsi_exec_vector *inputs;
struct tgsi_exec_vector *outputs;
 
inputs = align_malloc(sizeof(struct tgsi_exec_vector) *
TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS,
16);
 
if (!inputs)
return;
 
outputs = align_malloc(sizeof(struct tgsi_exec_vector) *
TGSI_MAX_TOTAL_VERTICES, 16);
 
if (!outputs) {
align_free(inputs);
return;
}
 
align_free(mach->Inputs);
align_free(mach->Outputs);
 
mach->Inputs = inputs;
mach->Outputs = outputs;
mach->UsedGeometryShader = TRUE;
}
 
declarations = (struct tgsi_full_declaration *)
MALLOC( maxDeclarations * sizeof(struct tgsi_full_declaration) );
 
if (!declarations) {
return;
}
 
instructions = (struct tgsi_full_instruction *)
MALLOC( maxInstructions * sizeof(struct tgsi_full_instruction) );
 
if (!instructions) {
FREE( declarations );
return;
}
 
while( !tgsi_parse_end_of_tokens( &parse ) ) {
uint i;
 
tgsi_parse_token( &parse );
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_DECLARATION:
/* save expanded declaration */
if (numDeclarations == maxDeclarations) {
declarations = REALLOC(declarations,
maxDeclarations
* sizeof(struct tgsi_full_declaration),
(maxDeclarations + 10)
* sizeof(struct tgsi_full_declaration));
maxDeclarations += 10;
}
if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_OUTPUT) {
unsigned reg;
for (reg = parse.FullToken.FullDeclaration.Range.First;
reg <= parse.FullToken.FullDeclaration.Range.Last;
++reg) {
++mach->NumOutputs;
}
}
memcpy(declarations + numDeclarations,
&parse.FullToken.FullDeclaration,
sizeof(declarations[0]));
numDeclarations++;
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
assert( size <= 4 );
assert( mach->ImmLimit + 1 <= TGSI_EXEC_NUM_IMMEDIATES );
 
for( i = 0; i < size; i++ ) {
mach->Imms[mach->ImmLimit][i] =
parse.FullToken.FullImmediate.u[i].Float;
}
mach->ImmLimit += 1;
}
break;
 
case TGSI_TOKEN_TYPE_INSTRUCTION:
 
/* save expanded instruction */
if (numInstructions == maxInstructions) {
instructions = REALLOC(instructions,
maxInstructions
* sizeof(struct tgsi_full_instruction),
(maxInstructions + 10)
* sizeof(struct tgsi_full_instruction));
maxInstructions += 10;
}
 
memcpy(instructions + numInstructions,
&parse.FullToken.FullInstruction,
sizeof(instructions[0]));
 
numInstructions++;
break;
 
case TGSI_TOKEN_TYPE_PROPERTY:
break;
 
default:
assert( 0 );
}
}
tgsi_parse_free (&parse);
 
FREE(mach->Declarations);
mach->Declarations = declarations;
mach->NumDeclarations = numDeclarations;
 
FREE(mach->Instructions);
mach->Instructions = instructions;
mach->NumInstructions = numInstructions;
}
 
 
struct tgsi_exec_machine *
tgsi_exec_machine_create( void )
{
struct tgsi_exec_machine *mach;
uint i;
 
mach = align_malloc( sizeof *mach, 16 );
if (!mach)
goto fail;
 
memset(mach, 0, sizeof(*mach));
 
mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR];
mach->MaxGeometryShaderOutputs = TGSI_MAX_TOTAL_VERTICES;
mach->Predicates = &mach->Temps[TGSI_EXEC_TEMP_P0];
 
mach->Inputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16);
mach->Outputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16);
if (!mach->Inputs || !mach->Outputs)
goto fail;
 
/* Setup constants needed by the SSE2 executor. */
for( i = 0; i < 4; i++ ) {
mach->Temps[TGSI_EXEC_TEMP_00000000_I].xyzw[TGSI_EXEC_TEMP_00000000_C].u[i] = 0x00000000;
mach->Temps[TGSI_EXEC_TEMP_7FFFFFFF_I].xyzw[TGSI_EXEC_TEMP_7FFFFFFF_C].u[i] = 0x7FFFFFFF;
mach->Temps[TGSI_EXEC_TEMP_80000000_I].xyzw[TGSI_EXEC_TEMP_80000000_C].u[i] = 0x80000000;
mach->Temps[TGSI_EXEC_TEMP_FFFFFFFF_I].xyzw[TGSI_EXEC_TEMP_FFFFFFFF_C].u[i] = 0xFFFFFFFF; /* not used */
mach->Temps[TGSI_EXEC_TEMP_ONE_I].xyzw[TGSI_EXEC_TEMP_ONE_C].f[i] = 1.0f;
mach->Temps[TGSI_EXEC_TEMP_TWO_I].xyzw[TGSI_EXEC_TEMP_TWO_C].f[i] = 2.0f; /* not used */
mach->Temps[TGSI_EXEC_TEMP_128_I].xyzw[TGSI_EXEC_TEMP_128_C].f[i] = 128.0f;
mach->Temps[TGSI_EXEC_TEMP_MINUS_128_I].xyzw[TGSI_EXEC_TEMP_MINUS_128_C].f[i] = -128.0f;
mach->Temps[TGSI_EXEC_TEMP_THREE_I].xyzw[TGSI_EXEC_TEMP_THREE_C].f[i] = 3.0f;
mach->Temps[TGSI_EXEC_TEMP_HALF_I].xyzw[TGSI_EXEC_TEMP_HALF_C].f[i] = 0.5f;
}
 
#ifdef DEBUG
/* silence warnings */
(void) print_chan;
(void) print_temp;
#endif
 
return mach;
 
fail:
if (mach) {
align_free(mach->Inputs);
align_free(mach->Outputs);
align_free(mach);
}
return NULL;
}
 
 
void
tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach)
{
if (mach) {
FREE(mach->Instructions);
FREE(mach->Declarations);
 
align_free(mach->Inputs);
align_free(mach->Outputs);
 
align_free(mach);
}
}
 
static void
micro_add(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] + src1->f[0];
dst->f[1] = src0->f[1] + src1->f[1];
dst->f[2] = src0->f[2] + src1->f[2];
dst->f[3] = src0->f[3] + src1->f[3];
}
 
static void
micro_div(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1 )
{
if (src1->f[0] != 0) {
dst->f[0] = src0->f[0] / src1->f[0];
}
if (src1->f[1] != 0) {
dst->f[1] = src0->f[1] / src1->f[1];
}
if (src1->f[2] != 0) {
dst->f[2] = src0->f[2] / src1->f[2];
}
if (src1->f[3] != 0) {
dst->f[3] = src0->f[3] / src1->f[3];
}
}
 
static void
micro_rcc(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
uint i;
 
for (i = 0; i < 4; i++) {
float recip = 1.0f / src->f[i];
 
if (recip > 0.0f) {
if (recip > 1.884467e+019f) {
dst->f[i] = 1.884467e+019f;
}
else if (recip < 5.42101e-020f) {
dst->f[i] = 5.42101e-020f;
}
else {
dst->f[i] = recip;
}
}
else {
if (recip < -1.884467e+019f) {
dst->f[i] = -1.884467e+019f;
}
else if (recip > -5.42101e-020f) {
dst->f[i] = -5.42101e-020f;
}
else {
dst->f[i] = recip;
}
}
}
}
 
static void
micro_lt(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2,
const union tgsi_exec_channel *src3 )
{
dst->f[0] = src0->f[0] < src1->f[0] ? src2->f[0] : src3->f[0];
dst->f[1] = src0->f[1] < src1->f[1] ? src2->f[1] : src3->f[1];
dst->f[2] = src0->f[2] < src1->f[2] ? src2->f[2] : src3->f[2];
dst->f[3] = src0->f[3] < src1->f[3] ? src2->f[3] : src3->f[3];
}
 
static void
micro_max(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] > src1->f[0] ? src0->f[0] : src1->f[0];
dst->f[1] = src0->f[1] > src1->f[1] ? src0->f[1] : src1->f[1];
dst->f[2] = src0->f[2] > src1->f[2] ? src0->f[2] : src1->f[2];
dst->f[3] = src0->f[3] > src1->f[3] ? src0->f[3] : src1->f[3];
}
 
static void
micro_min(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] < src1->f[0] ? src0->f[0] : src1->f[0];
dst->f[1] = src0->f[1] < src1->f[1] ? src0->f[1] : src1->f[1];
dst->f[2] = src0->f[2] < src1->f[2] ? src0->f[2] : src1->f[2];
dst->f[3] = src0->f[3] < src1->f[3] ? src0->f[3] : src1->f[3];
}
 
static void
micro_mul(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] * src1->f[0];
dst->f[1] = src0->f[1] * src1->f[1];
dst->f[2] = src0->f[2] * src1->f[2];
dst->f[3] = src0->f[3] * src1->f[3];
}
 
static void
micro_neg(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src )
{
dst->f[0] = -src->f[0];
dst->f[1] = -src->f[1];
dst->f[2] = -src->f[2];
dst->f[3] = -src->f[3];
}
 
static void
micro_pow(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1 )
{
#if FAST_MATH
dst->f[0] = util_fast_pow( src0->f[0], src1->f[0] );
dst->f[1] = util_fast_pow( src0->f[1], src1->f[1] );
dst->f[2] = util_fast_pow( src0->f[2], src1->f[2] );
dst->f[3] = util_fast_pow( src0->f[3], src1->f[3] );
#else
dst->f[0] = powf( src0->f[0], src1->f[0] );
dst->f[1] = powf( src0->f[1], src1->f[1] );
dst->f[2] = powf( src0->f[2], src1->f[2] );
dst->f[3] = powf( src0->f[3], src1->f[3] );
#endif
}
 
static void
micro_sub(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] - src1->f[0];
dst->f[1] = src0->f[1] - src1->f[1];
dst->f[2] = src0->f[2] - src1->f[2];
dst->f[3] = src0->f[3] - src1->f[3];
}
 
static void
fetch_src_file_channel(const struct tgsi_exec_machine *mach,
const uint chan_index,
const uint file,
const uint swizzle,
const union tgsi_exec_channel *index,
const union tgsi_exec_channel *index2D,
union tgsi_exec_channel *chan)
{
uint i;
 
assert(swizzle < 4);
 
switch (file) {
case TGSI_FILE_CONSTANT:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index2D->i[i] >= 0 && index2D->i[i] < PIPE_MAX_CONSTANT_BUFFERS);
assert(mach->Consts[index2D->i[i]]);
 
if (index->i[i] < 0) {
chan->u[i] = 0;
} else {
/* NOTE: copying the const value as a uint instead of float */
const uint constbuf = index2D->i[i];
const uint *buf = (const uint *)mach->Consts[constbuf];
const int pos = index->i[i] * 4 + swizzle;
/* const buffer bounds check */
if (pos < 0 || pos >= (int) mach->ConstsSize[constbuf]) {
if (0) {
/* Debug: print warning */
static int count = 0;
if (count++ < 100)
debug_printf("TGSI Exec: const buffer index %d"
" out of bounds\n", pos);
}
chan->u[i] = 0;
}
else
chan->u[i] = buf[pos];
}
}
break;
 
case TGSI_FILE_INPUT:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
/*
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
debug_printf("Fetching Input[%d] (2d=%d, 1d=%d)\n",
index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i],
index2D->i[i], index->i[i]);
}*/
int pos = index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i];
assert(pos >= 0);
assert(pos < TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS);
chan->u[i] = mach->Inputs[pos].xyzw[swizzle].u[i];
}
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 < TGSI_QUAD_SIZE; i++) {
chan->u[i] = mach->SystemValue[index->i[i]].u[i];
}
break;
 
case TGSI_FILE_TEMPORARY:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Temps[index->i[i]].xyzw[swizzle].u[i];
}
break;
 
case TGSI_FILE_IMMEDIATE:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0 && index->i[i] < (int)mach->ImmLimit);
assert(index2D->i[i] == 0);
 
chan->f[i] = mach->Imms[index->i[i]][swizzle];
}
break;
 
case TGSI_FILE_ADDRESS:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Addrs[index->i[i]].xyzw[swizzle].u[i];
}
break;
 
case TGSI_FILE_PREDICATE:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0 && index->i[i] < TGSI_EXEC_NUM_PREDS);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Predicates[0].xyzw[swizzle].u[i];
}
break;
 
case TGSI_FILE_OUTPUT:
/* vertex/fragment output vars can be read too */
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Outputs[index->i[i]].xyzw[swizzle].u[i];
}
break;
 
default:
assert(0);
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
chan->u[i] = 0;
}
}
}
 
static void
fetch_source(const struct tgsi_exec_machine *mach,
union tgsi_exec_channel *chan,
const struct tgsi_full_src_register *reg,
const uint chan_index,
enum tgsi_exec_datatype src_datatype)
{
union tgsi_exec_channel index;
union tgsi_exec_channel index2D;
uint swizzle;
 
/* We start with a direct index into a register file.
*
* file[1],
* where:
* file = Register.File
* [1] = Register.Index
*/
index.i[0] =
index.i[1] =
index.i[2] =
index.i[3] = reg->Register.Index;
 
/* There is an extra source register that indirectly subscripts
* a register file. The direct index now becomes an offset
* that is being added to the indirect register.
*
* file[ind[2].x+1],
* where:
* ind = Indirect.File
* [2] = Indirect.Index
* .x = Indirect.SwizzleX
*/
if (reg->Register.Indirect) {
union tgsi_exec_channel index2;
union tgsi_exec_channel indir_index;
const uint execmask = mach->ExecMask;
uint i;
 
/* which address register (always zero now) */
index2.i[0] =
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->Indirect.Index;
/* get current value of address register[swizzle] */
swizzle = reg->Indirect.Swizzle;
fetch_src_file_channel(mach,
chan_index,
reg->Indirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
 
/* add value of address register to the offset */
index.i[0] += indir_index.i[0];
index.i[1] += indir_index.i[1];
index.i[2] += indir_index.i[2];
index.i[3] += indir_index.i[3];
 
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0)
index.i[i] = 0;
}
}
 
/* There is an extra source register that is a second
* subscript to a register file. Effectively it means that
* the register file is actually a 2D array of registers.
*
* file[3][1],
* where:
* [3] = Dimension.Index
*/
if (reg->Register.Dimension) {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = reg->Dimension.Index;
 
/* Again, the second subscript index can be addressed indirectly
* identically to the first one.
* Nothing stops us from indirectly addressing the indirect register,
* but there is no need for that, so we won't exercise it.
*
* file[ind[4].y+3][1],
* where:
* ind = DimIndirect.File
* [4] = DimIndirect.Index
* .y = DimIndirect.SwizzleX
*/
if (reg->Dimension.Indirect) {
union tgsi_exec_channel index2;
union tgsi_exec_channel indir_index;
const uint execmask = mach->ExecMask;
uint i;
 
index2.i[0] =
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->DimIndirect.Index;
 
swizzle = reg->DimIndirect.Swizzle;
fetch_src_file_channel(mach,
chan_index,
reg->DimIndirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
 
index2D.i[0] += indir_index.i[0];
index2D.i[1] += indir_index.i[1];
index2D.i[2] += indir_index.i[2];
index2D.i[3] += indir_index.i[3];
 
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0) {
index2D.i[i] = 0;
}
}
}
 
/* If by any chance there was a need for a 3D array of register
* files, we would have to check whether Dimension is followed
* by a dimension register and continue the saga.
*/
} else {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = 0;
}
 
swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index );
fetch_src_file_channel(mach,
chan_index,
reg->Register.File,
swizzle,
&index,
&index2D,
chan);
 
if (reg->Register.Absolute) {
if (src_datatype == TGSI_EXEC_DATA_FLOAT) {
micro_abs(chan, chan);
} else {
micro_iabs(chan, chan);
}
}
 
if (reg->Register.Negate) {
if (src_datatype == TGSI_EXEC_DATA_FLOAT) {
micro_neg(chan, chan);
} else {
micro_ineg(chan, chan);
}
}
}
 
static void
store_dest(struct tgsi_exec_machine *mach,
const union tgsi_exec_channel *chan,
const struct tgsi_full_dst_register *reg,
const struct tgsi_full_instruction *inst,
uint chan_index,
enum tgsi_exec_datatype dst_datatype)
{
uint i;
union tgsi_exec_channel null;
union tgsi_exec_channel *dst;
union tgsi_exec_channel index2D;
uint execmask = mach->ExecMask;
int offset = 0; /* indirection offset */
int index;
 
/* for debugging */
if (0 && dst_datatype == TGSI_EXEC_DATA_FLOAT) {
check_inf_or_nan(chan);
}
 
/* There is an extra source register that indirectly subscripts
* a register file. The direct index now becomes an offset
* that is being added to the indirect register.
*
* file[ind[2].x+1],
* where:
* ind = Indirect.File
* [2] = Indirect.Index
* .x = Indirect.SwizzleX
*/
if (reg->Register.Indirect) {
union tgsi_exec_channel index;
union tgsi_exec_channel indir_index;
uint swizzle;
 
/* which address register (always zero for now) */
index.i[0] =
index.i[1] =
index.i[2] =
index.i[3] = reg->Indirect.Index;
 
/* get current value of address register[swizzle] */
swizzle = reg->Indirect.Swizzle;
 
/* fetch values from the address/indirection register */
fetch_src_file_channel(mach,
chan_index,
reg->Indirect.File,
swizzle,
&index,
&ZeroVec,
&indir_index);
 
/* save indirection offset */
offset = indir_index.i[0];
}
 
/* There is an extra source register that is a second
* subscript to a register file. Effectively it means that
* the register file is actually a 2D array of registers.
*
* file[3][1],
* where:
* [3] = Dimension.Index
*/
if (reg->Register.Dimension) {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = reg->Dimension.Index;
 
/* Again, the second subscript index can be addressed indirectly
* identically to the first one.
* Nothing stops us from indirectly addressing the indirect register,
* but there is no need for that, so we won't exercise it.
*
* file[ind[4].y+3][1],
* where:
* ind = DimIndirect.File
* [4] = DimIndirect.Index
* .y = DimIndirect.SwizzleX
*/
if (reg->Dimension.Indirect) {
union tgsi_exec_channel index2;
union tgsi_exec_channel indir_index;
const uint execmask = mach->ExecMask;
unsigned swizzle;
uint i;
 
index2.i[0] =
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->DimIndirect.Index;
 
swizzle = reg->DimIndirect.Swizzle;
fetch_src_file_channel(mach,
chan_index,
reg->DimIndirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
 
index2D.i[0] += indir_index.i[0];
index2D.i[1] += indir_index.i[1];
index2D.i[2] += indir_index.i[2];
index2D.i[3] += indir_index.i[3];
 
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0) {
index2D.i[i] = 0;
}
}
}
 
/* If by any chance there was a need for a 3D array of register
* files, we would have to check whether Dimension is followed
* by a dimension register and continue the saga.
*/
} else {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = 0;
}
 
switch (reg->Register.File) {
case TGSI_FILE_NULL:
dst = &null;
break;
 
case TGSI_FILE_OUTPUT:
index = mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0]
+ reg->Register.Index;
dst = &mach->Outputs[offset + index].xyzw[chan_index];
#if 0
debug_printf("NumOutputs = %d, TEMP_O_C/I = %d, redindex = %d\n",
mach->NumOutputs, mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0],
reg->Register.Index);
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
debug_printf("STORING OUT[%d] mask(%d), = (", offset + index, execmask);
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i))
debug_printf("%f, ", chan->f[i]);
debug_printf(")\n");
}
#endif
break;
 
case TGSI_FILE_TEMPORARY:
index = reg->Register.Index;
assert( index < TGSI_EXEC_NUM_TEMPS );
dst = &mach->Temps[offset + index].xyzw[chan_index];
break;
 
case TGSI_FILE_ADDRESS:
index = reg->Register.Index;
dst = &mach->Addrs[index].xyzw[chan_index];
break;
 
case TGSI_FILE_PREDICATE:
index = reg->Register.Index;
assert(index < TGSI_EXEC_NUM_PREDS);
dst = &mach->Predicates[index].xyzw[chan_index];
break;
 
default:
assert( 0 );
return;
}
 
if (inst->Instruction.Predicate) {
uint swizzle;
union tgsi_exec_channel *pred;
 
switch (chan_index) {
case TGSI_CHAN_X:
swizzle = inst->Predicate.SwizzleX;
break;
case TGSI_CHAN_Y:
swizzle = inst->Predicate.SwizzleY;
break;
case TGSI_CHAN_Z:
swizzle = inst->Predicate.SwizzleZ;
break;
case TGSI_CHAN_W:
swizzle = inst->Predicate.SwizzleW;
break;
default:
assert(0);
return;
}
 
assert(inst->Predicate.Index == 0);
 
pred = &mach->Predicates[inst->Predicate.Index].xyzw[swizzle];
 
if (inst->Predicate.Negate) {
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if (pred->u[i]) {
execmask &= ~(1 << i);
}
}
} else {
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if (!pred->u[i]) {
execmask &= ~(1 << i);
}
}
}
}
 
switch (inst->Instruction.Saturate) {
case TGSI_SAT_NONE:
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i))
dst->i[i] = chan->i[i];
break;
 
case TGSI_SAT_ZERO_ONE:
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i)) {
if (chan->f[i] < 0.0f)
dst->f[i] = 0.0f;
else if (chan->f[i] > 1.0f)
dst->f[i] = 1.0f;
else
dst->i[i] = chan->i[i];
}
break;
 
case TGSI_SAT_MINUS_PLUS_ONE:
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i)) {
if (chan->f[i] < -1.0f)
dst->f[i] = -1.0f;
else if (chan->f[i] > 1.0f)
dst->f[i] = 1.0f;
else
dst->i[i] = chan->i[i];
}
break;
 
default:
assert( 0 );
}
}
 
#define FETCH(VAL,INDEX,CHAN)\
fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_FLOAT)
 
#define IFETCH(VAL,INDEX,CHAN)\
fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_INT)
 
 
/**
* Execute ARB-style KIL which is predicated by a src register.
* Kill fragment if any of the four values is less than zero.
*/
static void
exec_kill_if(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
uint uniquemask;
uint chan_index;
uint kilmask = 0; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
union tgsi_exec_channel r[1];
 
/* This mask stores component bits that were already tested. */
uniquemask = 0;
 
for (chan_index = 0; chan_index < 4; chan_index++)
{
uint swizzle;
uint i;
 
/* unswizzle channel */
swizzle = tgsi_util_get_full_src_register_swizzle (
&inst->Src[0],
chan_index);
 
/* check if the component has not been already tested */
if (uniquemask & (1 << swizzle))
continue;
uniquemask |= 1 << swizzle;
 
FETCH(&r[0], 0, chan_index);
for (i = 0; i < 4; i++)
if (r[0].f[i] < 0.0f)
kilmask |= 1 << i;
}
 
mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
}
 
/**
* Unconditional fragment kill/discard.
*/
static void
exec_kill(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
uint kilmask; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
 
/* kill fragment for all fragments currently executing */
kilmask = mach->ExecMask;
mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
}
 
static void
emit_vertex(struct tgsi_exec_machine *mach)
{
/* FIXME: check for exec mask correctly
unsigned i;
for (i = 0; i < TGSI_QUAD_SIZE; ++i) {
if ((mach->ExecMask & (1 << i)))
*/
if (mach->ExecMask) {
mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += mach->NumOutputs;
mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++;
}
}
 
static void
emit_primitive(struct tgsi_exec_machine *mach)
{
unsigned *prim_count = &mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0];
/* FIXME: check for exec mask correctly
unsigned i;
for (i = 0; i < TGSI_QUAD_SIZE; ++i) {
if ((mach->ExecMask & (1 << i)))
*/
if (mach->ExecMask) {
++(*prim_count);
debug_assert((*prim_count * mach->NumOutputs) < mach->MaxGeometryShaderOutputs);
mach->Primitives[*prim_count] = 0;
}
}
 
static void
conditional_emit_primitive(struct tgsi_exec_machine *mach)
{
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
int emitted_verts =
mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]];
if (emitted_verts) {
emit_primitive(mach);
}
}
}
 
 
/*
* Fetch four texture samples using STR texture coordinates.
*/
static void
fetch_texel( struct tgsi_sampler *sampler,
const unsigned sview_idx,
const unsigned sampler_idx,
const union tgsi_exec_channel *s,
const union tgsi_exec_channel *t,
const union tgsi_exec_channel *p,
const union tgsi_exec_channel *c0,
const union tgsi_exec_channel *c1,
float derivs[3][2][TGSI_QUAD_SIZE],
const int8_t offset[3],
enum tgsi_sampler_control control,
union tgsi_exec_channel *r,
union tgsi_exec_channel *g,
union tgsi_exec_channel *b,
union tgsi_exec_channel *a )
{
uint j;
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
 
/* FIXME: handle explicit derivs, offsets */
sampler->get_samples(sampler, sview_idx, sampler_idx,
s->f, t->f, p->f, c0->f, c1->f, derivs, offset, control, rgba);
 
for (j = 0; j < 4; j++) {
r->f[j] = rgba[0][j];
g->f[j] = rgba[1][j];
b->f[j] = rgba[2][j];
a->f[j] = rgba[3][j];
}
}
 
 
#define TEX_MODIFIER_NONE 0
#define TEX_MODIFIER_PROJECTED 1
#define TEX_MODIFIER_LOD_BIAS 2
#define TEX_MODIFIER_EXPLICIT_LOD 3
#define TEX_MODIFIER_LEVEL_ZERO 4
 
 
/*
* Fetch all 3 (for s,t,r coords) texel offsets, put them into int array.
*/
static void
fetch_texel_offsets(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
int8_t offsets[3])
{
if (inst->Texture.NumOffsets == 1) {
union tgsi_exec_channel index;
union tgsi_exec_channel offset[3];
index.i[0] = index.i[1] = index.i[2] = index.i[3] = inst->TexOffsets[0].Index;
fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
inst->TexOffsets[0].SwizzleX, &index, &ZeroVec, &offset[0]);
fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
inst->TexOffsets[0].SwizzleY, &index, &ZeroVec, &offset[1]);
fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
inst->TexOffsets[0].SwizzleZ, &index, &ZeroVec, &offset[2]);
offsets[0] = offset[0].i[0];
offsets[1] = offset[1].i[0];
offsets[2] = offset[2].i[0];
} else {
assert(inst->Texture.NumOffsets == 0);
offsets[0] = offsets[1] = offsets[2] = 0;
}
}
 
 
/*
* Fetch dx and dy values for one channel (s, t or r).
* Put dx values into one float array, dy values into another.
*/
static void
fetch_assign_deriv_channel(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
unsigned regdsrcx,
unsigned chan,
float derivs[2][TGSI_QUAD_SIZE])
{
union tgsi_exec_channel d;
FETCH(&d, regdsrcx, chan);
derivs[0][0] = d.f[0];
derivs[0][1] = d.f[1];
derivs[0][2] = d.f[2];
derivs[0][3] = d.f[3];
FETCH(&d, regdsrcx + 1, chan);
derivs[1][0] = d.f[0];
derivs[1][1] = d.f[1];
derivs[1][2] = d.f[2];
derivs[1][3] = d.f[3];
}
 
 
/*
* execute a texture instruction.
*
* modifier is used to control the channel routing for the\
* instruction variants like proj, lod, and texture with lod bias.
* sampler indicates which src register the sampler is contained in.
*/
static void
exec_tex(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
uint modifier, uint sampler)
{
const uint unit = inst->Src[sampler].Register.Index;
const union tgsi_exec_channel *args[5], *proj = NULL;
union tgsi_exec_channel r[5];
enum tgsi_sampler_control control = tgsi_sampler_lod_none;
uint chan;
int8_t offsets[3];
int dim, shadow_ref, i;
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
assert(modifier != TEX_MODIFIER_LEVEL_ZERO);
assert(inst->Texture.Texture != TGSI_TEXTURE_BUFFER);
 
dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture, &shadow_ref);
 
assert(dim <= 4);
if (shadow_ref >= 0)
assert(shadow_ref >= dim && shadow_ref < Elements(args));
 
/* fetch modifier to the last argument */
if (modifier != TEX_MODIFIER_NONE) {
const int last = Elements(args) - 1;
 
/* fetch modifier from src0.w or src1.x */
if (sampler == 1) {
assert(dim <= TGSI_CHAN_W && shadow_ref != TGSI_CHAN_W);
FETCH(&r[last], 0, TGSI_CHAN_W);
}
else {
assert(shadow_ref != 4);
FETCH(&r[last], 1, TGSI_CHAN_X);
}
 
if (modifier != TEX_MODIFIER_PROJECTED) {
args[last] = &r[last];
}
else {
proj = &r[last];
args[last] = &ZeroVec;
}
 
/* point unused arguments to zero vector */
for (i = dim; i < last; i++)
args[i] = &ZeroVec;
 
if (modifier == TEX_MODIFIER_EXPLICIT_LOD)
control = tgsi_sampler_lod_explicit;
else if (modifier == TEX_MODIFIER_LOD_BIAS)
control = tgsi_sampler_lod_bias;
}
else {
for (i = dim; i < Elements(args); i++)
args[i] = &ZeroVec;
}
 
/* fetch coordinates */
for (i = 0; i < dim; i++) {
FETCH(&r[i], 0, TGSI_CHAN_X + i);
 
if (proj)
micro_div(&r[i], &r[i], proj);
 
args[i] = &r[i];
}
 
/* fetch reference value */
if (shadow_ref >= 0) {
FETCH(&r[shadow_ref], shadow_ref / 4, TGSI_CHAN_X + (shadow_ref % 4));
 
if (proj)
micro_div(&r[shadow_ref], &r[shadow_ref], proj);
 
args[shadow_ref] = &r[shadow_ref];
}
 
fetch_texel(mach->Sampler, unit, unit,
args[0], args[1], args[2], args[3], args[4],
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
 
#if 0
debug_printf("fetch r: %g %g %g %g\n",
r[0].f[0], r[0].f[1], r[0].f[2], r[0].f[3]);
debug_printf("fetch g: %g %g %g %g\n",
r[1].f[0], r[1].f[1], r[1].f[2], r[1].f[3]);
debug_printf("fetch b: %g %g %g %g\n",
r[2].f[0], r[2].f[1], r[2].f[2], r[2].f[3]);
debug_printf("fetch a: %g %g %g %g\n",
r[3].f[0], r[3].f[1], r[3].f[2], r[3].f[3]);
#endif
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
 
static void
exec_txd(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint unit = inst->Src[3].Register.Index;
union tgsi_exec_channel r[4];
float derivs[3][2][TGSI_QUAD_SIZE];
uint chan;
int8_t offsets[3];
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
switch (inst->Texture.Texture) {
case TGSI_TEXTURE_1D:
FETCH(&r[0], 0, TGSI_CHAN_X);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &ZeroVec, &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
case TGSI_TEXTURE_SHADOW1D:
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
/* SHADOW1D/1D_ARRAY would not need Y/Z respectively, but don't bother */
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &r[2], &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
 
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
/* only SHADOW2D_ARRAY actually needs W */
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &r[2], &r[3], &ZeroVec, /* inputs */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
 
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_CUBE_ARRAY:
/* only TEXTURE_CUBE_ARRAY actually needs W */
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Z, derivs[2]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &r[2], &r[3], &ZeroVec, /* inputs */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
 
default:
assert(0);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
 
static void
exec_txf(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint unit = inst->Src[1].Register.Index;
union tgsi_exec_channel r[4];
uint chan;
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
int j;
int8_t offsets[3];
unsigned target;
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
IFETCH(&r[3], 0, TGSI_CHAN_W);
 
if (inst->Instruction.Opcode == TGSI_OPCODE_SAMPLE_I) {
target = mach->SamplerViews[unit].Resource;
}
else {
target = inst->Texture.Texture;
}
switch(target) {
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
IFETCH(&r[2], 0, TGSI_CHAN_Z);
/* fallthrough */
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_1D_ARRAY:
IFETCH(&r[1], 0, TGSI_CHAN_Y);
/* fallthrough */
case TGSI_TEXTURE_BUFFER:
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_SHADOW1D:
IFETCH(&r[0], 0, TGSI_CHAN_X);
break;
default:
assert(0);
break;
}
 
mach->Sampler->get_texel(mach->Sampler, unit, r[0].i, r[1].i, r[2].i, r[3].i,
offsets, rgba);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
r[0].f[j] = rgba[0][j];
r[1].f[j] = rgba[1][j];
r[2].f[j] = rgba[2][j];
r[3].f[j] = rgba[3][j];
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_txq(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint unit = inst->Src[1].Register.Index;
int result[4];
union tgsi_exec_channel r[4], src;
uint chan;
int i,j;
 
fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_INT);
 
mach->Sampler->get_dims(mach->Sampler, unit, src.i[0], result);
 
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
for (j = 0; j < 4; j++) {
r[j].i[i] = result[j];
}
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan,
TGSI_EXEC_DATA_INT);
}
}
}
 
static void
exec_sample(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
uint modifier, boolean compare)
{
const uint resource_unit = inst->Src[1].Register.Index;
const uint sampler_unit = inst->Src[2].Register.Index;
union tgsi_exec_channel r[4], c1;
const union tgsi_exec_channel *lod = &ZeroVec;
enum tgsi_sampler_control control = tgsi_sampler_lod_none;
uint chan;
int8_t offsets[3];
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
assert(modifier != TEX_MODIFIER_PROJECTED);
 
if (modifier != TEX_MODIFIER_NONE) {
if (modifier == TEX_MODIFIER_LOD_BIAS) {
FETCH(&c1, 3, TGSI_CHAN_X);
lod = &c1;
control = tgsi_sampler_lod_bias;
}
else if (modifier == TEX_MODIFIER_EXPLICIT_LOD) {
FETCH(&c1, 3, TGSI_CHAN_X);
lod = &c1;
control = tgsi_sampler_lod_explicit;
}
else {
assert(modifier == TEX_MODIFIER_LEVEL_ZERO);
control = tgsi_sampler_lod_zero;
}
}
 
FETCH(&r[0], 0, TGSI_CHAN_X);
 
switch (mach->SamplerViews[resource_unit].Resource) {
case TGSI_TEXTURE_1D:
if (compare) {
FETCH(&r[2], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &ZeroVec, &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &ZeroVec, &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
}
break;
 
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
FETCH(&r[1], 0, TGSI_CHAN_Y);
if (compare) {
FETCH(&r[2], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
}
break;
 
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
if(compare) {
FETCH(&r[3], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], lod,
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &ZeroVec, lod,
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
break;
 
case TGSI_TEXTURE_CUBE_ARRAY:
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
if(compare) {
FETCH(&r[4], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], &r[4],
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], lod,
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
break;
 
 
default:
assert(0);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_sample_d(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint resource_unit = inst->Src[1].Register.Index;
const uint sampler_unit = inst->Src[2].Register.Index;
union tgsi_exec_channel r[4];
float derivs[3][2][TGSI_QUAD_SIZE];
uint chan;
int8_t offsets[3];
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
FETCH(&r[0], 0, TGSI_CHAN_X);
 
switch (mach->SamplerViews[resource_unit].Resource) {
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_1D_ARRAY:
/* only 1D array actually needs Y */
FETCH(&r[1], 0, TGSI_CHAN_Y);
 
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
 
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_2D_ARRAY:
/* only 2D array actually needs Z */
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
 
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]);
 
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &ZeroVec, &ZeroVec, /* inputs */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
 
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_CUBE_ARRAY:
/* only cube array actually needs W */
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
 
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]);
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Z, derivs[2]);
 
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], &ZeroVec,
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]);
break;
 
default:
assert(0);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
 
/**
* Evaluate a constant-valued coefficient at the position of the
* current quad.
*/
static void
eval_constant_coef(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan )
{
unsigned i;
 
for( i = 0; i < TGSI_QUAD_SIZE; i++ ) {
mach->Inputs[attrib].xyzw[chan].f[i] = mach->InterpCoefs[attrib].a0[chan];
}
}
 
/**
* Evaluate a linear-valued coefficient at the position of the
* current quad.
*/
static void
eval_linear_coef(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan )
{
const float x = mach->QuadPos.xyzw[0].f[0];
const float y = mach->QuadPos.xyzw[1].f[0];
const float dadx = mach->InterpCoefs[attrib].dadx[chan];
const float dady = mach->InterpCoefs[attrib].dady[chan];
const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
mach->Inputs[attrib].xyzw[chan].f[0] = a0;
mach->Inputs[attrib].xyzw[chan].f[1] = a0 + dadx;
mach->Inputs[attrib].xyzw[chan].f[2] = a0 + dady;
mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady;
}
 
/**
* Evaluate a perspective-valued coefficient at the position of the
* current quad.
*/
static void
eval_perspective_coef(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan )
{
const float x = mach->QuadPos.xyzw[0].f[0];
const float y = mach->QuadPos.xyzw[1].f[0];
const float dadx = mach->InterpCoefs[attrib].dadx[chan];
const float dady = mach->InterpCoefs[attrib].dady[chan];
const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
const float *w = mach->QuadPos.xyzw[3].f;
/* divide by W here */
mach->Inputs[attrib].xyzw[chan].f[0] = a0 / w[0];
mach->Inputs[attrib].xyzw[chan].f[1] = (a0 + dadx) / w[1];
mach->Inputs[attrib].xyzw[chan].f[2] = (a0 + dady) / w[2];
mach->Inputs[attrib].xyzw[chan].f[3] = (a0 + dadx + dady) / w[3];
}
 
 
typedef void (* eval_coef_func)(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan );
 
static void
exec_declaration(struct tgsi_exec_machine *mach,
const struct tgsi_full_declaration *decl)
{
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
mach->SamplerViews[decl->Range.First] = decl->SamplerView;
return;
}
 
if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
if (decl->Declaration.File == TGSI_FILE_INPUT) {
uint first, last, mask;
 
first = decl->Range.First;
last = decl->Range.Last;
mask = decl->Declaration.UsageMask;
 
/* XXX we could remove this special-case code since
* mach->InterpCoefs[first].a0 should already have the
* front/back-face value. But we should first update the
* 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;
 
assert(decl->Semantic.Index == 0);
assert(first == last);
 
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
mach->Inputs[first].xyzw[0].f[i] = mach->Face;
}
} else {
eval_coef_func eval;
uint i, j;
 
switch (decl->Interp.Interpolate) {
case TGSI_INTERPOLATE_CONSTANT:
eval = eval_constant_coef;
break;
 
case TGSI_INTERPOLATE_LINEAR:
eval = eval_linear_coef;
break;
 
case TGSI_INTERPOLATE_PERSPECTIVE:
eval = eval_perspective_coef;
break;
 
case TGSI_INTERPOLATE_COLOR:
eval = mach->flatshade_color ? eval_constant_coef : eval_perspective_coef;
break;
 
default:
assert(0);
return;
}
 
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
if (mask & (1 << j)) {
for (i = first; i <= last; i++) {
eval(mach, i, j);
}
}
}
}
 
if (DEBUG_EXECUTION) {
uint i, j;
for (i = first; i <= last; ++i) {
debug_printf("IN[%2u] = ", i);
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
if (j > 0) {
debug_printf(" ");
}
debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n",
mach->Inputs[i].xyzw[0].f[j], mach->Inputs[i].xyzw[0].u[j],
mach->Inputs[i].xyzw[1].f[j], mach->Inputs[i].xyzw[1].u[j],
mach->Inputs[i].xyzw[2].f[j], mach->Inputs[i].xyzw[2].u[j],
mach->Inputs[i].xyzw[3].f[j], mach->Inputs[i].xyzw[3].u[j]);
}
}
}
}
}
 
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
exec_vector(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_op op,
enum tgsi_exec_datatype dst_datatype)
{
unsigned int chan;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel dst;
 
op(&dst);
store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
typedef void (* micro_unary_op)(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src);
 
static void
exec_scalar_unary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_unary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
union tgsi_exec_channel src;
union tgsi_exec_channel dst;
 
fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, src_datatype);
op(&dst, &src);
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
static void
exec_vector_unary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_unary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
struct tgsi_exec_vector dst;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel src;
 
fetch_source(mach, &src, &inst->Src[0], chan, src_datatype);
op(&dst.xyzw[chan], &src);
}
}
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
typedef void (* micro_binary_op)(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1);
 
static void
exec_scalar_binary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_binary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
union tgsi_exec_channel src[2];
union tgsi_exec_channel dst;
 
fetch_source(mach, &src[0], &inst->Src[0], TGSI_CHAN_X, src_datatype);
fetch_source(mach, &src[1], &inst->Src[1], TGSI_CHAN_X, src_datatype);
op(&dst, &src[0], &src[1]);
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
static void
exec_vector_binary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_binary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
struct tgsi_exec_vector dst;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel src[2];
 
fetch_source(mach, &src[0], &inst->Src[0], chan, src_datatype);
fetch_source(mach, &src[1], &inst->Src[1], chan, src_datatype);
op(&dst.xyzw[chan], &src[0], &src[1]);
}
}
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
typedef void (* micro_trinary_op)(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2);
 
static void
exec_vector_trinary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_trinary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
struct tgsi_exec_vector dst;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel src[3];
 
fetch_source(mach, &src[0], &inst->Src[0], chan, src_datatype);
fetch_source(mach, &src[1], &inst->Src[1], chan, src_datatype);
fetch_source(mach, &src[2], &inst->Src[2], chan, src_datatype);
op(&dst.xyzw[chan], &src[0], &src[1], &src[2]);
}
}
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
static void
exec_dp3(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_Z; chan++) {
fetch_source(mach, &arg[0], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], chan, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dp4(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_W; chan++) {
fetch_source(mach, &arg[0], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], chan, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dp2a(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]);
 
fetch_source(mach, &arg[1], &inst->Src[2], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_add(&arg[0], &arg[0], &arg[1]);
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dph(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]);
 
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
micro_add(&arg[0], &arg[0], &arg[1]);
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dp2(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_nrm4(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[4];
union tgsi_exec_channel scale;
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&scale, &arg[0], &arg[0]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_W; chan++) {
union tgsi_exec_channel product;
 
fetch_source(mach, &arg[chan], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
micro_mul(&product, &arg[chan], &arg[chan]);
micro_add(&scale, &scale, &product);
}
 
micro_rsq(&scale, &scale);
 
for (chan = TGSI_CHAN_X; chan <= TGSI_CHAN_W; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
micro_mul(&arg[chan], &arg[chan], &scale);
store_dest(mach, &arg[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_nrm3(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XYZ) {
unsigned int chan;
union tgsi_exec_channel arg[3];
union tgsi_exec_channel scale;
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&scale, &arg[0], &arg[0]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_Z; chan++) {
union tgsi_exec_channel product;
 
fetch_source(mach, &arg[chan], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
micro_mul(&product, &arg[chan], &arg[chan]);
micro_add(&scale, &scale, &product);
}
 
micro_rsq(&scale, &scale);
 
for (chan = TGSI_CHAN_X; chan <= TGSI_CHAN_Z; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
micro_mul(&arg[chan], &arg[chan], &scale);
store_dest(mach, &arg[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_scs(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) {
union tgsi_exec_channel arg;
union tgsi_exec_channel result;
 
fetch_source(mach, &arg, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
micro_cos(&result, &arg);
store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_sin(&result, &arg);
store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &ZeroVec, &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_x2d(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[4];
union tgsi_exec_channel d[2];
 
fetch_source(mach, &r[0], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XZ) {
fetch_source(mach, &r[2], &inst->Src[2], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[2], &r[2], &r[0]);
fetch_source(mach, &r[3], &inst->Src[2], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[3], &r[3], &r[1]);
micro_add(&r[2], &r[2], &r[3]);
fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_add(&d[0], &r[2], &r[3]);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_YW) {
fetch_source(mach, &r[2], &inst->Src[2], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[2], &r[2], &r[0]);
fetch_source(mach, &r[3], &inst->Src[2], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[3], &r[3], &r[1]);
micro_add(&r[2], &r[2], &r[3]);
fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_add(&d[1], &r[2], &r[3]);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &d[0], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
store_dest(mach, &d[1], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &d[0], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &d[1], &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_rfl(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[9];
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XYZ) {
/* r0 = dp3(src0, src0) */
fetch_source(mach, &r[2], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[0], &r[2], &r[2]);
fetch_source(mach, &r[4], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[4], &r[4]);
micro_add(&r[0], &r[0], &r[8]);
fetch_source(mach, &r[6], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[6], &r[6]);
micro_add(&r[0], &r[0], &r[8]);
 
/* r1 = dp3(src0, src1) */
fetch_source(mach, &r[3], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[1], &r[2], &r[3]);
fetch_source(mach, &r[5], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[4], &r[5]);
micro_add(&r[1], &r[1], &r[8]);
fetch_source(mach, &r[7], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[6], &r[7]);
micro_add(&r[1], &r[1], &r[8]);
 
/* r1 = 2 * r1 / r0 */
micro_add(&r[1], &r[1], &r[1]);
micro_div(&r[1], &r[1], &r[0]);
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
micro_mul(&r[2], &r[2], &r[1]);
micro_sub(&r[2], &r[2], &r[3]);
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_mul(&r[4], &r[4], &r[1]);
micro_sub(&r[4], &r[4], &r[5]);
store_dest(mach, &r[4], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
micro_mul(&r[6], &r[6], &r[1]);
micro_sub(&r[6], &r[6], &r[7]);
store_dest(mach, &r[6], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_xpd(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[6];
union tgsi_exec_channel d[3];
 
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[2], &r[0], &r[1]);
 
fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[4], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[5], &r[3], &r[4] );
micro_sub(&d[TGSI_CHAN_X], &r[2], &r[5]);
 
fetch_source(mach, &r[2], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[3], &r[3], &r[2]);
 
fetch_source(mach, &r[5], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[1], &r[1], &r[5]);
micro_sub(&d[TGSI_CHAN_Y], &r[3], &r[1]);
 
micro_mul(&r[5], &r[5], &r[4]);
micro_mul(&r[0], &r[0], &r[2]);
micro_sub(&d[TGSI_CHAN_Z], &r[5], &r[0]);
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &d[TGSI_CHAN_X], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_dst(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[2];
union tgsi_exec_channel d[4];
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&d[TGSI_CHAN_Y], &r[0], &r[1]);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
fetch_source(mach, &d[TGSI_CHAN_Z], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
fetch_source(mach, &d[TGSI_CHAN_W], &inst->Src[1], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &d[TGSI_CHAN_W], &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_log(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[3];
 
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_abs(&r[2], &r[0]); /* r2 = abs(r0) */
micro_lg2(&r[1], &r[2]); /* r1 = lg2(r2) */
micro_flr(&r[0], &r[1]); /* r0 = floor(r1) */
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_exp2(&r[0], &r[0]); /* r0 = 2 ^ r0 */
micro_div(&r[0], &r[2], &r[0]); /* r0 = r2 / r0 */
store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_exp(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[3];
 
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_flr(&r[1], &r[0]); /* r1 = floor(r0) */
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
micro_exp2(&r[2], &r[1]); /* r2 = 2 ^ r1 */
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_sub(&r[2], &r[0], &r[1]); /* r2 = r0 - r1 */
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
micro_exp2(&r[2], &r[0]); /* r2 = 2 ^ r0 */
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_lit(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[3];
union tgsi_exec_channel d[3];
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_YZ) {
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
fetch_source(mach, &r[1], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_max(&r[1], &r[1], &ZeroVec);
 
fetch_source(mach, &r[2], &inst->Src[0], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
micro_min(&r[2], &r[2], &P128Vec);
micro_max(&r[2], &r[2], &M128Vec);
micro_pow(&r[1], &r[1], &r[2]);
micro_lt(&d[TGSI_CHAN_Z], &ZeroVec, &r[0], &r[1], &ZeroVec);
store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_max(&d[TGSI_CHAN_Y], &r[0], &ZeroVec);
store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_break(struct tgsi_exec_machine *mach)
{
if (mach->BreakType == TGSI_EXEC_BREAK_INSIDE_LOOP) {
/* turn off loop channels for each enabled exec channel */
mach->LoopMask &= ~mach->ExecMask;
/* Todo: if mach->LoopMask == 0, jump to end of loop */
UPDATE_EXEC_MASK(mach);
} else {
assert(mach->BreakType == TGSI_EXEC_BREAK_INSIDE_SWITCH);
 
mach->Switch.mask = 0x0;
 
UPDATE_EXEC_MASK(mach);
}
}
 
static void
exec_switch(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
assert(mach->SwitchStackTop < TGSI_EXEC_MAX_SWITCH_NESTING);
assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK);
 
mach->SwitchStack[mach->SwitchStackTop++] = mach->Switch;
fetch_source(mach, &mach->Switch.selector, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_UINT);
mach->Switch.mask = 0x0;
mach->Switch.defaultMask = 0x0;
 
mach->BreakStack[mach->BreakStackTop++] = mach->BreakType;
mach->BreakType = TGSI_EXEC_BREAK_INSIDE_SWITCH;
 
UPDATE_EXEC_MASK(mach);
}
 
static void
exec_case(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
uint prevMask = mach->SwitchStack[mach->SwitchStackTop - 1].mask;
union tgsi_exec_channel src;
uint mask = 0;
 
fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_UINT);
 
if (mach->Switch.selector.u[0] == src.u[0]) {
mask |= 0x1;
}
if (mach->Switch.selector.u[1] == src.u[1]) {
mask |= 0x2;
}
if (mach->Switch.selector.u[2] == src.u[2]) {
mask |= 0x4;
}
if (mach->Switch.selector.u[3] == src.u[3]) {
mask |= 0x8;
}
 
mach->Switch.defaultMask |= mask;
 
mach->Switch.mask |= mask & prevMask;
 
UPDATE_EXEC_MASK(mach);
}
 
/* FIXME: this will only work if default is last */
static void
exec_default(struct tgsi_exec_machine *mach)
{
uint prevMask = mach->SwitchStack[mach->SwitchStackTop - 1].mask;
 
mach->Switch.mask |= ~mach->Switch.defaultMask & prevMask;
 
UPDATE_EXEC_MASK(mach);
}
 
static void
exec_endswitch(struct tgsi_exec_machine *mach)
{
mach->Switch = mach->SwitchStack[--mach->SwitchStackTop];
mach->BreakType = mach->BreakStack[--mach->BreakStackTop];
 
UPDATE_EXEC_MASK(mach);
}
 
static void
micro_i2f(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = (float)src->i[0];
dst->f[1] = (float)src->i[1];
dst->f[2] = (float)src->i[2];
dst->f[3] = (float)src->i[3];
}
 
static void
micro_not(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->u[0] = ~src->u[0];
dst->u[1] = ~src->u[1];
dst->u[2] = ~src->u[2];
dst->u[3] = ~src->u[3];
}
 
static void
micro_shl(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] << src1->u[0];
dst->u[1] = src0->u[1] << src1->u[1];
dst->u[2] = src0->u[2] << src1->u[2];
dst->u[3] = src0->u[3] << src1->u[3];
}
 
static void
micro_and(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] & src1->u[0];
dst->u[1] = src0->u[1] & src1->u[1];
dst->u[2] = src0->u[2] & src1->u[2];
dst->u[3] = src0->u[3] & src1->u[3];
}
 
static void
micro_or(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] | src1->u[0];
dst->u[1] = src0->u[1] | src1->u[1];
dst->u[2] = src0->u[2] | src1->u[2];
dst->u[3] = src0->u[3] | src1->u[3];
}
 
static void
micro_xor(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] ^ src1->u[0];
dst->u[1] = src0->u[1] ^ src1->u[1];
dst->u[2] = src0->u[2] ^ src1->u[2];
dst->u[3] = src0->u[3] ^ src1->u[3];
}
 
static void
micro_mod(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] % src1->i[0];
dst->i[1] = src0->i[1] % src1->i[1];
dst->i[2] = src0->i[2] % src1->i[2];
dst->i[3] = src0->i[3] % src1->i[3];
}
 
static void
micro_f2i(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = (int)src->f[0];
dst->i[1] = (int)src->f[1];
dst->i[2] = (int)src->f[2];
dst->i[3] = (int)src->f[3];
}
 
static void
micro_idiv(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] / src1->i[0];
dst->i[1] = src0->i[1] / src1->i[1];
dst->i[2] = src0->i[2] / src1->i[2];
dst->i[3] = src0->i[3] / src1->i[3];
}
 
static void
micro_imax(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] > src1->i[0] ? src0->i[0] : src1->i[0];
dst->i[1] = src0->i[1] > src1->i[1] ? src0->i[1] : src1->i[1];
dst->i[2] = src0->i[2] > src1->i[2] ? src0->i[2] : src1->i[2];
dst->i[3] = src0->i[3] > src1->i[3] ? src0->i[3] : src1->i[3];
}
 
static void
micro_imin(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] < src1->i[0] ? src0->i[0] : src1->i[0];
dst->i[1] = src0->i[1] < src1->i[1] ? src0->i[1] : src1->i[1];
dst->i[2] = src0->i[2] < src1->i[2] ? src0->i[2] : src1->i[2];
dst->i[3] = src0->i[3] < src1->i[3] ? src0->i[3] : src1->i[3];
}
 
static void
micro_isge(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] >= src1->i[0] ? -1 : 0;
dst->i[1] = src0->i[1] >= src1->i[1] ? -1 : 0;
dst->i[2] = src0->i[2] >= src1->i[2] ? -1 : 0;
dst->i[3] = src0->i[3] >= src1->i[3] ? -1 : 0;
}
 
static void
micro_ishr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] >> src1->i[0];
dst->i[1] = src0->i[1] >> src1->i[1];
dst->i[2] = src0->i[2] >> src1->i[2];
dst->i[3] = src0->i[3] >> src1->i[3];
}
 
static void
micro_islt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] < src1->i[0] ? -1 : 0;
dst->i[1] = src0->i[1] < src1->i[1] ? -1 : 0;
dst->i[2] = src0->i[2] < src1->i[2] ? -1 : 0;
dst->i[3] = src0->i[3] < src1->i[3] ? -1 : 0;
}
 
static void
micro_f2u(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->u[0] = (uint)src->f[0];
dst->u[1] = (uint)src->f[1];
dst->u[2] = (uint)src->f[2];
dst->u[3] = (uint)src->f[3];
}
 
static void
micro_u2f(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = (float)src->u[0];
dst->f[1] = (float)src->u[1];
dst->f[2] = (float)src->u[2];
dst->f[3] = (float)src->u[3];
}
 
static void
micro_uadd(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] + src1->u[0];
dst->u[1] = src0->u[1] + src1->u[1];
dst->u[2] = src0->u[2] + src1->u[2];
dst->u[3] = src0->u[3] + src1->u[3];
}
 
static void
micro_udiv(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src1->u[0] ? src0->u[0] / src1->u[0] : ~0u;
dst->u[1] = src1->u[1] ? src0->u[1] / src1->u[1] : ~0u;
dst->u[2] = src1->u[2] ? src0->u[2] / src1->u[2] : ~0u;
dst->u[3] = src1->u[3] ? src0->u[3] / src1->u[3] : ~0u;
}
 
static void
micro_umad(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->u[0] = src0->u[0] * src1->u[0] + src2->u[0];
dst->u[1] = src0->u[1] * src1->u[1] + src2->u[1];
dst->u[2] = src0->u[2] * src1->u[2] + src2->u[2];
dst->u[3] = src0->u[3] * src1->u[3] + src2->u[3];
}
 
static void
micro_umax(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] > src1->u[0] ? src0->u[0] : src1->u[0];
dst->u[1] = src0->u[1] > src1->u[1] ? src0->u[1] : src1->u[1];
dst->u[2] = src0->u[2] > src1->u[2] ? src0->u[2] : src1->u[2];
dst->u[3] = src0->u[3] > src1->u[3] ? src0->u[3] : src1->u[3];
}
 
static void
micro_umin(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] < src1->u[0] ? src0->u[0] : src1->u[0];
dst->u[1] = src0->u[1] < src1->u[1] ? src0->u[1] : src1->u[1];
dst->u[2] = src0->u[2] < src1->u[2] ? src0->u[2] : src1->u[2];
dst->u[3] = src0->u[3] < src1->u[3] ? src0->u[3] : src1->u[3];
}
 
static void
micro_umod(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src1->u[0] ? src0->u[0] % src1->u[0] : ~0u;
dst->u[1] = src1->u[1] ? src0->u[1] % src1->u[1] : ~0u;
dst->u[2] = src1->u[2] ? src0->u[2] % src1->u[2] : ~0u;
dst->u[3] = src1->u[3] ? src0->u[3] % src1->u[3] : ~0u;
}
 
static void
micro_umul(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] * src1->u[0];
dst->u[1] = src0->u[1] * src1->u[1];
dst->u[2] = src0->u[2] * src1->u[2];
dst->u[3] = src0->u[3] * src1->u[3];
}
 
static void
micro_useq(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] == src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] == src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] == src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] == src1->u[3] ? ~0 : 0;
}
 
static void
micro_usge(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] >= src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] >= src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] >= src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] >= src1->u[3] ? ~0 : 0;
}
 
static void
micro_ushr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] >> src1->u[0];
dst->u[1] = src0->u[1] >> src1->u[1];
dst->u[2] = src0->u[2] >> src1->u[2];
dst->u[3] = src0->u[3] >> src1->u[3];
}
 
static void
micro_uslt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] < src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] < src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] < src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] < src1->u[3] ? ~0 : 0;
}
 
static void
micro_usne(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] != src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] != src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] != src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] != src1->u[3] ? ~0 : 0;
}
 
static void
micro_uarl(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = src->u[0];
dst->i[1] = src->u[1];
dst->i[2] = src->u[2];
dst->i[3] = src->u[3];
}
 
static void
micro_ucmp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->u[0] = src0->u[0] ? src1->u[0] : src2->u[0];
dst->u[1] = src0->u[1] ? src1->u[1] : src2->u[1];
dst->u[2] = src0->u[2] ? src1->u[2] : src2->u[2];
dst->u[3] = src0->u[3] ? src1->u[3] : src2->u[3];
}
 
static void
exec_instruction(
struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
int *pc )
{
union tgsi_exec_channel r[10];
 
(*pc)++;
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_ARL:
exec_vector_unary(mach, inst, micro_arl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_MOV:
exec_vector_unary(mach, inst, micro_mov, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_LIT:
exec_lit(mach, inst);
break;
 
case TGSI_OPCODE_RCP:
exec_scalar_unary(mach, inst, micro_rcp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_RSQ:
exec_scalar_unary(mach, inst, micro_rsq, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_EXP:
exec_exp(mach, inst);
break;
 
case TGSI_OPCODE_LOG:
exec_log(mach, inst);
break;
 
case TGSI_OPCODE_MUL:
exec_vector_binary(mach, inst, micro_mul, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_ADD:
exec_vector_binary(mach, inst, micro_add, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DP3:
exec_dp3(mach, inst);
break;
 
case TGSI_OPCODE_DP4:
exec_dp4(mach, inst);
break;
 
case TGSI_OPCODE_DST:
exec_dst(mach, inst);
break;
 
case TGSI_OPCODE_MIN:
exec_vector_binary(mach, inst, micro_min, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_MAX:
exec_vector_binary(mach, inst, micro_max, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SLT:
exec_vector_binary(mach, inst, micro_slt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SGE:
exec_vector_binary(mach, inst, micro_sge, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_MAD:
exec_vector_trinary(mach, inst, micro_mad, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SUB:
exec_vector_binary(mach, inst, micro_sub, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_LRP:
exec_vector_trinary(mach, inst, micro_lrp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_CND:
exec_vector_trinary(mach, inst, micro_cnd, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SQRT:
exec_scalar_unary(mach, inst, micro_sqrt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DP2A:
exec_dp2a(mach, inst);
break;
 
case TGSI_OPCODE_FRC:
exec_vector_unary(mach, inst, micro_frc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_CLAMP:
exec_vector_trinary(mach, inst, micro_clamp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_FLR:
exec_vector_unary(mach, inst, micro_flr, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_ROUND:
exec_vector_unary(mach, inst, micro_rnd, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_EX2:
exec_scalar_unary(mach, inst, micro_exp2, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_LG2:
exec_scalar_unary(mach, inst, micro_lg2, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_POW:
exec_scalar_binary(mach, inst, micro_pow, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_XPD:
exec_xpd(mach, inst);
break;
 
case TGSI_OPCODE_ABS:
exec_vector_unary(mach, inst, micro_abs, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_RCC:
exec_scalar_unary(mach, inst, micro_rcc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DPH:
exec_dph(mach, inst);
break;
 
case TGSI_OPCODE_COS:
exec_scalar_unary(mach, inst, micro_cos, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DDX:
exec_vector_unary(mach, inst, micro_ddx, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DDY:
exec_vector_unary(mach, inst, micro_ddy, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_KILL:
exec_kill (mach, inst);
break;
 
case TGSI_OPCODE_KILL_IF:
exec_kill_if (mach, inst);
break;
 
case TGSI_OPCODE_PK2H:
assert (0);
break;
 
case TGSI_OPCODE_PK2US:
assert (0);
break;
 
case TGSI_OPCODE_PK4B:
assert (0);
break;
 
case TGSI_OPCODE_PK4UB:
assert (0);
break;
 
case TGSI_OPCODE_RFL:
exec_rfl(mach, inst);
break;
 
case TGSI_OPCODE_SEQ:
exec_vector_binary(mach, inst, micro_seq, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SFL:
exec_vector(mach, inst, micro_sfl, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SGT:
exec_vector_binary(mach, inst, micro_sgt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SIN:
exec_scalar_unary(mach, inst, micro_sin, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SLE:
exec_vector_binary(mach, inst, micro_sle, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SNE:
exec_vector_binary(mach, inst, micro_sne, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_STR:
exec_vector(mach, inst, micro_str, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_TEX:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_NONE, 1);
break;
 
case TGSI_OPCODE_TXB:
/* Texture lookup with lod bias */
/* src[0] = texcoord (src[0].w = LOD bias) */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 1);
break;
 
case TGSI_OPCODE_TXD:
/* Texture lookup with explict partial derivatives */
/* src[0] = texcoord */
/* src[1] = d[strq]/dx */
/* src[2] = d[strq]/dy */
/* src[3] = sampler unit */
exec_txd(mach, inst);
break;
 
case TGSI_OPCODE_TXL:
/* Texture lookup with explit LOD */
/* src[0] = texcoord (src[0].w = LOD) */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 1);
break;
 
case TGSI_OPCODE_TXP:
/* Texture lookup with projection */
/* src[0] = texcoord (src[0].w = projection) */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_PROJECTED, 1);
break;
 
case TGSI_OPCODE_UP2H:
assert (0);
break;
 
case TGSI_OPCODE_UP2US:
assert (0);
break;
 
case TGSI_OPCODE_UP4B:
assert (0);
break;
 
case TGSI_OPCODE_UP4UB:
assert (0);
break;
 
case TGSI_OPCODE_X2D:
exec_x2d(mach, inst);
break;
 
case TGSI_OPCODE_ARA:
assert (0);
break;
 
case TGSI_OPCODE_ARR:
exec_vector_unary(mach, inst, micro_arr, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_BRA:
assert (0);
break;
 
case TGSI_OPCODE_CAL:
/* skip the call if no execution channels are enabled */
if (mach->ExecMask) {
/* do the call */
 
/* First, record the depths of the execution stacks.
* This is important for deeply nested/looped return statements.
* We have to unwind the stacks by the correct amount. For a
* real code generator, we could determine the number of entries
* to pop off each stack with simple static analysis and avoid
* implementing this data structure at run time.
*/
mach->CallStack[mach->CallStackTop].CondStackTop = mach->CondStackTop;
mach->CallStack[mach->CallStackTop].LoopStackTop = mach->LoopStackTop;
mach->CallStack[mach->CallStackTop].ContStackTop = mach->ContStackTop;
mach->CallStack[mach->CallStackTop].SwitchStackTop = mach->SwitchStackTop;
mach->CallStack[mach->CallStackTop].BreakStackTop = mach->BreakStackTop;
/* note that PC was already incremented above */
mach->CallStack[mach->CallStackTop].ReturnAddr = *pc;
 
mach->CallStackTop++;
 
/* Second, push the Cond, Loop, Cont, Func stacks */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->SwitchStackTop < TGSI_EXEC_MAX_SWITCH_NESTING);
assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK);
assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING);
 
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
mach->SwitchStack[mach->SwitchStackTop++] = mach->Switch;
mach->BreakStack[mach->BreakStackTop++] = mach->BreakType;
mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask;
 
/* Finally, jump to the subroutine */
*pc = inst->Label.Label;
}
break;
 
case TGSI_OPCODE_RET:
mach->FuncMask &= ~mach->ExecMask;
UPDATE_EXEC_MASK(mach);
 
if (mach->FuncMask == 0x0) {
/* really return now (otherwise, keep executing */
 
if (mach->CallStackTop == 0) {
/* returning from main() */
mach->CondStackTop = 0;
mach->LoopStackTop = 0;
*pc = -1;
return;
}
 
assert(mach->CallStackTop > 0);
mach->CallStackTop--;
 
mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop;
mach->CondMask = mach->CondStack[mach->CondStackTop];
 
mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop;
mach->LoopMask = mach->LoopStack[mach->LoopStackTop];
 
mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop;
mach->ContMask = mach->ContStack[mach->ContStackTop];
 
mach->SwitchStackTop = mach->CallStack[mach->CallStackTop].SwitchStackTop;
mach->Switch = mach->SwitchStack[mach->SwitchStackTop];
 
mach->BreakStackTop = mach->CallStack[mach->CallStackTop].BreakStackTop;
mach->BreakType = mach->BreakStack[mach->BreakStackTop];
 
assert(mach->FuncStackTop > 0);
mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
 
*pc = mach->CallStack[mach->CallStackTop].ReturnAddr;
 
UPDATE_EXEC_MASK(mach);
}
break;
 
case TGSI_OPCODE_SSG:
exec_vector_unary(mach, inst, micro_sgn, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_CMP:
exec_vector_trinary(mach, inst, micro_cmp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SCS:
exec_scs(mach, inst);
break;
 
case TGSI_OPCODE_NRM:
exec_nrm3(mach, inst);
break;
 
case TGSI_OPCODE_NRM4:
exec_nrm4(mach, inst);
break;
 
case TGSI_OPCODE_DIV:
exec_vector_binary(mach, inst, micro_div, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DP2:
exec_dp2(mach, inst);
break;
 
case TGSI_OPCODE_IF:
/* push CondMask */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
FETCH( &r[0], 0, TGSI_CHAN_X );
/* update CondMask */
if( ! r[0].f[0] ) {
mach->CondMask &= ~0x1;
}
if( ! r[0].f[1] ) {
mach->CondMask &= ~0x2;
}
if( ! r[0].f[2] ) {
mach->CondMask &= ~0x4;
}
if( ! r[0].f[3] ) {
mach->CondMask &= ~0x8;
}
UPDATE_EXEC_MASK(mach);
/* Todo: If CondMask==0, jump to ELSE */
break;
 
case TGSI_OPCODE_UIF:
/* push CondMask */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
IFETCH( &r[0], 0, TGSI_CHAN_X );
/* update CondMask */
if( ! r[0].u[0] ) {
mach->CondMask &= ~0x1;
}
if( ! r[0].u[1] ) {
mach->CondMask &= ~0x2;
}
if( ! r[0].u[2] ) {
mach->CondMask &= ~0x4;
}
if( ! r[0].u[3] ) {
mach->CondMask &= ~0x8;
}
UPDATE_EXEC_MASK(mach);
/* Todo: If CondMask==0, jump to ELSE */
break;
 
case TGSI_OPCODE_ELSE:
/* invert CondMask wrt previous mask */
{
uint prevMask;
assert(mach->CondStackTop > 0);
prevMask = mach->CondStack[mach->CondStackTop - 1];
mach->CondMask = ~mach->CondMask & prevMask;
UPDATE_EXEC_MASK(mach);
/* Todo: If CondMask==0, jump to ENDIF */
}
break;
 
case TGSI_OPCODE_ENDIF:
/* pop CondMask */
assert(mach->CondStackTop > 0);
mach->CondMask = mach->CondStack[--mach->CondStackTop];
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_END:
/* make sure we end primitives which haven't
* been explicitly emitted */
conditional_emit_primitive(mach);
/* halt execution */
*pc = -1;
break;
 
case TGSI_OPCODE_PUSHA:
assert (0);
break;
 
case TGSI_OPCODE_POPA:
assert (0);
break;
 
case TGSI_OPCODE_CEIL:
exec_vector_unary(mach, inst, micro_ceil, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_I2F:
exec_vector_unary(mach, inst, micro_i2f, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_NOT:
exec_vector_unary(mach, inst, micro_not, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_TRUNC:
exec_vector_unary(mach, inst, micro_trunc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SHL:
exec_vector_binary(mach, inst, micro_shl, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_AND:
exec_vector_binary(mach, inst, micro_and, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_OR:
exec_vector_binary(mach, inst, micro_or, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_MOD:
exec_vector_binary(mach, inst, micro_mod, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_XOR:
exec_vector_binary(mach, inst, micro_xor, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_SAD:
assert (0);
break;
 
case TGSI_OPCODE_TXF:
exec_txf(mach, inst);
break;
 
case TGSI_OPCODE_TXQ:
exec_txq(mach, inst);
break;
 
case TGSI_OPCODE_EMIT:
emit_vertex(mach);
break;
 
case TGSI_OPCODE_ENDPRIM:
emit_primitive(mach);
break;
 
case TGSI_OPCODE_BGNLOOP:
/* push LoopMask and ContMasks */
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->LoopLabelStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK);
 
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
mach->LoopLabelStack[mach->LoopLabelStackTop++] = *pc - 1;
mach->BreakStack[mach->BreakStackTop++] = mach->BreakType;
mach->BreakType = TGSI_EXEC_BREAK_INSIDE_LOOP;
break;
 
case TGSI_OPCODE_ENDLOOP:
/* Restore ContMask, but don't pop */
assert(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
UPDATE_EXEC_MASK(mach);
if (mach->ExecMask) {
/* repeat loop: jump to instruction just past BGNLOOP */
assert(mach->LoopLabelStackTop > 0);
*pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1;
}
else {
/* exit loop: pop LoopMask */
assert(mach->LoopStackTop > 0);
mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
/* pop ContMask */
assert(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[--mach->ContStackTop];
assert(mach->LoopLabelStackTop > 0);
--mach->LoopLabelStackTop;
 
mach->BreakType = mach->BreakStack[--mach->BreakStackTop];
}
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_BRK:
exec_break(mach);
break;
 
case TGSI_OPCODE_CONT:
/* turn off cont channels for each enabled exec channel */
mach->ContMask &= ~mach->ExecMask;
/* Todo: if mach->LoopMask == 0, jump to end of loop */
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_BGNSUB:
/* no-op */
break;
 
case TGSI_OPCODE_ENDSUB:
/*
* XXX: This really should be a no-op. We should never reach this opcode.
*/
 
assert(mach->CallStackTop > 0);
mach->CallStackTop--;
 
mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop;
mach->CondMask = mach->CondStack[mach->CondStackTop];
 
mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop;
mach->LoopMask = mach->LoopStack[mach->LoopStackTop];
 
mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop;
mach->ContMask = mach->ContStack[mach->ContStackTop];
 
mach->SwitchStackTop = mach->CallStack[mach->CallStackTop].SwitchStackTop;
mach->Switch = mach->SwitchStack[mach->SwitchStackTop];
 
mach->BreakStackTop = mach->CallStack[mach->CallStackTop].BreakStackTop;
mach->BreakType = mach->BreakStack[mach->BreakStackTop];
 
assert(mach->FuncStackTop > 0);
mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
 
*pc = mach->CallStack[mach->CallStackTop].ReturnAddr;
 
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_NOP:
break;
 
case TGSI_OPCODE_BREAKC:
IFETCH(&r[0], 0, TGSI_CHAN_X);
/* update CondMask */
if (r[0].u[0] && (mach->ExecMask & 0x1)) {
mach->LoopMask &= ~0x1;
}
if (r[0].u[1] && (mach->ExecMask & 0x2)) {
mach->LoopMask &= ~0x2;
}
if (r[0].u[2] && (mach->ExecMask & 0x4)) {
mach->LoopMask &= ~0x4;
}
if (r[0].u[3] && (mach->ExecMask & 0x8)) {
mach->LoopMask &= ~0x8;
}
/* Todo: if mach->LoopMask == 0, jump to end of loop */
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_F2I:
exec_vector_unary(mach, inst, micro_f2i, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_IDIV:
exec_vector_binary(mach, inst, micro_idiv, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_IMAX:
exec_vector_binary(mach, inst, micro_imax, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_IMIN:
exec_vector_binary(mach, inst, micro_imin, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_INEG:
exec_vector_unary(mach, inst, micro_ineg, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISGE:
exec_vector_binary(mach, inst, micro_isge, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISHR:
exec_vector_binary(mach, inst, micro_ishr, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISLT:
exec_vector_binary(mach, inst, micro_islt, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_F2U:
exec_vector_unary(mach, inst, micro_f2u, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_U2F:
exec_vector_unary(mach, inst, micro_u2f, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UADD:
exec_vector_binary(mach, inst, micro_uadd, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_UDIV:
exec_vector_binary(mach, inst, micro_udiv, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMAD:
exec_vector_trinary(mach, inst, micro_umad, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMAX:
exec_vector_binary(mach, inst, micro_umax, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMIN:
exec_vector_binary(mach, inst, micro_umin, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMOD:
exec_vector_binary(mach, inst, micro_umod, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMUL:
exec_vector_binary(mach, inst, micro_umul, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USEQ:
exec_vector_binary(mach, inst, micro_useq, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USGE:
exec_vector_binary(mach, inst, micro_usge, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USHR:
exec_vector_binary(mach, inst, micro_ushr, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USLT:
exec_vector_binary(mach, inst, micro_uslt, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USNE:
exec_vector_binary(mach, inst, micro_usne, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_SWITCH:
exec_switch(mach, inst);
break;
 
case TGSI_OPCODE_CASE:
exec_case(mach, inst);
break;
 
case TGSI_OPCODE_DEFAULT:
exec_default(mach);
break;
 
case TGSI_OPCODE_ENDSWITCH:
exec_endswitch(mach);
break;
 
case TGSI_OPCODE_SAMPLE_I:
exec_txf(mach, inst);
break;
 
case TGSI_OPCODE_SAMPLE_I_MS:
assert(0);
break;
 
case TGSI_OPCODE_SAMPLE:
exec_sample(mach, inst, TEX_MODIFIER_NONE, FALSE);
break;
 
case TGSI_OPCODE_SAMPLE_B:
exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS, FALSE);
break;
 
case TGSI_OPCODE_SAMPLE_C:
exec_sample(mach, inst, TEX_MODIFIER_NONE, TRUE);
break;
 
case TGSI_OPCODE_SAMPLE_C_LZ:
exec_sample(mach, inst, TEX_MODIFIER_LEVEL_ZERO, TRUE);
break;
 
case TGSI_OPCODE_SAMPLE_D:
exec_sample_d(mach, inst);
break;
 
case TGSI_OPCODE_SAMPLE_L:
exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, FALSE);
break;
 
case TGSI_OPCODE_GATHER4:
assert(0);
break;
 
case TGSI_OPCODE_SVIEWINFO:
exec_txq(mach, inst);
break;
 
case TGSI_OPCODE_SAMPLE_POS:
assert(0);
break;
 
case TGSI_OPCODE_SAMPLE_INFO:
assert(0);
break;
 
case TGSI_OPCODE_UARL:
exec_vector_unary(mach, inst, micro_uarl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UCMP:
exec_vector_trinary(mach, inst, micro_ucmp, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_IABS:
exec_vector_unary(mach, inst, micro_iabs, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISSG:
exec_vector_unary(mach, inst, micro_isgn, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_TEX2:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = compare */
/* src[2] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_NONE, 2);
break;
case TGSI_OPCODE_TXB2:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = bias */
/* src[2] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 2);
break;
case TGSI_OPCODE_TXL2:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = lod */
/* src[2] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 2);
break;
default:
assert( 0 );
}
}
 
 
/**
* Run TGSI interpreter.
* \return bitmask of "alive" quad components
*/
uint
tgsi_exec_machine_run( struct tgsi_exec_machine *mach )
{
uint i;
int pc = 0;
uint default_mask = 0xf;
 
mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0;
mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0;
 
if( mach->Processor == TGSI_PROCESSOR_GEOMETRY ) {
mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0;
mach->Primitives[0] = 0;
/* GS runs on a single primitive for now */
default_mask = 0x1;
}
 
mach->CondMask = default_mask;
mach->LoopMask = default_mask;
mach->ContMask = default_mask;
mach->FuncMask = default_mask;
mach->ExecMask = default_mask;
 
mach->Switch.mask = default_mask;
 
assert(mach->CondStackTop == 0);
assert(mach->LoopStackTop == 0);
assert(mach->ContStackTop == 0);
assert(mach->SwitchStackTop == 0);
assert(mach->BreakStackTop == 0);
assert(mach->CallStackTop == 0);
 
 
/* execute declarations (interpolants) */
for (i = 0; i < mach->NumDeclarations; i++) {
exec_declaration( mach, mach->Declarations+i );
}
 
{
#if DEBUG_EXECUTION
struct tgsi_exec_vector temps[TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_TEMP_EXTRAS];
struct tgsi_exec_vector outputs[PIPE_MAX_ATTRIBS];
uint inst = 1;
 
memset(mach->Temps, 0, sizeof(temps));
memset(mach->Outputs, 0, sizeof(outputs));
memset(temps, 0, sizeof(temps));
memset(outputs, 0, sizeof(outputs));
#endif
 
/* execute instructions, until pc is set to -1 */
while (pc != -1) {
 
#if DEBUG_EXECUTION
uint i;
 
tgsi_dump_instruction(&mach->Instructions[pc], inst++);
#endif
 
assert(pc < (int) mach->NumInstructions);
exec_instruction(mach, mach->Instructions + pc, &pc);
 
#if DEBUG_EXECUTION
for (i = 0; i < TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_TEMP_EXTRAS; i++) {
if (memcmp(&temps[i], &mach->Temps[i], sizeof(temps[i]))) {
uint j;
 
memcpy(&temps[i], &mach->Temps[i], sizeof(temps[i]));
debug_printf("TEMP[%2u] = ", i);
for (j = 0; j < 4; j++) {
if (j > 0) {
debug_printf(" ");
}
debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n",
temps[i].xyzw[0].f[j], temps[i].xyzw[0].u[j],
temps[i].xyzw[1].f[j], temps[i].xyzw[1].u[j],
temps[i].xyzw[2].f[j], temps[i].xyzw[2].u[j],
temps[i].xyzw[3].f[j], temps[i].xyzw[3].u[j]);
}
}
}
for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
if (memcmp(&outputs[i], &mach->Outputs[i], sizeof(outputs[i]))) {
uint j;
 
memcpy(&outputs[i], &mach->Outputs[i], sizeof(outputs[i]));
debug_printf("OUT[%2u] = ", i);
for (j = 0; j < 4; j++) {
if (j > 0) {
debug_printf(" ");
}
debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n",
outputs[i].xyzw[0].f[j], outputs[i].xyzw[0].u[j],
outputs[i].xyzw[1].f[j], outputs[i].xyzw[1].u[j],
outputs[i].xyzw[2].f[j], outputs[i].xyzw[2].u[j],
outputs[i].xyzw[3].f[j], outputs[i].xyzw[3].u[j]);
}
}
}
#endif
}
}
 
#if 0
/* we scale from floats in [0,1] to Zbuffer ints in sp_quad_depth_test.c */
if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
/*
* Scale back depth component.
*/
for (i = 0; i < 4; i++)
mach->Outputs[0].xyzw[2].f[i] *= ctx->DrawBuffer->_DepthMaxF;
}
#endif
 
/* Strictly speaking, these assertions aren't really needed but they
* can potentially catch some bugs in the control flow code.
*/
assert(mach->CondStackTop == 0);
assert(mach->LoopStackTop == 0);
assert(mach->ContStackTop == 0);
assert(mach->SwitchStackTop == 0);
assert(mach->BreakStackTop == 0);
assert(mach->CallStackTop == 0);
 
return ~mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_exec.h
0,0 → 1,463
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009-2010 VMware, Inc. All rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_EXEC_H
#define TGSI_EXEC_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
#define TGSI_CHAN_X 0
#define TGSI_CHAN_Y 1
#define TGSI_CHAN_Z 2
#define TGSI_CHAN_W 3
 
#define TGSI_NUM_CHANNELS 4 /* R,G,B,A */
#define TGSI_QUAD_SIZE 4 /* 4 pixel/quad */
 
#define TGSI_FOR_EACH_CHANNEL( CHAN )\
for (CHAN = 0; CHAN < TGSI_NUM_CHANNELS; CHAN++)
 
#define TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
((INST)->Dst[0].Register.WriteMask & (1 << (CHAN)))
 
#define TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
if (TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN ))
 
#define TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
TGSI_FOR_EACH_CHANNEL( CHAN )\
TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
 
 
/**
* Registers may be treated as float, signed int or unsigned int.
*/
union tgsi_exec_channel
{
float f[TGSI_QUAD_SIZE];
int i[TGSI_QUAD_SIZE];
unsigned u[TGSI_QUAD_SIZE];
};
 
/**
* A vector[RGBA] of channels[4 pixels]
*/
struct tgsi_exec_vector
{
union tgsi_exec_channel xyzw[TGSI_NUM_CHANNELS];
};
 
/**
* For fragment programs, information for computing fragment input
* values from plane equation of the triangle/line.
*/
struct tgsi_interp_coef
{
float a0[TGSI_NUM_CHANNELS]; /* in an xyzw layout */
float dadx[TGSI_NUM_CHANNELS];
float dady[TGSI_NUM_CHANNELS];
};
 
enum tgsi_sampler_control {
tgsi_sampler_lod_none,
tgsi_sampler_lod_bias,
tgsi_sampler_lod_explicit,
tgsi_sampler_lod_zero,
tgsi_sampler_derivs_explicit
};
 
/**
* Information for sampling textures, which must be implemented
* by code outside the TGSI executor.
*/
struct tgsi_sampler
{
/** Get samples for four fragments in a quad */
/* this interface contains 5 sets of channels that vary
* depending on the sampler.
* s - the first texture coordinate for sampling.
* t - the second texture coordinate for sampling - unused for 1D,
layer for 1D arrays.
* r - the third coordinate for sampling for 3D, cube, cube arrays,
* layer for 2D arrays. Compare value for 1D/2D shadows.
* c0 - Compare value for shadow cube and shadow 2d arrays,
* layer for cube arrays.
* derivs - explicit derivatives.
* offset - texel offsets
* lod - lod value, except for shadow cube arrays (compare value there).
*/
void (*get_samples)(struct tgsi_sampler *sampler,
const unsigned sview_index,
const unsigned sampler_index,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float r[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float c1[TGSI_QUAD_SIZE],
float derivs[3][2][TGSI_QUAD_SIZE],
const int8_t offset[3],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
void (*get_dims)(struct tgsi_sampler *sampler,
const unsigned sview_index,
int level, int dims[4]);
void (*get_texel)(struct tgsi_sampler *sampler,
const unsigned sview_index,
const int i[TGSI_QUAD_SIZE],
const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
};
 
#define TGSI_EXEC_NUM_TEMPS 4096
#define TGSI_EXEC_NUM_IMMEDIATES 256
 
/*
* Locations of various utility registers (_I = Index, _C = Channel)
*/
#define TGSI_EXEC_TEMP_00000000_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_00000000_C 0
 
#define TGSI_EXEC_TEMP_7FFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_7FFFFFFF_C 1
 
#define TGSI_EXEC_TEMP_80000000_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_80000000_C 2
 
#define TGSI_EXEC_TEMP_FFFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_FFFFFFFF_C 3
 
#define TGSI_EXEC_TEMP_ONE_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_ONE_C 0
 
#define TGSI_EXEC_TEMP_TWO_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_TWO_C 1
 
#define TGSI_EXEC_TEMP_128_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_128_C 2
 
#define TGSI_EXEC_TEMP_MINUS_128_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_MINUS_128_C 3
 
#define TGSI_EXEC_TEMP_KILMASK_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_KILMASK_C 0
 
#define TGSI_EXEC_TEMP_OUTPUT_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_OUTPUT_C 1
 
#define TGSI_EXEC_TEMP_PRIMITIVE_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_PRIMITIVE_C 2
 
#define TGSI_EXEC_TEMP_THREE_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_THREE_C 3
 
#define TGSI_EXEC_TEMP_HALF_I (TGSI_EXEC_NUM_TEMPS + 3)
#define TGSI_EXEC_TEMP_HALF_C 0
 
/* execution mask, each value is either 0 or ~0 */
#define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3)
#define TGSI_EXEC_MASK_C 1
 
/* 4 register buffer for various purposes */
#define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4)
#define TGSI_EXEC_NUM_TEMP_R 4
 
#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8)
#define TGSI_EXEC_NUM_ADDRS 1
 
/* predicate register */
#define TGSI_EXEC_TEMP_P0 (TGSI_EXEC_NUM_TEMPS + 9)
#define TGSI_EXEC_NUM_PREDS 1
 
#define TGSI_EXEC_NUM_TEMP_EXTRAS 10
 
 
 
#define TGSI_EXEC_MAX_NESTING 32
#define TGSI_EXEC_MAX_COND_NESTING TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_LOOP_NESTING TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_SWITCH_NESTING TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_CALL_NESTING TGSI_EXEC_MAX_NESTING
 
/* The maximum number of input attributes per vertex. For 2D
* input register files, this is the stride between two 1D
* arrays.
*/
#define TGSI_EXEC_MAX_INPUT_ATTRIBS 17
 
/* The maximum number of constant vectors per constant buffer.
*/
#define TGSI_EXEC_MAX_CONST_BUFFER 4096
 
/* The maximum number of vertices per primitive */
#define TGSI_MAX_PRIM_VERTICES 6
 
/* The maximum number of primitives to be generated */
#define TGSI_MAX_PRIMITIVES 64
 
/* 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
{
uint CondStackTop;
uint LoopStackTop;
uint ContStackTop;
int SwitchStackTop;
int BreakStackTop;
uint ReturnAddr;
};
 
 
/* Switch-case block state. */
struct tgsi_switch_record {
uint mask; /**< execution mask */
union tgsi_exec_channel selector; /**< a value case statements are compared to */
uint defaultMask; /**< non-execute mask for default case */
};
 
 
enum tgsi_break_type {
TGSI_EXEC_BREAK_INSIDE_LOOP,
TGSI_EXEC_BREAK_INSIDE_SWITCH
};
 
 
#define TGSI_EXEC_MAX_BREAK_STACK (TGSI_EXEC_MAX_LOOP_NESTING + TGSI_EXEC_MAX_SWITCH_NESTING)
 
 
/**
* Run-time virtual machine state for executing TGSI shader.
*/
struct tgsi_exec_machine
{
/* Total = program temporaries + internal temporaries
*/
struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS +
TGSI_EXEC_NUM_TEMP_EXTRAS];
 
float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
 
float ImmArray[TGSI_EXEC_NUM_IMMEDIATES][4];
 
struct tgsi_exec_vector *Inputs;
struct tgsi_exec_vector *Outputs;
 
/* System values */
unsigned SysSemanticToIndex[TGSI_SEMANTIC_COUNT];
union tgsi_exec_channel SystemValue[TGSI_MAX_MISC_INPUTS];
 
struct tgsi_exec_vector *Addrs;
struct tgsi_exec_vector *Predicates;
 
struct tgsi_sampler *Sampler;
 
unsigned ImmLimit;
 
const void *Consts[PIPE_MAX_CONSTANT_BUFFERS];
unsigned ConstsSize[PIPE_MAX_CONSTANT_BUFFERS];
 
const struct tgsi_token *Tokens; /**< Declarations, instructions */
unsigned Processor; /**< TGSI_PROCESSOR_x */
 
/* GEOMETRY processor only. */
unsigned *Primitives;
unsigned NumOutputs;
unsigned MaxGeometryShaderOutputs;
 
/* FRAGMENT processor only. */
const struct tgsi_interp_coef *InterpCoefs;
struct tgsi_exec_vector QuadPos;
float Face; /**< +1 if front facing, -1 if back facing */
bool flatshade_color;
/* Conditional execution masks */
uint CondMask; /**< For IF/ELSE/ENDIF */
uint LoopMask; /**< For BGNLOOP/ENDLOOP */
uint ContMask; /**< For loop CONT statements */
uint FuncMask; /**< For function calls */
uint ExecMask; /**< = CondMask & LoopMask */
 
/* Current switch-case state. */
struct tgsi_switch_record Switch;
 
/* Current break type. */
enum tgsi_break_type BreakType;
 
/** Condition mask stack (for nested conditionals) */
uint CondStack[TGSI_EXEC_MAX_COND_NESTING];
int CondStackTop;
 
/** Loop mask stack (for nested loops) */
uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING];
int LoopStackTop;
 
/** Loop label stack */
uint LoopLabelStack[TGSI_EXEC_MAX_LOOP_NESTING];
int LoopLabelStackTop;
 
/** Loop continue mask stack (see comments in tgsi_exec.c) */
uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING];
int ContStackTop;
 
/** Switch case stack */
struct tgsi_switch_record SwitchStack[TGSI_EXEC_MAX_SWITCH_NESTING];
int SwitchStackTop;
 
enum tgsi_break_type BreakStack[TGSI_EXEC_MAX_BREAK_STACK];
int BreakStackTop;
 
/** Function execution mask stack (for executing subroutine code) */
uint FuncStack[TGSI_EXEC_MAX_CALL_NESTING];
int FuncStackTop;
 
/** Function call stack for saving/restoring the program counter */
struct tgsi_call_record CallStack[TGSI_EXEC_MAX_CALL_NESTING];
int CallStackTop;
 
struct tgsi_full_instruction *Instructions;
uint NumInstructions;
 
struct tgsi_full_declaration *Declarations;
uint NumDeclarations;
 
struct tgsi_declaration_sampler_view
SamplerViews[PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
boolean UsedGeometryShader;
};
 
struct tgsi_exec_machine *
tgsi_exec_machine_create( void );
 
void
tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach);
 
 
void
tgsi_exec_machine_bind_shader(
struct tgsi_exec_machine *mach,
const struct tgsi_token *tokens,
struct tgsi_sampler *sampler);
 
uint
tgsi_exec_machine_run(
struct tgsi_exec_machine *mach );
 
 
void
tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach);
 
 
boolean
tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst);
 
 
static INLINE void
tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask)
{
mach->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] =
mask;
}
 
 
/** Set execution mask values prior to executing the shader */
static INLINE void
tgsi_set_exec_mask(struct tgsi_exec_machine *mach,
boolean ch0, boolean ch1, boolean ch2, boolean ch3)
{
int *mask = mach->Temps[TGSI_EXEC_MASK_I].xyzw[TGSI_EXEC_MASK_C].i;
mask[0] = ch0 ? ~0 : 0;
mask[1] = ch1 ? ~0 : 0;
mask[2] = ch2 ? ~0 : 0;
mask[3] = ch3 ? ~0 : 0;
}
 
 
extern void
tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
unsigned num_bufs,
const void **bufs,
const unsigned *buf_sizes);
 
 
static INLINE int
tgsi_exec_get_shader_param(enum pipe_shader_cap param)
{
switch(param) {
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
return INT_MAX;
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
return TGSI_EXEC_MAX_NESTING;
case PIPE_SHADER_CAP_MAX_INPUTS:
return TGSI_EXEC_MAX_INPUT_ATTRIBS;
case PIPE_SHADER_CAP_MAX_CONSTS:
return TGSI_EXEC_MAX_CONST_BUFFER;
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return PIPE_MAX_CONSTANT_BUFFERS;
case PIPE_SHADER_CAP_MAX_TEMPS:
return TGSI_EXEC_NUM_TEMPS;
case PIPE_SHADER_CAP_MAX_ADDRS:
return TGSI_EXEC_NUM_ADDRS;
case PIPE_SHADER_CAP_MAX_PREDS:
return TGSI_EXEC_NUM_PREDS;
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
return 1;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
return 1;
case PIPE_SHADER_CAP_SUBROUTINES:
return 1;
case PIPE_SHADER_CAP_INTEGERS:
return 1;
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
return PIPE_MAX_SAMPLERS;
case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
return 1;
default:
return 0;
}
}
 
#if defined __cplusplus
} /* extern "C" */
#endif
 
#endif /* TGSI_EXEC_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_info.c
0,0 → 1,360
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "tgsi_info.h"
 
#define NONE TGSI_OUTPUT_NONE
#define COMP TGSI_OUTPUT_COMPONENTWISE
#define REPL TGSI_OUTPUT_REPLICATE
#define CHAN TGSI_OUTPUT_CHAN_DEPENDENT
#define OTHR TGSI_OUTPUT_OTHER
 
static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
{
{ 1, 1, 0, 0, 0, 0, COMP, "ARL", TGSI_OPCODE_ARL },
{ 1, 1, 0, 0, 0, 0, COMP, "MOV", TGSI_OPCODE_MOV },
{ 1, 1, 0, 0, 0, 0, CHAN, "LIT", TGSI_OPCODE_LIT },
{ 1, 1, 0, 0, 0, 0, REPL, "RCP", TGSI_OPCODE_RCP },
{ 1, 1, 0, 0, 0, 0, REPL, "RSQ", TGSI_OPCODE_RSQ },
{ 1, 1, 0, 0, 0, 0, CHAN, "EXP", TGSI_OPCODE_EXP },
{ 1, 1, 0, 0, 0, 0, CHAN, "LOG", TGSI_OPCODE_LOG },
{ 1, 2, 0, 0, 0, 0, COMP, "MUL", TGSI_OPCODE_MUL },
{ 1, 2, 0, 0, 0, 0, COMP, "ADD", TGSI_OPCODE_ADD },
{ 1, 2, 0, 0, 0, 0, REPL, "DP3", TGSI_OPCODE_DP3 },
{ 1, 2, 0, 0, 0, 0, REPL, "DP4", TGSI_OPCODE_DP4 },
{ 1, 2, 0, 0, 0, 0, CHAN, "DST", TGSI_OPCODE_DST },
{ 1, 2, 0, 0, 0, 0, COMP, "MIN", TGSI_OPCODE_MIN },
{ 1, 2, 0, 0, 0, 0, COMP, "MAX", TGSI_OPCODE_MAX },
{ 1, 2, 0, 0, 0, 0, COMP, "SLT", TGSI_OPCODE_SLT },
{ 1, 2, 0, 0, 0, 0, COMP, "SGE", TGSI_OPCODE_SGE },
{ 1, 3, 0, 0, 0, 0, COMP, "MAD", TGSI_OPCODE_MAD },
{ 1, 2, 0, 0, 0, 0, COMP, "SUB", TGSI_OPCODE_SUB },
{ 1, 3, 0, 0, 0, 0, COMP, "LRP", TGSI_OPCODE_LRP },
{ 1, 3, 0, 0, 0, 0, COMP, "CND", TGSI_OPCODE_CND },
{ 1, 1, 0, 0, 0, 0, REPL, "SQRT", TGSI_OPCODE_SQRT },
{ 1, 3, 0, 0, 0, 0, REPL, "DP2A", TGSI_OPCODE_DP2A },
{ 0, 0, 0, 0, 0, 0, NONE, "", 22 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 23 }, /* removed */
{ 1, 1, 0, 0, 0, 0, COMP, "FRC", TGSI_OPCODE_FRC },
{ 1, 3, 0, 0, 0, 0, COMP, "CLAMP", TGSI_OPCODE_CLAMP },
{ 1, 1, 0, 0, 0, 0, COMP, "FLR", TGSI_OPCODE_FLR },
{ 1, 1, 0, 0, 0, 0, COMP, "ROUND", TGSI_OPCODE_ROUND },
{ 1, 1, 0, 0, 0, 0, REPL, "EX2", TGSI_OPCODE_EX2 },
{ 1, 1, 0, 0, 0, 0, REPL, "LG2", TGSI_OPCODE_LG2 },
{ 1, 2, 0, 0, 0, 0, REPL, "POW", TGSI_OPCODE_POW },
{ 1, 2, 0, 0, 0, 0, COMP, "XPD", TGSI_OPCODE_XPD },
{ 0, 0, 0, 0, 0, 0, NONE, "", 32 }, /* removed */
{ 1, 1, 0, 0, 0, 0, COMP, "ABS", TGSI_OPCODE_ABS },
{ 1, 1, 0, 0, 0, 0, REPL, "RCC", TGSI_OPCODE_RCC },
{ 1, 2, 0, 0, 0, 0, REPL, "DPH", TGSI_OPCODE_DPH },
{ 1, 1, 0, 0, 0, 0, REPL, "COS", TGSI_OPCODE_COS },
{ 1, 1, 0, 0, 0, 0, COMP, "DDX", TGSI_OPCODE_DDX },
{ 1, 1, 0, 0, 0, 0, COMP, "DDY", TGSI_OPCODE_DDY },
{ 0, 0, 0, 0, 0, 0, NONE, "KILL", TGSI_OPCODE_KILL },
{ 1, 1, 0, 0, 0, 0, COMP, "PK2H", TGSI_OPCODE_PK2H },
{ 1, 1, 0, 0, 0, 0, COMP, "PK2US", TGSI_OPCODE_PK2US },
{ 1, 1, 0, 0, 0, 0, COMP, "PK4B", TGSI_OPCODE_PK4B },
{ 1, 1, 0, 0, 0, 0, COMP, "PK4UB", TGSI_OPCODE_PK4UB },
{ 1, 2, 0, 0, 0, 0, COMP, "RFL", TGSI_OPCODE_RFL },
{ 1, 2, 0, 0, 0, 0, COMP, "SEQ", TGSI_OPCODE_SEQ },
{ 1, 2, 0, 0, 0, 0, REPL, "SFL", TGSI_OPCODE_SFL },
{ 1, 2, 0, 0, 0, 0, COMP, "SGT", TGSI_OPCODE_SGT },
{ 1, 1, 0, 0, 0, 0, REPL, "SIN", TGSI_OPCODE_SIN },
{ 1, 2, 0, 0, 0, 0, COMP, "SLE", TGSI_OPCODE_SLE },
{ 1, 2, 0, 0, 0, 0, COMP, "SNE", TGSI_OPCODE_SNE },
{ 1, 2, 0, 0, 0, 0, REPL, "STR", TGSI_OPCODE_STR },
{ 1, 2, 1, 0, 0, 0, OTHR, "TEX", TGSI_OPCODE_TEX },
{ 1, 4, 1, 0, 0, 0, OTHR, "TXD", TGSI_OPCODE_TXD },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXP", TGSI_OPCODE_TXP },
{ 1, 1, 0, 0, 0, 0, COMP, "UP2H", TGSI_OPCODE_UP2H },
{ 1, 1, 0, 0, 0, 0, COMP, "UP2US", TGSI_OPCODE_UP2US },
{ 1, 1, 0, 0, 0, 0, COMP, "UP4B", TGSI_OPCODE_UP4B },
{ 1, 1, 0, 0, 0, 0, COMP, "UP4UB", TGSI_OPCODE_UP4UB },
{ 1, 3, 0, 0, 0, 0, COMP, "X2D", TGSI_OPCODE_X2D },
{ 1, 1, 0, 0, 0, 0, COMP, "ARA", TGSI_OPCODE_ARA },
{ 1, 1, 0, 0, 0, 0, COMP, "ARR", TGSI_OPCODE_ARR },
{ 0, 1, 0, 0, 0, 0, NONE, "BRA", TGSI_OPCODE_BRA },
{ 0, 0, 0, 1, 0, 0, NONE, "CAL", TGSI_OPCODE_CAL },
{ 0, 0, 0, 0, 0, 0, NONE, "RET", TGSI_OPCODE_RET },
{ 1, 1, 0, 0, 0, 0, COMP, "SSG", TGSI_OPCODE_SSG },
{ 1, 3, 0, 0, 0, 0, COMP, "CMP", TGSI_OPCODE_CMP },
{ 1, 1, 0, 0, 0, 0, CHAN, "SCS", TGSI_OPCODE_SCS },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXB", TGSI_OPCODE_TXB },
{ 1, 1, 0, 0, 0, 0, COMP, "NRM", TGSI_OPCODE_NRM },
{ 1, 2, 0, 0, 0, 0, COMP, "DIV", TGSI_OPCODE_DIV },
{ 1, 2, 0, 0, 0, 0, REPL, "DP2", TGSI_OPCODE_DP2 },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXL", TGSI_OPCODE_TXL },
{ 0, 0, 0, 0, 0, 0, NONE, "BRK", TGSI_OPCODE_BRK },
{ 0, 1, 0, 1, 0, 1, NONE, "IF", TGSI_OPCODE_IF },
{ 0, 1, 0, 1, 0, 1, NONE, "UIF", TGSI_OPCODE_UIF },
{ 0, 1, 0, 0, 0, 1, NONE, "", 76 }, /* removed */
{ 0, 0, 0, 1, 1, 1, NONE, "ELSE", TGSI_OPCODE_ELSE },
{ 0, 0, 0, 0, 1, 0, NONE, "ENDIF", TGSI_OPCODE_ENDIF },
{ 1, 0, 0, 0, 1, 0, NONE, "", 79 }, /* removed */
{ 0, 0, 0, 0, 1, 0, NONE, "", 80 }, /* removed */
{ 0, 1, 0, 0, 0, 0, NONE, "PUSHA", TGSI_OPCODE_PUSHA },
{ 1, 0, 0, 0, 0, 0, NONE, "POPA", TGSI_OPCODE_POPA },
{ 1, 1, 0, 0, 0, 0, COMP, "CEIL", TGSI_OPCODE_CEIL },
{ 1, 1, 0, 0, 0, 0, COMP, "I2F", TGSI_OPCODE_I2F },
{ 1, 1, 0, 0, 0, 0, COMP, "NOT", TGSI_OPCODE_NOT },
{ 1, 1, 0, 0, 0, 0, COMP, "TRUNC", TGSI_OPCODE_TRUNC },
{ 1, 2, 0, 0, 0, 0, COMP, "SHL", TGSI_OPCODE_SHL },
{ 0, 0, 0, 0, 0, 0, NONE, "", 88 }, /* removed */
{ 1, 2, 0, 0, 0, 0, COMP, "AND", TGSI_OPCODE_AND },
{ 1, 2, 0, 0, 0, 0, COMP, "OR", TGSI_OPCODE_OR },
{ 1, 2, 0, 0, 0, 0, COMP, "MOD", TGSI_OPCODE_MOD },
{ 1, 2, 0, 0, 0, 0, COMP, "XOR", TGSI_OPCODE_XOR },
{ 1, 3, 0, 0, 0, 0, COMP, "SAD", TGSI_OPCODE_SAD },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXF", TGSI_OPCODE_TXF },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXQ", TGSI_OPCODE_TXQ },
{ 0, 0, 0, 0, 0, 0, NONE, "CONT", TGSI_OPCODE_CONT },
{ 0, 0, 0, 0, 0, 0, NONE, "EMIT", TGSI_OPCODE_EMIT },
{ 0, 0, 0, 0, 0, 0, NONE, "ENDPRIM", TGSI_OPCODE_ENDPRIM },
{ 0, 0, 0, 1, 0, 1, NONE, "BGNLOOP", TGSI_OPCODE_BGNLOOP },
{ 0, 0, 0, 0, 0, 1, NONE, "BGNSUB", TGSI_OPCODE_BGNSUB },
{ 0, 0, 0, 1, 1, 0, NONE, "ENDLOOP", TGSI_OPCODE_ENDLOOP },
{ 0, 0, 0, 0, 1, 0, NONE, "ENDSUB", TGSI_OPCODE_ENDSUB },
{ 1, 1, 1, 0, 0, 0, OTHR, "TXQ_LZ", TGSI_OPCODE_TXQ_LZ },
{ 0, 0, 0, 0, 0, 0, NONE, "", 104 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 105 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 106 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "NOP", TGSI_OPCODE_NOP },
{ 0, 0, 0, 0, 0, 0, NONE, "", 108 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 109 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 110 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 111 }, /* removed */
{ 1, 1, 0, 0, 0, 0, REPL, "NRM4", TGSI_OPCODE_NRM4 },
{ 0, 1, 0, 0, 0, 0, NONE, "CALLNZ", TGSI_OPCODE_CALLNZ },
{ 0, 1, 0, 0, 0, 0, NONE, "", 114 }, /* removed */
{ 0, 1, 0, 0, 0, 0, NONE, "BREAKC", TGSI_OPCODE_BREAKC },
{ 0, 1, 0, 0, 0, 0, NONE, "KILL_IF", TGSI_OPCODE_KILL_IF },
{ 0, 0, 0, 0, 0, 0, NONE, "END", TGSI_OPCODE_END },
{ 0, 0, 0, 0, 0, 0, NONE, "", 118 }, /* removed */
{ 1, 1, 0, 0, 0, 0, COMP, "F2I", TGSI_OPCODE_F2I },
{ 1, 2, 0, 0, 0, 0, COMP, "IDIV", TGSI_OPCODE_IDIV },
{ 1, 2, 0, 0, 0, 0, COMP, "IMAX", TGSI_OPCODE_IMAX },
{ 1, 2, 0, 0, 0, 0, COMP, "IMIN", TGSI_OPCODE_IMIN },
{ 1, 1, 0, 0, 0, 0, COMP, "INEG", TGSI_OPCODE_INEG },
{ 1, 2, 0, 0, 0, 0, COMP, "ISGE", TGSI_OPCODE_ISGE },
{ 1, 2, 0, 0, 0, 0, COMP, "ISHR", TGSI_OPCODE_ISHR },
{ 1, 2, 0, 0, 0, 0, COMP, "ISLT", TGSI_OPCODE_ISLT },
{ 1, 1, 0, 0, 0, 0, COMP, "F2U", TGSI_OPCODE_F2U },
{ 1, 1, 0, 0, 0, 0, COMP, "U2F", TGSI_OPCODE_U2F },
{ 1, 2, 0, 0, 0, 0, COMP, "UADD", TGSI_OPCODE_UADD },
{ 1, 2, 0, 0, 0, 0, COMP, "UDIV", TGSI_OPCODE_UDIV },
{ 1, 3, 0, 0, 0, 0, COMP, "UMAD", TGSI_OPCODE_UMAD },
{ 1, 2, 0, 0, 0, 0, COMP, "UMAX", TGSI_OPCODE_UMAX },
{ 1, 2, 0, 0, 0, 0, COMP, "UMIN", TGSI_OPCODE_UMIN },
{ 1, 2, 0, 0, 0, 0, COMP, "UMOD", TGSI_OPCODE_UMOD },
{ 1, 2, 0, 0, 0, 0, COMP, "UMUL", TGSI_OPCODE_UMUL },
{ 1, 2, 0, 0, 0, 0, COMP, "USEQ", TGSI_OPCODE_USEQ },
{ 1, 2, 0, 0, 0, 0, COMP, "USGE", TGSI_OPCODE_USGE },
{ 1, 2, 0, 0, 0, 0, COMP, "USHR", TGSI_OPCODE_USHR },
{ 1, 2, 0, 0, 0, 0, COMP, "USLT", TGSI_OPCODE_USLT },
{ 1, 2, 0, 0, 0, 0, COMP, "USNE", TGSI_OPCODE_USNE },
{ 0, 1, 0, 0, 0, 0, NONE, "SWITCH", TGSI_OPCODE_SWITCH },
{ 0, 1, 0, 0, 0, 0, NONE, "CASE", TGSI_OPCODE_CASE },
{ 0, 0, 0, 0, 0, 0, NONE, "DEFAULT", TGSI_OPCODE_DEFAULT },
{ 0, 0, 0, 0, 0, 0, NONE, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH },
 
{ 1, 3, 0, 0, 0, 0, OTHR, "SAMPLE", TGSI_OPCODE_SAMPLE },
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_I", TGSI_OPCODE_SAMPLE_I },
{ 1, 3, 0, 0, 0, 0, OTHR, "SAMPLE_I_MS", TGSI_OPCODE_SAMPLE_I_MS },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_B", TGSI_OPCODE_SAMPLE_B },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_C", TGSI_OPCODE_SAMPLE_C },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_C_LZ", TGSI_OPCODE_SAMPLE_C_LZ },
{ 1, 5, 0, 0, 0, 0, OTHR, "SAMPLE_D", TGSI_OPCODE_SAMPLE_D },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_L", TGSI_OPCODE_SAMPLE_L },
{ 1, 3, 0, 0, 0, 0, OTHR, "GATHER4", TGSI_OPCODE_GATHER4 },
{ 1, 2, 0, 0, 0, 0, OTHR, "SVIEWINFO", TGSI_OPCODE_SVIEWINFO },
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_POS", TGSI_OPCODE_SAMPLE_POS },
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_INFO", TGSI_OPCODE_SAMPLE_INFO },
{ 1, 1, 0, 0, 0, 0, COMP, "UARL", TGSI_OPCODE_UARL },
{ 1, 3, 0, 0, 0, 0, COMP, "UCMP", TGSI_OPCODE_UCMP },
{ 1, 1, 0, 0, 0, 0, COMP, "IABS", TGSI_OPCODE_IABS },
{ 1, 1, 0, 0, 0, 0, COMP, "ISSG", TGSI_OPCODE_ISSG },
{ 1, 2, 0, 0, 0, 0, OTHR, "LOAD", TGSI_OPCODE_LOAD },
{ 1, 2, 0, 0, 0, 0, OTHR, "STORE", TGSI_OPCODE_STORE },
{ 1, 0, 0, 0, 0, 0, OTHR, "MFENCE", TGSI_OPCODE_MFENCE },
{ 1, 0, 0, 0, 0, 0, OTHR, "LFENCE", TGSI_OPCODE_LFENCE },
{ 1, 0, 0, 0, 0, 0, OTHR, "SFENCE", TGSI_OPCODE_SFENCE },
{ 0, 0, 0, 0, 0, 0, OTHR, "BARRIER", TGSI_OPCODE_BARRIER },
 
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUADD", TGSI_OPCODE_ATOMUADD },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMXCHG", TGSI_OPCODE_ATOMXCHG },
{ 1, 4, 0, 0, 0, 0, OTHR, "ATOMCAS", TGSI_OPCODE_ATOMCAS },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMAND", TGSI_OPCODE_ATOMAND },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMOR", TGSI_OPCODE_ATOMOR },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMXOR", TGSI_OPCODE_ATOMXOR },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUMIN", TGSI_OPCODE_ATOMUMIN },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUMAX", TGSI_OPCODE_ATOMUMAX },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMIMIN", TGSI_OPCODE_ATOMIMIN },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMIMAX", TGSI_OPCODE_ATOMIMAX },
{ 1, 3, 1, 0, 0, 0, OTHR, "TEX2", TGSI_OPCODE_TEX2 },
{ 1, 3, 1, 0, 0, 0, OTHR, "TXB2", TGSI_OPCODE_TXB2 },
{ 1, 3, 1, 0, 0, 0, OTHR, "TXL2", TGSI_OPCODE_TXL2 },
};
 
const struct tgsi_opcode_info *
tgsi_get_opcode_info( uint opcode )
{
static boolean firsttime = 1;
 
if (firsttime) {
unsigned i;
firsttime = 0;
for (i = 0; i < Elements(opcode_info); i++)
assert(opcode_info[i].opcode == i);
}
if (opcode < TGSI_OPCODE_LAST)
return &opcode_info[opcode];
 
assert( 0 );
return NULL;
}
 
 
const char *
tgsi_get_opcode_name( uint opcode )
{
const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
return info->mnemonic;
}
 
 
const char *
tgsi_get_processor_name( uint processor )
{
switch (processor) {
case TGSI_PROCESSOR_VERTEX:
return "vertex shader";
case TGSI_PROCESSOR_FRAGMENT:
return "fragment shader";
case TGSI_PROCESSOR_GEOMETRY:
return "geometry shader";
default:
return "unknown shader type!";
}
}
 
/**
* Infer the type (of the dst) of the opcode.
*
* MOV and UCMP is special so return VOID
*/
static INLINE enum tgsi_opcode_type
tgsi_opcode_infer_type( uint opcode )
{
switch (opcode) {
case TGSI_OPCODE_MOV:
case TGSI_OPCODE_UCMP:
return TGSI_TYPE_UNTYPED;
case TGSI_OPCODE_NOT:
case TGSI_OPCODE_SHL:
case TGSI_OPCODE_AND:
case TGSI_OPCODE_OR:
case TGSI_OPCODE_XOR:
case TGSI_OPCODE_SAD: /* XXX some src args may be signed for SAD ? */
case TGSI_OPCODE_TXQ:
case TGSI_OPCODE_TXQ_LZ:
case TGSI_OPCODE_F2U:
case TGSI_OPCODE_UDIV:
case TGSI_OPCODE_UMAD:
case TGSI_OPCODE_UMAX:
case TGSI_OPCODE_UMIN:
case TGSI_OPCODE_UMOD:
case TGSI_OPCODE_UMUL:
case TGSI_OPCODE_USEQ:
case TGSI_OPCODE_USGE:
case TGSI_OPCODE_USHR:
case TGSI_OPCODE_USLT:
case TGSI_OPCODE_USNE:
case TGSI_OPCODE_SVIEWINFO:
return TGSI_TYPE_UNSIGNED;
case TGSI_OPCODE_ARL:
case TGSI_OPCODE_ARR:
case TGSI_OPCODE_MOD:
case TGSI_OPCODE_F2I:
case TGSI_OPCODE_IDIV:
case TGSI_OPCODE_IMAX:
case TGSI_OPCODE_IMIN:
case TGSI_OPCODE_INEG:
case TGSI_OPCODE_ISGE:
case TGSI_OPCODE_ISHR:
case TGSI_OPCODE_ISLT:
case TGSI_OPCODE_UADD:
case TGSI_OPCODE_UARL:
case TGSI_OPCODE_IABS:
case TGSI_OPCODE_ISSG:
return TGSI_TYPE_SIGNED;
default:
return TGSI_TYPE_FLOAT;
}
}
 
/*
* infer the source type of a TGSI opcode.
*/
enum tgsi_opcode_type
tgsi_opcode_infer_src_type( uint opcode )
{
switch (opcode) {
case TGSI_OPCODE_UIF:
case TGSI_OPCODE_TXF:
case TGSI_OPCODE_BREAKC:
case TGSI_OPCODE_U2F:
case TGSI_OPCODE_UADD:
case TGSI_OPCODE_SWITCH:
case TGSI_OPCODE_CASE:
case TGSI_OPCODE_SAMPLE_I:
case TGSI_OPCODE_SAMPLE_I_MS:
return TGSI_TYPE_UNSIGNED;
case TGSI_OPCODE_I2F:
return TGSI_TYPE_SIGNED;
case TGSI_OPCODE_ARL:
case TGSI_OPCODE_ARR:
case TGSI_OPCODE_TXQ_LZ:
case TGSI_OPCODE_F2I:
case TGSI_OPCODE_F2U:
case TGSI_OPCODE_UCMP:
return TGSI_TYPE_FLOAT;
default:
return tgsi_opcode_infer_type(opcode);
}
}
 
/*
* infer the destination type of a TGSI opcode.
*/
enum tgsi_opcode_type
tgsi_opcode_infer_dst_type( uint opcode )
{
return tgsi_opcode_infer_type(opcode);
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_info.h
0,0 → 1,113
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_INFO_H
#define TGSI_INFO_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_format.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
/* This enum describes how an opcode calculates its result. */
enum tgsi_output_mode {
/** The opcode produces no result. */
TGSI_OUTPUT_NONE = 0,
 
/** When this opcode writes to a channel of the destination register,
* it takes as arguments values from the same channel of the source
* register(s).
*
* Example: TGSI_OPCODE_ADD
*/
TGSI_OUTPUT_COMPONENTWISE = 1,
 
/** This opcode writes the same value to all enabled channels of the
* destination register.
*
* Example: TGSI_OPCODE_RSQ
*/
TGSI_OUTPUT_REPLICATE = 2,
 
/** The operation performed by this opcode is dependent on which channel
* of the destination register is being written.
*
* Example: TGSI_OPCODE_LOG
*/
TGSI_OUTPUT_CHAN_DEPENDENT = 3,
 
/**
* Example: TGSI_OPCODE_TEX
*/
TGSI_OUTPUT_OTHER = 4
};
 
struct tgsi_opcode_info
{
unsigned num_dst:3;
unsigned num_src:3;
unsigned is_tex:1;
unsigned is_branch:1;
int pre_dedent:2;
int post_indent:2;
enum tgsi_output_mode output_mode:3;
const char *mnemonic;
uint opcode;
};
 
const struct tgsi_opcode_info *
tgsi_get_opcode_info( uint opcode );
 
const char *
tgsi_get_opcode_name( uint opcode );
 
const char *
tgsi_get_processor_name( uint processor );
 
enum tgsi_opcode_type {
TGSI_TYPE_UNTYPED, /* for MOV */
TGSI_TYPE_VOID,
TGSI_TYPE_UNSIGNED,
TGSI_TYPE_SIGNED,
TGSI_TYPE_FLOAT,
TGSI_TYPE_DOUBLE
};
 
enum tgsi_opcode_type
tgsi_opcode_infer_src_type( uint opcode );
 
enum tgsi_opcode_type
tgsi_opcode_infer_dst_type( uint opcode );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_INFO_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_iterate.c
0,0 → 1,90
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "tgsi_iterate.h"
 
boolean
tgsi_iterate_shader(
const struct tgsi_token *tokens,
struct tgsi_iterate_context *ctx )
{
struct tgsi_parse_context parse;
 
if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK)
return FALSE;
 
ctx->processor = parse.FullHeader.Processor;
 
if (ctx->prolog)
if (!ctx->prolog( ctx ))
goto fail;
 
while (!tgsi_parse_end_of_tokens( &parse )) {
tgsi_parse_token( &parse );
 
switch (parse.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
if (ctx->iterate_instruction)
if (!ctx->iterate_instruction( ctx, &parse.FullToken.FullInstruction ))
goto fail;
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
if (ctx->iterate_declaration)
if (!ctx->iterate_declaration( ctx, &parse.FullToken.FullDeclaration ))
goto fail;
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
if (ctx->iterate_immediate)
if (!ctx->iterate_immediate( ctx, &parse.FullToken.FullImmediate ))
goto fail;
break;
 
case TGSI_TOKEN_TYPE_PROPERTY:
if (ctx->iterate_property)
if (!ctx->iterate_property( ctx, &parse.FullToken.FullProperty ))
goto fail;
break;
 
default:
assert( 0 );
}
}
 
if (ctx->epilog)
if (!ctx->epilog( ctx ))
goto fail;
 
tgsi_parse_free( &parse );
return TRUE;
 
fail:
tgsi_parse_free( &parse );
return FALSE;
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_iterate.h
0,0 → 1,80
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_ITERATE_H
#define TGSI_ITERATE_H
 
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
struct tgsi_iterate_context
{
boolean
(* prolog)(
struct tgsi_iterate_context *ctx );
 
boolean
(* iterate_instruction)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_instruction *inst );
 
boolean
(* iterate_declaration)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_declaration *decl );
 
boolean
(* iterate_immediate)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_immediate *imm );
 
boolean
(* iterate_property)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_property *prop );
 
boolean
(* epilog)(
struct tgsi_iterate_context *ctx );
 
struct tgsi_processor processor;
};
 
boolean
tgsi_iterate_shader(
const struct tgsi_token *tokens,
struct tgsi_iterate_context *ctx );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_ITERATE_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
0,0 → 1,226
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef OP12_TEX
#define OP12_TEX(a) OP12(a)
#endif
 
#ifndef OP14_TEX
#define OP14_TEX(a) OP14(a)
#endif
 
#ifndef OP12_SAMPLE
#define OP12_SAMPLE(a) OP12(a)
#endif
 
#ifndef OP13_SAMPLE
#define OP13_SAMPLE(a) OP13(a)
#endif
 
#ifndef OP14_SAMPLE
#define OP14_SAMPLE(a) OP14(a)
#endif
 
#ifndef OP15_SAMPLE
#define OP15_SAMPLE(a) OP15(a)
#endif
 
#ifndef OP00_LBL
#define OP00_LBL(a) OP00(a)
#endif
 
#ifndef OP01_LBL
#define OP01_LBL(a) OP01(a)
#endif
 
OP11(ARL)
OP11(MOV)
OP11(LIT)
OP11(RCP)
OP11(RSQ)
OP11(EXP)
OP11(LOG)
OP12(MUL)
OP12(ADD)
OP12(DP3)
OP12(DP4)
OP12(DST)
OP12(MIN)
OP12(MAX)
OP12(SLT)
OP12(SGE)
OP13(MAD)
OP12(SUB)
OP13(LRP)
OP13(CND)
OP11(SQRT)
OP13(DP2A)
OP11(FRC)
OP13(CLAMP)
OP11(FLR)
OP11(ROUND)
OP11(EX2)
OP11(LG2)
OP12(POW)
OP12(XPD)
OP11(ABS)
OP11(RCC)
OP12(DPH)
OP11(COS)
OP11(DDX)
OP11(DDY)
OP00(KILL)
OP11(PK2H)
OP11(PK2US)
OP11(PK4B)
OP11(PK4UB)
OP12(RFL)
OP12(SEQ)
OP12(SFL)
OP12(SGT)
OP11(SIN)
OP12(SLE)
OP12(SNE)
OP12(STR)
OP12_TEX(TEX)
OP14_TEX(TXD)
OP12_TEX(TXP)
OP11(UP2H)
OP11(UP2US)
OP11(UP4B)
OP11(UP4UB)
OP13(X2D)
OP11(ARA)
OP11(ARR)
OP01(BRA)
OP00_LBL(CAL)
OP00(RET)
OP11(SSG)
OP13(CMP)
OP11(SCS)
OP12_TEX(TXB)
OP11(NRM)
OP12(DIV)
OP12(DP2)
OP12_TEX(TXL)
OP00(BRK)
OP01_LBL(IF)
OP01_LBL(UIF)
OP00_LBL(ELSE)
OP00(ENDIF)
OP01(PUSHA)
OP10(POPA)
OP11(CEIL)
OP11(I2F)
OP11(NOT)
OP11(TRUNC)
OP12(SHL)
OP12(AND)
OP12(OR)
OP12(MOD)
OP12(XOR)
OP13(SAD)
OP12_TEX(TXF)
OP12_TEX(TXQ)
OP00(CONT)
OP00(EMIT)
OP00(ENDPRIM)
OP00_LBL(BGNLOOP)
OP00(BGNSUB)
OP00_LBL(ENDLOOP)
OP00(ENDSUB)
OP00(NOP)
OP11(NRM4)
OP01(CALLNZ)
OP01(BREAKC)
OP01(KILL_IF)
OP00(END)
OP11(F2I)
OP12(IDIV)
OP12(IMAX)
OP12(IMIN)
OP11(INEG)
OP12(ISGE)
OP12(ISHR)
OP12(ISLT)
OP11(F2U)
OP11(U2F)
OP12(UADD)
OP12(UDIV)
OP13(UMAD)
OP12(UMAX)
OP12(UMIN)
OP12(UMOD)
OP12(UMUL)
OP12(USEQ)
OP12(USGE)
OP12(USHR)
OP12(USLT)
OP12(USNE)
OP01(SWITCH)
OP01(CASE)
OP00(DEFAULT)
OP00(ENDSWITCH)
 
OP13_SAMPLE(SAMPLE)
OP12_SAMPLE(SAMPLE_I)
OP13_SAMPLE(SAMPLE_I_MS)
OP14_SAMPLE(SAMPLE_B)
OP14_SAMPLE(SAMPLE_C)
OP14_SAMPLE(SAMPLE_C_LZ)
OP15_SAMPLE(SAMPLE_D)
OP14_SAMPLE(SAMPLE_L)
OP13_SAMPLE(GATHER4)
OP12(SVIEWINFO)
OP13(SAMPLE_POS)
OP12(SAMPLE_INFO)
 
 
#undef OP00
#undef OP01
#undef OP10
#undef OP11
#undef OP12
#undef OP13
 
#ifdef OP14
#undef OP14
#endif
 
#ifdef OP15
#undef OP15
#endif
 
#undef OP00_LBL
#undef OP01_LBL
 
#undef OP12_TEX
#undef OP14_TEX
 
#undef OP12_SAMPLE
#undef OP13_SAMPLE
#undef OP14_SAMPLE
#undef OP15_SAMPLE
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_parse.c
0,0 → 1,307
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi_parse.h"
#include "util/u_memory.h"
 
unsigned
tgsi_parse_init(
struct tgsi_parse_context *ctx,
const struct tgsi_token *tokens )
{
ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[0];
if( ctx->FullHeader.Header.HeaderSize >= 2 ) {
ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[1];
}
else {
return TGSI_PARSE_ERROR;
}
 
ctx->Tokens = tokens;
ctx->Position = ctx->FullHeader.Header.HeaderSize;
 
return TGSI_PARSE_OK;
}
 
void
tgsi_parse_free(
struct tgsi_parse_context *ctx )
{
}
 
boolean
tgsi_parse_end_of_tokens(
struct tgsi_parse_context *ctx )
{
return ctx->Position >=
ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize;
}
 
 
/**
* This function is used to avoid and work-around type punning/aliasing
* warnings. The warnings seem harmless on x86 but on PPC they cause
* real failures.
*/
static INLINE void
copy_token(void *dst, const void *src)
{
memcpy(dst, src, 4);
}
 
 
/**
* Get next 4-byte token, return it at address specified by 'token'
*/
static void
next_token(
struct tgsi_parse_context *ctx,
void *token )
{
assert( !tgsi_parse_end_of_tokens( ctx ) );
copy_token(token, &ctx->Tokens[ctx->Position]);
ctx->Position++;
}
 
 
void
tgsi_parse_token(
struct tgsi_parse_context *ctx )
{
struct tgsi_token token;
unsigned i;
 
next_token( ctx, &token );
 
switch( token.Type ) {
case TGSI_TOKEN_TYPE_DECLARATION:
{
struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration;
 
memset(decl, 0, sizeof *decl);
copy_token(&decl->Declaration, &token);
 
next_token( ctx, &decl->Range );
 
if (decl->Declaration.Dimension) {
next_token(ctx, &decl->Dim);
}
 
if( decl->Declaration.Interpolate ) {
next_token( ctx, &decl->Interp );
}
 
if( decl->Declaration.Semantic ) {
next_token( ctx, &decl->Semantic );
}
 
if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
next_token(ctx, &decl->Resource);
}
 
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
next_token(ctx, &decl->SamplerView);
}
 
if( decl->Declaration.Array ) {
next_token(ctx, &decl->Array);
}
 
break;
}
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
uint imm_count;
 
memset(imm, 0, sizeof *imm);
copy_token(&imm->Immediate, &token);
 
imm_count = imm->Immediate.NrTokens - 1;
 
switch (imm->Immediate.DataType) {
case TGSI_IMM_FLOAT32:
for (i = 0; i < imm_count; i++) {
next_token(ctx, &imm->u[i].Float);
}
break;
 
case TGSI_IMM_UINT32:
for (i = 0; i < imm_count; i++) {
next_token(ctx, &imm->u[i].Uint);
}
break;
 
case TGSI_IMM_INT32:
for (i = 0; i < imm_count; i++) {
next_token(ctx, &imm->u[i].Int);
}
break;
 
default:
assert( 0 );
}
 
break;
}
 
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
 
memset(inst, 0, sizeof *inst);
copy_token(&inst->Instruction, &token);
 
if (inst->Instruction.Predicate) {
next_token(ctx, &inst->Predicate);
}
 
if (inst->Instruction.Label) {
next_token( ctx, &inst->Label);
}
 
if (inst->Instruction.Texture) {
next_token( ctx, &inst->Texture);
for( i = 0; i < inst->Texture.NumOffsets; i++ ) {
next_token( ctx, &inst->TexOffsets[i] );
}
}
 
assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
 
for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
 
next_token( ctx, &inst->Dst[i].Register );
 
if( inst->Dst[i].Register.Indirect )
next_token( ctx, &inst->Dst[i].Indirect );
 
if( inst->Dst[i].Register.Dimension ) {
next_token( ctx, &inst->Dst[i].Dimension );
 
/*
* No support for multi-dimensional addressing.
*/
assert( !inst->Dst[i].Dimension.Dimension );
 
if( inst->Dst[i].Dimension.Indirect )
next_token( ctx, &inst->Dst[i].DimIndirect );
}
}
 
assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
 
for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
 
next_token( ctx, &inst->Src[i].Register );
 
if( inst->Src[i].Register.Indirect )
next_token( ctx, &inst->Src[i].Indirect );
 
if( inst->Src[i].Register.Dimension ) {
next_token( ctx, &inst->Src[i].Dimension );
 
/*
* No support for multi-dimensional addressing.
*/
assert( !inst->Src[i].Dimension.Dimension );
 
if( inst->Src[i].Dimension.Indirect )
next_token( ctx, &inst->Src[i].DimIndirect );
}
}
 
break;
}
 
case TGSI_TOKEN_TYPE_PROPERTY:
{
struct tgsi_full_property *prop = &ctx->FullToken.FullProperty;
uint prop_count;
 
memset(prop, 0, sizeof *prop);
copy_token(&prop->Property, &token);
 
prop_count = prop->Property.NrTokens - 1;
for (i = 0; i < prop_count; i++) {
next_token(ctx, &prop->u[i]);
}
 
break;
}
 
default:
assert( 0 );
}
}
 
 
 
 
/**
* Make a new copy of a token array.
*/
struct tgsi_token *
tgsi_dup_tokens(const struct tgsi_token *tokens)
{
unsigned n = tgsi_num_tokens(tokens);
unsigned bytes = n * sizeof(struct tgsi_token);
struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
if (new_tokens)
memcpy(new_tokens, tokens, bytes);
return new_tokens;
}
 
 
/**
* Allocate memory for num_tokens tokens.
*/
struct tgsi_token *
tgsi_alloc_tokens(unsigned num_tokens)
{
unsigned bytes = num_tokens * sizeof(struct tgsi_token);
return (struct tgsi_token *) MALLOC(bytes);
}
 
 
void
tgsi_dump_tokens(const struct tgsi_token *tokens)
{
const unsigned *dwords = (const unsigned *)tokens;
int nr = tgsi_num_tokens(tokens);
int i;
assert(sizeof(*tokens) == sizeof(unsigned));
 
debug_printf("const unsigned tokens[%d] = {\n", nr);
for (i = 0; i < nr; i++)
debug_printf("0x%08x,\n", dwords[i]);
debug_printf("};\n");
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_parse.h
0,0 → 1,159
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_PARSE_H
#define TGSI_PARSE_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
struct tgsi_full_header
{
struct tgsi_header Header;
struct tgsi_processor Processor;
};
 
struct tgsi_full_dst_register
{
struct tgsi_dst_register Register;
struct tgsi_ind_register Indirect;
struct tgsi_dimension Dimension;
struct tgsi_ind_register DimIndirect;
};
 
struct tgsi_full_src_register
{
struct tgsi_src_register Register;
struct tgsi_ind_register Indirect;
struct tgsi_dimension Dimension;
struct tgsi_ind_register DimIndirect;
};
 
struct tgsi_full_declaration
{
struct tgsi_declaration Declaration;
struct tgsi_declaration_range Range;
struct tgsi_declaration_dimension Dim;
struct tgsi_declaration_interp Interp;
struct tgsi_declaration_semantic Semantic;
struct tgsi_declaration_resource Resource;
struct tgsi_declaration_sampler_view SamplerView;
struct tgsi_declaration_array Array;
};
 
struct tgsi_full_immediate
{
struct tgsi_immediate Immediate;
union tgsi_immediate_data u[4];
};
 
struct tgsi_full_property
{
struct tgsi_property Property;
struct tgsi_property_data u[8];
};
 
#define TGSI_FULL_MAX_DST_REGISTERS 2
#define TGSI_FULL_MAX_SRC_REGISTERS 5 /* SAMPLE_D has 5 */
#define TGSI_FULL_MAX_TEX_OFFSETS 4
 
struct tgsi_full_instruction
{
struct tgsi_instruction Instruction;
struct tgsi_instruction_predicate Predicate;
struct tgsi_instruction_label Label;
struct tgsi_instruction_texture Texture;
struct tgsi_full_dst_register Dst[TGSI_FULL_MAX_DST_REGISTERS];
struct tgsi_full_src_register Src[TGSI_FULL_MAX_SRC_REGISTERS];
struct tgsi_texture_offset TexOffsets[TGSI_FULL_MAX_TEX_OFFSETS];
};
 
union tgsi_full_token
{
struct tgsi_token Token;
struct tgsi_full_declaration FullDeclaration;
struct tgsi_full_immediate FullImmediate;
struct tgsi_full_instruction FullInstruction;
struct tgsi_full_property FullProperty;
};
 
struct tgsi_parse_context
{
const struct tgsi_token *Tokens;
unsigned Position;
struct tgsi_full_header FullHeader;
union tgsi_full_token FullToken;
};
 
#define TGSI_PARSE_OK 0
#define TGSI_PARSE_ERROR 1
 
unsigned
tgsi_parse_init(
struct tgsi_parse_context *ctx,
const struct tgsi_token *tokens );
 
void
tgsi_parse_free(
struct tgsi_parse_context *ctx );
 
boolean
tgsi_parse_end_of_tokens(
struct tgsi_parse_context *ctx );
 
void
tgsi_parse_token(
struct tgsi_parse_context *ctx );
 
static INLINE unsigned
tgsi_num_tokens(const struct tgsi_token *tokens)
{
struct tgsi_header header;
memcpy(&header, tokens, sizeof(header));
return header.HeaderSize + header.BodySize;
}
 
void
tgsi_dump_tokens(const struct tgsi_token *tokens);
 
struct tgsi_token *
tgsi_dup_tokens(const struct tgsi_token *tokens);
 
struct tgsi_token *
tgsi_alloc_tokens(unsigned num_tokens);
 
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_PARSE_H */
 
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_sanity.c
0,0 → 1,562
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "cso_cache/cso_hash.h"
#include "tgsi_sanity.h"
#include "tgsi_info.h"
#include "tgsi_iterate.h"
 
 
DEBUG_GET_ONCE_BOOL_OPTION(print_sanity, "TGSI_PRINT_SANITY", FALSE)
 
 
typedef struct {
uint file : 28;
/* max 2 dimensions */
uint dimensions : 4;
uint indices[2];
} scan_register;
 
struct sanity_check_ctx
{
struct tgsi_iterate_context iter;
struct cso_hash *regs_decl;
struct cso_hash *regs_used;
struct cso_hash *regs_ind_used;
 
uint num_imms;
uint num_instructions;
uint index_of_END;
 
uint errors;
uint warnings;
uint implied_array_size;
 
boolean print;
};
 
static INLINE unsigned
scan_register_key(const scan_register *reg)
{
unsigned key = reg->file;
key |= (reg->indices[0] << 4);
key |= (reg->indices[1] << 18);
 
return key;
}
 
static void
fill_scan_register1d(scan_register *reg,
uint file, uint index)
{
reg->file = file;
reg->dimensions = 1;
reg->indices[0] = index;
reg->indices[1] = 0;
}
 
static void
fill_scan_register2d(scan_register *reg,
uint file, uint index1, uint index2)
{
reg->file = file;
reg->dimensions = 2;
reg->indices[0] = index1;
reg->indices[1] = index2;
}
 
static void
scan_register_dst(scan_register *reg,
struct tgsi_full_dst_register *dst)
{
if (dst->Register.Dimension) {
/*FIXME: right now we don't support indirect
* multidimensional addressing */
fill_scan_register2d(reg,
dst->Register.File,
dst->Register.Index,
dst->Dimension.Index);
} else {
fill_scan_register1d(reg,
dst->Register.File,
dst->Register.Index);
}
}
 
static void
scan_register_src(scan_register *reg,
struct tgsi_full_src_register *src)
{
if (src->Register.Dimension) {
/*FIXME: right now we don't support indirect
* multidimensional addressing */
fill_scan_register2d(reg,
src->Register.File,
src->Register.Index,
src->Dimension.Index);
} else {
fill_scan_register1d(reg,
src->Register.File,
src->Register.Index);
}
}
 
static scan_register *
create_scan_register_src(struct tgsi_full_src_register *src)
{
scan_register *reg = MALLOC(sizeof(scan_register));
scan_register_src(reg, src);
 
return reg;
}
 
static scan_register *
create_scan_register_dst(struct tgsi_full_dst_register *dst)
{
scan_register *reg = MALLOC(sizeof(scan_register));
scan_register_dst(reg, dst);
 
return reg;
}
 
static void
report_error(
struct sanity_check_ctx *ctx,
const char *format,
... )
{
va_list args;
 
if (!ctx->print)
return;
 
debug_printf( "Error : " );
va_start( args, format );
_debug_vprintf( format, args );
va_end( args );
debug_printf( "\n" );
ctx->errors++;
}
 
static void
report_warning(
struct sanity_check_ctx *ctx,
const char *format,
... )
{
va_list args;
 
if (!ctx->print)
return;
 
debug_printf( "Warning: " );
va_start( args, format );
_debug_vprintf( format, args );
va_end( args );
debug_printf( "\n" );
ctx->warnings++;
}
 
static boolean
check_file_name(
struct sanity_check_ctx *ctx,
uint file )
{
if (file <= TGSI_FILE_NULL || file >= TGSI_FILE_COUNT) {
report_error( ctx, "(%u): Invalid register file name", file );
return FALSE;
}
return TRUE;
}
 
static boolean
is_register_declared(
struct sanity_check_ctx *ctx,
const scan_register *reg)
{
void *data = cso_hash_find_data_from_template(
ctx->regs_decl, scan_register_key(reg),
(void*)reg, sizeof(scan_register));
return data ? TRUE : FALSE;
}
 
static boolean
is_any_register_declared(
struct sanity_check_ctx *ctx,
uint file )
{
struct cso_hash_iter iter =
cso_hash_first_node(ctx->regs_decl);
 
while (!cso_hash_iter_is_null(iter)) {
scan_register *reg = (scan_register *)cso_hash_iter_data(iter);
if (reg->file == file)
return TRUE;
iter = cso_hash_iter_next(iter);
}
 
return FALSE;
}
 
static boolean
is_register_used(
struct sanity_check_ctx *ctx,
scan_register *reg)
{
void *data = cso_hash_find_data_from_template(
ctx->regs_used, scan_register_key(reg),
reg, sizeof(scan_register));
return data ? TRUE : FALSE;
}
 
 
static boolean
is_ind_register_used(
struct sanity_check_ctx *ctx,
scan_register *reg)
{
return cso_hash_contains(ctx->regs_ind_used, reg->file);
}
 
static const char *file_names[TGSI_FILE_COUNT] =
{
"NULL",
"CONST",
"IN",
"OUT",
"TEMP",
"SAMP",
"ADDR",
"IMM",
"PRED",
"SV",
"RES"
};
 
static boolean
check_register_usage(
struct sanity_check_ctx *ctx,
scan_register *reg,
const char *name,
boolean indirect_access )
{
if (!check_file_name( ctx, reg->file )) {
FREE(reg);
return FALSE;
}
 
if (indirect_access) {
/* Note that 'index' is an offset relative to the value of the
* address register. No range checking done here.*/
reg->indices[0] = 0;
reg->indices[1] = 0;
if (!is_any_register_declared( ctx, reg->file ))
report_error( ctx, "%s: Undeclared %s register", file_names[reg->file], name );
if (!is_ind_register_used(ctx, reg))
cso_hash_insert(ctx->regs_ind_used, reg->file, reg);
else
FREE(reg);
}
else {
if (!is_register_declared( ctx, reg )) {
if (reg->dimensions == 2) {
report_error( ctx, "%s[%d][%d]: Undeclared %s register", file_names[reg->file],
reg->indices[0], reg->indices[1], name );
}
else {
report_error( ctx, "%s[%d]: Undeclared %s register", file_names[reg->file],
reg->indices[0], name );
}
}
if (!is_register_used( ctx, reg ))
cso_hash_insert(ctx->regs_used, scan_register_key(reg), reg);
else
FREE(reg);
}
return TRUE;
}
 
static boolean
iter_instruction(
struct tgsi_iterate_context *iter,
struct tgsi_full_instruction *inst )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
const struct tgsi_opcode_info *info;
uint i;
 
if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
if (ctx->index_of_END != ~0) {
report_error( ctx, "Too many END instructions" );
}
ctx->index_of_END = ctx->num_instructions;
}
 
info = tgsi_get_opcode_info( inst->Instruction.Opcode );
if (info == NULL) {
report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode );
return TRUE;
}
 
if (info->num_dst != inst->Instruction.NumDstRegs) {
report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst );
}
if (info->num_src != inst->Instruction.NumSrcRegs) {
report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src );
}
 
/* Check destination and source registers' validity.
* Mark the registers as used.
*/
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
scan_register *reg = create_scan_register_dst(&inst->Dst[i]);
check_register_usage(
ctx,
reg,
"destination",
FALSE );
if (!inst->Dst[i].Register.WriteMask) {
report_error(ctx, "Destination register has empty writemask");
}
}
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
scan_register *reg = create_scan_register_src(&inst->Src[i]);
check_register_usage(
ctx,
reg,
"source",
(boolean)inst->Src[i].Register.Indirect );
if (inst->Src[i].Register.Indirect) {
scan_register *ind_reg = MALLOC(sizeof(scan_register));
 
fill_scan_register1d(ind_reg,
inst->Src[i].Indirect.File,
inst->Src[i].Indirect.Index);
check_register_usage(
ctx,
ind_reg,
"indirect",
FALSE );
}
}
 
ctx->num_instructions++;
 
return TRUE;
}
 
static void
check_and_declare(struct sanity_check_ctx *ctx,
scan_register *reg)
{
if (is_register_declared( ctx, reg))
report_error( ctx, "%s[%u]: The same register declared more than once",
file_names[reg->file], reg->indices[0] );
cso_hash_insert(ctx->regs_decl,
scan_register_key(reg),
reg);
}
 
 
static boolean
iter_declaration(
struct tgsi_iterate_context *iter,
struct tgsi_full_declaration *decl )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
uint file;
uint i;
 
/* No declarations allowed after the first instruction.
*/
if (ctx->num_instructions > 0)
report_error( ctx, "Instruction expected but declaration found" );
 
/* Check registers' validity.
* Mark the registers as declared.
*/
file = decl->Declaration.File;
if (!check_file_name( ctx, file ))
return TRUE;
for (i = decl->Range.First; i <= decl->Range.Last; i++) {
/* declared TGSI_FILE_INPUT's for geometry processor
* have an implied second dimension */
if (file == TGSI_FILE_INPUT &&
ctx->iter.processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
uint vert;
for (vert = 0; vert < ctx->implied_array_size; ++vert) {
scan_register *reg = MALLOC(sizeof(scan_register));
fill_scan_register2d(reg, file, i, vert);
check_and_declare(ctx, reg);
}
} else {
scan_register *reg = MALLOC(sizeof(scan_register));
if (decl->Declaration.Dimension) {
fill_scan_register2d(reg, file, i, decl->Dim.Index2D);
} else {
fill_scan_register1d(reg, file, i);
}
check_and_declare(ctx, reg);
}
}
 
return TRUE;
}
 
static boolean
iter_immediate(
struct tgsi_iterate_context *iter,
struct tgsi_full_immediate *imm )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
scan_register *reg;
 
/* No immediates allowed after the first instruction.
*/
if (ctx->num_instructions > 0)
report_error( ctx, "Instruction expected but immediate found" );
 
/* Mark the register as declared.
*/
reg = MALLOC(sizeof(scan_register));
fill_scan_register1d(reg, TGSI_FILE_IMMEDIATE, ctx->num_imms);
cso_hash_insert(ctx->regs_decl, scan_register_key(reg), reg);
ctx->num_imms++;
 
/* Check data type validity.
*/
if (imm->Immediate.DataType != TGSI_IMM_FLOAT32 &&
imm->Immediate.DataType != TGSI_IMM_UINT32 &&
imm->Immediate.DataType != TGSI_IMM_INT32) {
report_error( ctx, "(%u): Invalid immediate data type", imm->Immediate.DataType );
return TRUE;
}
 
return TRUE;
}
 
 
static boolean
iter_property(
struct tgsi_iterate_context *iter,
struct tgsi_full_property *prop )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
 
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY &&
prop->Property.PropertyName == TGSI_PROPERTY_GS_INPUT_PRIM) {
ctx->implied_array_size = u_vertices_per_prim(prop->u[0].Data);
}
return TRUE;
}
 
static boolean
epilog(
struct tgsi_iterate_context *iter )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
 
/* There must be an END instruction somewhere.
*/
if (ctx->index_of_END == ~0) {
report_error( ctx, "Missing END instruction" );
}
 
/* Check if all declared registers were used.
*/
{
struct cso_hash_iter iter =
cso_hash_first_node(ctx->regs_decl);
 
while (!cso_hash_iter_is_null(iter)) {
scan_register *reg = (scan_register *)cso_hash_iter_data(iter);
if (!is_register_used(ctx, reg) && !is_ind_register_used(ctx, reg)) {
report_warning( ctx, "%s[%u]: Register never used",
file_names[reg->file], reg->indices[0] );
}
iter = cso_hash_iter_next(iter);
}
}
 
/* Print totals, if any.
*/
if (ctx->errors || ctx->warnings)
debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings );
 
return TRUE;
}
 
static void
regs_hash_destroy(struct cso_hash *hash)
{
struct cso_hash_iter iter = cso_hash_first_node(hash);
while (!cso_hash_iter_is_null(iter)) {
scan_register *reg = (scan_register *)cso_hash_iter_data(iter);
iter = cso_hash_erase(hash, iter);
assert(reg->file < TGSI_FILE_COUNT);
FREE(reg);
}
cso_hash_delete(hash);
}
 
boolean
tgsi_sanity_check(
const struct tgsi_token *tokens )
{
struct sanity_check_ctx ctx;
 
ctx.iter.prolog = NULL;
ctx.iter.iterate_instruction = iter_instruction;
ctx.iter.iterate_declaration = iter_declaration;
ctx.iter.iterate_immediate = iter_immediate;
ctx.iter.iterate_property = iter_property;
ctx.iter.epilog = epilog;
 
ctx.regs_decl = cso_hash_create();
ctx.regs_used = cso_hash_create();
ctx.regs_ind_used = cso_hash_create();
 
ctx.num_imms = 0;
ctx.num_instructions = 0;
ctx.index_of_END = ~0;
 
ctx.errors = 0;
ctx.warnings = 0;
ctx.implied_array_size = 0;
ctx.print = debug_get_option_print_sanity();
 
if (!tgsi_iterate_shader( tokens, &ctx.iter ))
return FALSE;
 
regs_hash_destroy(ctx.regs_decl);
regs_hash_destroy(ctx.regs_used);
regs_hash_destroy(ctx.regs_ind_used);
return ctx.errors == 0;
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_sanity.h
0,0 → 1,52
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_SANITY_H
#define TGSI_SANITY_H
 
#if defined __cplusplus
extern "C" {
#endif
 
#include "pipe/p_compiler.h"
 
struct tgsi_token;
 
/* Check the given token stream for errors and common mistakes.
* Diagnostic messages are printed out to the debug output, and is
* controlled by the debug option TGSI_PRINT_SANITY (default false).
* Returns TRUE if there are no errors, even though there could be some warnings.
*/
boolean
tgsi_sanity_check(
const struct tgsi_token *tokens );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_SANITY_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_scan.c
0,0 → 1,380
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. All rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* TGSI program scan utility.
* Used to determine which registers and instructions are used by a shader.
*
* Authors: Brian Paul
*/
 
 
#include "util/u_debug.h"
#include "util/u_math.h"
#include "util/u_prim.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_scan.h"
 
 
 
 
/**
* Scan the given TGSI shader to collect information such as number of
* registers used, special instructions used, etc.
* \return info the result of the scan
*/
void
tgsi_scan_shader(const struct tgsi_token *tokens,
struct tgsi_shader_info *info)
{
uint procType, i;
struct tgsi_parse_context parse;
 
memset(info, 0, sizeof(*info));
for (i = 0; i < TGSI_FILE_COUNT; i++)
info->file_max[i] = -1;
 
/**
** Setup to begin parsing input shader
**/
if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
return;
}
procType = parse.FullHeader.Processor.Processor;
assert(procType == TGSI_PROCESSOR_FRAGMENT ||
procType == TGSI_PROCESSOR_VERTEX ||
procType == TGSI_PROCESSOR_GEOMETRY ||
procType == TGSI_PROCESSOR_COMPUTE);
info->processor = procType;
 
 
/**
** Loop over incoming program tokens/instructions
*/
while( !tgsi_parse_end_of_tokens( &parse ) ) {
 
info->num_tokens++;
 
tgsi_parse_token( &parse );
 
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
const struct tgsi_full_instruction *fullinst
= &parse.FullToken.FullInstruction;
uint i;
 
assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
info->opcode_count[fullinst->Instruction.Opcode]++;
 
for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *src =
&fullinst->Src[i];
int ind = src->Register.Index;
 
/* Mark which inputs are effectively used */
if (src->Register.File == TGSI_FILE_INPUT) {
unsigned usage_mask;
usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
if (src->Register.Indirect) {
for (ind = 0; ind < info->num_inputs; ++ind) {
info->input_usage_mask[ind] |= usage_mask;
}
} else {
assert(ind >= 0);
assert(ind < PIPE_MAX_SHADER_INPUTS);
info->input_usage_mask[ind] |= usage_mask;
}
 
if (procType == TGSI_PROCESSOR_FRAGMENT &&
src->Register.File == TGSI_FILE_INPUT &&
info->reads_position &&
src->Register.Index == 0 &&
(src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
src->Register.SwizzleW == TGSI_SWIZZLE_Z)) {
info->reads_z = TRUE;
}
}
 
/* check for indirect register reads */
if (src->Register.Indirect) {
info->indirect_files |= (1 << src->Register.File);
}
}
 
/* check for indirect register writes */
for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
if (dst->Register.Indirect) {
info->indirect_files |= (1 << dst->Register.File);
}
}
 
info->num_instructions++;
}
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
{
const struct tgsi_full_declaration *fulldecl
= &parse.FullToken.FullDeclaration;
const uint file = fulldecl->Declaration.File;
uint reg;
for (reg = fulldecl->Range.First;
reg <= fulldecl->Range.Last;
reg++) {
 
/* only first 32 regs will appear in this bitfield */
info->file_mask[file] |= (1 << reg);
info->file_count[file]++;
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
 
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->Interp.Interpolate;
info->input_centroid[reg] = (ubyte)fulldecl->Interp.Centroid;
info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
info->num_inputs++;
 
if (procType == TGSI_PROCESSOR_FRAGMENT &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
info->reads_position = TRUE;
}
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 (fulldecl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) {
info->uses_vertexid = TRUE;
} else if (fulldecl->Semantic.Name == TGSI_SEMANTIC_PRIMID) {
info->uses_primid = 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;
info->num_outputs++;
 
if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_CLIPDIST) {
info->num_written_clipdistance += util_bitcount(fulldecl->Declaration.UsageMask);
}
if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_CULLDIST) {
info->num_written_culldistance += util_bitcount(fulldecl->Declaration.UsageMask);
}
/* extra info for special outputs */
if (procType == TGSI_PROCESSOR_FRAGMENT &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
info->writes_z = TRUE;
if (procType == TGSI_PROCESSOR_FRAGMENT &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_STENCIL)
info->writes_stencil = TRUE;
if (procType == TGSI_PROCESSOR_VERTEX &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) {
info->writes_edgeflag = TRUE;
}
 
if (procType == TGSI_PROCESSOR_GEOMETRY &&
fulldecl->Semantic.Name ==
TGSI_SEMANTIC_VIEWPORT_INDEX) {
info->writes_viewport_index = TRUE;
}
if (procType == TGSI_PROCESSOR_GEOMETRY &&
fulldecl->Semantic.Name ==
TGSI_SEMANTIC_LAYER) {
info->writes_layer = TRUE;
}
}
 
}
}
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
uint reg = info->immediate_count++;
uint file = TGSI_FILE_IMMEDIATE;
 
info->file_mask[file] |= (1 << reg);
info->file_count[file]++;
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
}
break;
 
case TGSI_TOKEN_TYPE_PROPERTY:
{
const struct tgsi_full_property *fullprop
= &parse.FullToken.FullProperty;
 
info->properties[info->num_properties].name =
fullprop->Property.PropertyName;
memcpy(info->properties[info->num_properties].data,
fullprop->u, 8 * sizeof(unsigned));;
 
++info->num_properties;
}
break;
 
default:
assert( 0 );
}
}
 
info->uses_kill = (info->opcode_count[TGSI_OPCODE_KILL_IF] ||
info->opcode_count[TGSI_OPCODE_KILL]);
 
/* extract simple properties */
for (i = 0; i < info->num_properties; ++i) {
switch (info->properties[i].name) {
case TGSI_PROPERTY_FS_COORD_ORIGIN:
info->origin_lower_left = info->properties[i].data[0];
break;
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
info->pixel_center_integer = info->properties[i].data[0];
break;
case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
info->color0_writes_all_cbufs = info->properties[i].data[0];
break;
case TGSI_PROPERTY_GS_INPUT_PRIM:
/* The dimensions of the IN decleration in geometry shader have
* to be deduced from the type of the input primitive.
*/
if (procType == TGSI_PROCESSOR_GEOMETRY) {
unsigned input_primitive = info->properties[i].data[0];
int num_verts = u_vertices_per_prim(input_primitive);
int j;
info->file_count[TGSI_FILE_INPUT] = num_verts;
info->file_max[TGSI_FILE_INPUT] =
MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1);
for (j = 0; j < num_verts; ++j) {
info->file_mask[TGSI_FILE_INPUT] |= (1 << j);
}
}
break;
default:
;
}
}
 
tgsi_parse_free (&parse);
}
 
 
 
/**
* Check if the given shader is a "passthrough" shader consisting of only
* MOV instructions of the form: MOV OUT[n], IN[n]
*
*/
boolean
tgsi_is_passthrough_shader(const struct tgsi_token *tokens)
{
struct tgsi_parse_context parse;
 
/**
** Setup to begin parsing input shader
**/
if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n");
return FALSE;
}
 
/**
** Loop over incoming program tokens/instructions
*/
while (!tgsi_parse_end_of_tokens(&parse)) {
 
tgsi_parse_token(&parse);
 
switch (parse.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
struct tgsi_full_instruction *fullinst =
&parse.FullToken.FullInstruction;
const struct tgsi_full_src_register *src =
&fullinst->Src[0];
const struct tgsi_full_dst_register *dst =
&fullinst->Dst[0];
 
/* Do a whole bunch of checks for a simple move */
if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV ||
(src->Register.File != TGSI_FILE_INPUT &&
src->Register.File != TGSI_FILE_SYSTEM_VALUE) ||
dst->Register.File != TGSI_FILE_OUTPUT ||
src->Register.Index != dst->Register.Index ||
 
src->Register.Negate ||
src->Register.Absolute ||
 
src->Register.SwizzleX != TGSI_SWIZZLE_X ||
src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
src->Register.SwizzleW != TGSI_SWIZZLE_W ||
 
dst->Register.WriteMask != TGSI_WRITEMASK_XYZW)
{
tgsi_parse_free(&parse);
return FALSE;
}
}
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
/* fall-through */
case TGSI_TOKEN_TYPE_IMMEDIATE:
/* fall-through */
case TGSI_TOKEN_TYPE_PROPERTY:
/* fall-through */
default:
; /* no-op */
}
}
 
tgsi_parse_free(&parse);
 
/* if we get here, it's a pass-through shader */
return TRUE;
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_scan.h
0,0 → 1,107
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_SCAN_H
#define TGSI_SCAN_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
 
/**
* Shader summary info
*/
struct tgsi_shader_info
{
uint num_tokens;
 
ubyte num_inputs;
ubyte num_outputs;
ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; /**< TGSI_SEMANTIC_x */
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
ubyte input_interpolate[PIPE_MAX_SHADER_INPUTS];
ubyte input_centroid[PIPE_MAX_SHADER_INPUTS];
ubyte input_usage_mask[PIPE_MAX_SHADER_INPUTS];
ubyte input_cylindrical_wrap[PIPE_MAX_SHADER_INPUTS];
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];
 
ubyte processor;
 
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 */
 
uint immediate_count; /**< number of immediates declared */
uint num_instructions;
 
uint opcode_count[TGSI_OPCODE_LAST]; /**< opcode histogram */
 
boolean reads_position; /**< does fragment shader read position? */
boolean reads_z; /**< does fragment shader read depth? */
boolean writes_z; /**< does fragment shader write Z value? */
boolean writes_stencil; /**< does fragment shader write stencil value? */
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
boolean uses_kill; /**< KILL or KILL_IF instruction used? */
boolean uses_instanceid;
boolean uses_vertexid;
boolean uses_primid;
boolean origin_lower_left;
boolean pixel_center_integer;
boolean color0_writes_all_cbufs;
boolean writes_viewport_index;
boolean writes_layer;
 
unsigned num_written_culldistance;
unsigned num_written_clipdistance;
/**
* Bitmask indicating which register files are accessed with
* indirect addressing. The bits are (1 << TGSI_FILE_x), etc.
*/
unsigned indirect_files;
 
struct {
unsigned name;
unsigned data[8];
} properties[TGSI_PROPERTY_COUNT];
uint num_properties;
};
 
extern void
tgsi_scan_shader(const struct tgsi_token *tokens,
struct tgsi_shader_info *info);
 
 
extern boolean
tgsi_is_passthrough_shader(const struct tgsi_token *tokens);
 
 
#endif /* TGSI_SCAN_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_strings.c
0,0 → 1,201
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2012 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
 
#include "pipe/p_compiler.h"
#include "util/u_memory.h"
#include "tgsi_strings.h"
 
 
const char *tgsi_processor_type_names[4] =
{
"FRAG",
"VERT",
"GEOM",
"COMP"
};
 
static const char *tgsi_file_names[] =
{
"NULL",
"CONST",
"IN",
"OUT",
"TEMP",
"SAMP",
"ADDR",
"IMM",
"PRED",
"SV",
"RES",
"SVIEW"
};
 
const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT] =
{
"POSITION",
"COLOR",
"BCOLOR",
"FOG",
"PSIZE",
"GENERIC",
"NORMAL",
"FACE",
"EDGEFLAG",
"PRIM_ID",
"INSTANCEID",
"VERTEXID",
"STENCIL",
"CLIPDIST",
"CLIPVERTEX",
"GRID_SIZE",
"BLOCK_ID",
"BLOCK_SIZE",
"THREAD_ID",
"TEXCOORD",
"PCOORD",
"VIEWPORT_INDEX",
"LAYER",
"CULLDIST"
};
 
const char *tgsi_texture_names[TGSI_TEXTURE_COUNT] =
{
"BUFFER",
"1D",
"2D",
"3D",
"CUBE",
"RECT",
"SHADOW1D",
"SHADOW2D",
"SHADOWRECT",
"1D_ARRAY",
"2D_ARRAY",
"SHADOW1D_ARRAY",
"SHADOW2D_ARRAY",
"SHADOWCUBE",
"2D_MSAA",
"2D_ARRAY_MSAA",
"CUBEARRAY",
"SHADOWCUBEARRAY",
"UNKNOWN",
};
 
const char *tgsi_property_names[TGSI_PROPERTY_COUNT] =
{
"GS_INPUT_PRIMITIVE",
"GS_OUTPUT_PRIMITIVE",
"GS_MAX_OUTPUT_VERTICES",
"FS_COORD_ORIGIN",
"FS_COORD_PIXEL_CENTER",
"FS_COLOR0_WRITES_ALL_CBUFS",
"FS_DEPTH_LAYOUT",
"VS_PROHIBIT_UCPS"
};
 
const char *tgsi_type_names[5] =
{
"UNORM",
"SNORM",
"SINT",
"UINT",
"FLOAT"
};
 
const char *tgsi_interpolate_names[TGSI_INTERPOLATE_COUNT] =
{
"CONSTANT",
"LINEAR",
"PERSPECTIVE",
"COLOR"
};
 
const char *tgsi_primitive_names[PIPE_PRIM_MAX] =
{
"POINTS",
"LINES",
"LINE_LOOP",
"LINE_STRIP",
"TRIANGLES",
"TRIANGLE_STRIP",
"TRIANGLE_FAN",
"QUADS",
"QUAD_STRIP",
"POLYGON",
"LINES_ADJACENCY",
"LINE_STRIP_ADJACENCY",
"TRIANGLES_ADJACENCY",
"TRIANGLE_STRIP_ADJACENCY"
};
 
const char *tgsi_fs_coord_origin_names[2] =
{
"UPPER_LEFT",
"LOWER_LEFT"
};
 
const char *tgsi_fs_coord_pixel_center_names[2] =
{
"HALF_INTEGER",
"INTEGER"
};
 
const char *tgsi_immediate_type_names[3] =
{
"FLT32",
"UINT32",
"INT32"
};
 
 
static INLINE void
tgsi_strings_check(void)
{
STATIC_ASSERT(Elements(tgsi_semantic_names) == TGSI_SEMANTIC_COUNT);
STATIC_ASSERT(Elements(tgsi_texture_names) == TGSI_TEXTURE_COUNT);
STATIC_ASSERT(Elements(tgsi_property_names) == TGSI_PROPERTY_COUNT);
STATIC_ASSERT(Elements(tgsi_primitive_names) == PIPE_PRIM_MAX);
STATIC_ASSERT(Elements(tgsi_interpolate_names) == TGSI_INTERPOLATE_COUNT);
(void) tgsi_processor_type_names;
(void) tgsi_type_names;
(void) tgsi_immediate_type_names;
(void) tgsi_fs_coord_origin_names;
(void) tgsi_fs_coord_pixel_center_names;
}
 
 
const char *
tgsi_file_name(unsigned file)
{
STATIC_ASSERT(Elements(tgsi_file_names) == TGSI_FILE_COUNT);
if (file < Elements(tgsi_file_names))
return tgsi_file_names[file];
else
return "invalid file";
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_strings.h
0,0 → 1,71
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2012 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_STRINGS_H
#define TGSI_STRINGS_H
 
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
 
 
#if defined __cplusplus
extern "C" {
#endif
 
 
extern const char *tgsi_processor_type_names[4];
 
extern const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT];
 
extern const char *tgsi_texture_names[TGSI_TEXTURE_COUNT];
 
extern const char *tgsi_property_names[TGSI_PROPERTY_COUNT];
 
extern const char *tgsi_type_names[5];
 
extern const char *tgsi_interpolate_names[TGSI_INTERPOLATE_COUNT];
 
extern const char *tgsi_primitive_names[PIPE_PRIM_MAX];
 
extern const char *tgsi_fs_coord_origin_names[2];
 
extern const char *tgsi_fs_coord_pixel_center_names[2];
 
extern const char *tgsi_immediate_type_names[3];
 
 
const char *
tgsi_file_name(unsigned file);
 
 
#if defined __cplusplus
}
#endif
 
 
#endif /* TGSI_STRINGS_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_text.c
0,0 → 1,1591
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "tgsi_text.h"
#include "tgsi_build.h"
#include "tgsi_info.h"
#include "tgsi_parse.h"
#include "tgsi_sanity.h"
#include "tgsi_strings.h"
#include "tgsi_util.h"
#include "tgsi_dump.h"
 
static boolean is_alpha_underscore( const char *cur )
{
return
(*cur >= 'a' && *cur <= 'z') ||
(*cur >= 'A' && *cur <= 'Z') ||
*cur == '_';
}
 
static boolean is_digit( const char *cur )
{
return *cur >= '0' && *cur <= '9';
}
 
static boolean is_digit_alpha_underscore( const char *cur )
{
return is_digit( cur ) || is_alpha_underscore( cur );
}
 
static char uprcase( char c )
{
if (c >= 'a' && c <= 'z')
return c + 'A' - 'a';
return c;
}
 
/*
* Ignore case of str1 and assume str1 is already uppercase.
* Return TRUE iff str1 and str2 are equal.
*/
static int
streq_nocase_uprcase(const char *str1,
const char *str2)
{
while (*str1 && *str2) {
if (*str1 != uprcase(*str2))
return FALSE;
str1++;
str2++;
}
return *str1 == 0 && *str2 == 0;
}
 
/* Return TRUE if both strings match.
* The second string is terminated by zero.
* The pointer to the first string is moved at end of the read word
* on success.
*/
static boolean str_match_no_case( const char **pcur, const char *str )
{
const char *cur = *pcur;
 
while (*str != '\0' && *str == uprcase( *cur )) {
str++;
cur++;
}
if (*str == '\0') {
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
/* Return TRUE if both strings match.
* The first string is be terminated by a non-digit non-letter non-underscore
* character, the second string is terminated by zero.
* The pointer to the first string is moved at end of the read word
* on success.
*/
static boolean str_match_nocase_whole( const char **pcur, const char *str )
{
const char *cur = *pcur;
 
if (str_match_no_case(&cur, str) &&
!is_digit_alpha_underscore(cur)) {
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
/* Eat zero or more whitespaces.
*/
static void eat_opt_white( const char **pcur )
{
while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
(*pcur)++;
}
 
/* Eat one or more whitespaces.
* Return TRUE if at least one whitespace eaten.
*/
static boolean eat_white( const char **pcur )
{
const char *cur = *pcur;
 
eat_opt_white( pcur );
return *pcur > cur;
}
 
/* Parse unsigned integer.
* No checks for overflow.
*/
static boolean parse_uint( const char **pcur, uint *val )
{
const char *cur = *pcur;
 
if (is_digit( cur )) {
*val = *cur++ - '0';
while (is_digit( cur ))
*val = *val * 10 + *cur++ - '0';
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
static boolean parse_int( const char **pcur, int *val )
{
const char *cur = *pcur;
int sign = (*cur == '-' ? -1 : 1);
 
if (*cur == '+' || *cur == '-')
cur++;
 
if (parse_uint(&cur, (uint *)val)) {
*val *= sign;
*pcur = cur;
return TRUE;
}
 
return FALSE;
}
 
static boolean parse_identifier( const char **pcur, char *ret )
{
const char *cur = *pcur;
int i = 0;
if (is_alpha_underscore( cur )) {
ret[i++] = *cur++;
while (is_alpha_underscore( cur ) || is_digit( cur ))
ret[i++] = *cur++;
ret[i++] = '\0';
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
/* Parse floating point.
*/
static boolean parse_float( const char **pcur, float *val )
{
const char *cur = *pcur;
boolean integral_part = FALSE;
boolean fractional_part = FALSE;
 
*val = (float) atof( cur );
 
if (*cur == '-' || *cur == '+')
cur++;
if (is_digit( cur )) {
cur++;
integral_part = TRUE;
while (is_digit( cur ))
cur++;
}
if (*cur == '.') {
cur++;
if (is_digit( cur )) {
cur++;
fractional_part = TRUE;
while (is_digit( cur ))
cur++;
}
}
if (!integral_part && !fractional_part)
return FALSE;
if (uprcase( *cur ) == 'E') {
cur++;
if (*cur == '-' || *cur == '+')
cur++;
if (is_digit( cur )) {
cur++;
while (is_digit( cur ))
cur++;
}
else
return FALSE;
}
*pcur = cur;
return TRUE;
}
 
struct translate_ctx
{
const char *text;
const char *cur;
struct tgsi_token *tokens;
struct tgsi_token *tokens_cur;
struct tgsi_token *tokens_end;
struct tgsi_header *header;
unsigned processor : 4;
int implied_array_size : 5;
unsigned num_immediates;
};
 
static void report_error( struct translate_ctx *ctx, const char *msg )
{
int line = 1;
int column = 1;
const char *itr = ctx->text;
 
while (itr != ctx->cur) {
if (*itr == '\n') {
column = 1;
++line;
}
++column;
++itr;
}
 
debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
}
 
/* Parse shader header.
* Return TRUE for one of the following headers.
* FRAG
* GEOM
* VERT
*/
static boolean parse_header( struct translate_ctx *ctx )
{
uint processor;
 
if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
processor = TGSI_PROCESSOR_FRAGMENT;
else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
processor = TGSI_PROCESSOR_VERTEX;
else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
processor = TGSI_PROCESSOR_GEOMETRY;
else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
processor = TGSI_PROCESSOR_COMPUTE;
else {
report_error( ctx, "Unknown header" );
return FALSE;
}
 
if (ctx->tokens_cur >= ctx->tokens_end)
return FALSE;
ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
*ctx->header = tgsi_build_header();
 
if (ctx->tokens_cur >= ctx->tokens_end)
return FALSE;
*(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
ctx->processor = processor;
 
return TRUE;
}
 
static boolean parse_label( struct translate_ctx *ctx, uint *val )
{
const char *cur = ctx->cur;
 
if (parse_uint( &cur, val )) {
eat_opt_white( &cur );
if (*cur == ':') {
cur++;
ctx->cur = cur;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_file( const char **pcur, uint *file )
{
uint i;
 
for (i = 0; i < TGSI_FILE_COUNT; i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
*pcur = cur;
*file = i;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_opt_writemask(
struct translate_ctx *ctx,
uint *writemask )
{
const char *cur;
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == '.') {
cur++;
*writemask = TGSI_WRITEMASK_NONE;
eat_opt_white( &cur );
if (uprcase( *cur ) == 'X') {
cur++;
*writemask |= TGSI_WRITEMASK_X;
}
if (uprcase( *cur ) == 'Y') {
cur++;
*writemask |= TGSI_WRITEMASK_Y;
}
if (uprcase( *cur ) == 'Z') {
cur++;
*writemask |= TGSI_WRITEMASK_Z;
}
if (uprcase( *cur ) == 'W') {
cur++;
*writemask |= TGSI_WRITEMASK_W;
}
 
if (*writemask == TGSI_WRITEMASK_NONE) {
report_error( ctx, "Writemask expected" );
return FALSE;
}
 
ctx->cur = cur;
}
else {
*writemask = TGSI_WRITEMASK_XYZW;
}
return TRUE;
}
 
 
/* <register_file_bracket> ::= <file> `['
*/
static boolean
parse_register_file_bracket(
struct translate_ctx *ctx,
uint *file )
{
if (!parse_file( &ctx->cur, file )) {
report_error( ctx, "Unknown register file" );
return FALSE;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != '[') {
report_error( ctx, "Expected `['" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
 
/* <register_file_bracket_index> ::= <register_file_bracket> <uint>
*/
static boolean
parse_register_file_bracket_index(
struct translate_ctx *ctx,
uint *file,
int *index )
{
uint uindex;
 
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
*index = (int) uindex;
return TRUE;
}
 
/* Parse simple 1d register operand.
* <register_dst> ::= <register_file_bracket_index> `]'
*/
static boolean
parse_register_1d(struct translate_ctx *ctx,
uint *file,
int *index )
{
if (!parse_register_file_bracket_index( ctx, file, index ))
return FALSE;
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
 
struct parsed_bracket {
int index;
 
uint ind_file;
int ind_index;
uint ind_comp;
uint ind_array;
};
 
 
static boolean
parse_register_bracket(
struct translate_ctx *ctx,
struct parsed_bracket *brackets)
{
const char *cur;
uint uindex;
 
memset(brackets, 0, sizeof(struct parsed_bracket));
 
eat_opt_white( &ctx->cur );
 
cur = ctx->cur;
if (parse_file( &cur, &brackets->ind_file )) {
if (!parse_register_1d( ctx, &brackets->ind_file,
&brackets->ind_index ))
return FALSE;
eat_opt_white( &ctx->cur );
 
if (*ctx->cur == '.') {
ctx->cur++;
eat_opt_white(&ctx->cur);
 
switch (uprcase(*ctx->cur)) {
case 'X':
brackets->ind_comp = TGSI_SWIZZLE_X;
break;
case 'Y':
brackets->ind_comp = TGSI_SWIZZLE_Y;
break;
case 'Z':
brackets->ind_comp = TGSI_SWIZZLE_Z;
break;
case 'W':
brackets->ind_comp = TGSI_SWIZZLE_W;
break;
default:
report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
return FALSE;
}
ctx->cur++;
eat_opt_white(&ctx->cur);
}
 
if (*ctx->cur == '+' || *ctx->cur == '-')
parse_int( &ctx->cur, &brackets->index );
else
brackets->index = 0;
}
else {
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
brackets->index = (int) uindex;
brackets->ind_file = TGSI_FILE_NULL;
brackets->ind_index = 0;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
ctx->cur++;
if (*ctx->cur == '(') {
ctx->cur++;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != ')') {
report_error( ctx, "Expected `)'" );
return FALSE;
}
ctx->cur++;
}
return TRUE;
}
 
static boolean
parse_opt_register_src_bracket(
struct translate_ctx *ctx,
struct parsed_bracket *brackets,
int *parsed_brackets)
{
const char *cur = ctx->cur;
 
*parsed_brackets = 0;
 
eat_opt_white( &cur );
if (cur[0] == '[') {
++cur;
ctx->cur = cur;
 
if (!parse_register_bracket(ctx, brackets))
return FALSE;
 
*parsed_brackets = 1;
}
 
return TRUE;
}
 
 
/* Parse source register operand.
* <register_src> ::= <register_file_bracket_index> `]' |
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
*/
static boolean
parse_register_src(
struct translate_ctx *ctx,
uint *file,
struct parsed_bracket *brackets)
{
brackets->ind_comp = TGSI_SWIZZLE_X;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
if (!parse_register_bracket( ctx, brackets ))
return FALSE;
 
return TRUE;
}
 
struct parsed_dcl_bracket {
uint first;
uint last;
};
 
static boolean
parse_register_dcl_bracket(
struct translate_ctx *ctx,
struct parsed_dcl_bracket *bracket)
{
uint uindex;
memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
 
eat_opt_white( &ctx->cur );
 
if (!parse_uint( &ctx->cur, &uindex )) {
/* it can be an empty bracket [] which means its range
* is from 0 to some implied size */
if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
bracket->first = 0;
bracket->last = ctx->implied_array_size - 1;
goto cleanup;
}
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
bracket->first = uindex;
 
eat_opt_white( &ctx->cur );
 
if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
uint uindex;
 
ctx->cur += 2;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal integer" );
return FALSE;
}
bracket->last = (int) uindex;
eat_opt_white( &ctx->cur );
}
else {
bracket->last = bracket->first;
}
 
cleanup:
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]' or `..'" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
 
/* Parse register declaration.
* <register_dcl> ::= <register_file_bracket_index> `]' |
* <register_file_bracket_index> `..' <index> `]'
*/
static boolean
parse_register_dcl(
struct translate_ctx *ctx,
uint *file,
struct parsed_dcl_bracket *brackets,
int *num_brackets)
{
const char *cur;
 
*num_brackets = 0;
 
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
return FALSE;
 
*num_brackets = 1;
 
cur = ctx->cur;
eat_opt_white( &cur );
 
if (cur[0] == '[') {
++cur;
ctx->cur = cur;
if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
return FALSE;
/* for geometry shader we don't really care about
* the first brackets it's always the size of the
* input primitive. so we want to declare just
* the index relevant to the semantics which is in
* the second bracket */
if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
brackets[0] = brackets[1];
*num_brackets = 1;
} else {
*num_brackets = 2;
}
}
 
return TRUE;
}
 
 
/* Parse destination register operand.*/
static boolean
parse_register_dst(
struct translate_ctx *ctx,
uint *file,
struct parsed_bracket *brackets)
{
brackets->ind_comp = TGSI_SWIZZLE_X;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
if (!parse_register_bracket( ctx, brackets ))
return FALSE;
 
return TRUE;
}
 
static boolean
parse_dst_operand(
struct translate_ctx *ctx,
struct tgsi_full_dst_register *dst )
{
uint file;
uint writemask;
const char *cur;
struct parsed_bracket bracket[2];
int parsed_opt_brackets;
 
if (!parse_register_dst( ctx, &file, &bracket[0] ))
return FALSE;
if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
return FALSE;
 
cur = ctx->cur;
eat_opt_white( &cur );
 
if (!parse_opt_writemask( ctx, &writemask ))
return FALSE;
 
dst->Register.File = file;
if (parsed_opt_brackets) {
dst->Register.Dimension = 1;
dst->Dimension.Indirect = 0;
dst->Dimension.Dimension = 0;
dst->Dimension.Index = bracket[0].index;
bracket[0] = bracket[1];
}
dst->Register.Index = bracket[0].index;
dst->Register.WriteMask = writemask;
if (bracket[0].ind_file != TGSI_FILE_NULL) {
dst->Register.Indirect = 1;
dst->Indirect.File = bracket[0].ind_file;
dst->Indirect.Index = bracket[0].ind_index;
dst->Indirect.Swizzle = bracket[0].ind_comp;
dst->Indirect.ArrayID = bracket[0].ind_array;
}
return TRUE;
}
 
static boolean
parse_optional_swizzle(
struct translate_ctx *ctx,
uint swizzle[4],
boolean *parsed_swizzle )
{
const char *cur = ctx->cur;
 
*parsed_swizzle = FALSE;
 
eat_opt_white( &cur );
if (*cur == '.') {
uint i;
 
cur++;
eat_opt_white( &cur );
for (i = 0; i < 4; i++) {
if (uprcase( *cur ) == 'X')
swizzle[i] = TGSI_SWIZZLE_X;
else if (uprcase( *cur ) == 'Y')
swizzle[i] = TGSI_SWIZZLE_Y;
else if (uprcase( *cur ) == 'Z')
swizzle[i] = TGSI_SWIZZLE_Z;
else if (uprcase( *cur ) == 'W')
swizzle[i] = TGSI_SWIZZLE_W;
else {
report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
return FALSE;
}
cur++;
}
*parsed_swizzle = TRUE;
ctx->cur = cur;
}
return TRUE;
}
 
static boolean
parse_src_operand(
struct translate_ctx *ctx,
struct tgsi_full_src_register *src )
{
uint file;
uint swizzle[4];
boolean parsed_swizzle;
struct parsed_bracket bracket[2];
int parsed_opt_brackets;
 
if (*ctx->cur == '-') {
ctx->cur++;
eat_opt_white( &ctx->cur );
src->Register.Negate = 1;
}
 
if (*ctx->cur == '|') {
ctx->cur++;
eat_opt_white( &ctx->cur );
src->Register.Absolute = 1;
}
 
if (!parse_register_src(ctx, &file, &bracket[0]))
return FALSE;
if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
return FALSE;
 
src->Register.File = file;
if (parsed_opt_brackets) {
src->Register.Dimension = 1;
src->Dimension.Indirect = 0;
src->Dimension.Dimension = 0;
src->Dimension.Index = bracket[0].index;
bracket[0] = bracket[1];
}
src->Register.Index = bracket[0].index;
if (bracket[0].ind_file != TGSI_FILE_NULL) {
src->Register.Indirect = 1;
src->Indirect.File = bracket[0].ind_file;
src->Indirect.Index = bracket[0].ind_index;
src->Indirect.Swizzle = bracket[0].ind_comp;
src->Indirect.ArrayID = bracket[0].ind_array;
}
 
/* Parse optional swizzle.
*/
if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
if (parsed_swizzle) {
src->Register.SwizzleX = swizzle[0];
src->Register.SwizzleY = swizzle[1];
src->Register.SwizzleZ = swizzle[2];
src->Register.SwizzleW = swizzle[3];
}
}
 
if (src->Register.Absolute) {
eat_opt_white( &ctx->cur );
if (*ctx->cur != '|') {
report_error( ctx, "Expected `|'" );
return FALSE;
}
ctx->cur++;
}
 
 
return TRUE;
}
 
static boolean
match_inst(const char **pcur,
unsigned *saturate,
const struct tgsi_opcode_info *info)
{
const char *cur = *pcur;
 
/* simple case: the whole string matches the instruction name */
if (str_match_nocase_whole(&cur, info->mnemonic)) {
*pcur = cur;
*saturate = TGSI_SAT_NONE;
return TRUE;
}
 
if (str_match_no_case(&cur, info->mnemonic)) {
/* the instruction has a suffix, figure it out */
if (str_match_nocase_whole(&cur, "_SAT")) {
*pcur = cur;
*saturate = TGSI_SAT_ZERO_ONE;
return TRUE;
}
 
if (str_match_nocase_whole(&cur, "_SATNV")) {
*pcur = cur;
*saturate = TGSI_SAT_MINUS_PLUS_ONE;
return TRUE;
}
}
 
return FALSE;
}
 
static boolean
parse_instruction(
struct translate_ctx *ctx,
boolean has_label )
{
uint i;
uint saturate = TGSI_SAT_NONE;
const struct tgsi_opcode_info *info;
struct tgsi_full_instruction inst;
const char *cur;
uint advance;
 
inst = tgsi_default_full_instruction();
 
/* Parse predicate.
*/
eat_opt_white( &ctx->cur );
if (*ctx->cur == '(') {
uint file;
int index;
uint swizzle[4];
boolean parsed_swizzle;
 
inst.Instruction.Predicate = 1;
 
ctx->cur++;
if (*ctx->cur == '!') {
ctx->cur++;
inst.Predicate.Negate = 1;
}
 
if (!parse_register_1d( ctx, &file, &index ))
return FALSE;
 
if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
if (parsed_swizzle) {
inst.Predicate.SwizzleX = swizzle[0];
inst.Predicate.SwizzleY = swizzle[1];
inst.Predicate.SwizzleZ = swizzle[2];
inst.Predicate.SwizzleW = swizzle[3];
}
}
 
if (*ctx->cur != ')') {
report_error( ctx, "Expected `)'" );
return FALSE;
}
 
ctx->cur++;
}
 
/* Parse instruction name.
*/
eat_opt_white( &ctx->cur );
for (i = 0; i < TGSI_OPCODE_LAST; i++) {
cur = ctx->cur;
 
info = tgsi_get_opcode_info( i );
if (match_inst(&cur, &saturate, info)) {
if (info->num_dst + info->num_src + info->is_tex == 0) {
ctx->cur = cur;
break;
}
else if (*cur == '\0' || eat_white( &cur )) {
ctx->cur = cur;
break;
}
}
}
if (i == TGSI_OPCODE_LAST) {
if (has_label)
report_error( ctx, "Unknown opcode" );
else
report_error( ctx, "Expected `DCL', `IMM' or a label" );
return FALSE;
}
 
inst.Instruction.Opcode = i;
inst.Instruction.Saturate = saturate;
inst.Instruction.NumDstRegs = info->num_dst;
inst.Instruction.NumSrcRegs = info->num_src;
 
if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
/*
* These are not considered tex opcodes here (no additional
* target argument) however we're required to set the Texture
* bit so we can set the number of tex offsets (offsets aren't
* actually handled here yet in any case).
*/
inst.Instruction.Texture = 1;
inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
}
 
/* Parse instruction operands.
*/
for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
if (i > 0) {
eat_opt_white( &ctx->cur );
if (*ctx->cur != ',') {
report_error( ctx, "Expected `,'" );
return FALSE;
}
ctx->cur++;
eat_opt_white( &ctx->cur );
}
 
if (i < info->num_dst) {
if (!parse_dst_operand( ctx, &inst.Dst[i] ))
return FALSE;
}
else if (i < info->num_dst + info->num_src) {
if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
return FALSE;
}
else {
uint j;
 
for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
inst.Instruction.Texture = 1;
inst.Texture.Texture = j;
break;
}
}
if (j == TGSI_TEXTURE_COUNT) {
report_error( ctx, "Expected texture target" );
return FALSE;
}
}
}
 
cur = ctx->cur;
eat_opt_white( &cur );
if (info->is_branch && *cur == ':') {
uint target;
 
cur++;
eat_opt_white( &cur );
if (!parse_uint( &cur, &target )) {
report_error( ctx, "Expected a label" );
return FALSE;
}
inst.Instruction.Label = 1;
inst.Label.Label = target;
ctx->cur = cur;
}
 
advance = tgsi_build_full_instruction(
&inst,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
return TRUE;
}
 
/* parses a 4-touple of the form {x, y, z, w}
* where x, y, z, w are numbers */
static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
union tgsi_immediate_data *values)
{
unsigned i;
int ret;
 
eat_opt_white( &ctx->cur );
if (*ctx->cur != '{') {
report_error( ctx, "Expected `{'" );
return FALSE;
}
ctx->cur++;
for (i = 0; i < 4; i++) {
eat_opt_white( &ctx->cur );
if (i > 0) {
if (*ctx->cur != ',') {
report_error( ctx, "Expected `,'" );
return FALSE;
}
ctx->cur++;
eat_opt_white( &ctx->cur );
}
 
switch (type) {
case TGSI_IMM_FLOAT32:
ret = parse_float(&ctx->cur, &values[i].Float);
break;
case TGSI_IMM_UINT32:
ret = parse_uint(&ctx->cur, &values[i].Uint);
break;
case TGSI_IMM_INT32:
ret = parse_int(&ctx->cur, &values[i].Int);
break;
default:
assert(0);
ret = FALSE;
break;
}
 
if (!ret) {
report_error( ctx, "Expected immediate constant" );
return FALSE;
}
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != '}') {
report_error( ctx, "Expected `}'" );
return FALSE;
}
ctx->cur++;
 
return TRUE;
}
 
static boolean parse_declaration( struct translate_ctx *ctx )
{
struct tgsi_full_declaration decl;
uint file;
struct parsed_dcl_bracket brackets[2];
int num_brackets;
uint writemask;
const char *cur, *cur2;
uint advance;
boolean is_vs_input;
 
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
return FALSE;
if (!parse_opt_writemask( ctx, &writemask ))
return FALSE;
 
decl = tgsi_default_full_declaration();
decl.Declaration.File = file;
decl.Declaration.UsageMask = writemask;
 
if (num_brackets == 1) {
decl.Range.First = brackets[0].first;
decl.Range.Last = brackets[0].last;
} else {
decl.Range.First = brackets[1].first;
decl.Range.Last = brackets[1].last;
 
decl.Declaration.Dimension = 1;
decl.Dim.Index2D = brackets[0].first;
}
 
is_vs_input = (file == TGSI_FILE_INPUT &&
ctx->processor == TGSI_PROCESSOR_VERTEX);
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',') {
cur2 = cur;
cur2++;
eat_opt_white( &cur2 );
if (str_match_nocase_whole( &cur2, "ARRAY" )) {
int arrayid;
if (*cur2 != '(') {
report_error( ctx, "Expected `('" );
return FALSE;
}
cur2++;
eat_opt_white( &cur2 );
if (!parse_int( &cur2, &arrayid )) {
report_error( ctx, "Expected `,'" );
return FALSE;
}
eat_opt_white( &cur2 );
if (*cur2 != ')') {
report_error( ctx, "Expected `)'" );
return FALSE;
}
cur2++;
decl.Declaration.Array = 1;
decl.Array.ArrayID = arrayid;
ctx->cur = cur = cur2;
}
}
 
if (*cur == ',' && !is_vs_input) {
uint i, j;
 
cur++;
eat_opt_white( &cur );
if (file == TGSI_FILE_RESOURCE) {
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
decl.Resource.Resource = i;
break;
}
}
if (i == TGSI_TEXTURE_COUNT) {
report_error(ctx, "Expected texture target");
return FALSE;
}
 
cur2 = cur;
eat_opt_white(&cur2);
while (*cur2 == ',') {
cur2++;
eat_opt_white(&cur2);
if (str_match_nocase_whole(&cur2, "RAW")) {
decl.Resource.Raw = 1;
 
} else if (str_match_nocase_whole(&cur2, "WR")) {
decl.Resource.Writable = 1;
 
} else {
break;
}
cur = cur2;
eat_opt_white(&cur2);
}
 
ctx->cur = cur;
 
} else if (file == TGSI_FILE_SAMPLER_VIEW) {
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
decl.SamplerView.Resource = i;
break;
}
}
if (i == TGSI_TEXTURE_COUNT) {
report_error(ctx, "Expected texture target");
return FALSE;
}
eat_opt_white( &cur );
if (*cur != ',') {
report_error( ctx, "Expected `,'" );
return FALSE;
}
++cur;
eat_opt_white( &cur );
for (j = 0; j < 4; ++j) {
for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
switch (j) {
case 0:
decl.SamplerView.ReturnTypeX = i;
break;
case 1:
decl.SamplerView.ReturnTypeY = i;
break;
case 2:
decl.SamplerView.ReturnTypeZ = i;
break;
case 3:
decl.SamplerView.ReturnTypeW = i;
break;
default:
assert(0);
}
break;
}
}
if (i == PIPE_TYPE_COUNT) {
if (j == 0 || j > 2) {
report_error(ctx, "Expected type name");
return FALSE;
}
break;
} else {
cur2 = cur;
eat_opt_white( &cur2 );
if (*cur2 == ',') {
cur2++;
eat_opt_white( &cur2 );
cur = cur2;
continue;
} else
break;
}
}
if (j < 4) {
decl.SamplerView.ReturnTypeY =
decl.SamplerView.ReturnTypeZ =
decl.SamplerView.ReturnTypeW =
decl.SamplerView.ReturnTypeX;
}
ctx->cur = cur;
} else {
if (str_match_nocase_whole(&cur, "LOCAL")) {
decl.Declaration.Local = 1;
ctx->cur = cur;
}
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',') {
cur++;
eat_opt_white( &cur );
 
for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
uint index;
 
cur2 = cur;
eat_opt_white( &cur2 );
if (*cur2 == '[') {
cur2++;
eat_opt_white( &cur2 );
if (!parse_uint( &cur2, &index )) {
report_error( ctx, "Expected literal integer" );
return FALSE;
}
eat_opt_white( &cur2 );
if (*cur2 != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
cur2++;
 
decl.Semantic.Index = index;
 
cur = cur2;
}
 
decl.Declaration.Semantic = 1;
decl.Semantic.Name = i;
 
ctx->cur = cur;
break;
}
}
}
}
}
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',' && !is_vs_input) {
uint i;
 
cur++;
eat_opt_white( &cur );
for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
decl.Declaration.Interpolate = 1;
decl.Interp.Interpolate = i;
 
ctx->cur = cur;
break;
}
}
if (i == TGSI_INTERPOLATE_COUNT) {
report_error( ctx, "Expected semantic or interpolate attribute" );
return FALSE;
}
}
 
advance = tgsi_build_full_declaration(
&decl,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
 
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
return TRUE;
}
 
static boolean parse_immediate( struct translate_ctx *ctx )
{
struct tgsi_full_immediate imm;
uint advance;
int type;
 
if (*ctx->cur == '[') {
uint uindex;
 
++ctx->cur;
 
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
 
if (uindex != ctx->num_immediates) {
report_error( ctx, "Immediates must be sorted" );
return FALSE;
}
 
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
 
ctx->cur++;
}
 
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
break;
}
if (type == Elements(tgsi_immediate_type_names)) {
report_error( ctx, "Expected immediate type" );
return FALSE;
}
 
imm = tgsi_default_full_immediate();
imm.Immediate.NrTokens += 4;
imm.Immediate.DataType = type;
parse_immediate_data(ctx, type, imm.u);
 
advance = tgsi_build_full_immediate(
&imm,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
ctx->num_immediates++;
 
return TRUE;
}
 
static boolean
parse_primitive( const char **pcur, uint *primitive )
{
uint i;
 
for (i = 0; i < PIPE_PRIM_MAX; i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
*primitive = i;
*pcur = cur;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
{
uint i;
 
for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
*fs_coord_origin = i;
*pcur = cur;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
{
uint i;
 
for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
*fs_coord_pixel_center = i;
*pcur = cur;
return TRUE;
}
}
return FALSE;
}
 
 
static boolean parse_property( struct translate_ctx *ctx )
{
struct tgsi_full_property prop;
uint property_name;
uint values[8];
uint advance;
char id[64];
 
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
if (!parse_identifier( &ctx->cur, id )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
++property_name) {
if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
break;
}
}
if (property_name >= TGSI_PROPERTY_COUNT) {
debug_printf( "\nError: Unknown property : '%s'", id );
return FALSE;
}
 
eat_opt_white( &ctx->cur );
switch(property_name) {
case TGSI_PROPERTY_GS_INPUT_PRIM:
case TGSI_PROPERTY_GS_OUTPUT_PRIM:
if (!parse_primitive(&ctx->cur, &values[0] )) {
report_error( ctx, "Unknown primitive name as property!" );
return FALSE;
}
if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
ctx->implied_array_size = u_vertices_per_prim(values[0]);
}
break;
case TGSI_PROPERTY_FS_COORD_ORIGIN:
if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
return FALSE;
}
break;
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
return FALSE;
}
break;
case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
default:
if (!parse_uint(&ctx->cur, &values[0] )) {
report_error( ctx, "Expected unsigned integer as property!" );
return FALSE;
}
}
 
prop = tgsi_default_full_property();
prop.Property.PropertyName = property_name;
prop.Property.NrTokens += 1;
prop.u[0].Data = values[0];
 
advance = tgsi_build_full_property(
&prop,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
return TRUE;
}
 
 
static boolean translate( struct translate_ctx *ctx )
{
eat_opt_white( &ctx->cur );
if (!parse_header( ctx ))
return FALSE;
 
while (*ctx->cur != '\0') {
uint label_val = 0;
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
 
if (*ctx->cur == '\0')
break;
if (parse_label( ctx, &label_val )) {
if (!parse_instruction( ctx, TRUE ))
return FALSE;
}
else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
if (!parse_declaration( ctx ))
return FALSE;
}
else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
if (!parse_immediate( ctx ))
return FALSE;
}
else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
if (!parse_property( ctx ))
return FALSE;
}
else if (!parse_instruction( ctx, FALSE )) {
return FALSE;
}
}
 
return TRUE;
}
 
boolean
tgsi_text_translate(
const char *text,
struct tgsi_token *tokens,
uint num_tokens )
{
struct translate_ctx ctx = {0};
 
ctx.text = text;
ctx.cur = text;
ctx.tokens = tokens;
ctx.tokens_cur = tokens;
ctx.tokens_end = tokens + num_tokens;
 
if (!translate( &ctx ))
return FALSE;
 
return tgsi_sanity_check( tokens );
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_text.h
0,0 → 1,49
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_TEXT_H
#define TGSI_TEXT_H
 
#if defined __cplusplus
extern "C" {
#endif
 
#include "pipe/p_compiler.h"
 
struct tgsi_token;
 
boolean
tgsi_text_translate(
const char *text,
struct tgsi_token *tokens,
uint num_tokens );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_TEXT_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_transform.c
0,0 → 1,250
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* TGSI program transformation utility.
*
* Authors: Brian Paul
*/
 
#include "util/u_debug.h"
 
#include "tgsi_transform.h"
 
 
 
static void
emit_instruction(struct tgsi_transform_context *ctx,
const struct tgsi_full_instruction *inst)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_instruction(inst,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
static void
emit_declaration(struct tgsi_transform_context *ctx,
const struct tgsi_full_declaration *decl)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_declaration(decl,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
static void
emit_immediate(struct tgsi_transform_context *ctx,
const struct tgsi_full_immediate *imm)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_immediate(imm,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
static void
emit_property(struct tgsi_transform_context *ctx,
const struct tgsi_full_property *prop)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_property(prop,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
/**
* Apply user-defined transformations to the input shader to produce
* the output shader.
* For example, a register search-and-replace operation could be applied
* by defining a transform_instruction() callback that examined and changed
* the instruction src/dest regs.
*
* \return number of tokens emitted
*/
int
tgsi_transform_shader(const struct tgsi_token *tokens_in,
struct tgsi_token *tokens_out,
uint max_tokens_out,
struct tgsi_transform_context *ctx)
{
uint procType;
 
/* input shader */
struct tgsi_parse_context parse;
 
/* output shader */
struct tgsi_processor *processor;
 
 
/**
** callback context init
**/
ctx->emit_instruction = emit_instruction;
ctx->emit_declaration = emit_declaration;
ctx->emit_immediate = emit_immediate;
ctx->emit_property = emit_property;
ctx->tokens_out = tokens_out;
ctx->max_tokens_out = max_tokens_out;
 
 
/**
** Setup to begin parsing input shader
**/
if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) {
debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n");
return -1;
}
procType = parse.FullHeader.Processor.Processor;
assert(procType == TGSI_PROCESSOR_FRAGMENT ||
procType == TGSI_PROCESSOR_VERTEX ||
procType == TGSI_PROCESSOR_GEOMETRY);
 
 
/**
** Setup output shader
**/
ctx->header = (struct tgsi_header *)tokens_out;
*ctx->header = tgsi_build_header();
 
processor = (struct tgsi_processor *) (tokens_out + 1);
*processor = tgsi_build_processor( procType, ctx->header );
 
ctx->ti = 2;
 
 
/**
** Loop over incoming program tokens/instructions
*/
while( !tgsi_parse_end_of_tokens( &parse ) ) {
 
tgsi_parse_token( &parse );
 
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
struct tgsi_full_instruction *fullinst
= &parse.FullToken.FullInstruction;
 
if (ctx->transform_instruction)
ctx->transform_instruction(ctx, fullinst);
else
ctx->emit_instruction(ctx, fullinst);
}
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
{
struct tgsi_full_declaration *fulldecl
= &parse.FullToken.FullDeclaration;
 
if (ctx->transform_declaration)
ctx->transform_declaration(ctx, fulldecl);
else
ctx->emit_declaration(ctx, fulldecl);
}
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
struct tgsi_full_immediate *fullimm
= &parse.FullToken.FullImmediate;
 
if (ctx->transform_immediate)
ctx->transform_immediate(ctx, fullimm);
else
ctx->emit_immediate(ctx, fullimm);
}
break;
case TGSI_TOKEN_TYPE_PROPERTY:
{
struct tgsi_full_property *fullprop
= &parse.FullToken.FullProperty;
 
if (ctx->transform_property)
ctx->transform_property(ctx, fullprop);
else
ctx->emit_property(ctx, fullprop);
}
break;
 
default:
assert( 0 );
}
}
 
if (ctx->epilog) {
ctx->epilog(ctx);
}
 
tgsi_parse_free (&parse);
 
return ctx->ti;
}
 
 
#include "tgsi_text.h"
 
extern int tgsi_transform_foo( struct tgsi_token *tokens_out,
uint max_tokens_out );
 
/* This function exists only so that tgsi_text_translate() doesn't get
* magic-ed out of the libtgsi.a archive by the build system. Don't
* remove unless you know this has been fixed - check on mingw/scons
* builds as well.
*/
int
tgsi_transform_foo( struct tgsi_token *tokens_out,
uint max_tokens_out )
{
const char *text =
"FRAG\n"
"DCL IN[0], COLOR, CONSTANT\n"
"DCL OUT[0], COLOR\n"
" 0: MOV OUT[0], IN[0]\n"
" 1: END";
return tgsi_text_translate( text,
tokens_out,
max_tokens_out );
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_transform.h
0,0 → 1,96
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_TRANSFORM_H
#define TGSI_TRANSFORM_H
 
 
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_build.h"
 
 
 
/**
* Subclass this to add caller-specific data
*/
struct tgsi_transform_context
{
/**** PUBLIC ***/
 
/**
* User-defined callbacks invoked per instruction.
*/
void (*transform_instruction)(struct tgsi_transform_context *ctx,
struct tgsi_full_instruction *inst);
 
void (*transform_declaration)(struct tgsi_transform_context *ctx,
struct tgsi_full_declaration *decl);
 
void (*transform_immediate)(struct tgsi_transform_context *ctx,
struct tgsi_full_immediate *imm);
void (*transform_property)(struct tgsi_transform_context *ctx,
struct tgsi_full_property *prop);
 
/**
* Called at end of input program to allow caller to append extra
* instructions. Return number of tokens emitted.
*/
void (*epilog)(struct tgsi_transform_context *ctx);
 
 
/*** PRIVATE ***/
 
/**
* These are setup by tgsi_transform_shader() and cannot be overridden.
* Meant to be called from in the above user callback functions.
*/
void (*emit_instruction)(struct tgsi_transform_context *ctx,
const struct tgsi_full_instruction *inst);
void (*emit_declaration)(struct tgsi_transform_context *ctx,
const struct tgsi_full_declaration *decl);
void (*emit_immediate)(struct tgsi_transform_context *ctx,
const struct tgsi_full_immediate *imm);
void (*emit_property)(struct tgsi_transform_context *ctx,
const struct tgsi_full_property *prop);
 
struct tgsi_header *header;
uint max_tokens_out;
struct tgsi_token *tokens_out;
uint ti;
};
 
 
 
extern int
tgsi_transform_shader(const struct tgsi_token *tokens_in,
struct tgsi_token *tokens_out,
uint max_tokens_out,
struct tgsi_transform_context *ctx);
 
 
#endif /* TGSI_TRANSFORM_H */
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_ureg.c
0,0 → 1,1795
/**************************************************************************
*
* Copyright 2009-2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
 
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "tgsi/tgsi_ureg.h"
#include "tgsi/tgsi_build.h"
#include "tgsi/tgsi_info.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_sanity.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_bitmask.h"
 
union tgsi_any_token {
struct tgsi_header header;
struct tgsi_processor processor;
struct tgsi_token token;
struct tgsi_property prop;
struct tgsi_property_data prop_data;
struct tgsi_declaration decl;
struct tgsi_declaration_range decl_range;
struct tgsi_declaration_dimension decl_dim;
struct tgsi_declaration_interp decl_interp;
struct tgsi_declaration_semantic decl_semantic;
struct tgsi_declaration_sampler_view decl_sampler_view;
struct tgsi_declaration_array array;
struct tgsi_immediate imm;
union tgsi_immediate_data imm_data;
struct tgsi_instruction insn;
struct tgsi_instruction_predicate insn_predicate;
struct tgsi_instruction_label insn_label;
struct tgsi_instruction_texture insn_texture;
struct tgsi_texture_offset insn_texture_offset;
struct tgsi_src_register src;
struct tgsi_ind_register ind;
struct tgsi_dimension dim;
struct tgsi_dst_register dst;
unsigned value;
};
 
 
struct ureg_tokens {
union tgsi_any_token *tokens;
unsigned size;
unsigned order;
unsigned count;
};
 
#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
#define UREG_MAX_OUTPUT PIPE_MAX_SHADER_OUTPUTS
#define UREG_MAX_CONSTANT_RANGE 32
#define UREG_MAX_IMMEDIATE 256
#define UREG_MAX_ADDR 2
#define UREG_MAX_PRED 1
#define UREG_MAX_ARRAY_TEMPS 256
 
struct const_decl {
struct {
unsigned first;
unsigned last;
} constant_range[UREG_MAX_CONSTANT_RANGE];
unsigned nr_constant_ranges;
};
 
#define DOMAIN_DECL 0
#define DOMAIN_INSN 1
 
struct ureg_program
{
unsigned processor;
struct pipe_context *pipe;
 
struct {
unsigned semantic_name;
unsigned semantic_index;
unsigned interp;
unsigned char cylindrical_wrap;
unsigned char centroid;
} fs_input[UREG_MAX_INPUT];
unsigned nr_fs_inputs;
 
unsigned vs_inputs[UREG_MAX_INPUT/32];
 
struct {
unsigned index;
unsigned semantic_name;
unsigned semantic_index;
} gs_input[UREG_MAX_INPUT];
unsigned nr_gs_inputs;
 
struct {
unsigned index;
unsigned semantic_name;
unsigned semantic_index;
} system_value[UREG_MAX_SYSTEM_VALUE];
unsigned nr_system_values;
 
struct {
unsigned semantic_name;
unsigned semantic_index;
unsigned usage_mask; /* = TGSI_WRITEMASK_* */
} output[UREG_MAX_OUTPUT];
unsigned nr_outputs;
 
struct {
union {
float f[4];
unsigned u[4];
int i[4];
} value;
unsigned nr;
unsigned type;
} immediate[UREG_MAX_IMMEDIATE];
unsigned nr_immediates;
 
struct ureg_src sampler[PIPE_MAX_SAMPLERS];
unsigned nr_samplers;
 
struct {
unsigned index;
unsigned target;
unsigned return_type_x;
unsigned return_type_y;
unsigned return_type_z;
unsigned return_type_w;
} sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS];
unsigned nr_sampler_views;
 
struct util_bitmask *free_temps;
struct util_bitmask *local_temps;
struct util_bitmask *decl_temps;
unsigned nr_temps;
 
unsigned array_temps[UREG_MAX_ARRAY_TEMPS];
unsigned nr_array_temps;
 
struct const_decl const_decls;
struct const_decl const_decls2D[PIPE_MAX_CONSTANT_BUFFERS];
 
unsigned property_gs_input_prim;
unsigned property_gs_output_prim;
unsigned property_gs_max_vertices;
unsigned char property_fs_coord_origin; /* = TGSI_FS_COORD_ORIGIN_* */
unsigned char property_fs_coord_pixel_center; /* = TGSI_FS_COORD_PIXEL_CENTER_* */
unsigned char property_fs_color0_writes_all_cbufs; /* = TGSI_FS_COLOR0_WRITES_ALL_CBUFS * */
unsigned char property_fs_depth_layout; /* TGSI_FS_DEPTH_LAYOUT */
 
unsigned nr_addrs;
unsigned nr_preds;
unsigned nr_instructions;
 
struct ureg_tokens domain[2];
};
 
static union tgsi_any_token error_tokens[32];
 
static void tokens_error( struct ureg_tokens *tokens )
{
if (tokens->tokens && tokens->tokens != error_tokens)
FREE(tokens->tokens);
 
tokens->tokens = error_tokens;
tokens->size = Elements(error_tokens);
tokens->count = 0;
}
 
 
static void tokens_expand( struct ureg_tokens *tokens,
unsigned count )
{
unsigned old_size = tokens->size * sizeof(unsigned);
 
if (tokens->tokens == error_tokens) {
return;
}
 
while (tokens->count + count > tokens->size) {
tokens->size = (1 << ++tokens->order);
}
 
tokens->tokens = REALLOC(tokens->tokens,
old_size,
tokens->size * sizeof(unsigned));
if (tokens->tokens == NULL) {
tokens_error(tokens);
}
}
 
static void set_bad( struct ureg_program *ureg )
{
tokens_error(&ureg->domain[0]);
}
 
 
 
static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
unsigned domain,
unsigned count )
{
struct ureg_tokens *tokens = &ureg->domain[domain];
union tgsi_any_token *result;
 
if (tokens->count + count > tokens->size)
tokens_expand(tokens, count);
 
result = &tokens->tokens[tokens->count];
tokens->count += count;
return result;
}
 
 
static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
unsigned domain,
unsigned nr )
{
if (ureg->domain[domain].tokens == error_tokens)
return &error_tokens[0];
 
return &ureg->domain[domain].tokens[nr];
}
 
 
 
static INLINE struct ureg_dst
ureg_dst_register( unsigned file,
unsigned index )
{
struct ureg_dst dst;
 
dst.File = file;
dst.WriteMask = TGSI_WRITEMASK_XYZW;
dst.Indirect = 0;
dst.IndirectFile = TGSI_FILE_NULL;
dst.IndirectIndex = 0;
dst.IndirectSwizzle = 0;
dst.Saturate = 0;
dst.Predicate = 0;
dst.PredNegate = 0;
dst.PredSwizzleX = TGSI_SWIZZLE_X;
dst.PredSwizzleY = TGSI_SWIZZLE_Y;
dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
dst.PredSwizzleW = TGSI_SWIZZLE_W;
dst.Index = index;
dst.ArrayID = 0;
 
return dst;
}
 
 
void
ureg_property_gs_input_prim(struct ureg_program *ureg,
unsigned input_prim)
{
ureg->property_gs_input_prim = input_prim;
}
 
void
ureg_property_gs_output_prim(struct ureg_program *ureg,
unsigned output_prim)
{
ureg->property_gs_output_prim = output_prim;
}
 
void
ureg_property_gs_max_vertices(struct ureg_program *ureg,
unsigned max_vertices)
{
ureg->property_gs_max_vertices = max_vertices;
}
 
void
ureg_property_fs_coord_origin(struct ureg_program *ureg,
unsigned fs_coord_origin)
{
ureg->property_fs_coord_origin = fs_coord_origin;
}
 
void
ureg_property_fs_coord_pixel_center(struct ureg_program *ureg,
unsigned fs_coord_pixel_center)
{
ureg->property_fs_coord_pixel_center = fs_coord_pixel_center;
}
 
void
ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg,
unsigned fs_color0_writes_all_cbufs)
{
ureg->property_fs_color0_writes_all_cbufs = fs_color0_writes_all_cbufs;
}
 
void
ureg_property_fs_depth_layout(struct ureg_program *ureg,
unsigned fs_depth_layout)
{
ureg->property_fs_depth_layout = fs_depth_layout;
}
 
struct ureg_src
ureg_DECL_fs_input_cyl_centroid(struct ureg_program *ureg,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode,
unsigned cylindrical_wrap,
unsigned centroid)
{
unsigned i;
 
for (i = 0; i < ureg->nr_fs_inputs; i++) {
if (ureg->fs_input[i].semantic_name == semantic_name &&
ureg->fs_input[i].semantic_index == semantic_index) {
goto out;
}
}
 
if (ureg->nr_fs_inputs < UREG_MAX_INPUT) {
ureg->fs_input[i].semantic_name = semantic_name;
ureg->fs_input[i].semantic_index = semantic_index;
ureg->fs_input[i].interp = interp_mode;
ureg->fs_input[i].cylindrical_wrap = cylindrical_wrap;
ureg->fs_input[i].centroid = centroid;
ureg->nr_fs_inputs++;
} else {
set_bad(ureg);
}
 
out:
return ureg_src_register(TGSI_FILE_INPUT, i);
}
 
 
struct ureg_src
ureg_DECL_vs_input( struct ureg_program *ureg,
unsigned index )
{
assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
ureg->vs_inputs[index/32] |= 1 << (index % 32);
return ureg_src_register( TGSI_FILE_INPUT, index );
}
 
 
struct ureg_src
ureg_DECL_gs_input(struct ureg_program *ureg,
unsigned index,
unsigned semantic_name,
unsigned semantic_index)
{
if (ureg->nr_gs_inputs < UREG_MAX_INPUT) {
ureg->gs_input[ureg->nr_gs_inputs].index = index;
ureg->gs_input[ureg->nr_gs_inputs].semantic_name = semantic_name;
ureg->gs_input[ureg->nr_gs_inputs].semantic_index = semantic_index;
ureg->nr_gs_inputs++;
} else {
set_bad(ureg);
}
 
/* XXX: Add suport for true 2D input registers. */
return ureg_src_register(TGSI_FILE_INPUT, index);
}
 
 
struct ureg_src
ureg_DECL_system_value(struct ureg_program *ureg,
unsigned index,
unsigned semantic_name,
unsigned semantic_index)
{
if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) {
ureg->system_value[ureg->nr_system_values].index = index;
ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name;
ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index;
ureg->nr_system_values++;
} else {
set_bad(ureg);
}
 
return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index);
}
 
 
struct ureg_dst
ureg_DECL_output_masked( struct ureg_program *ureg,
unsigned name,
unsigned index,
unsigned usage_mask )
{
unsigned i;
 
assert(usage_mask != 0);
 
for (i = 0; i < ureg->nr_outputs; i++) {
if (ureg->output[i].semantic_name == name &&
ureg->output[i].semantic_index == index) {
ureg->output[i].usage_mask |= usage_mask;
goto out;
}
}
 
if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
ureg->output[i].semantic_name = name;
ureg->output[i].semantic_index = index;
ureg->output[i].usage_mask = usage_mask;
ureg->nr_outputs++;
}
else {
set_bad( ureg );
}
 
out:
return ureg_dst_register( TGSI_FILE_OUTPUT, i );
}
 
 
struct ureg_dst
ureg_DECL_output( struct ureg_program *ureg,
unsigned name,
unsigned index )
{
return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW);
}
 
 
/* Returns a new constant register. Keep track of which have been
* referred to so that we can emit decls later.
*
* Constant operands declared with this function must be addressed
* with a two-dimensional index.
*
* There is nothing in this code to bind this constant to any tracked
* value or manage any constant_buffer contents -- that's the
* resposibility of the calling code.
*/
void
ureg_DECL_constant2D(struct ureg_program *ureg,
unsigned first,
unsigned last,
unsigned index2D)
{
struct const_decl *decl = &ureg->const_decls2D[index2D];
 
assert(index2D < PIPE_MAX_CONSTANT_BUFFERS);
 
if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
uint i = decl->nr_constant_ranges++;
 
decl->constant_range[i].first = first;
decl->constant_range[i].last = last;
}
}
 
 
/* A one-dimensional, depricated version of ureg_DECL_constant2D().
*
* Constant operands declared with this function must be addressed
* with a one-dimensional index.
*/
struct ureg_src
ureg_DECL_constant(struct ureg_program *ureg,
unsigned index)
{
struct const_decl *decl = &ureg->const_decls;
unsigned minconst = index, maxconst = index;
unsigned i;
 
/* Inside existing range?
*/
for (i = 0; i < decl->nr_constant_ranges; i++) {
if (decl->constant_range[i].first <= index &&
decl->constant_range[i].last >= index) {
goto out;
}
}
 
/* Extend existing range?
*/
for (i = 0; i < decl->nr_constant_ranges; i++) {
if (decl->constant_range[i].last == index - 1) {
decl->constant_range[i].last = index;
goto out;
}
 
if (decl->constant_range[i].first == index + 1) {
decl->constant_range[i].first = index;
goto out;
}
 
minconst = MIN2(minconst, decl->constant_range[i].first);
maxconst = MAX2(maxconst, decl->constant_range[i].last);
}
 
/* Create new range?
*/
if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
i = decl->nr_constant_ranges++;
decl->constant_range[i].first = index;
decl->constant_range[i].last = index;
goto out;
}
 
/* Collapse all ranges down to one:
*/
i = 0;
decl->constant_range[0].first = minconst;
decl->constant_range[0].last = maxconst;
decl->nr_constant_ranges = 1;
 
out:
assert(i < decl->nr_constant_ranges);
assert(decl->constant_range[i].first <= index);
assert(decl->constant_range[i].last >= index);
return ureg_src_register(TGSI_FILE_CONSTANT, index);
}
 
static struct ureg_dst alloc_temporary( struct ureg_program *ureg,
boolean local )
{
unsigned i;
 
/* Look for a released temporary.
*/
for (i = util_bitmask_get_first_index(ureg->free_temps);
i != UTIL_BITMASK_INVALID_INDEX;
i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) {
if (util_bitmask_get(ureg->local_temps, i) == local)
break;
}
 
/* Or allocate a new one.
*/
if (i == UTIL_BITMASK_INVALID_INDEX) {
i = ureg->nr_temps++;
 
if (local)
util_bitmask_set(ureg->local_temps, i);
 
/* Start a new declaration when the local flag changes */
if (!i || util_bitmask_get(ureg->local_temps, i - 1) != local)
util_bitmask_set(ureg->decl_temps, i);
}
 
util_bitmask_clear(ureg->free_temps, i);
 
return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
}
 
struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
{
return alloc_temporary(ureg, FALSE);
}
 
struct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg )
{
return alloc_temporary(ureg, TRUE);
}
 
struct ureg_dst ureg_DECL_array_temporary( struct ureg_program *ureg,
unsigned size,
boolean local )
{
unsigned i = ureg->nr_temps;
struct ureg_dst dst = ureg_dst_register( TGSI_FILE_TEMPORARY, i );
 
if (local)
util_bitmask_set(ureg->local_temps, i);
 
/* Always start a new declaration at the start */
util_bitmask_set(ureg->decl_temps, i);
 
ureg->nr_temps += size;
 
/* and also at the end of the array */
util_bitmask_set(ureg->decl_temps, ureg->nr_temps);
 
if (ureg->nr_array_temps < UREG_MAX_ARRAY_TEMPS) {
ureg->array_temps[ureg->nr_array_temps++] = i;
dst.ArrayID = ureg->nr_array_temps;
}
 
return dst;
}
 
void ureg_release_temporary( struct ureg_program *ureg,
struct ureg_dst tmp )
{
if(tmp.File == TGSI_FILE_TEMPORARY)
util_bitmask_set(ureg->free_temps, tmp.Index);
}
 
 
/* Allocate a new address register.
*/
struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
{
if (ureg->nr_addrs < UREG_MAX_ADDR)
return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
 
assert( 0 );
return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
}
 
/* Allocate a new predicate register.
*/
struct ureg_dst
ureg_DECL_predicate(struct ureg_program *ureg)
{
if (ureg->nr_preds < UREG_MAX_PRED) {
return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++);
}
 
assert(0);
return ureg_dst_register(TGSI_FILE_PREDICATE, 0);
}
 
/* Allocate a new sampler.
*/
struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
unsigned nr )
{
unsigned i;
 
for (i = 0; i < ureg->nr_samplers; i++)
if (ureg->sampler[i].Index == nr)
return ureg->sampler[i];
if (i < PIPE_MAX_SAMPLERS) {
ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
ureg->nr_samplers++;
return ureg->sampler[i];
}
 
assert( 0 );
return ureg->sampler[0];
}
 
/*
* Allocate a new shader sampler view.
*/
struct ureg_src
ureg_DECL_sampler_view(struct ureg_program *ureg,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w)
{
struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index);
uint i;
 
for (i = 0; i < ureg->nr_sampler_views; i++) {
if (ureg->sampler_view[i].index == index) {
return reg;
}
}
 
if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) {
ureg->sampler_view[i].index = index;
ureg->sampler_view[i].target = target;
ureg->sampler_view[i].return_type_x = return_type_x;
ureg->sampler_view[i].return_type_y = return_type_y;
ureg->sampler_view[i].return_type_z = return_type_z;
ureg->sampler_view[i].return_type_w = return_type_w;
ureg->nr_sampler_views++;
return reg;
}
 
assert(0);
return reg;
}
 
static int
match_or_expand_immediate( const unsigned *v,
unsigned nr,
unsigned *v2,
unsigned *pnr2,
unsigned *swizzle )
{
unsigned nr2 = *pnr2;
unsigned i, j;
 
*swizzle = 0;
 
for (i = 0; i < nr; i++) {
boolean found = FALSE;
 
for (j = 0; j < nr2 && !found; j++) {
if (v[i] == v2[j]) {
*swizzle |= j << (i * 2);
found = TRUE;
}
}
 
if (!found) {
if (nr2 >= 4) {
return FALSE;
}
 
v2[nr2] = v[i];
*swizzle |= nr2 << (i * 2);
nr2++;
}
}
 
/* Actually expand immediate only when fully succeeded.
*/
*pnr2 = nr2;
return TRUE;
}
 
 
static struct ureg_src
decl_immediate( struct ureg_program *ureg,
const unsigned *v,
unsigned nr,
unsigned type )
{
unsigned i, j;
unsigned swizzle = 0;
 
/* Could do a first pass where we examine all existing immediates
* without expanding.
*/
 
for (i = 0; i < ureg->nr_immediates; i++) {
if (ureg->immediate[i].type != type) {
continue;
}
if (match_or_expand_immediate(v,
nr,
ureg->immediate[i].value.u,
&ureg->immediate[i].nr,
&swizzle)) {
goto out;
}
}
 
if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
i = ureg->nr_immediates++;
ureg->immediate[i].type = type;
if (match_or_expand_immediate(v,
nr,
ureg->immediate[i].value.u,
&ureg->immediate[i].nr,
&swizzle)) {
goto out;
}
}
 
set_bad(ureg);
 
out:
/* Make sure that all referenced elements are from this immediate.
* Has the effect of making size-one immediates into scalars.
*/
for (j = nr; j < 4; j++) {
swizzle |= (swizzle & 0x3) << (j * 2);
}
 
return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i),
(swizzle >> 0) & 0x3,
(swizzle >> 2) & 0x3,
(swizzle >> 4) & 0x3,
(swizzle >> 6) & 0x3);
}
 
 
struct ureg_src
ureg_DECL_immediate( struct ureg_program *ureg,
const float *v,
unsigned nr )
{
union {
float f[4];
unsigned u[4];
} fu;
unsigned int i;
 
for (i = 0; i < nr; i++) {
fu.f[i] = v[i];
}
 
return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32);
}
 
 
struct ureg_src
ureg_DECL_immediate_uint( struct ureg_program *ureg,
const unsigned *v,
unsigned nr )
{
return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32);
}
 
 
struct ureg_src
ureg_DECL_immediate_block_uint( struct ureg_program *ureg,
const unsigned *v,
unsigned nr )
{
uint index;
uint i;
 
if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) {
set_bad(ureg);
return ureg_src_register(TGSI_FILE_IMMEDIATE, 0);
}
 
index = ureg->nr_immediates;
ureg->nr_immediates += (nr + 3) / 4;
 
for (i = index; i < ureg->nr_immediates; i++) {
ureg->immediate[i].type = TGSI_IMM_UINT32;
ureg->immediate[i].nr = nr > 4 ? 4 : nr;
memcpy(ureg->immediate[i].value.u,
&v[(i - index) * 4],
ureg->immediate[i].nr * sizeof(uint));
nr -= 4;
}
 
return ureg_src_register(TGSI_FILE_IMMEDIATE, index);
}
 
 
struct ureg_src
ureg_DECL_immediate_int( struct ureg_program *ureg,
const int *v,
unsigned nr )
{
return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32);
}
 
 
void
ureg_emit_src( struct ureg_program *ureg,
struct ureg_src src )
{
unsigned size = 1 + (src.Indirect ? 1 : 0) +
(src.Dimension ? (src.DimIndirect ? 2 : 1) : 0);
 
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
unsigned n = 0;
 
assert(src.File != TGSI_FILE_NULL);
assert(src.File < TGSI_FILE_COUNT);
out[n].value = 0;
out[n].src.File = src.File;
out[n].src.SwizzleX = src.SwizzleX;
out[n].src.SwizzleY = src.SwizzleY;
out[n].src.SwizzleZ = src.SwizzleZ;
out[n].src.SwizzleW = src.SwizzleW;
out[n].src.Index = src.Index;
out[n].src.Negate = src.Negate;
out[0].src.Absolute = src.Absolute;
n++;
 
if (src.Indirect) {
out[0].src.Indirect = 1;
out[n].value = 0;
out[n].ind.File = src.IndirectFile;
out[n].ind.Swizzle = src.IndirectSwizzle;
out[n].ind.Index = src.IndirectIndex;
out[n].ind.ArrayID = src.ArrayID;
n++;
}
 
if (src.Dimension) {
out[0].src.Dimension = 1;
out[n].dim.Dimension = 0;
out[n].dim.Padding = 0;
if (src.DimIndirect) {
out[n].dim.Indirect = 1;
out[n].dim.Index = src.DimensionIndex;
n++;
out[n].value = 0;
out[n].ind.File = src.DimIndFile;
out[n].ind.Swizzle = src.DimIndSwizzle;
out[n].ind.Index = src.DimIndIndex;
out[n].ind.ArrayID = src.ArrayID;
} else {
out[n].dim.Indirect = 0;
out[n].dim.Index = src.DimensionIndex;
}
n++;
}
 
assert(n == size);
}
 
 
void
ureg_emit_dst( struct ureg_program *ureg,
struct ureg_dst dst )
{
unsigned size = (1 +
(dst.Indirect ? 1 : 0));
 
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
unsigned n = 0;
 
assert(dst.File != TGSI_FILE_NULL);
assert(dst.File != TGSI_FILE_CONSTANT);
assert(dst.File != TGSI_FILE_INPUT);
assert(dst.File != TGSI_FILE_SAMPLER);
assert(dst.File != TGSI_FILE_SAMPLER_VIEW);
assert(dst.File != TGSI_FILE_IMMEDIATE);
assert(dst.File < TGSI_FILE_COUNT);
 
out[n].value = 0;
out[n].dst.File = dst.File;
out[n].dst.WriteMask = dst.WriteMask;
out[n].dst.Indirect = dst.Indirect;
out[n].dst.Index = dst.Index;
n++;
if (dst.Indirect) {
out[n].value = 0;
out[n].ind.File = dst.IndirectFile;
out[n].ind.Swizzle = dst.IndirectSwizzle;
out[n].ind.Index = dst.IndirectIndex;
out[n].ind.ArrayID = dst.ArrayID;
n++;
}
 
assert(n == size);
}
 
 
static void validate( unsigned opcode,
unsigned nr_dst,
unsigned nr_src )
{
#ifdef DEBUG
const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
assert(info);
if(info) {
assert(nr_dst == info->num_dst);
assert(nr_src == info->num_src);
}
#endif
}
 
struct ureg_emit_insn_result
ureg_emit_insn(struct ureg_program *ureg,
unsigned opcode,
boolean saturate,
boolean predicate,
boolean pred_negate,
unsigned pred_swizzle_x,
unsigned pred_swizzle_y,
unsigned pred_swizzle_z,
unsigned pred_swizzle_w,
unsigned num_dst,
unsigned num_src )
{
union tgsi_any_token *out;
uint count = predicate ? 2 : 1;
struct ureg_emit_insn_result result;
 
validate( opcode, num_dst, num_src );
out = get_tokens( ureg, DOMAIN_INSN, count );
out[0].insn = tgsi_default_instruction();
out[0].insn.Opcode = opcode;
out[0].insn.Saturate = saturate;
out[0].insn.NumDstRegs = num_dst;
out[0].insn.NumSrcRegs = num_src;
 
result.insn_token = ureg->domain[DOMAIN_INSN].count - count;
result.extended_token = result.insn_token;
 
if (predicate) {
out[0].insn.Predicate = 1;
out[1].insn_predicate = tgsi_default_instruction_predicate();
out[1].insn_predicate.Negate = pred_negate;
out[1].insn_predicate.SwizzleX = pred_swizzle_x;
out[1].insn_predicate.SwizzleY = pred_swizzle_y;
out[1].insn_predicate.SwizzleZ = pred_swizzle_z;
out[1].insn_predicate.SwizzleW = pred_swizzle_w;
}
 
ureg->nr_instructions++;
 
return result;
}
 
 
void
ureg_emit_label(struct ureg_program *ureg,
unsigned extended_token,
unsigned *label_token )
{
union tgsi_any_token *out, *insn;
 
if(!label_token)
return;
 
out = get_tokens( ureg, DOMAIN_INSN, 1 );
out[0].value = 0;
 
insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
insn->insn.Label = 1;
 
*label_token = ureg->domain[DOMAIN_INSN].count - 1;
}
 
/* Will return a number which can be used in a label to point to the
* next instruction to be emitted.
*/
unsigned
ureg_get_instruction_number( struct ureg_program *ureg )
{
return ureg->nr_instructions;
}
 
/* Patch a given label (expressed as a token number) to point to a
* given instruction (expressed as an instruction number).
*/
void
ureg_fixup_label(struct ureg_program *ureg,
unsigned label_token,
unsigned instruction_number )
{
union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
 
out->insn_label.Label = instruction_number;
}
 
 
void
ureg_emit_texture(struct ureg_program *ureg,
unsigned extended_token,
unsigned target, unsigned num_offsets)
{
union tgsi_any_token *out, *insn;
 
out = get_tokens( ureg, DOMAIN_INSN, 1 );
insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
 
insn->insn.Texture = 1;
 
out[0].value = 0;
out[0].insn_texture.Texture = target;
out[0].insn_texture.NumOffsets = num_offsets;
}
 
void
ureg_emit_texture_offset(struct ureg_program *ureg,
const struct tgsi_texture_offset *offset)
{
union tgsi_any_token *out;
 
out = get_tokens( ureg, DOMAIN_INSN, 1);
 
out[0].value = 0;
out[0].insn_texture_offset = *offset;
}
 
 
void
ureg_fixup_insn_size(struct ureg_program *ureg,
unsigned insn )
{
union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
 
assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
}
 
 
void
ureg_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
const struct ureg_src *src,
unsigned nr_src )
{
struct ureg_emit_insn_result insn;
unsigned i;
boolean saturate;
boolean predicate;
boolean negate = FALSE;
unsigned swizzle[4] = { 0 };
 
saturate = nr_dst ? dst[0].Saturate : FALSE;
predicate = nr_dst ? dst[0].Predicate : FALSE;
if (predicate) {
negate = dst[0].PredNegate;
swizzle[0] = dst[0].PredSwizzleX;
swizzle[1] = dst[0].PredSwizzleY;
swizzle[2] = dst[0].PredSwizzleZ;
swizzle[3] = dst[0].PredSwizzleW;
}
 
insn = ureg_emit_insn(ureg,
opcode,
saturate,
predicate,
negate,
swizzle[0],
swizzle[1],
swizzle[2],
swizzle[3],
nr_dst,
nr_src);
 
for (i = 0; i < nr_dst; i++)
ureg_emit_dst( ureg, dst[i] );
 
for (i = 0; i < nr_src; i++)
ureg_emit_src( ureg, src[i] );
 
ureg_fixup_insn_size( ureg, insn.insn_token );
}
 
void
ureg_tex_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
unsigned target,
const struct tgsi_texture_offset *texoffsets,
unsigned nr_offset,
const struct ureg_src *src,
unsigned nr_src )
{
struct ureg_emit_insn_result insn;
unsigned i;
boolean saturate;
boolean predicate;
boolean negate = FALSE;
unsigned swizzle[4] = { 0 };
 
saturate = nr_dst ? dst[0].Saturate : FALSE;
predicate = nr_dst ? dst[0].Predicate : FALSE;
if (predicate) {
negate = dst[0].PredNegate;
swizzle[0] = dst[0].PredSwizzleX;
swizzle[1] = dst[0].PredSwizzleY;
swizzle[2] = dst[0].PredSwizzleZ;
swizzle[3] = dst[0].PredSwizzleW;
}
 
insn = ureg_emit_insn(ureg,
opcode,
saturate,
predicate,
negate,
swizzle[0],
swizzle[1],
swizzle[2],
swizzle[3],
nr_dst,
nr_src);
 
ureg_emit_texture( ureg, insn.extended_token, target, nr_offset );
 
for (i = 0; i < nr_offset; i++)
ureg_emit_texture_offset( ureg, &texoffsets[i]);
 
for (i = 0; i < nr_dst; i++)
ureg_emit_dst( ureg, dst[i] );
 
for (i = 0; i < nr_src; i++)
ureg_emit_src( ureg, src[i] );
 
ureg_fixup_insn_size( ureg, insn.insn_token );
}
 
 
void
ureg_label_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_src *src,
unsigned nr_src,
unsigned *label_token )
{
struct ureg_emit_insn_result insn;
unsigned i;
 
insn = ureg_emit_insn(ureg,
opcode,
FALSE,
FALSE,
FALSE,
TGSI_SWIZZLE_X,
TGSI_SWIZZLE_Y,
TGSI_SWIZZLE_Z,
TGSI_SWIZZLE_W,
0,
nr_src);
 
ureg_emit_label( ureg, insn.extended_token, label_token );
 
for (i = 0; i < nr_src; i++)
ureg_emit_src( ureg, src[i] );
 
ureg_fixup_insn_size( ureg, insn.insn_token );
}
 
 
static void
emit_decl_semantic(struct ureg_program *ureg,
unsigned file,
unsigned index,
unsigned semantic_name,
unsigned semantic_index,
unsigned usage_mask)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 3;
out[0].decl.File = file;
out[0].decl.UsageMask = usage_mask;
out[0].decl.Semantic = 1;
 
out[1].value = 0;
out[1].decl_range.First = index;
out[1].decl_range.Last = index;
 
out[2].value = 0;
out[2].decl_semantic.Name = semantic_name;
out[2].decl_semantic.Index = semantic_index;
}
 
 
static void
emit_decl_fs(struct ureg_program *ureg,
unsigned file,
unsigned index,
unsigned semantic_name,
unsigned semantic_index,
unsigned interpolate,
unsigned cylindrical_wrap,
unsigned centroid)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 4);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 4;
out[0].decl.File = file;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */
out[0].decl.Interpolate = 1;
out[0].decl.Semantic = 1;
 
out[1].value = 0;
out[1].decl_range.First = index;
out[1].decl_range.Last = index;
 
out[2].value = 0;
out[2].decl_interp.Interpolate = interpolate;
out[2].decl_interp.CylindricalWrap = cylindrical_wrap;
out[2].decl_interp.Centroid = centroid;
 
out[3].value = 0;
out[3].decl_semantic.Name = semantic_name;
out[3].decl_semantic.Index = semantic_index;
}
 
static void
emit_decl_temps( struct ureg_program *ureg,
unsigned first, unsigned last,
boolean local,
unsigned arrayid )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL,
arrayid ? 3 : 2 );
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 2;
out[0].decl.File = TGSI_FILE_TEMPORARY;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
out[0].decl.Local = local;
 
out[1].value = 0;
out[1].decl_range.First = first;
out[1].decl_range.Last = last;
 
if (arrayid) {
out[0].decl.Array = 1;
out[2].value = 0;
out[2].array.ArrayID = arrayid;
}
}
 
static void emit_decl_range( struct ureg_program *ureg,
unsigned file,
unsigned first,
unsigned count )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 2;
out[0].decl.File = file;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
out[0].decl.Semantic = 0;
 
out[1].value = 0;
out[1].decl_range.First = first;
out[1].decl_range.Last = first + count - 1;
}
 
static void
emit_decl_range2D(struct ureg_program *ureg,
unsigned file,
unsigned first,
unsigned last,
unsigned index2D)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 3;
out[0].decl.File = file;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
out[0].decl.Dimension = 1;
 
out[1].value = 0;
out[1].decl_range.First = first;
out[1].decl_range.Last = last;
 
out[2].value = 0;
out[2].decl_dim.Index2D = index2D;
}
 
static void
emit_decl_sampler_view(struct ureg_program *ureg,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w )
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 3;
out[0].decl.File = TGSI_FILE_SAMPLER_VIEW;
out[0].decl.UsageMask = 0xf;
 
out[1].value = 0;
out[1].decl_range.First = index;
out[1].decl_range.Last = index;
 
out[2].value = 0;
out[2].decl_sampler_view.Resource = target;
out[2].decl_sampler_view.ReturnTypeX = return_type_x;
out[2].decl_sampler_view.ReturnTypeY = return_type_y;
out[2].decl_sampler_view.ReturnTypeZ = return_type_z;
out[2].decl_sampler_view.ReturnTypeW = return_type_w;
}
 
static void
emit_immediate( struct ureg_program *ureg,
const unsigned *v,
unsigned type )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
 
out[0].value = 0;
out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
out[0].imm.NrTokens = 5;
out[0].imm.DataType = type;
out[0].imm.Padding = 0;
 
out[1].imm_data.Uint = v[0];
out[2].imm_data.Uint = v[1];
out[3].imm_data.Uint = v[2];
out[4].imm_data.Uint = v[3];
}
 
static void
emit_property(struct ureg_program *ureg,
unsigned name,
unsigned data)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
 
out[0].value = 0;
out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY;
out[0].prop.NrTokens = 2;
out[0].prop.PropertyName = name;
 
out[1].prop_data.Data = data;
}
 
 
static void emit_decls( struct ureg_program *ureg )
{
unsigned i;
 
if (ureg->property_gs_input_prim != ~0) {
assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
 
emit_property(ureg,
TGSI_PROPERTY_GS_INPUT_PRIM,
ureg->property_gs_input_prim);
}
 
if (ureg->property_gs_output_prim != ~0) {
assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
 
emit_property(ureg,
TGSI_PROPERTY_GS_OUTPUT_PRIM,
ureg->property_gs_output_prim);
}
 
if (ureg->property_gs_max_vertices != ~0) {
assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
 
emit_property(ureg,
TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
ureg->property_gs_max_vertices);
}
 
if (ureg->property_fs_coord_origin) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_COORD_ORIGIN,
ureg->property_fs_coord_origin);
}
 
if (ureg->property_fs_coord_pixel_center) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_COORD_PIXEL_CENTER,
ureg->property_fs_coord_pixel_center);
}
 
if (ureg->property_fs_color0_writes_all_cbufs) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS,
ureg->property_fs_color0_writes_all_cbufs);
}
 
if (ureg->property_fs_depth_layout) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_DEPTH_LAYOUT,
ureg->property_fs_depth_layout);
}
 
if (ureg->processor == TGSI_PROCESSOR_VERTEX) {
for (i = 0; i < UREG_MAX_INPUT; i++) {
if (ureg->vs_inputs[i/32] & (1 << (i%32))) {
emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 );
}
}
} else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) {
for (i = 0; i < ureg->nr_fs_inputs; i++) {
emit_decl_fs(ureg,
TGSI_FILE_INPUT,
i,
ureg->fs_input[i].semantic_name,
ureg->fs_input[i].semantic_index,
ureg->fs_input[i].interp,
ureg->fs_input[i].cylindrical_wrap,
ureg->fs_input[i].centroid);
}
} else {
for (i = 0; i < ureg->nr_gs_inputs; i++) {
emit_decl_semantic(ureg,
TGSI_FILE_INPUT,
ureg->gs_input[i].index,
ureg->gs_input[i].semantic_name,
ureg->gs_input[i].semantic_index,
TGSI_WRITEMASK_XYZW);
}
}
 
for (i = 0; i < ureg->nr_system_values; i++) {
emit_decl_semantic(ureg,
TGSI_FILE_SYSTEM_VALUE,
ureg->system_value[i].index,
ureg->system_value[i].semantic_name,
ureg->system_value[i].semantic_index,
TGSI_WRITEMASK_XYZW);
}
 
for (i = 0; i < ureg->nr_outputs; i++) {
emit_decl_semantic(ureg,
TGSI_FILE_OUTPUT,
i,
ureg->output[i].semantic_name,
ureg->output[i].semantic_index,
ureg->output[i].usage_mask);
}
 
for (i = 0; i < ureg->nr_samplers; i++) {
emit_decl_range( ureg,
TGSI_FILE_SAMPLER,
ureg->sampler[i].Index, 1 );
}
 
for (i = 0; i < ureg->nr_sampler_views; i++) {
emit_decl_sampler_view(ureg,
ureg->sampler_view[i].index,
ureg->sampler_view[i].target,
ureg->sampler_view[i].return_type_x,
ureg->sampler_view[i].return_type_y,
ureg->sampler_view[i].return_type_z,
ureg->sampler_view[i].return_type_w);
}
 
if (ureg->const_decls.nr_constant_ranges) {
for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) {
emit_decl_range(ureg,
TGSI_FILE_CONSTANT,
ureg->const_decls.constant_range[i].first,
ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1);
}
}
 
for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
struct const_decl *decl = &ureg->const_decls2D[i];
 
if (decl->nr_constant_ranges) {
uint j;
 
for (j = 0; j < decl->nr_constant_ranges; j++) {
emit_decl_range2D(ureg,
TGSI_FILE_CONSTANT,
decl->constant_range[j].first,
decl->constant_range[j].last,
i);
}
}
}
 
if (ureg->nr_temps) {
unsigned array = 0;
for (i = 0; i < ureg->nr_temps;) {
boolean local = util_bitmask_get(ureg->local_temps, i);
unsigned first = i;
i = util_bitmask_get_next_index(ureg->decl_temps, i + 1);
if (i == UTIL_BITMASK_INVALID_INDEX)
i = ureg->nr_temps;
 
if (array < ureg->nr_array_temps && ureg->array_temps[array] == first)
emit_decl_temps( ureg, first, i - 1, local, ++array );
else
emit_decl_temps( ureg, first, i - 1, local, 0 );
}
}
 
if (ureg->nr_addrs) {
emit_decl_range( ureg,
TGSI_FILE_ADDRESS,
0, ureg->nr_addrs );
}
 
if (ureg->nr_preds) {
emit_decl_range(ureg,
TGSI_FILE_PREDICATE,
0,
ureg->nr_preds);
}
 
for (i = 0; i < ureg->nr_immediates; i++) {
emit_immediate( ureg,
ureg->immediate[i].value.u,
ureg->immediate[i].type );
}
}
 
/* Append the instruction tokens onto the declarations to build a
* contiguous stream suitable to send to the driver.
*/
static void copy_instructions( struct ureg_program *ureg )
{
unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
union tgsi_any_token *out = get_tokens( ureg,
DOMAIN_DECL,
nr_tokens );
 
memcpy(out,
ureg->domain[DOMAIN_INSN].tokens,
nr_tokens * sizeof out[0] );
}
 
 
static void
fixup_header_size(struct ureg_program *ureg)
{
union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 );
 
out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2;
}
 
 
static void
emit_header( struct ureg_program *ureg )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
 
out[0].header.HeaderSize = 2;
out[0].header.BodySize = 0;
 
out[1].processor.Processor = ureg->processor;
out[1].processor.Padding = 0;
}
 
 
const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
{
const struct tgsi_token *tokens;
 
emit_header( ureg );
emit_decls( ureg );
copy_instructions( ureg );
fixup_header_size( ureg );
if (ureg->domain[0].tokens == error_tokens ||
ureg->domain[1].tokens == error_tokens) {
debug_printf("%s: error in generated shader\n", __FUNCTION__);
assert(0);
return NULL;
}
 
tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
 
if (0) {
debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
ureg->domain[DOMAIN_DECL].count);
tgsi_dump( tokens, 0 );
}
 
#if DEBUG
if (tokens && !tgsi_sanity_check(tokens)) {
debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n");
tgsi_dump(tokens, 0);
assert(0);
}
#endif
 
return tokens;
}
 
 
void *ureg_create_shader( struct ureg_program *ureg,
struct pipe_context *pipe,
const struct pipe_stream_output_info *so )
{
struct pipe_shader_state state;
 
state.tokens = ureg_finalize(ureg);
if(!state.tokens)
return NULL;
 
if (so)
state.stream_output = *so;
else
memset(&state.stream_output, 0, sizeof(state.stream_output));
 
if (ureg->processor == TGSI_PROCESSOR_VERTEX)
return pipe->create_vs_state( pipe, &state );
else
return pipe->create_fs_state( pipe, &state );
}
 
 
const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg,
unsigned *nr_tokens )
{
const struct tgsi_token *tokens;
 
ureg_finalize(ureg);
 
tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
 
if (nr_tokens)
*nr_tokens = ureg->domain[DOMAIN_DECL].size;
 
ureg->domain[DOMAIN_DECL].tokens = 0;
ureg->domain[DOMAIN_DECL].size = 0;
ureg->domain[DOMAIN_DECL].order = 0;
ureg->domain[DOMAIN_DECL].count = 0;
 
return tokens;
}
 
 
void ureg_free_tokens( const struct tgsi_token *tokens )
{
FREE((struct tgsi_token *)tokens);
}
 
 
struct ureg_program *ureg_create( unsigned processor )
{
struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
if (ureg == NULL)
goto no_ureg;
 
ureg->processor = processor;
ureg->property_gs_input_prim = ~0;
ureg->property_gs_output_prim = ~0;
ureg->property_gs_max_vertices = ~0;
 
ureg->free_temps = util_bitmask_create();
if (ureg->free_temps == NULL)
goto no_free_temps;
 
ureg->local_temps = util_bitmask_create();
if (ureg->local_temps == NULL)
goto no_local_temps;
 
ureg->decl_temps = util_bitmask_create();
if (ureg->decl_temps == NULL)
goto no_decl_temps;
 
return ureg;
 
no_decl_temps:
util_bitmask_destroy(ureg->local_temps);
no_local_temps:
util_bitmask_destroy(ureg->free_temps);
no_free_temps:
FREE(ureg);
no_ureg:
return NULL;
}
 
 
const unsigned
ureg_get_nr_outputs( const struct ureg_program *ureg )
{
if (!ureg)
return 0;
return ureg->nr_outputs;
}
 
 
void ureg_destroy( struct ureg_program *ureg )
{
unsigned i;
 
for (i = 0; i < Elements(ureg->domain); i++) {
if (ureg->domain[i].tokens &&
ureg->domain[i].tokens != error_tokens)
FREE(ureg->domain[i].tokens);
}
 
util_bitmask_destroy(ureg->free_temps);
util_bitmask_destroy(ureg->local_temps);
util_bitmask_destroy(ureg->decl_temps);
 
FREE(ureg);
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_ureg.h
0,0 → 1,1278
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_UREG_H
#define TGSI_UREG_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_debug.h"
 
#ifdef __cplusplus
extern "C" {
#endif
struct ureg_program;
struct pipe_stream_output_info;
 
/* Almost a tgsi_src_register, but we need to pull in the Absolute
* flag from the _ext token. Indirect flag always implies ADDR[0].
*/
struct ureg_src
{
unsigned File : 4; /* TGSI_FILE_ */
unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
unsigned Indirect : 1; /* BOOL */
unsigned DimIndirect : 1; /* BOOL */
unsigned Dimension : 1; /* BOOL */
unsigned Absolute : 1; /* BOOL */
unsigned Negate : 1; /* BOOL */
unsigned IndirectFile : 4; /* TGSI_FILE_ */
unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
unsigned DimIndFile : 4; /* TGSI_FILE_ */
unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */
int Index : 16; /* SINT */
int IndirectIndex : 16; /* SINT */
int DimensionIndex : 16; /* SINT */
int DimIndIndex : 16; /* SINT */
unsigned ArrayID : 10; /* UINT */
};
 
/* Very similar to a tgsi_dst_register, removing unsupported fields
* and adding a Saturate flag. It's easier to push saturate into the
* destination register than to try and create a _SAT variant of each
* instruction function.
*/
struct ureg_dst
{
unsigned File : 4; /* TGSI_FILE_ */
unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
unsigned Indirect : 1; /* BOOL */
unsigned Saturate : 1; /* BOOL */
unsigned Predicate : 1;
unsigned PredNegate : 1; /* BOOL */
unsigned PredSwizzleX : 2; /* TGSI_SWIZZLE_ */
unsigned PredSwizzleY : 2; /* TGSI_SWIZZLE_ */
unsigned PredSwizzleZ : 2; /* TGSI_SWIZZLE_ */
unsigned PredSwizzleW : 2; /* TGSI_SWIZZLE_ */
int Index : 16; /* SINT */
int IndirectIndex : 16; /* SINT */
unsigned IndirectFile : 4; /* TGSI_FILE_ */
int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
unsigned ArrayID : 10; /* UINT */
};
 
struct pipe_context;
 
struct ureg_program *
ureg_create( unsigned processor );
 
const struct tgsi_token *
ureg_finalize( struct ureg_program * );
 
/* Create and return a shader:
*/
void *
ureg_create_shader( struct ureg_program *,
struct pipe_context *pipe,
const struct pipe_stream_output_info *so );
 
 
/* Alternately, return the built token stream and hand ownership of
* that memory to the caller:
*/
const struct tgsi_token *
ureg_get_tokens( struct ureg_program *ureg,
unsigned *nr_tokens );
 
/*
* Returns the number of currently declared outputs.
*/
const unsigned
ureg_get_nr_outputs( const struct ureg_program *ureg );
 
 
/* Free the tokens created by ureg_get_tokens() */
void ureg_free_tokens( const struct tgsi_token *tokens );
 
 
void
ureg_destroy( struct ureg_program * );
 
 
/***********************************************************************
* Convenience routine:
*/
static INLINE void *
ureg_create_shader_with_so_and_destroy( struct ureg_program *p,
struct pipe_context *pipe,
const struct pipe_stream_output_info *so )
{
void *result = ureg_create_shader( p, pipe, so );
ureg_destroy( p );
return result;
}
 
static INLINE void *
ureg_create_shader_and_destroy( struct ureg_program *p,
struct pipe_context *pipe )
{
return ureg_create_shader_with_so_and_destroy(p, pipe, NULL);
}
 
 
/***********************************************************************
* Build shader properties:
*/
 
void
ureg_property_gs_input_prim(struct ureg_program *ureg,
unsigned input_prim);
 
void
ureg_property_gs_output_prim(struct ureg_program *ureg,
unsigned output_prim);
 
void
ureg_property_gs_max_vertices(struct ureg_program *ureg,
unsigned max_vertices);
 
void
ureg_property_fs_coord_origin(struct ureg_program *ureg,
unsigned fs_coord_origin);
 
void
ureg_property_fs_coord_pixel_center(struct ureg_program *ureg,
unsigned fs_coord_pixel_center);
 
void
ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg,
unsigned fs_color0_writes_all_cbufs);
 
void
ureg_property_fs_depth_layout(struct ureg_program *ureg,
unsigned fs_depth_layout);
 
 
/***********************************************************************
* Build shader declarations:
*/
 
struct ureg_src
ureg_DECL_fs_input_cyl_centroid(struct ureg_program *,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode,
unsigned cylindrical_wrap,
unsigned centroid);
 
static INLINE struct ureg_src
ureg_DECL_fs_input_cyl(struct ureg_program *ureg,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode,
unsigned cylindrical_wrap)
{
return ureg_DECL_fs_input_cyl_centroid(ureg,
semantic_name,
semantic_index,
interp_mode,
cylindrical_wrap,
0);
}
 
static INLINE struct ureg_src
ureg_DECL_fs_input(struct ureg_program *ureg,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode)
{
return ureg_DECL_fs_input_cyl_centroid(ureg,
semantic_name,
semantic_index,
interp_mode,
0, 0);
}
 
struct ureg_src
ureg_DECL_vs_input( struct ureg_program *,
unsigned index );
 
struct ureg_src
ureg_DECL_gs_input(struct ureg_program *,
unsigned index,
unsigned semantic_name,
unsigned semantic_index);
 
struct ureg_src
ureg_DECL_system_value(struct ureg_program *,
unsigned index,
unsigned semantic_name,
unsigned semantic_index);
 
struct ureg_dst
ureg_DECL_output_masked( struct ureg_program *,
unsigned semantic_name,
unsigned semantic_index,
unsigned usage_mask );
 
struct ureg_dst
ureg_DECL_output( struct ureg_program *,
unsigned semantic_name,
unsigned semantic_index );
 
struct ureg_src
ureg_DECL_immediate( struct ureg_program *,
const float *v,
unsigned nr );
 
struct ureg_src
ureg_DECL_immediate_uint( struct ureg_program *,
const unsigned *v,
unsigned nr );
 
struct ureg_src
ureg_DECL_immediate_block_uint( struct ureg_program *,
const unsigned *v,
unsigned nr );
 
struct ureg_src
ureg_DECL_immediate_int( struct ureg_program *,
const int *v,
unsigned nr );
 
void
ureg_DECL_constant2D(struct ureg_program *ureg,
unsigned first,
unsigned last,
unsigned index2D);
 
struct ureg_src
ureg_DECL_constant( struct ureg_program *,
unsigned index );
 
struct ureg_dst
ureg_DECL_temporary( struct ureg_program * );
 
/**
* Emit a temporary with the LOCAL declaration flag set. For use when
* the register value is not required to be preserved across
* subroutine boundaries.
*/
struct ureg_dst
ureg_DECL_local_temporary( struct ureg_program * );
 
/**
* Declare "size" continuous temporary registers.
*/
struct ureg_dst
ureg_DECL_array_temporary( struct ureg_program *,
unsigned size,
boolean local );
 
void
ureg_release_temporary( struct ureg_program *ureg,
struct ureg_dst tmp );
 
struct ureg_dst
ureg_DECL_address( struct ureg_program * );
 
struct ureg_dst
ureg_DECL_predicate(struct ureg_program *);
 
/* Supply an index to the sampler declaration as this is the hook to
* the external pipe_sampler state. Users of this function probably
* don't want just any sampler, but a specific one which they've set
* up state for in the context.
*/
struct ureg_src
ureg_DECL_sampler( struct ureg_program *,
unsigned index );
 
struct ureg_src
ureg_DECL_sampler_view(struct ureg_program *,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w );
 
 
static INLINE struct ureg_src
ureg_imm4f( struct ureg_program *ureg,
float a, float b,
float c, float d)
{
float v[4];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
return ureg_DECL_immediate( ureg, v, 4 );
}
 
static INLINE struct ureg_src
ureg_imm3f( struct ureg_program *ureg,
float a, float b,
float c)
{
float v[3];
v[0] = a;
v[1] = b;
v[2] = c;
return ureg_DECL_immediate( ureg, v, 3 );
}
 
static INLINE struct ureg_src
ureg_imm2f( struct ureg_program *ureg,
float a, float b)
{
float v[2];
v[0] = a;
v[1] = b;
return ureg_DECL_immediate( ureg, v, 2 );
}
 
static INLINE struct ureg_src
ureg_imm1f( struct ureg_program *ureg,
float a)
{
float v[1];
v[0] = a;
return ureg_DECL_immediate( ureg, v, 1 );
}
 
static INLINE struct ureg_src
ureg_imm4u( struct ureg_program *ureg,
unsigned a, unsigned b,
unsigned c, unsigned d)
{
unsigned v[4];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
return ureg_DECL_immediate_uint( ureg, v, 4 );
}
 
static INLINE struct ureg_src
ureg_imm3u( struct ureg_program *ureg,
unsigned a, unsigned b,
unsigned c)
{
unsigned v[3];
v[0] = a;
v[1] = b;
v[2] = c;
return ureg_DECL_immediate_uint( ureg, v, 3 );
}
 
static INLINE struct ureg_src
ureg_imm2u( struct ureg_program *ureg,
unsigned a, unsigned b)
{
unsigned v[2];
v[0] = a;
v[1] = b;
return ureg_DECL_immediate_uint( ureg, v, 2 );
}
 
static INLINE struct ureg_src
ureg_imm1u( struct ureg_program *ureg,
unsigned a)
{
return ureg_DECL_immediate_uint( ureg, &a, 1 );
}
 
static INLINE struct ureg_src
ureg_imm4i( struct ureg_program *ureg,
int a, int b,
int c, int d)
{
int v[4];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
return ureg_DECL_immediate_int( ureg, v, 4 );
}
 
static INLINE struct ureg_src
ureg_imm3i( struct ureg_program *ureg,
int a, int b,
int c)
{
int v[3];
v[0] = a;
v[1] = b;
v[2] = c;
return ureg_DECL_immediate_int( ureg, v, 3 );
}
 
static INLINE struct ureg_src
ureg_imm2i( struct ureg_program *ureg,
int a, int b)
{
int v[2];
v[0] = a;
v[1] = b;
return ureg_DECL_immediate_int( ureg, v, 2 );
}
 
static INLINE struct ureg_src
ureg_imm1i( struct ureg_program *ureg,
int a)
{
return ureg_DECL_immediate_int( ureg, &a, 1 );
}
 
/***********************************************************************
* Functions for patching up labels
*/
 
 
/* Will return a number which can be used in a label to point to the
* next instruction to be emitted.
*/
unsigned
ureg_get_instruction_number( struct ureg_program *ureg );
 
 
/* Patch a given label (expressed as a token number) to point to a
* given instruction (expressed as an instruction number).
*
* Labels are obtained from instruction emitters, eg ureg_CAL().
* Instruction numbers are obtained from ureg_get_instruction_number(),
* above.
*/
void
ureg_fixup_label(struct ureg_program *ureg,
unsigned label_token,
unsigned instruction_number );
 
 
/* Generic instruction emitter. Use if you need to pass the opcode as
* a parameter, rather than using the emit_OP() variants below.
*/
void
ureg_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
const struct ureg_src *src,
unsigned nr_src );
 
 
void
ureg_tex_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
unsigned target,
const struct tgsi_texture_offset *texoffsets,
unsigned nr_offset,
const struct ureg_src *src,
unsigned nr_src );
 
 
void
ureg_label_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_src *src,
unsigned nr_src,
unsigned *label);
 
 
/***********************************************************************
* Internal instruction helpers, don't call these directly:
*/
 
struct ureg_emit_insn_result {
unsigned insn_token; /*< Used to fixup insn size. */
unsigned extended_token; /*< Used to set the Extended bit, usually the same as insn_token. */
};
 
struct ureg_emit_insn_result
ureg_emit_insn(struct ureg_program *ureg,
unsigned opcode,
boolean saturate,
boolean predicate,
boolean pred_negate,
unsigned pred_swizzle_x,
unsigned pred_swizzle_y,
unsigned pred_swizzle_z,
unsigned pred_swizzle_w,
unsigned num_dst,
unsigned num_src );
 
void
ureg_emit_label(struct ureg_program *ureg,
unsigned insn_token,
unsigned *label_token );
 
void
ureg_emit_texture(struct ureg_program *ureg,
unsigned insn_token,
unsigned target, unsigned num_offsets);
 
void
ureg_emit_texture_offset(struct ureg_program *ureg,
const struct tgsi_texture_offset *offset);
 
void
ureg_emit_dst( struct ureg_program *ureg,
struct ureg_dst dst );
 
void
ureg_emit_src( struct ureg_program *ureg,
struct ureg_src src );
 
void
ureg_fixup_insn_size(struct ureg_program *ureg,
unsigned insn );
 
 
#define OP00( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
0).insn_token; \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP01( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_src src ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
1).insn_token; \
ureg_emit_src( ureg, src ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP00_LBL( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
unsigned *label_token ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
0); \
ureg_emit_label( ureg, insn.extended_token, label_token ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP01_LBL( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_src src, \
unsigned *label_token ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
1); \
ureg_emit_label( ureg, insn.extended_token, label_token ); \
ureg_emit_src( ureg, src ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP10( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
0).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
 
#define OP11( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
1).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP12( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
2).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP12_TEX( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
unsigned target, \
struct ureg_src src0, \
struct ureg_src src1 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
2); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP12_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
2); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP13( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
3).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP13_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
3); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP14_TEX( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
unsigned target, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
4); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP14_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
4); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
 
#define OP14( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
4).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
 
#define OP15( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3, \
struct ureg_src src4 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
5).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_emit_src( ureg, src4 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP15_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3, \
struct ureg_src src4 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
5); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_emit_src( ureg, src4 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
/* Use a template include to generate a correctly-typed ureg_OP()
* function for each TGSI opcode:
*/
#include "tgsi_opcode_tmp.h"
 
 
/***********************************************************************
* Inline helpers for manipulating register structs:
*/
static INLINE struct ureg_src
ureg_negate( struct ureg_src reg )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Negate ^= 1;
return reg;
}
 
static INLINE struct ureg_src
ureg_abs( struct ureg_src reg )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Absolute = 1;
reg.Negate = 0;
return reg;
}
 
static INLINE struct ureg_src
ureg_swizzle( struct ureg_src reg,
int x, int y, int z, int w )
{
unsigned swz = ( (reg.SwizzleX << 0) |
(reg.SwizzleY << 2) |
(reg.SwizzleZ << 4) |
(reg.SwizzleW << 6));
 
assert(reg.File != TGSI_FILE_NULL);
assert(x < 4);
assert(y < 4);
assert(z < 4);
assert(w < 4);
 
reg.SwizzleX = (swz >> (x*2)) & 0x3;
reg.SwizzleY = (swz >> (y*2)) & 0x3;
reg.SwizzleZ = (swz >> (z*2)) & 0x3;
reg.SwizzleW = (swz >> (w*2)) & 0x3;
return reg;
}
 
static INLINE struct ureg_src
ureg_scalar( struct ureg_src reg, int x )
{
return ureg_swizzle(reg, x, x, x, x);
}
 
static INLINE struct ureg_dst
ureg_writemask( struct ureg_dst reg,
unsigned writemask )
{
assert(reg.File != TGSI_FILE_NULL);
reg.WriteMask &= writemask;
return reg;
}
 
static INLINE struct ureg_dst
ureg_saturate( struct ureg_dst reg )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Saturate = 1;
return reg;
}
 
static INLINE struct ureg_dst
ureg_predicate(struct ureg_dst reg,
boolean negate,
unsigned swizzle_x,
unsigned swizzle_y,
unsigned swizzle_z,
unsigned swizzle_w)
{
assert(reg.File != TGSI_FILE_NULL);
reg.Predicate = 1;
reg.PredNegate = negate;
reg.PredSwizzleX = swizzle_x;
reg.PredSwizzleY = swizzle_y;
reg.PredSwizzleZ = swizzle_z;
reg.PredSwizzleW = swizzle_w;
return reg;
}
 
static INLINE struct ureg_dst
ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
{
assert(reg.File != TGSI_FILE_NULL);
assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY);
reg.Indirect = 1;
reg.IndirectFile = addr.File;
reg.IndirectIndex = addr.Index;
reg.IndirectSwizzle = addr.SwizzleX;
return reg;
}
 
static INLINE struct ureg_src
ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
{
assert(reg.File != TGSI_FILE_NULL);
assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY);
reg.Indirect = 1;
reg.IndirectFile = addr.File;
reg.IndirectIndex = addr.Index;
reg.IndirectSwizzle = addr.SwizzleX;
return reg;
}
 
static INLINE struct ureg_src
ureg_src_dimension( struct ureg_src reg, int index )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Dimension = 1;
reg.DimIndirect = 0;
reg.DimensionIndex = index;
return reg;
}
 
 
static INLINE struct ureg_src
ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr,
int index )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Dimension = 1;
reg.DimIndirect = 1;
reg.DimensionIndex = index;
reg.DimIndFile = addr.File;
reg.DimIndIndex = addr.Index;
reg.DimIndSwizzle = addr.SwizzleX;
return reg;
}
 
static INLINE struct ureg_dst
ureg_dst_array_offset( struct ureg_dst reg, int offset )
{
assert(reg.File == TGSI_FILE_TEMPORARY);
reg.Index += offset;
return reg;
}
 
static INLINE struct ureg_dst
ureg_dst( struct ureg_src src )
{
struct ureg_dst dst;
 
assert(!src.Indirect ||
(src.IndirectFile == TGSI_FILE_ADDRESS ||
src.IndirectFile == TGSI_FILE_TEMPORARY));
 
dst.File = src.File;
dst.WriteMask = TGSI_WRITEMASK_XYZW;
dst.IndirectFile = src.IndirectFile;
dst.Indirect = src.Indirect;
dst.IndirectIndex = src.IndirectIndex;
dst.IndirectSwizzle = src.IndirectSwizzle;
dst.Saturate = 0;
dst.Predicate = 0;
dst.PredNegate = 0;
dst.PredSwizzleX = TGSI_SWIZZLE_X;
dst.PredSwizzleY = TGSI_SWIZZLE_Y;
dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
dst.PredSwizzleW = TGSI_SWIZZLE_W;
dst.Index = src.Index;
dst.ArrayID = src.ArrayID;
 
return dst;
}
 
static INLINE struct ureg_src
ureg_src_register(unsigned file,
unsigned index)
{
struct ureg_src src;
 
src.File = file;
src.SwizzleX = TGSI_SWIZZLE_X;
src.SwizzleY = TGSI_SWIZZLE_Y;
src.SwizzleZ = TGSI_SWIZZLE_Z;
src.SwizzleW = TGSI_SWIZZLE_W;
src.Indirect = 0;
src.IndirectFile = TGSI_FILE_NULL;
src.IndirectIndex = 0;
src.IndirectSwizzle = 0;
src.Absolute = 0;
src.Index = index;
src.Negate = 0;
src.Dimension = 0;
src.DimensionIndex = 0;
src.DimIndirect = 0;
src.DimIndFile = TGSI_FILE_NULL;
src.DimIndIndex = 0;
src.DimIndSwizzle = 0;
src.ArrayID = 0;
 
return src;
}
 
static INLINE struct ureg_src
ureg_src( struct ureg_dst dst )
{
struct ureg_src src;
 
src.File = dst.File;
src.SwizzleX = TGSI_SWIZZLE_X;
src.SwizzleY = TGSI_SWIZZLE_Y;
src.SwizzleZ = TGSI_SWIZZLE_Z;
src.SwizzleW = TGSI_SWIZZLE_W;
src.Indirect = dst.Indirect;
src.IndirectFile = dst.IndirectFile;
src.IndirectIndex = dst.IndirectIndex;
src.IndirectSwizzle = dst.IndirectSwizzle;
src.Absolute = 0;
src.Index = dst.Index;
src.Negate = 0;
src.Dimension = 0;
src.DimensionIndex = 0;
src.DimIndirect = 0;
src.DimIndFile = TGSI_FILE_NULL;
src.DimIndIndex = 0;
src.DimIndSwizzle = 0;
src.ArrayID = dst.ArrayID;
 
return src;
}
 
 
 
static INLINE struct ureg_dst
ureg_dst_undef( void )
{
struct ureg_dst dst;
 
dst.File = TGSI_FILE_NULL;
dst.WriteMask = 0;
dst.Indirect = 0;
dst.IndirectFile = TGSI_FILE_NULL;
dst.IndirectIndex = 0;
dst.IndirectSwizzle = 0;
dst.Saturate = 0;
dst.Predicate = 0;
dst.PredNegate = 0;
dst.PredSwizzleX = TGSI_SWIZZLE_X;
dst.PredSwizzleY = TGSI_SWIZZLE_Y;
dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
dst.PredSwizzleW = TGSI_SWIZZLE_W;
dst.Index = 0;
dst.ArrayID = 0;
 
return dst;
}
 
static INLINE struct ureg_src
ureg_src_undef( void )
{
struct ureg_src src;
 
src.File = TGSI_FILE_NULL;
src.SwizzleX = 0;
src.SwizzleY = 0;
src.SwizzleZ = 0;
src.SwizzleW = 0;
src.Indirect = 0;
src.IndirectFile = TGSI_FILE_NULL;
src.IndirectIndex = 0;
src.IndirectSwizzle = 0;
src.Absolute = 0;
src.Index = 0;
src.Negate = 0;
src.Dimension = 0;
src.DimensionIndex = 0;
src.DimIndirect = 0;
src.DimIndFile = TGSI_FILE_NULL;
src.DimIndIndex = 0;
src.DimIndSwizzle = 0;
src.ArrayID = 0;
 
return src;
}
 
static INLINE boolean
ureg_src_is_undef( struct ureg_src src )
{
return src.File == TGSI_FILE_NULL;
}
 
static INLINE boolean
ureg_dst_is_undef( struct ureg_dst dst )
{
return dst.File == TGSI_FILE_NULL;
}
 
 
#ifdef __cplusplus
}
#endif
 
#endif
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_util.c
0,0 → 1,433
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi_parse.h"
#include "tgsi_util.h"
 
union pointer_hack
{
void *pointer;
uint64_t uint64;
};
 
void *
tgsi_align_128bit(
void *unaligned )
{
union pointer_hack ph;
 
ph.uint64 = 0;
ph.pointer = unaligned;
ph.uint64 = (ph.uint64 + 15) & ~15;
return ph.pointer;
}
 
unsigned
tgsi_util_get_src_register_swizzle(
const struct tgsi_src_register *reg,
unsigned component )
{
switch( component ) {
case 0:
return reg->SwizzleX;
case 1:
return reg->SwizzleY;
case 2:
return reg->SwizzleZ;
case 3:
return reg->SwizzleW;
default:
assert( 0 );
}
return 0;
}
 
 
unsigned
tgsi_util_get_full_src_register_swizzle(
const struct tgsi_full_src_register *reg,
unsigned component )
{
return tgsi_util_get_src_register_swizzle(
&reg->Register,
component );
}
 
void
tgsi_util_set_src_register_swizzle(
struct tgsi_src_register *reg,
unsigned swizzle,
unsigned component )
{
switch( component ) {
case 0:
reg->SwizzleX = swizzle;
break;
case 1:
reg->SwizzleY = swizzle;
break;
case 2:
reg->SwizzleZ = swizzle;
break;
case 3:
reg->SwizzleW = swizzle;
break;
default:
assert( 0 );
}
}
 
unsigned
tgsi_util_get_full_src_register_sign_mode(
const struct tgsi_full_src_register *reg,
unsigned component )
{
unsigned sign_mode;
 
if( reg->Register.Absolute ) {
/* Consider only the post-abs negation. */
 
if( reg->Register.Negate ) {
sign_mode = TGSI_UTIL_SIGN_SET;
}
else {
sign_mode = TGSI_UTIL_SIGN_CLEAR;
}
}
else {
if( reg->Register.Negate ) {
sign_mode = TGSI_UTIL_SIGN_TOGGLE;
}
else {
sign_mode = TGSI_UTIL_SIGN_KEEP;
}
}
 
return sign_mode;
}
 
void
tgsi_util_set_full_src_register_sign_mode(
struct tgsi_full_src_register *reg,
unsigned sign_mode )
{
switch (sign_mode)
{
case TGSI_UTIL_SIGN_CLEAR:
reg->Register.Negate = 0;
reg->Register.Absolute = 1;
break;
 
case TGSI_UTIL_SIGN_SET:
reg->Register.Absolute = 1;
reg->Register.Negate = 1;
break;
 
case TGSI_UTIL_SIGN_TOGGLE:
reg->Register.Negate = 1;
reg->Register.Absolute = 0;
break;
 
case TGSI_UTIL_SIGN_KEEP:
reg->Register.Negate = 0;
reg->Register.Absolute = 0;
break;
 
default:
assert( 0 );
}
}
 
/**
* Determine which channels of the specificed src register are effectively
* used by this instruction.
*/
unsigned
tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
unsigned src_idx)
{
const struct tgsi_full_src_register *src = &inst->Src[src_idx];
unsigned write_mask = inst->Dst[0].Register.WriteMask;
unsigned read_mask;
unsigned usage_mask;
unsigned chan;
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_MOV:
case TGSI_OPCODE_ARL:
case TGSI_OPCODE_ARR:
case TGSI_OPCODE_RCP:
case TGSI_OPCODE_MUL:
case TGSI_OPCODE_DIV:
case TGSI_OPCODE_ADD:
case TGSI_OPCODE_MIN:
case TGSI_OPCODE_MAX:
case TGSI_OPCODE_SLT:
case TGSI_OPCODE_SGE:
case TGSI_OPCODE_MAD:
case TGSI_OPCODE_SUB:
case TGSI_OPCODE_LRP:
case TGSI_OPCODE_CND:
case TGSI_OPCODE_FRC:
case TGSI_OPCODE_CEIL:
case TGSI_OPCODE_CLAMP:
case TGSI_OPCODE_FLR:
case TGSI_OPCODE_ROUND:
case TGSI_OPCODE_POW:
case TGSI_OPCODE_ABS:
case TGSI_OPCODE_COS:
case TGSI_OPCODE_SIN:
case TGSI_OPCODE_DDX:
case TGSI_OPCODE_DDY:
case TGSI_OPCODE_SEQ:
case TGSI_OPCODE_SGT:
case TGSI_OPCODE_SLE:
case TGSI_OPCODE_SNE:
case TGSI_OPCODE_SSG:
case TGSI_OPCODE_CMP:
case TGSI_OPCODE_TRUNC:
case TGSI_OPCODE_NOT:
case TGSI_OPCODE_AND:
case TGSI_OPCODE_OR:
case TGSI_OPCODE_XOR:
case TGSI_OPCODE_SAD:
/* Channel-wise operations */
read_mask = write_mask;
break;
 
case TGSI_OPCODE_EX2:
case TGSI_OPCODE_LG2:
case TGSI_OPCODE_RCC:
read_mask = TGSI_WRITEMASK_X;
break;
 
case TGSI_OPCODE_SCS:
read_mask = write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0;
break;
 
case TGSI_OPCODE_EXP:
case TGSI_OPCODE_LOG:
read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0;
break;
 
case TGSI_OPCODE_DP2A:
read_mask = src_idx == 2 ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_XY;
break;
 
case TGSI_OPCODE_DP2:
read_mask = TGSI_WRITEMASK_XY;
break;
 
case TGSI_OPCODE_DP3:
read_mask = TGSI_WRITEMASK_XYZ;
break;
 
case TGSI_OPCODE_DP4:
read_mask = TGSI_WRITEMASK_XYZW;
break;
 
case TGSI_OPCODE_DPH:
read_mask = src_idx == 0 ? TGSI_WRITEMASK_XYZ : TGSI_WRITEMASK_XYZW;
break;
 
case TGSI_OPCODE_TEX:
case TGSI_OPCODE_TXD:
case TGSI_OPCODE_TXB:
case TGSI_OPCODE_TXL:
case TGSI_OPCODE_TXP:
if (src_idx == 0) {
/* Note that the SHADOW variants use the Z component too */
switch (inst->Texture.Texture) {
case TGSI_TEXTURE_1D:
read_mask = TGSI_WRITEMASK_X;
break;
case TGSI_TEXTURE_SHADOW1D:
read_mask = TGSI_WRITEMASK_XZ;
break;
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
read_mask = TGSI_WRITEMASK_XY;
break;
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_2D_MSAA:
read_mask = TGSI_WRITEMASK_XYZ;
break;
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_CUBE_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
read_mask = TGSI_WRITEMASK_XYZW;
break;
default:
assert(0);
read_mask = 0;
}
 
if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) {
read_mask |= TGSI_WRITEMASK_W;
}
} else {
/* A safe approximation */
read_mask = TGSI_WRITEMASK_XYZW;
}
break;
 
default:
/* Assume all channels are read */
read_mask = TGSI_WRITEMASK_XYZW;
break;
}
 
usage_mask = 0;
for (chan = 0; chan < 4; ++chan) {
if (read_mask & (1 << chan)) {
usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan);
}
}
 
return usage_mask;
}
 
/**
* Convert a tgsi_ind_register into a tgsi_src_register
*/
struct tgsi_src_register
tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg)
{
struct tgsi_src_register src = { 0 };
 
src.File = reg->File;
src.Index = reg->Index;
src.SwizzleX = reg->Swizzle;
src.SwizzleY = reg->Swizzle;
src.SwizzleZ = reg->Swizzle;
src.SwizzleW = reg->Swizzle;
 
return src;
}
 
/**
* Return the dimension of the texture coordinates (layer included for array
* textures), as well as the location of the shadow reference value or the
* sample index.
*/
int
tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample)
{
int dim;
 
/*
* Depending on the texture target, (src0.xyzw, src1.x) is interpreted
* differently:
*
* (s, X, X, X, X), for BUFFER
* (s, X, X, X, X), for 1D
* (s, t, X, X, X), for 2D, RECT
* (s, t, r, X, X), for 3D, CUBE
*
* (s, layer, X, X, X), for 1D_ARRAY
* (s, t, layer, X, X), for 2D_ARRAY
* (s, t, r, layer, X), for CUBE_ARRAY
*
* (s, X, shadow, X, X), for SHADOW1D
* (s, t, shadow, X, X), for SHADOW2D, SHADOWRECT
* (s, t, r, shadow, X), for SHADOWCUBE
*
* (s, layer, shadow, X, X), for SHADOW1D_ARRAY
* (s, t, layer, shadow, X), for SHADOW2D_ARRAY
* (s, t, r, layer, shadow), for SHADOWCUBE_ARRAY
*
* (s, t, sample, X, X), for 2D_MSAA
* (s, t, layer, sample, X), for 2D_ARRAY_MSAA
*/
switch (tgsi_tex) {
case TGSI_TEXTURE_BUFFER:
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_SHADOW1D:
dim = 1;
break;
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_2D_MSAA:
dim = 2;
break;
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
dim = 3;
break;
case TGSI_TEXTURE_CUBE_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
dim = 4;
break;
default:
assert(!"unknown texture target");
dim = 0;
break;
}
 
if (shadow_or_sample) {
switch (tgsi_tex) {
case TGSI_TEXTURE_SHADOW1D:
/* there is a gap */
*shadow_or_sample = 2;
break;
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
case TGSI_TEXTURE_2D_MSAA:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
*shadow_or_sample = dim;
break;
default:
/* no shadow nor sample */
*shadow_or_sample = -1;
break;
}
}
 
return dim;
}
/contrib/sdk/sources/Mesa/src/gallium/auxiliary/tgsi/tgsi_util.h
0,0 → 1,89
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef TGSI_UTIL_H
#define TGSI_UTIL_H
 
#if defined __cplusplus
extern "C" {
#endif
 
struct tgsi_src_register;
struct tgsi_full_src_register;
struct tgsi_full_instruction;
 
void *
tgsi_align_128bit(
void *unaligned );
 
unsigned
tgsi_util_get_src_register_swizzle(
const struct tgsi_src_register *reg,
unsigned component );
 
 
unsigned
tgsi_util_get_full_src_register_swizzle(
const struct tgsi_full_src_register *reg,
unsigned component );
 
void
tgsi_util_set_src_register_swizzle(
struct tgsi_src_register *reg,
unsigned swizzle,
unsigned component );
 
#define TGSI_UTIL_SIGN_CLEAR 0 /* Force positive */
#define TGSI_UTIL_SIGN_SET 1 /* Force negative */
#define TGSI_UTIL_SIGN_TOGGLE 2 /* Negate */
#define TGSI_UTIL_SIGN_KEEP 3 /* No change */
 
unsigned
tgsi_util_get_full_src_register_sign_mode(
const struct tgsi_full_src_register *reg,
unsigned component );
 
void
tgsi_util_set_full_src_register_sign_mode(
struct tgsi_full_src_register *reg,
unsigned sign_mode );
 
unsigned
tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
unsigned src_idx);
 
struct tgsi_src_register
tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg);
 
int
tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample);
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_UTIL_H */