mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 09:38:07 +02:00
Merge commit 'origin/master' into gallium-0.2
This commit is contained in:
commit
ef2bf418b4
13 changed files with 696 additions and 364 deletions
|
|
@ -186,7 +186,7 @@ void intel_flush_prim(struct intel_context *intel)
|
|||
OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0,
|
||||
offset | (intel->vertex_size << S0_VB_PITCH_SHIFT_830) |
|
||||
S0_VB_ENABLE_830);
|
||||
/* S1
|
||||
/* S2
|
||||
* This is somewhat unfortunate -- VB width is tied up with
|
||||
* vertex format data that we've already uploaded through
|
||||
* _3DSTATE_VFT[01]_CMD. We may want to replace emits of VFT state with
|
||||
|
|
|
|||
|
|
@ -308,6 +308,15 @@ decode_3d_1c(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
|||
case 0x10:
|
||||
instr_out(data, hw_offset, 0, "3DSTATE_SCISSOR_ENABLE\n");
|
||||
return 1;
|
||||
case 0x01:
|
||||
instr_out(data, hw_offset, 0, "3DSTATE_MAP_COORD_SET_I830\n");
|
||||
return 1;
|
||||
case 0x0a:
|
||||
instr_out(data, hw_offset, 0, "3DSTATE_MAP_CUBE_I830\n");
|
||||
return 1;
|
||||
case 0x05:
|
||||
instr_out(data, hw_offset, 0, "3DSTATE_MAP_TEX_STREAM_I830\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
instr_out(data, hw_offset, 0, "3D UNKNOWN\n");
|
||||
|
|
@ -316,33 +325,39 @@ decode_3d_1c(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
|||
}
|
||||
|
||||
static int
|
||||
decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
||||
decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures, int i830)
|
||||
{
|
||||
unsigned int len, i, c, opcode, word, map, sampler, instr;
|
||||
|
||||
struct {
|
||||
uint32_t opcode;
|
||||
int i830_only;
|
||||
int min_len;
|
||||
int max_len;
|
||||
char *name;
|
||||
} opcodes_3d_1d[] = {
|
||||
{ 0x8e, 3, 3, "3DSTATE_BUFFER_INFO" },
|
||||
{ 0x86, 4, 4, "3DSTATE_CHROMA_KEY" },
|
||||
{ 0x9c, 1, 1, "3DSTATE_CLEAR_PARAMETERS" },
|
||||
{ 0x88, 2, 2, "3DSTATE_CONSTANT_BLEND_COLOR" },
|
||||
{ 0x99, 2, 2, "3DSTATE_DEFAULT_DIFFUSE" },
|
||||
{ 0x9a, 2, 2, "3DSTATE_DEFAULT_SPECULAR" },
|
||||
{ 0x98, 2, 2, "3DSTATE_DEFAULT_Z" },
|
||||
{ 0x97, 2, 2, "3DSTATE_DEPTH_OFFSET_SCALE" },
|
||||
{ 0x85, 2, 2, "3DSTATE_DEST_BUFFER_VARIABLES" },
|
||||
{ 0x80, 5, 5, "3DSTATE_DRAWING_RECTANGLE" },
|
||||
{ 0x8e, 3, 3, "3DSTATE_BUFFER_INFO" },
|
||||
{ 0x9d, 65, 65, "3DSTATE_FILTER_COEFFICIENTS_4X4" },
|
||||
{ 0x9e, 4, 4, "3DSTATE_MONO_FILTER" },
|
||||
{ 0x89, 4, 4, "3DSTATE_FOG_MODE" },
|
||||
{ 0x8f, 2, 16, "3DSTATE_MAP_PALLETE_LOAD_32" },
|
||||
{ 0x81, 3, 3, "3DSTATE_SCISSOR_RECTANGLE" },
|
||||
{ 0x83, 2, 2, "3DSTATE_SPAN_STIPPLE" },
|
||||
{ 0x8e, 0, 3, 3, "3DSTATE_BUFFER_INFO" },
|
||||
{ 0x86, 0, 4, 4, "3DSTATE_CHROMA_KEY" },
|
||||
{ 0x9c, 0, 1, 1, "3DSTATE_CLEAR_PARAMETERS" },
|
||||
{ 0x88, 0, 2, 2, "3DSTATE_CONSTANT_BLEND_COLOR" },
|
||||
{ 0x99, 0, 2, 2, "3DSTATE_DEFAULT_DIFFUSE" },
|
||||
{ 0x9a, 0, 2, 2, "3DSTATE_DEFAULT_SPECULAR" },
|
||||
{ 0x98, 0, 2, 2, "3DSTATE_DEFAULT_Z" },
|
||||
{ 0x97, 0, 2, 2, "3DSTATE_DEPTH_OFFSET_SCALE" },
|
||||
{ 0x85, 0, 2, 2, "3DSTATE_DEST_BUFFER_VARIABLES" },
|
||||
{ 0x80, 0, 5, 5, "3DSTATE_DRAWING_RECTANGLE" },
|
||||
{ 0x8e, 0, 3, 3, "3DSTATE_BUFFER_INFO" },
|
||||
{ 0x9d, 0, 65, 65, "3DSTATE_FILTER_COEFFICIENTS_4X4" },
|
||||
{ 0x9e, 0, 4, 4, "3DSTATE_MONO_FILTER" },
|
||||
{ 0x89, 0, 4, 4, "3DSTATE_FOG_MODE" },
|
||||
{ 0x8f, 0, 2, 16, "3DSTATE_MAP_PALLETE_LOAD_32" },
|
||||
{ 0x81, 0, 3, 3, "3DSTATE_SCISSOR_RECTANGLE" },
|
||||
{ 0x83, 0, 2, 2, "3DSTATE_SPAN_STIPPLE" },
|
||||
{ 0x8c, 1, 2, 2, "3DSTATE_MAP_COORD_TRANSFORM_I830" },
|
||||
{ 0x8b, 1, 2, 2, "3DSTATE_MAP_VERTEX_TRANSFORM_I830" },
|
||||
{ 0x8d, 1, 3, 3, "3DSTATE_W_STATE_I830" },
|
||||
{ 0x01, 1, 2, 2, "3DSTATE_COLOR_FACTOR_I830" },
|
||||
{ 0x02, 1, 2, 2, "3DSTATE_MAP_COORD_SETBIND_I830" },
|
||||
};
|
||||
|
||||
switch ((data[0] & 0x00ff0000) >> 16) {
|
||||
|
|
@ -488,6 +503,8 @@ decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
|||
}
|
||||
return len;
|
||||
case 0x01:
|
||||
if (i830)
|
||||
break;
|
||||
instr_out(data, hw_offset, 0, "3DSTATE_SAMPLER_STATE\n");
|
||||
len = (data[0] & 0x0000003f) + 2;
|
||||
i = 1;
|
||||
|
|
@ -513,6 +530,9 @@ decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
|||
for (opcode = 0; opcode < sizeof(opcodes_3d_1d) / sizeof(opcodes_3d_1d[0]);
|
||||
opcode++)
|
||||
{
|
||||
if (opcodes_3d_1d[opcode].i830_only && !i830)
|
||||
continue;
|
||||
|
||||
if (((data[0] & 0x00ff0000) >> 16) == opcodes_3d_1d[opcode].opcode) {
|
||||
len = 1;
|
||||
|
||||
|
|
@ -756,7 +776,7 @@ decode_3d(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
|||
case 0x1f:
|
||||
return decode_3d_primitive(data, count, hw_offset, failures);
|
||||
case 0x1d:
|
||||
return decode_3d_1d(data, count, hw_offset, failures);
|
||||
return decode_3d_1d(data, count, hw_offset, failures, 0);
|
||||
case 0x1c:
|
||||
return decode_3d_1c(data, count, hw_offset, failures);
|
||||
}
|
||||
|
|
@ -999,6 +1019,73 @@ decode_3d_965(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_3d_i830(uint32_t *data, int count, uint32_t hw_offset, int *failures)
|
||||
{
|
||||
unsigned int opcode;
|
||||
|
||||
struct {
|
||||
uint32_t opcode;
|
||||
int min_len;
|
||||
int max_len;
|
||||
char *name;
|
||||
} opcodes_3d[] = {
|
||||
{ 0x02, 1, 1, "3DSTATE_MODES_3" },
|
||||
{ 0x03, 1, 1, "3DSTATE_ENABLES_1"},
|
||||
{ 0x04, 1, 1, "3DSTATE_ENABLES_2"},
|
||||
{ 0x05, 1, 1, "3DSTATE_VFT0"},
|
||||
{ 0x06, 1, 1, "3DSTATE_AA"},
|
||||
{ 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES" },
|
||||
{ 0x08, 1, 1, "3DSTATE_MODES_1" },
|
||||
{ 0x09, 1, 1, "3DSTATE_STENCIL_TEST" },
|
||||
{ 0x0a, 1, 1, "3DSTATE_VFT1"},
|
||||
{ 0x0b, 1, 1, "3DSTATE_INDPT_ALPHA_BLEND" },
|
||||
{ 0x0c, 1, 1, "3DSTATE_MODES_5" },
|
||||
{ 0x0d, 1, 1, "3DSTATE_MAP_BLEND_OP" },
|
||||
{ 0x0e, 1, 1, "3DSTATE_MAP_BLEND_ARG" },
|
||||
{ 0x0f, 1, 1, "3DSTATE_MODES_2" },
|
||||
{ 0x15, 1, 1, "3DSTATE_FOG_COLOR" },
|
||||
{ 0x16, 1, 1, "3DSTATE_MODES_4" },
|
||||
};
|
||||
|
||||
switch ((data[0] & 0x1f000000) >> 24) {
|
||||
case 0x1f:
|
||||
return decode_3d_primitive(data, count, hw_offset, failures);
|
||||
case 0x1d:
|
||||
return decode_3d_1d(data, count, hw_offset, failures, 1);
|
||||
case 0x1c:
|
||||
return decode_3d_1c(data, count, hw_offset, failures);
|
||||
}
|
||||
|
||||
for (opcode = 0; opcode < sizeof(opcodes_3d) / sizeof(opcodes_3d[0]);
|
||||
opcode++) {
|
||||
if ((data[0] & 0x1f000000) >> 24 == opcodes_3d[opcode].opcode) {
|
||||
unsigned int len = 1, i;
|
||||
|
||||
instr_out(data, hw_offset, 0, "%s\n", opcodes_3d[opcode].name);
|
||||
if (opcodes_3d[opcode].max_len > 1) {
|
||||
len = (data[0] & 0xff) + 2;
|
||||
if (len < opcodes_3d[opcode].min_len ||
|
||||
len > opcodes_3d[opcode].max_len)
|
||||
{
|
||||
fprintf(out, "Bad count in %s\n", opcodes_3d[opcode].name);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
if (i >= count)
|
||||
BUFFER_FAIL(count, len, opcodes_3d[opcode].name);
|
||||
instr_out(data, hw_offset, i, "dword %d\n", i);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
instr_out(data, hw_offset, 0, "3D UNKNOWN\n");
|
||||
(*failures)++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an i830-i915 batch buffer, writing the output to stdout.
|
||||
*
|
||||
|
|
@ -1028,9 +1115,12 @@ intel_decode(uint32_t *data, int count, uint32_t hw_offset, uint32_t devid)
|
|||
if (IS_965(devid)) {
|
||||
index += decode_3d_965(data + index, count - index,
|
||||
hw_offset + index * 4, &failures);
|
||||
} else {
|
||||
} else if (IS_9XX(devid)) {
|
||||
index += decode_3d(data + index, count - index,
|
||||
hw_offset + index * 4, &failures);
|
||||
} else {
|
||||
index += decode_3d_i830(data + index, count - index,
|
||||
hw_offset + index * 4, &failures);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
*/
|
||||
#define S0_VB_OFFSET_MASK_830 0xffffff8
|
||||
#define S0_VB_PITCH_SHIFT_830 1
|
||||
#define S0_VB_ENABLE_830 0
|
||||
#define S0_VB_ENABLE_830 (1<<0)
|
||||
/** @} */
|
||||
|
||||
#define S1_VERTEX_WIDTH_SHIFT 24
|
||||
|
|
@ -100,8 +100,8 @@
|
|||
#define S2_TEXCOORD_FMT(unit, type) ((type)<<(unit*4))
|
||||
#define S2_TEXCOORD_NONE (~0)
|
||||
#define S2_TEX_COUNT_SHIFT_830 12
|
||||
#define S2_VERTEX_0_WIDTH_SHIFT_830 0
|
||||
#define S2_VERTEX_1_WIDTH_SHIFT_830 6
|
||||
#define S2_VERTEX_1_WIDTH_SHIFT_830 0
|
||||
#define S2_VERTEX_0_WIDTH_SHIFT_830 6
|
||||
/* S3 not interesting */
|
||||
|
||||
#define S4_POINT_WIDTH_SHIFT 23
|
||||
|
|
|
|||
|
|
@ -1689,7 +1689,7 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
|||
|
||||
if (dstFormat == GL_LUMINANCE || dstFormat == GL_LUMINANCE_ALPHA) {
|
||||
/* compute luminance values */
|
||||
if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
|
||||
if (transferOps & IMAGE_CLAMP_BIT) {
|
||||
for (i = 0; i < n; i++) {
|
||||
GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
|
||||
luminance[i] = CLAMP(sum, 0.0F, 1.0F);
|
||||
|
|
|
|||
|
|
@ -297,10 +297,13 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
|
|||
|
||||
for (i=0;i<MAX_TEXTURE_UNITS;i++) {
|
||||
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
|
||||
GLenum format;
|
||||
|
||||
if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
|
||||
continue;
|
||||
|
||||
format = texUnit->_Current->Image[0][texUnit->_Current->BaseLevel]->_BaseFormat;
|
||||
|
||||
key->unit[i].enabled = 1;
|
||||
key->enabled_units |= (1<<i);
|
||||
key->nr_enabled_units = i+1;
|
||||
|
|
@ -308,7 +311,9 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
|
|||
|
||||
key->unit[i].source_index =
|
||||
translate_tex_src_bit(texUnit->_ReallyEnabled);
|
||||
key->unit[i].shadow = texUnit->_Current->CompareMode == GL_COMPARE_R_TO_TEXTURE;
|
||||
key->unit[i].shadow = ((texUnit->_Current->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
|
||||
((format == GL_DEPTH_COMPONENT) ||
|
||||
(format == GL_DEPTH_STENCIL_EXT)));
|
||||
|
||||
key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
|
||||
key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;
|
||||
|
|
|
|||
|
|
@ -3719,6 +3719,14 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
|
|||
/* general case: convert row to RGBA format */
|
||||
GLfloat rgba[MAX_WIDTH][4];
|
||||
GLint col;
|
||||
GLbitfield transferOps = 0x0;
|
||||
|
||||
if (type == GL_FLOAT &&
|
||||
((ctx->Color.ClampReadColor == GL_TRUE) ||
|
||||
(ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB &&
|
||||
texImage->TexFormat->DataType != GL_FLOAT)))
|
||||
transferOps |= IMAGE_CLAMP_BIT;
|
||||
|
||||
for (col = 0; col < width; col++) {
|
||||
(*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
|
||||
if (texImage->TexFormat->BaseFormat == GL_ALPHA) {
|
||||
|
|
@ -3743,7 +3751,7 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
|
|||
}
|
||||
_mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
|
||||
format, type, dest,
|
||||
&ctx->Pack, 0x0 /*image xfer ops*/);
|
||||
&ctx->Pack, transferOps /*image xfer ops*/);
|
||||
} /* format */
|
||||
} /* row */
|
||||
} /* img */
|
||||
|
|
|
|||
|
|
@ -837,10 +837,8 @@ parameter_type_specifier_3
|
|||
* <init_declarator_list> ::= <single_declaration>
|
||||
* | <init_declarator_list> "," <identifier>
|
||||
* | <init_declarator_list> "," <identifier> "[" "]"
|
||||
* | <init_declarator_list> "," <identifier> "["
|
||||
* <constant_expression> "]"
|
||||
* | <init_declarator_list> "," <identifier> "="
|
||||
* <initializer>
|
||||
* | <init_declarator_list> "," <identifier> "[" <constant_expression> "]"
|
||||
* | <init_declarator_list> "," <identifier> "=" <initializer>
|
||||
*/
|
||||
init_declarator_list
|
||||
single_declaration .and .loop init_declarator_list_1 .emit DECLARATOR_NEXT .and
|
||||
|
|
@ -860,10 +858,9 @@ init_declarator_list_5
|
|||
* <single_declaration> ::= <fully_specified_type>
|
||||
* | <fully_specified_type> <identifier>
|
||||
* | <fully_specified_type> <identifier> "[" "]"
|
||||
* | <fully_specified_type> <identifier> "["
|
||||
* <constant_expression> "]"
|
||||
* | <fully_specified_type> <identifier> "[" <constant_expression> "]"
|
||||
* | <fully_specified_type> <identifier> "=" <initializer>
|
||||
*/
|
||||
*/
|
||||
single_declaration
|
||||
single_declaration_nospace .or single_declaration_space;
|
||||
single_declaration_space
|
||||
|
|
@ -924,12 +921,12 @@ centroid_qualifier
|
|||
|
||||
|
||||
/*
|
||||
* <type_qualifier> ::= "const"
|
||||
* | "attribute" // Vertex only.
|
||||
* | "varying"
|
||||
* | "uniform"
|
||||
* | "__fixed_output"
|
||||
* | "__fixed_input"
|
||||
* <type_qualifier> ::= "const"
|
||||
* | "attribute" // Vertex only.
|
||||
* | "varying"
|
||||
* | "uniform"
|
||||
* | "__fixed_output"
|
||||
* | "__fixed_input"
|
||||
*
|
||||
* note: this is an extension to the standard language specification,
|
||||
* normally slang disallows __fixed_output and __fixed_input type qualifiers
|
||||
|
|
@ -1013,7 +1010,7 @@ type_specifier_nospace
|
|||
|
||||
/*
|
||||
* <struct_specifier> ::= "struct" <identifier> "{" <struct_declaration_list> "}"
|
||||
* | "struct" "{" <struct_declaration_list> "}"
|
||||
* | "struct" "{" <struct_declaration_list> "}"
|
||||
*/
|
||||
struct_specifier
|
||||
"struct" .and struct_specifier_1 .and optional_space .and lbrace .error LBRACE_EXPECTED .and
|
||||
|
|
@ -1025,7 +1022,7 @@ struct_specifier_2
|
|||
|
||||
/*
|
||||
* <struct_declaration_list> ::= <struct_declaration>
|
||||
* | <struct_declaration_list> <struct_declaration>
|
||||
* | <struct_declaration_list> <struct_declaration>
|
||||
*/
|
||||
struct_declaration_list
|
||||
struct_declaration .and .loop struct_declaration .emit FIELD_NEXT;
|
||||
|
|
@ -1042,7 +1039,7 @@ struct_declaration_nospace
|
|||
|
||||
/*
|
||||
* <struct_declarator_list> ::= <struct_declarator>
|
||||
* | <struct_declarator_list> "," <struct_declarator>
|
||||
* | <struct_declarator_list> "," <struct_declarator>
|
||||
*/
|
||||
struct_declarator_list
|
||||
struct_declarator .and .loop struct_declarator_list_1 .emit FIELD_NEXT;
|
||||
|
|
|
|||
|
|
@ -1477,6 +1477,8 @@ _slang_simple_writemask(GLuint writemask, GLuint swizzle)
|
|||
* Convert the given swizzle into a writemask. In some cases this
|
||||
* is trivial, in other cases, we'll need to also swizzle the right
|
||||
* hand side to put components in the right places.
|
||||
* See comment above for more info.
|
||||
* XXX this function could be simplified and should probably be renamed.
|
||||
* \param swizzle the incoming swizzle
|
||||
* \param writemaskOut returns the writemask
|
||||
* \param swizzleOut swizzle to apply to the right-hand-side
|
||||
|
|
@ -3114,7 +3116,7 @@ _slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
|
|||
/* oper->a_id is the field name */
|
||||
slang_ir_node *base, *n;
|
||||
slang_typeinfo field_ti;
|
||||
GLint fieldSize, fieldOffset = -1, swz;
|
||||
GLint fieldSize, fieldOffset = -1;
|
||||
|
||||
/* type of field */
|
||||
slang_typeinfo_construct(&field_ti);
|
||||
|
|
@ -3147,22 +3149,12 @@ _slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
|
|||
if (!n)
|
||||
return NULL;
|
||||
|
||||
|
||||
/* setup the storage info for this node */
|
||||
swz = fieldOffset % 4;
|
||||
|
||||
n->Field = (char *) oper->a_id;
|
||||
n->Store = _slang_new_ir_storage_relative(fieldOffset / 4,
|
||||
fieldSize,
|
||||
base->Store);
|
||||
if (fieldSize == 1)
|
||||
n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
|
||||
else if (fieldSize == 2)
|
||||
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
|
||||
SWIZZLE_NIL, SWIZZLE_NIL);
|
||||
else if (fieldSize == 3)
|
||||
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
|
||||
SWIZZLE_Z, SWIZZLE_NIL);
|
||||
|
||||
/* Store the field's offset in storage->Index */
|
||||
n->Store = _slang_new_ir_storage(base->Store->File,
|
||||
fieldOffset,
|
||||
fieldSize);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
@ -3255,12 +3247,12 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
|
|||
}
|
||||
|
||||
elem = new_node2(IR_ELEMENT, array, index);
|
||||
elem->Store = _slang_new_ir_storage_relative(constIndex,
|
||||
elemSize,
|
||||
array->Store);
|
||||
|
||||
assert(elem->Store->Parent);
|
||||
/* XXX try to do some array bounds checking here */
|
||||
/* The storage info here will be updated during code emit */
|
||||
elem->Store = _slang_new_ir_storage(array->Store->File,
|
||||
array->Store->Index,
|
||||
elemSize);
|
||||
|
||||
return elem;
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -167,6 +167,16 @@ typedef struct slang_output_ctx_
|
|||
|
||||
/* _slang_compile() */
|
||||
|
||||
|
||||
/* Debugging aid, print file/line where parsing error is detected */
|
||||
#define RETURN0 \
|
||||
do { \
|
||||
if (0) \
|
||||
printf("slang error at %s:%d\n", __FILE__, __LINE__); \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
static void
|
||||
parse_identifier_str(slang_parse_ctx * C, char **id)
|
||||
{
|
||||
|
|
@ -223,7 +233,7 @@ parse_float(slang_parse_ctx * C, float *number)
|
|||
_mesa_strlen(exponent) + 3) * sizeof(char));
|
||||
if (whole == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
slang_string_copy(whole, integral);
|
||||
|
|
@ -247,7 +257,7 @@ check_revision(slang_parse_ctx * C)
|
|||
{
|
||||
if (*C->I != REVISION) {
|
||||
slang_info_log_error(C->L, "Internal compiler error.");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
C->I++;
|
||||
return 1;
|
||||
|
|
@ -387,23 +397,23 @@ parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
|
||||
o.structs = st->structs;
|
||||
if (!parse_type_specifier(C, &o, sp))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
do {
|
||||
slang_atom a_name;
|
||||
slang_variable *var = slang_variable_scope_grow(st->fields);
|
||||
if (!var) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
a_name = parse_identifier(C);
|
||||
if (_slang_locate_variable(st->fields, a_name, GL_FALSE)) {
|
||||
slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
if (!parse_struct_field_var(C, &o, var, a_name, sp))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
while (*C->I++ != FIELD_NONE);
|
||||
|
||||
|
|
@ -419,26 +429,26 @@ parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
|
|||
/* parse struct name (if any) and make sure it is unique in current scope */
|
||||
a_name = parse_identifier(C);
|
||||
if (a_name == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
name = slang_atom_pool_id(C->atoms, a_name);
|
||||
if (name[0] != '\0'
|
||||
&& slang_struct_scope_find(O->structs, a_name, 0) != NULL) {
|
||||
slang_info_log_error(C->L, "%s: duplicate type name.", name);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* set-up a new struct */
|
||||
*st = (slang_struct *) _slang_alloc(sizeof(slang_struct));
|
||||
if (*st == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
if (!slang_struct_construct(*st)) {
|
||||
_slang_free(*st);
|
||||
*st = NULL;
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
(**st).a_name = a_name;
|
||||
(**st).structs->outer_scope = O->structs;
|
||||
|
|
@ -450,7 +460,7 @@ parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
|
|||
slang_type_specifier_ctr(&sp);
|
||||
if (!parse_struct_field(C, O, *st, &sp)) {
|
||||
slang_type_specifier_dtr(&sp);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
slang_type_specifier_dtr(&sp);
|
||||
}
|
||||
|
|
@ -468,14 +478,14 @@ parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
|
|||
* sizeof(slang_struct));
|
||||
if (O->structs->structs == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
s = &O->structs->structs[O->structs->num_structs];
|
||||
if (!slang_struct_construct(s))
|
||||
return 0;
|
||||
RETURN0;
|
||||
O->structs->num_structs++;
|
||||
if (!slang_struct_copy(s, *st))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
@ -498,7 +508,7 @@ parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant)
|
|||
*variant = SLANG_INVARIANT;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -519,7 +529,7 @@ parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid)
|
|||
*centroid = SLANG_CENTROID;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -560,7 +570,7 @@ parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
|
|||
*qual = SLANG_QUAL_FIXEDINPUT;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -698,7 +708,7 @@ parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
case TYPE_SPECIFIER_STRUCT:
|
||||
spec->type = SLANG_SPEC_STRUCT;
|
||||
if (!parse_struct(C, O, &spec->_struct))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case TYPE_SPECIFIER_TYPENAME:
|
||||
spec->type = SLANG_SPEC_STRUCT;
|
||||
|
|
@ -708,31 +718,31 @@ parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
|
||||
a_name = parse_identifier(C);
|
||||
if (a_name == NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
stru = slang_struct_scope_find(O->structs, a_name, 1);
|
||||
if (stru == NULL) {
|
||||
slang_info_log_error(C->L, "undeclared type name '%s'",
|
||||
slang_atom_pool_id(C->atoms, a_name));
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
|
||||
if (spec->_struct == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
if (!slang_struct_construct(spec->_struct)) {
|
||||
_slang_free(spec->_struct);
|
||||
spec->_struct = NULL;
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
if (!slang_struct_copy(spec->_struct, stru))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -762,7 +772,7 @@ parse_type_precision(slang_parse_ctx *C,
|
|||
*precision = SLANG_PREC_HIGH;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -771,36 +781,36 @@ parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
slang_fully_specified_type * type)
|
||||
{
|
||||
if (!parse_type_variant(C, &type->variant))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
if (!parse_type_centroid(C, &type->centroid))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
if (!parse_type_qualifier(C, &type->qualifier))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
if (!parse_type_precision(C, &type->precision))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
if (!parse_type_specifier(C, O, &type->specifier))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
if (!O->allow_invariant && type->variant == SLANG_INVARIANT) {
|
||||
slang_info_log_error(C->L,
|
||||
"'invariant' keyword not allowed (perhaps set #version 120)");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
if (!O->allow_centroid && type->centroid == SLANG_CENTROID) {
|
||||
slang_info_log_error(C->L,
|
||||
"'centroid' keyword not allowed (perhaps set #version 120)");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
else if (type->centroid == SLANG_CENTROID &&
|
||||
type->qualifier != SLANG_QUAL_VARYING) {
|
||||
slang_info_log_error(C->L,
|
||||
"'centroid' keyword only allowed for varying vars");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -809,7 +819,7 @@ parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
type->variant == SLANG_INVARIANT) {
|
||||
slang_info_log_error(C->L,
|
||||
"invariant qualifer only allowed for varying vars");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
@ -824,7 +834,7 @@ parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
/* only default is allowed */
|
||||
if (type->precision != SLANG_PREC_DEFAULT) {
|
||||
slang_info_log_error(C->L, "precision qualifiers not allowed");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -935,7 +945,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
|
||||
while (*C->I != OP_END)
|
||||
if (!parse_child_operation(C, O, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
C->I++;
|
||||
break;
|
||||
case OP_BLOCK_BEGIN_NEW_SCOPE:
|
||||
|
|
@ -947,7 +957,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
o.vars = oper->locals;
|
||||
while (*C->I != OP_END)
|
||||
if (!parse_child_operation(C, &o, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
C->I++;
|
||||
}
|
||||
break;
|
||||
|
|
@ -963,7 +973,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
* than one declarators
|
||||
*/
|
||||
if (!parse_declaration(C, O))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (first_var < O->vars->num_variables) {
|
||||
const unsigned int num_vars = O->vars->num_variables - first_var;
|
||||
unsigned int i;
|
||||
|
|
@ -972,7 +982,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
oper->children = slang_operation_new(num_vars);
|
||||
if (oper->children == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
for (i = first_var; i < O->vars->num_variables; i++) {
|
||||
slang_operation *o = &oper->children[i - first_var];
|
||||
|
|
@ -983,7 +993,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
if (!legal_identifier(o->a_id)) {
|
||||
slang_info_log_error(C->L, "illegal variable name '%s'",
|
||||
(char *) o->a_id);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -996,10 +1006,10 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
oper->type = SLANG_OPER_ASM;
|
||||
oper->a_id = parse_identifier(C);
|
||||
if (oper->a_id == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
while (*C->I != OP_END) {
|
||||
if (!parse_child_operation(C, O, oper, 0))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
C->I++;
|
||||
break;
|
||||
|
|
@ -1015,21 +1025,21 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
case OP_RETURN:
|
||||
oper->type = SLANG_OPER_RETURN;
|
||||
if (!parse_child_operation(C, O, oper, 0))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_EXPRESSION:
|
||||
oper->type = SLANG_OPER_EXPRESSION;
|
||||
if (!parse_child_operation(C, O, oper, 0))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_IF:
|
||||
oper->type = SLANG_OPER_IF;
|
||||
if (!parse_child_operation(C, O, oper, 0))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_child_operation(C, O, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_child_operation(C, O, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_WHILE:
|
||||
{
|
||||
|
|
@ -1038,17 +1048,17 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
oper->type = SLANG_OPER_WHILE;
|
||||
o.vars = oper->locals;
|
||||
if (!parse_child_operation(C, &o, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_child_operation(C, &o, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
case OP_DO:
|
||||
oper->type = SLANG_OPER_DO;
|
||||
if (!parse_child_operation(C, O, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_child_operation(C, O, oper, 0))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_FOR:
|
||||
{
|
||||
|
|
@ -1057,13 +1067,13 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
oper->type = SLANG_OPER_FOR;
|
||||
o.vars = oper->locals;
|
||||
if (!parse_child_operation(C, &o, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_child_operation(C, &o, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_child_operation(C, &o, oper, 0))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_child_operation(C, &o, oper, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
case OP_PRECISION:
|
||||
|
|
@ -1077,7 +1087,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1092,7 +1102,7 @@ handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
|
|||
op->children = slang_operation_new(n);
|
||||
if (op->children == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
op->num_children = n;
|
||||
|
||||
|
|
@ -1110,7 +1120,7 @@ handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
|
|||
*total_ops * sizeof(slang_operation));
|
||||
if (*ops == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1143,12 +1153,12 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
(num_ops + 1) * sizeof(slang_operation));
|
||||
if (ops == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
op = &ops[num_ops];
|
||||
if (!slang_operation_construct(op)) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
num_ops++;
|
||||
op->locals->outer_scope = O->vars;
|
||||
|
|
@ -1160,7 +1170,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
case OP_PUSH_BOOL:
|
||||
op->type = SLANG_OPER_LITERAL_BOOL;
|
||||
if (!parse_number(C, &number))
|
||||
return 0;
|
||||
RETURN0;
|
||||
op->literal[0] =
|
||||
op->literal[1] =
|
||||
op->literal[2] =
|
||||
|
|
@ -1170,7 +1180,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
case OP_PUSH_INT:
|
||||
op->type = SLANG_OPER_LITERAL_INT;
|
||||
if (!parse_number(C, &number))
|
||||
return 0;
|
||||
RETURN0;
|
||||
op->literal[0] =
|
||||
op->literal[1] =
|
||||
op->literal[2] =
|
||||
|
|
@ -1180,7 +1190,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
case OP_PUSH_FLOAT:
|
||||
op->type = SLANG_OPER_LITERAL_FLOAT;
|
||||
if (!parse_float(C, &op->literal[0]))
|
||||
return 0;
|
||||
RETURN0;
|
||||
op->literal[1] =
|
||||
op->literal[2] =
|
||||
op->literal[3] = op->literal[0];
|
||||
|
|
@ -1190,37 +1200,37 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
op->type = SLANG_OPER_IDENTIFIER;
|
||||
op->a_id = parse_identifier(C);
|
||||
if (op->a_id == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_SEQUENCE:
|
||||
op->type = SLANG_OPER_SEQUENCE;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_ASSIGN:
|
||||
op->type = SLANG_OPER_ASSIGN;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_ADDASSIGN:
|
||||
op->type = SLANG_OPER_ADDASSIGN;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_SUBASSIGN:
|
||||
op->type = SLANG_OPER_SUBASSIGN;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_MULASSIGN:
|
||||
op->type = SLANG_OPER_MULASSIGN;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_DIVASSIGN:
|
||||
op->type = SLANG_OPER_DIVASSIGN;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
/*case OP_MODASSIGN: */
|
||||
/*case OP_LSHASSIGN: */
|
||||
|
|
@ -1231,22 +1241,22 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
case OP_SELECT:
|
||||
op->type = SLANG_OPER_SELECT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 3))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_LOGICALOR:
|
||||
op->type = SLANG_OPER_LOGICALOR;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_LOGICALXOR:
|
||||
op->type = SLANG_OPER_LOGICALXOR;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_LOGICALAND:
|
||||
op->type = SLANG_OPER_LOGICALAND;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
/*case OP_BITOR: */
|
||||
/*case OP_BITXOR: */
|
||||
|
|
@ -1254,95 +1264,95 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
case OP_EQUAL:
|
||||
op->type = SLANG_OPER_EQUAL;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_NOTEQUAL:
|
||||
op->type = SLANG_OPER_NOTEQUAL;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_LESS:
|
||||
op->type = SLANG_OPER_LESS;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_GREATER:
|
||||
op->type = SLANG_OPER_GREATER;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_LESSEQUAL:
|
||||
op->type = SLANG_OPER_LESSEQUAL;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_GREATEREQUAL:
|
||||
op->type = SLANG_OPER_GREATEREQUAL;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
/*case OP_LSHIFT: */
|
||||
/*case OP_RSHIFT: */
|
||||
case OP_ADD:
|
||||
op->type = SLANG_OPER_ADD;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_SUBTRACT:
|
||||
op->type = SLANG_OPER_SUBTRACT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_MULTIPLY:
|
||||
op->type = SLANG_OPER_MULTIPLY;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_DIVIDE:
|
||||
op->type = SLANG_OPER_DIVIDE;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
/*case OP_MODULUS: */
|
||||
case OP_PREINCREMENT:
|
||||
op->type = SLANG_OPER_PREINCREMENT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_PREDECREMENT:
|
||||
op->type = SLANG_OPER_PREDECREMENT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_PLUS:
|
||||
op->type = SLANG_OPER_PLUS;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_MINUS:
|
||||
op->type = SLANG_OPER_MINUS;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_NOT:
|
||||
op->type = SLANG_OPER_NOT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
/*case OP_COMPLEMENT: */
|
||||
case OP_SUBSCRIPT:
|
||||
op->type = SLANG_OPER_SUBSCRIPT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_CALL:
|
||||
op->type = SLANG_OPER_CALL;
|
||||
op->a_id = parse_identifier(C);
|
||||
if (op->a_id == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
while (*C->I != OP_END)
|
||||
if (!parse_child_operation(C, O, op, 0))
|
||||
return 0;
|
||||
RETURN0;
|
||||
C->I++;
|
||||
|
||||
if (!C->parsing_builtin
|
||||
|
|
@ -1352,7 +1362,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
id = slang_atom_pool_id(C->atoms, op->a_id);
|
||||
if (!is_constructor_name(id, op->a_id, O->structs)) {
|
||||
slang_info_log_error(C->L, "%s: undeclared function name.", id);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1360,22 +1370,22 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
op->type = SLANG_OPER_FIELD;
|
||||
op->a_id = parse_identifier(C);
|
||||
if (op->a_id == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_POSTINCREMENT:
|
||||
op->type = SLANG_OPER_POSTINCREMENT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_POSTDECREMENT:
|
||||
op->type = SLANG_OPER_POSTDECREMENT;
|
||||
if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
C->I++;
|
||||
|
|
@ -1406,7 +1416,7 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
* two at most) because not all combinations are valid
|
||||
*/
|
||||
if (!parse_type_qualifier(C, ¶m->type.qualifier))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
param_qual = *C->I++;
|
||||
switch (param_qual) {
|
||||
|
|
@ -1414,7 +1424,7 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
if (param->type.qualifier != SLANG_QUAL_CONST
|
||||
&& param->type.qualifier != SLANG_QUAL_NONE) {
|
||||
slang_info_log_error(C->L, "Invalid type qualifier.");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
case PARAM_QUALIFIER_OUT:
|
||||
|
|
@ -1422,7 +1432,7 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
param->type.qualifier = SLANG_QUAL_OUT;
|
||||
else {
|
||||
slang_info_log_error(C->L, "Invalid type qualifier.");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
case PARAM_QUALIFIER_INOUT:
|
||||
|
|
@ -1430,11 +1440,11 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
param->type.qualifier = SLANG_QUAL_INOUT;
|
||||
else {
|
||||
slang_info_log_error(C->L, "Invalid type qualifier.");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* parse precision qualifier (lowp, mediump, highp */
|
||||
|
|
@ -1444,10 +1454,10 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
|
||||
/* parse parameter's type specifier and name */
|
||||
if (!parse_type_specifier(C, O, ¶m->type.specifier))
|
||||
return 0;
|
||||
RETURN0;
|
||||
param->a_name = parse_identifier(C);
|
||||
if (param->a_name == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
/* if the parameter is an array, parse its size (the size must be
|
||||
* explicitly defined
|
||||
|
|
@ -1564,13 +1574,13 @@ parse_operator_name(slang_parse_ctx * C)
|
|||
slang_atom_pool_atom(C->atoms, operator_names[i].o_name);
|
||||
if (atom == SLANG_ATOM_NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
C->I++;
|
||||
return atom;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1581,7 +1591,7 @@ parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
GLuint functype;
|
||||
/* parse function type and name */
|
||||
if (!parse_fully_specified_type(C, O, &func->header.type))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
functype = *C->I++;
|
||||
switch (functype) {
|
||||
|
|
@ -1589,35 +1599,35 @@ parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
func->kind = SLANG_FUNC_ORDINARY;
|
||||
func->header.a_name = parse_identifier(C);
|
||||
if (func->header.a_name == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case FUNCTION_CONSTRUCTOR:
|
||||
func->kind = SLANG_FUNC_CONSTRUCTOR;
|
||||
if (func->header.type.specifier.type == SLANG_SPEC_STRUCT)
|
||||
return 0;
|
||||
RETURN0;
|
||||
func->header.a_name =
|
||||
slang_atom_pool_atom(C->atoms,
|
||||
slang_type_specifier_type_to_string
|
||||
(func->header.type.specifier.type));
|
||||
if (func->header.a_name == SLANG_ATOM_NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
case FUNCTION_OPERATOR:
|
||||
func->kind = SLANG_FUNC_OPERATOR;
|
||||
func->header.a_name = parse_operator_name(C);
|
||||
if (func->header.a_name == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
if (!legal_identifier(func->header.a_name)) {
|
||||
slang_info_log_error(C->L, "illegal function name '%s'",
|
||||
(char *) func->header.a_name);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* parse function parameters */
|
||||
|
|
@ -1625,10 +1635,10 @@ parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
slang_variable *p = slang_variable_scope_grow(func->parameters);
|
||||
if (!p) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
if (!parse_parameter_declaration(C, O, p))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* if the function returns a value, append a hidden __retVal 'out'
|
||||
|
|
@ -1662,19 +1672,19 @@ parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
slang_output_ctx o = *O;
|
||||
|
||||
if (!parse_function_prototype(C, O, func))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
/* create function's body operation */
|
||||
func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation));
|
||||
if (func->body == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
if (!slang_operation_construct(func->body)) {
|
||||
_slang_free(func->body);
|
||||
func->body = NULL;
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* to parse the body the parse context is modified in order to
|
||||
|
|
@ -1683,7 +1693,7 @@ parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
C->global_scope = GL_FALSE;
|
||||
o.vars = func->parameters;
|
||||
if (!parse_statement(C, &o, func->body))
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
C->global_scope = GL_TRUE;
|
||||
return 1;
|
||||
|
|
@ -1779,46 +1789,46 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
slang_info_log_error(C->L,
|
||||
"declaration of '%s' conflicts with previous declaration",
|
||||
(char *) a_name);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* make room for the new variable and initialize it */
|
||||
var = slang_variable_scope_grow(O->vars);
|
||||
if (!var) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* copy the declarator qualifier type, parse the identifier */
|
||||
var->type.qualifier = type->qualifier;
|
||||
var->a_name = a_name;
|
||||
if (var->a_name == SLANG_ATOM_NULL)
|
||||
return 0;
|
||||
RETURN0;
|
||||
|
||||
switch (*C->I++) {
|
||||
case VARIABLE_NONE:
|
||||
/* simple variable declarator - just copy the specifier */
|
||||
if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case VARIABLE_INITIALIZER:
|
||||
/* initialized variable - copy the specifier and parse the expression */
|
||||
if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
|
||||
return 0;
|
||||
RETURN0;
|
||||
var->initializer =
|
||||
(slang_operation *) _slang_alloc(sizeof(slang_operation));
|
||||
if (var->initializer == NULL) {
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
if (!slang_operation_construct(var->initializer)) {
|
||||
_slang_free(var->initializer);
|
||||
var->initializer = NULL;
|
||||
slang_info_log_memory(C->L);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
if (!parse_expression(C, O, var->initializer))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case VARIABLE_ARRAY_UNKNOWN:
|
||||
/* unsized array - mark it as array and copy the specifier to
|
||||
|
|
@ -1834,7 +1844,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
return GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* allocate global address space for a variable with a known size */
|
||||
|
|
@ -1858,7 +1868,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
A.log = C->L;
|
||||
A.curFuncEndLabel = NULL;
|
||||
if (!_slang_codegen_global_variable(&A, var, C->type))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* initialize global variable */
|
||||
|
|
@ -1871,7 +1881,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
A.space.structs = O->structs;
|
||||
A.space.vars = O->vars;
|
||||
if (!initialize_global(&A, var))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
|
@ -1888,17 +1898,17 @@ parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
|
|||
|
||||
/* parse the fully specified type, common to all declarators */
|
||||
if (!slang_fully_specified_type_construct(&type))
|
||||
return 0;
|
||||
RETURN0;
|
||||
if (!parse_fully_specified_type(C, O, &type)) {
|
||||
slang_fully_specified_type_destruct(&type);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
/* parse declarators, pass-in the parsed type */
|
||||
do {
|
||||
if (!parse_init_declarator(C, O, &type)) {
|
||||
slang_fully_specified_type_destruct(&type);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
while (*C->I++ == DECLARATOR_NEXT);
|
||||
|
|
@ -2005,18 +2015,18 @@ parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
|
|||
switch (*C->I++) {
|
||||
case DECLARATION_INIT_DECLARATOR_LIST:
|
||||
if (!parse_init_declarator_list(C, O))
|
||||
return 0;
|
||||
RETURN0;
|
||||
break;
|
||||
case DECLARATION_FUNCTION_PROTOTYPE:
|
||||
{
|
||||
slang_function *dummy_func;
|
||||
|
||||
if (!parse_function(C, O, 0, &dummy_func))
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -2028,7 +2038,7 @@ parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
|
|||
|
||||
if (!O->allow_precision) {
|
||||
slang_info_log_error(C->L, "syntax error at \"precision\"");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
precision = *C->I++;
|
||||
|
|
@ -2041,7 +2051,7 @@ parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
|
|||
default:
|
||||
_mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
|
||||
precision, __FILE__, __LINE__);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
type = *C->I++;
|
||||
|
|
@ -2061,7 +2071,7 @@ parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
|
|||
default:
|
||||
_mesa_problem(NULL, "unexpected type %d at %s:%d\n",
|
||||
type, __FILE__, __LINE__);
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
|
||||
assert(type < TYPE_SPECIFIER_COUNT);
|
||||
|
|
@ -2108,7 +2118,7 @@ parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
|
|||
}
|
||||
else {
|
||||
slang_info_log_error(C->L, "syntax error at \"invariant\"");
|
||||
return 0;
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ typedef struct
|
|||
struct gl_program **Subroutines;
|
||||
GLuint NumSubroutines;
|
||||
|
||||
GLuint MaxInstructions; /**< size of prog->Instructions[] buffer */
|
||||
|
||||
/* code-gen options */
|
||||
GLboolean EmitHighLevelInstructions;
|
||||
GLboolean EmitCondCodes;
|
||||
|
|
@ -259,13 +261,16 @@ fix_swizzle(GLuint swizzle)
|
|||
static void
|
||||
storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st)
|
||||
{
|
||||
const GLboolean relAddr = st->RelAddr;
|
||||
const GLint size = st->Size;
|
||||
GLint index = st->Index;
|
||||
GLuint swizzle = st->Swizzle;
|
||||
|
||||
assert(index >= 0);
|
||||
/* if this is storage relative to some parent storage, walk up the tree */
|
||||
while (st->Parent) {
|
||||
st = st->Parent;
|
||||
assert(st->Index >= 0);
|
||||
index += st->Index;
|
||||
swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
|
||||
}
|
||||
|
|
@ -302,6 +307,8 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st)
|
|||
}
|
||||
dst->WriteMask = writemask;
|
||||
}
|
||||
|
||||
dst->RelAddr = relAddr;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -316,8 +323,10 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
|
|||
GLuint swizzle = st->Swizzle;
|
||||
|
||||
/* if this is storage relative to some parent storage, walk up the tree */
|
||||
assert(index >= 0);
|
||||
while (st->Parent) {
|
||||
st = st->Parent;
|
||||
assert(st->Index >= 0);
|
||||
index += st->Index;
|
||||
swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle);
|
||||
}
|
||||
|
|
@ -387,9 +396,17 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
|
|||
_mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);
|
||||
}
|
||||
#endif
|
||||
prog->Instructions = _mesa_realloc_instructions(prog->Instructions,
|
||||
prog->NumInstructions,
|
||||
prog->NumInstructions + 1);
|
||||
assert(prog->NumInstructions <= emitInfo->MaxInstructions);
|
||||
|
||||
if (prog->NumInstructions == emitInfo->MaxInstructions) {
|
||||
/* grow the instruction buffer */
|
||||
emitInfo->MaxInstructions += 20;
|
||||
prog->Instructions =
|
||||
_mesa_realloc_instructions(prog->Instructions,
|
||||
prog->NumInstructions,
|
||||
emitInfo->MaxInstructions);
|
||||
}
|
||||
|
||||
inst = prog->Instructions + prog->NumInstructions;
|
||||
prog->NumInstructions++;
|
||||
_mesa_init_instructions(inst, 1);
|
||||
|
|
@ -403,60 +420,149 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emit a new instruction with given opcode, operands.
|
||||
*/
|
||||
static struct prog_instruction *
|
||||
emit_instruction(slang_emit_info *emitInfo,
|
||||
gl_inst_opcode opcode,
|
||||
const slang_ir_storage *dst,
|
||||
const slang_ir_storage *src1,
|
||||
const slang_ir_storage *src2,
|
||||
const slang_ir_storage *src3)
|
||||
emit_arl_load(slang_emit_info *emitInfo,
|
||||
enum register_file file, GLint index, GLuint swizzle)
|
||||
{
|
||||
struct gl_program *prog = emitInfo->prog;
|
||||
struct prog_instruction *inst;
|
||||
|
||||
prog->Instructions = _mesa_realloc_instructions(prog->Instructions,
|
||||
prog->NumInstructions,
|
||||
prog->NumInstructions + 1);
|
||||
inst = prog->Instructions + prog->NumInstructions;
|
||||
prog->NumInstructions++;
|
||||
|
||||
_mesa_init_instructions(inst, 1);
|
||||
inst->Opcode = opcode;
|
||||
inst->BranchTarget = -1; /* invalid */
|
||||
|
||||
if (dst)
|
||||
storage_to_dst_reg(&inst->DstReg, dst);
|
||||
|
||||
if (src1)
|
||||
storage_to_src_reg(&inst->SrcReg[0], src1);
|
||||
if (src2)
|
||||
storage_to_src_reg(&inst->SrcReg[1], src2);
|
||||
if (src3)
|
||||
storage_to_src_reg(&inst->SrcReg[2], src3);
|
||||
|
||||
struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL);
|
||||
inst->SrcReg[0].File = file;
|
||||
inst->SrcReg[0].Index = index;
|
||||
inst->SrcReg[0].Swizzle = swizzle;
|
||||
inst->DstReg.File = PROGRAM_ADDRESS;
|
||||
inst->DstReg.Index = 0;
|
||||
inst->DstReg.WriteMask = WRITEMASK_X;
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emit an ARL instruction.
|
||||
* Emit a new instruction with given opcode, operands.
|
||||
* At this point the instruction may have multiple indirect register
|
||||
* loads/stores. We convert those into ARL loads and address-relative
|
||||
* operands. See comments inside.
|
||||
* At some point in the future we could directly emit indirectly addressed
|
||||
* registers in Mesa GPU instructions.
|
||||
*/
|
||||
static struct prog_instruction *
|
||||
emit_arl_instruction(slang_emit_info *emitInfo,
|
||||
GLint addrReg,
|
||||
const slang_ir_storage *src)
|
||||
emit_instruction(slang_emit_info *emitInfo,
|
||||
gl_inst_opcode opcode,
|
||||
const slang_ir_storage *dst,
|
||||
const slang_ir_storage *src0,
|
||||
const slang_ir_storage *src1,
|
||||
const slang_ir_storage *src2)
|
||||
{
|
||||
struct prog_instruction *inst;
|
||||
GLuint numIndirect = 0;
|
||||
const slang_ir_storage *src[3];
|
||||
slang_ir_storage newSrc[3], newDst;
|
||||
GLuint i;
|
||||
GLboolean isTemp[3];
|
||||
|
||||
isTemp[0] = isTemp[1] = isTemp[2] = GL_FALSE;
|
||||
|
||||
src[0] = src0;
|
||||
src[1] = src1;
|
||||
src[2] = src2;
|
||||
|
||||
/* count up how many operands are indirect loads */
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (src[i] && src[i]->IsIndirect)
|
||||
numIndirect++;
|
||||
}
|
||||
if (dst && dst->IsIndirect)
|
||||
numIndirect++;
|
||||
|
||||
/* Take special steps for indirect register loads.
|
||||
* If we had multiple address registers this would be simpler.
|
||||
* For example, this GLSL code:
|
||||
* x[i] = y[j] + z[k];
|
||||
* would translate into something like:
|
||||
* ARL ADDR.x, i;
|
||||
* ARL ADDR.y, j;
|
||||
* ARL ADDR.z, k;
|
||||
* ADD TEMP[ADDR.x+5], TEMP[ADDR.y+9], TEMP[ADDR.z+4];
|
||||
* But since we currently only have one address register we have to do this:
|
||||
* ARL ADDR.x, i;
|
||||
* MOV t1, TEMP[ADDR.x+9];
|
||||
* ARL ADDR.x, j;
|
||||
* MOV t2, TEMP[ADDR.x+4];
|
||||
* ARL ADDR.x, k;
|
||||
* ADD TEMP[ADDR.x+5], t1, t2;
|
||||
* The code here figures this out...
|
||||
*/
|
||||
if (numIndirect > 0) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (src[i] && src[i]->IsIndirect) {
|
||||
/* load the ARL register with the indirect register */
|
||||
emit_arl_load(emitInfo,
|
||||
src[i]->IndirectFile,
|
||||
src[i]->IndirectIndex,
|
||||
src[i]->IndirectSwizzle);
|
||||
|
||||
if (numIndirect > 1) {
|
||||
/* Need to load src[i] into a temporary register */
|
||||
slang_ir_storage srcRelAddr;
|
||||
alloc_local_temp(emitInfo, &newSrc[i], src[i]->Size);
|
||||
isTemp[i] = GL_TRUE;
|
||||
|
||||
/* set RelAddr flag on src register */
|
||||
srcRelAddr = *src[i];
|
||||
srcRelAddr.RelAddr = GL_TRUE;
|
||||
srcRelAddr.IsIndirect = GL_FALSE; /* not really needed */
|
||||
|
||||
/* MOV newSrc, srcRelAddr; */
|
||||
inst = emit_instruction(emitInfo,
|
||||
OPCODE_MOV,
|
||||
&newSrc[i],
|
||||
&srcRelAddr,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
src[i] = &newSrc[i];
|
||||
}
|
||||
else {
|
||||
/* just rewrite the src[i] storage to be ARL-relative */
|
||||
newSrc[i] = *src[i];
|
||||
newSrc[i].RelAddr = GL_TRUE;
|
||||
newSrc[i].IsIndirect = GL_FALSE; /* not really needed */
|
||||
src[i] = &newSrc[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Take special steps for indirect dest register write */
|
||||
if (dst && dst->IsIndirect) {
|
||||
/* load the ARL register with the indirect register */
|
||||
emit_arl_load(emitInfo,
|
||||
dst->IndirectFile,
|
||||
dst->IndirectIndex,
|
||||
dst->IndirectSwizzle);
|
||||
newDst = *dst;
|
||||
newDst.RelAddr = GL_TRUE;
|
||||
newDst.IsIndirect = GL_FALSE;
|
||||
dst = &newDst;
|
||||
}
|
||||
|
||||
/* OK, emit the instruction and its dst, src regs */
|
||||
inst = new_instruction(emitInfo, opcode);
|
||||
if (!inst)
|
||||
return NULL;
|
||||
|
||||
if (dst)
|
||||
storage_to_dst_reg(&inst->DstReg, dst);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (src[i])
|
||||
storage_to_src_reg(&inst->SrcReg[i], src[i]);
|
||||
}
|
||||
|
||||
/* Free any temp registers that we allocated above */
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (isTemp[i])
|
||||
_slang_free_temp(emitInfo->vt, &newSrc[i]);
|
||||
}
|
||||
|
||||
assert(addrReg == 0); /* only one addr reg at this time */
|
||||
inst = new_instruction(emitInfo, OPCODE_ARL);
|
||||
storage_to_src_reg(&inst->SrcReg[0], src);
|
||||
inst->DstReg.File = PROGRAM_ADDRESS;
|
||||
inst->DstReg.Index = addrReg;
|
||||
inst->DstReg.WriteMask = WRITEMASK_X;
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
|
@ -1034,13 +1140,17 @@ emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
struct gl_program *progSave;
|
||||
struct prog_instruction *inst;
|
||||
GLuint subroutineId;
|
||||
GLuint maxInstSave;
|
||||
|
||||
assert(n->Opcode == IR_CALL);
|
||||
assert(n->Label);
|
||||
|
||||
/* save/push cur program */
|
||||
maxInstSave = emitInfo->MaxInstructions;
|
||||
progSave = emitInfo->prog;
|
||||
|
||||
emitInfo->prog = new_subroutine(emitInfo, &subroutineId);
|
||||
emitInfo->MaxInstructions = emitInfo->prog->NumInstructions;
|
||||
|
||||
_slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
|
||||
emitInfo->prog);
|
||||
|
|
@ -1072,6 +1182,7 @@ emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
|
||||
/* pop/restore cur program */
|
||||
emitInfo->prog = progSave;
|
||||
emitInfo->MaxInstructions = maxInstSave;
|
||||
|
||||
/* emit the function call */
|
||||
inst = new_instruction(emitInfo, OPCODE_CAL);
|
||||
|
|
@ -1212,7 +1323,8 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
if (inst &&
|
||||
_slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
|
||||
(inst->DstReg.File == n->Children[1]->Store->File) &&
|
||||
(inst->DstReg.Index == n->Children[1]->Store->Index)) {
|
||||
(inst->DstReg.Index == n->Children[1]->Store->Index) &&
|
||||
!n->Children[0]->Store->IsIndirect) {
|
||||
/* Peephole optimization:
|
||||
* The Right-Hand-Side has its results in a temporary place.
|
||||
* Modify the RHS (and the prev instruction) to store its results
|
||||
|
|
@ -1670,80 +1782,38 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
|
||||
inst = emit(emitInfo, n->Children[0]);
|
||||
|
||||
/* setup storage info, if needed */
|
||||
if (!n->Store->Parent)
|
||||
n->Store->Parent = n->Children[0]->Store;
|
||||
|
||||
#if 0
|
||||
assert(n->Store->Parent);
|
||||
|
||||
/* Apply this node's swizzle to parent's storage */
|
||||
GLuint swizzle = n->Store->Swizzle;
|
||||
_slang_copy_ir_storage(n->Store, n->Store->Parent);
|
||||
n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
|
||||
assert(!n->Store->Parent);
|
||||
#endif
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move a block registers from src to dst (or move a single register).
|
||||
* \param size size of block, in floats (<=4 means one register)
|
||||
*/
|
||||
static struct prog_instruction *
|
||||
move_block(slang_emit_info *emitInfo,
|
||||
GLuint size, GLboolean relAddr,
|
||||
const slang_ir_storage *dst,
|
||||
const slang_ir_storage *src)
|
||||
{
|
||||
struct prog_instruction *inst;
|
||||
|
||||
if (size > 4) {
|
||||
/* move matrix/struct etc (block of registers) */
|
||||
slang_ir_storage dstStore = *dst;
|
||||
slang_ir_storage srcStore = *src;
|
||||
|
||||
dstStore.Size = 4;
|
||||
srcStore.Size = 4;
|
||||
while (size >= 4) {
|
||||
inst = emit_instruction(emitInfo, OPCODE_MOV,
|
||||
&dstStore,
|
||||
&srcStore,
|
||||
NULL,
|
||||
NULL);
|
||||
inst->SrcReg[0].RelAddr = relAddr;
|
||||
inst_comment(inst, "IR_COPY block");
|
||||
srcStore.Index++;
|
||||
dstStore.Index++;
|
||||
size -= 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* single register move */
|
||||
inst = emit_instruction(emitInfo,
|
||||
OPCODE_MOV,
|
||||
dst,
|
||||
src,
|
||||
NULL,
|
||||
NULL);
|
||||
inst->SrcReg[0].RelAddr = relAddr;
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Dereference array element. Just resolve storage for the array
|
||||
* element represented by this node.
|
||||
* This is typically where Indirect addressing comes into play.
|
||||
* See comments on struct slang_ir_storage.
|
||||
* Dereference array element: element == array[index]
|
||||
* This basically involves emitting code for computing the array index
|
||||
* and updating the node/element's storage info.
|
||||
*/
|
||||
static struct prog_instruction *
|
||||
emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||
{
|
||||
assert(n->Opcode == IR_ELEMENT);
|
||||
assert(n->Store);
|
||||
assert(n->Store->File == PROGRAM_UNDEFINED);
|
||||
assert(n->Store->Parent);
|
||||
assert(n->Store->Size > 0);
|
||||
slang_ir_storage *arrayStore, *indexStore;
|
||||
const int elemSize = n->Store->Size; /* number of floats */
|
||||
const GLint elemSizeVec = (elemSize + 3) / 4; /* number of vec4 */
|
||||
struct prog_instruction *inst;
|
||||
|
||||
assert(n->Opcode == IR_ELEMENT);
|
||||
assert(elemSize > 0);
|
||||
|
||||
/* special case for built-in state variables, like light state */
|
||||
{
|
||||
slang_ir_storage *root = n->Store;
|
||||
assert(!root->Parent);
|
||||
while (root->Parent)
|
||||
root = root->Parent;
|
||||
|
||||
|
|
@ -1754,69 +1824,98 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
}
|
||||
}
|
||||
|
||||
/* do codegen for array */
|
||||
/* do codegen for array itself */
|
||||
emit(emitInfo, n->Children[0]);
|
||||
arrayStore = n->Children[0]->Store;
|
||||
|
||||
/* The initial array element storage is the array's storage,
|
||||
* then modified below.
|
||||
*/
|
||||
_slang_copy_ir_storage(n->Store, arrayStore);
|
||||
|
||||
|
||||
if (n->Children[1]->Opcode == IR_FLOAT) {
|
||||
/* Constant array index.
|
||||
* Set Store's index to be the offset of the array element in
|
||||
* the register file.
|
||||
*/
|
||||
/* Constant array index */
|
||||
const GLint element = (GLint) n->Children[1]->Value[0];
|
||||
const GLint sz = (n->Store->Size + 3) / 4; /* size in slots/registers */
|
||||
|
||||
n->Store->Index = sz * element;
|
||||
assert(n->Store->Parent);
|
||||
/* this element's storage is the array's storage, plus constant offset */
|
||||
n->Store->Index += elemSizeVec * element;
|
||||
}
|
||||
else {
|
||||
/* Variable array index */
|
||||
struct prog_instruction *inst;
|
||||
|
||||
/* do codegen for array index expression */
|
||||
emit(emitInfo, n->Children[1]);
|
||||
indexStore = n->Children[1]->Store;
|
||||
|
||||
/* allocate temp storage for the array element */
|
||||
assert(n->Store->Index < 0);
|
||||
n->Store->File = PROGRAM_TEMPORARY;
|
||||
n->Store->Parent = NULL;
|
||||
alloc_node_storage(emitInfo, n, -1);
|
||||
if (indexStore->IsIndirect) {
|
||||
/* need to put the array index into a temporary since we can't
|
||||
* directly support a[b[i]] constructs.
|
||||
*/
|
||||
|
||||
if (n->Store->Size > 4) {
|
||||
/* need to multiply the index by the element size */
|
||||
const GLint elemSize = (n->Store->Size + 3) / 4;
|
||||
slang_ir_storage indexTemp, elemSizeStore;
|
||||
|
||||
/* constant containing the element size */
|
||||
constant_to_storage(emitInfo, (float) elemSize, &elemSizeStore);
|
||||
/*indexStore = tempstore();*/
|
||||
}
|
||||
|
||||
|
||||
if (elemSize > 4) {
|
||||
/* need to multiply array index by array element size */
|
||||
struct prog_instruction *inst;
|
||||
slang_ir_storage *indexTemp;
|
||||
slang_ir_storage elemSizeStore;
|
||||
|
||||
/* allocate 1 float indexTemp */
|
||||
alloc_local_temp(emitInfo, &indexTemp, 1);
|
||||
indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
|
||||
_slang_alloc_temp(emitInfo->vt, indexTemp);
|
||||
|
||||
/* MUL temp, index, elemSize */
|
||||
inst = emit_instruction(emitInfo, OPCODE_MUL,
|
||||
&indexTemp, /* dest */
|
||||
n->Children[1]->Store, /* the index */
|
||||
/* allocate a constant containing the element size */
|
||||
constant_to_storage(emitInfo, (float) elemSizeVec, &elemSizeStore);
|
||||
|
||||
/* multiply array index by element size */
|
||||
inst = emit_instruction(emitInfo,
|
||||
OPCODE_MUL,
|
||||
indexTemp, /* dest */
|
||||
indexStore, /* the index */
|
||||
&elemSizeStore,
|
||||
NULL);
|
||||
|
||||
/* load ADDR[0].X = temp */
|
||||
inst = emit_arl_instruction(emitInfo, 0, &indexTemp);
|
||||
|
||||
_slang_free_temp(emitInfo->vt, &indexTemp);
|
||||
}
|
||||
else {
|
||||
/* simply load address reg w/ array index */
|
||||
inst = emit_arl_instruction(emitInfo, 0, n->Children[1]->Store);
|
||||
indexStore = indexTemp;
|
||||
}
|
||||
|
||||
/* copy from array element to temp storage */
|
||||
move_block(emitInfo, n->Store->Size, GL_TRUE,
|
||||
n->Store, n->Children[0]->Store);
|
||||
if (arrayStore->IsIndirect) {
|
||||
/* ex: in a[i][j], a[i] (the arrayStore) is indirect */
|
||||
/* Need to add indexStore to arrayStore->Indirect store */
|
||||
slang_ir_storage indirectArray;
|
||||
slang_ir_storage *indexTemp;
|
||||
|
||||
_slang_init_ir_storage(&indirectArray,
|
||||
arrayStore->IndirectFile,
|
||||
arrayStore->IndirectIndex,
|
||||
1,
|
||||
arrayStore->IndirectSwizzle);
|
||||
|
||||
/* allocate 1 float indexTemp */
|
||||
indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
|
||||
_slang_alloc_temp(emitInfo->vt, indexTemp);
|
||||
|
||||
inst = emit_instruction(emitInfo,
|
||||
OPCODE_ADD,
|
||||
indexTemp, /* dest */
|
||||
indexStore, /* the index */
|
||||
&indirectArray, /* indirect array base */
|
||||
NULL);
|
||||
|
||||
indexStore = indexTemp;
|
||||
}
|
||||
|
||||
/* update the array element storage info */
|
||||
n->Store->IsIndirect = GL_TRUE;
|
||||
n->Store->IndirectFile = indexStore->File;
|
||||
n->Store->IndirectIndex = indexStore->Index;
|
||||
n->Store->IndirectSwizzle = indexStore->Swizzle;
|
||||
}
|
||||
|
||||
/* if array element size is one, make sure we only access X */
|
||||
if (n->Store->Size == 1)
|
||||
n->Store->Swizzle = SWIZZLE_XXXX;
|
||||
n->Store->Size = elemSize;
|
||||
|
||||
return NULL; /* no instruction */
|
||||
}
|
||||
|
|
@ -1829,9 +1928,11 @@ static struct prog_instruction *
|
|||
emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||
{
|
||||
slang_ir_storage *root = n->Store;
|
||||
GLint fieldOffset, fieldSize;
|
||||
|
||||
assert(n->Opcode == IR_FIELD);
|
||||
|
||||
assert(!root->Parent);
|
||||
while (root->Parent)
|
||||
root = root->Parent;
|
||||
|
||||
|
|
@ -1847,12 +1948,45 @@ emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
slang_info_log_error(emitInfo->log, "Error parsing state variable");
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
/* do codegen for struct */
|
||||
emit(emitInfo, n->Children[0]);
|
||||
assert(n->Children[0]->Store->Index >= 0);
|
||||
}
|
||||
|
||||
fieldOffset = n->Store->Index;
|
||||
fieldSize = n->Store->Size;
|
||||
|
||||
_slang_copy_ir_storage(n->Store, n->Children[0]->Store);
|
||||
|
||||
n->Store->Index = n->Children[0]->Store->Index + fieldOffset / 4;
|
||||
/* XXX test this:
|
||||
n->Store->Index += fieldOffset / 4;
|
||||
*/
|
||||
|
||||
switch (fieldSize) {
|
||||
case 1:
|
||||
{
|
||||
GLint swz = fieldOffset % 4;
|
||||
n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
|
||||
SWIZZLE_NIL, SWIZZLE_NIL);
|
||||
break;
|
||||
case 3:
|
||||
n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
|
||||
SWIZZLE_Z, SWIZZLE_NIL);
|
||||
break;
|
||||
default:
|
||||
n->Store->Swizzle = SWIZZLE_XYZW;
|
||||
}
|
||||
|
||||
assert(n->Store->Index >= 0);
|
||||
|
||||
return NULL; /* no instruction */
|
||||
}
|
||||
|
||||
|
|
@ -1909,7 +2043,7 @@ emit_var_decl(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
|
||||
/**
|
||||
* Emit code for a reference to a variable.
|
||||
* Actually, no code is generated but we may do some memory alloation.
|
||||
* Actually, no code is generated but we may do some memory allocation.
|
||||
* In particular, state vars (uniforms) are allocated on an as-needed basis.
|
||||
*/
|
||||
static struct prog_instruction *
|
||||
|
|
@ -2130,7 +2264,7 @@ _slang_resolve_subroutines(slang_emit_info *emitInfo)
|
|||
total += emitInfo->Subroutines[i]->NumInstructions;
|
||||
}
|
||||
|
||||
/* adjust BrancTargets within the functions */
|
||||
/* adjust BranchTargets within the functions */
|
||||
for (i = 0; i < emitInfo->NumSubroutines; i++) {
|
||||
struct gl_program *sub = emitInfo->Subroutines[i];
|
||||
GLuint j;
|
||||
|
|
@ -2199,6 +2333,7 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
|
|||
emitInfo.prog = prog;
|
||||
emitInfo.Subroutines = NULL;
|
||||
emitInfo.NumSubroutines = 0;
|
||||
emitInfo.MaxInstructions = prog->NumInstructions;
|
||||
|
||||
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
|
||||
emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,20 @@ _slang_ir_info(slang_ir_opcode opcode)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
_slang_init_ir_storage(slang_ir_storage *st,
|
||||
enum register_file file, GLint index, GLint size,
|
||||
GLuint swizzle)
|
||||
{
|
||||
st->File = file;
|
||||
st->Index = index;
|
||||
st->Size = size;
|
||||
st->Swizzle = swizzle;
|
||||
st->Parent = NULL;
|
||||
st->IsIndirect = GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a new slang_ir_storage object.
|
||||
*/
|
||||
|
|
@ -130,6 +144,7 @@ _slang_new_ir_storage(enum register_file file, GLint index, GLint size)
|
|||
st->Size = size;
|
||||
st->Swizzle = SWIZZLE_NOOP;
|
||||
st->Parent = NULL;
|
||||
st->IsIndirect = GL_FALSE;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
|
@ -150,6 +165,7 @@ _slang_new_ir_storage_swz(enum register_file file, GLint index, GLint size,
|
|||
st->Size = size;
|
||||
st->Swizzle = swizzle;
|
||||
st->Parent = NULL;
|
||||
st->IsIndirect = GL_FALSE;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
|
@ -170,11 +186,45 @@ _slang_new_ir_storage_relative(GLint index, GLint size,
|
|||
st->Size = size;
|
||||
st->Swizzle = SWIZZLE_NOOP;
|
||||
st->Parent = parent;
|
||||
st->IsIndirect = GL_FALSE;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
slang_ir_storage *
|
||||
_slang_new_ir_storage_indirect(enum register_file file,
|
||||
GLint index,
|
||||
GLint size,
|
||||
enum register_file indirectFile,
|
||||
GLint indirectIndex,
|
||||
GLuint indirectSwizzle)
|
||||
{
|
||||
slang_ir_storage *st;
|
||||
st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
|
||||
if (st) {
|
||||
st->File = file;
|
||||
st->Index = index;
|
||||
st->Size = size;
|
||||
st->Swizzle = SWIZZLE_NOOP;
|
||||
st->IsIndirect = GL_TRUE;
|
||||
st->IndirectFile = indirectFile;
|
||||
st->IndirectIndex = indirectIndex;
|
||||
st->IndirectSwizzle = indirectSwizzle;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
/* XXX temporary function */
|
||||
void
|
||||
_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src)
|
||||
{
|
||||
*dst = *src;
|
||||
dst->Parent = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *
|
||||
_slang_ir_name(slang_ir_opcode opcode)
|
||||
|
|
|
|||
|
|
@ -140,24 +140,53 @@ typedef enum
|
|||
|
||||
|
||||
/**
|
||||
* Describes where data storage is allocated.
|
||||
* Describes where data/variables are stored in the various register files.
|
||||
*
|
||||
* In the simple case, the File, Index and Size fields indicate where
|
||||
* a variable is stored. For example, a vec3 variable may be stored
|
||||
* as (File=PROGRAM_TEMPORARY, Index=6, Size=3). Or, File[Index].
|
||||
* Or, a program input like color may be stored as
|
||||
* (File=PROGRAM_INPUT,Index=3,Size=4);
|
||||
*
|
||||
* For single-float values, the Swizzle field indicates which component
|
||||
* of the vector contains the float.
|
||||
*
|
||||
* If IsIndirect is set, the storage is accessed through an indirect
|
||||
* register lookup. The value in question will be located at:
|
||||
* File[Index + IndirectFile[IndirectIndex]]
|
||||
*
|
||||
* This is primary used for indexing arrays. For example, consider this
|
||||
* GLSL code:
|
||||
* uniform int i;
|
||||
* float a[10];
|
||||
* float x = a[i];
|
||||
*
|
||||
* here, storage for a[i] would be described by (File=PROGRAM_TEMPORAY,
|
||||
* Index=aPos, IndirectFile=PROGRAM_UNIFORM, IndirectIndex=iPos), which
|
||||
* would mean TEMP[aPos + UNIFORM[iPos]]
|
||||
*/
|
||||
struct _slang_ir_storage
|
||||
struct slang_ir_storage_
|
||||
{
|
||||
enum register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
|
||||
GLint Index; /**< -1 means unallocated */
|
||||
GLint Size; /**< number of floats */
|
||||
GLuint Swizzle;
|
||||
GLuint Swizzle; /**< Swizzle AND writemask info */
|
||||
GLint RefCount; /**< Used during IR tree delete */
|
||||
GLboolean RelAddr;
|
||||
|
||||
GLboolean RelAddr; /* we'll remove this eventually */
|
||||
|
||||
GLboolean IsIndirect;
|
||||
enum register_file IndirectFile;
|
||||
GLint IndirectIndex;
|
||||
GLuint IndirectSwizzle;
|
||||
|
||||
/** If Parent is non-null, Index is relative to parent.
|
||||
* The other fields are ignored.
|
||||
*/
|
||||
struct _slang_ir_storage *Parent;
|
||||
struct slang_ir_storage_ *Parent;
|
||||
};
|
||||
|
||||
typedef struct _slang_ir_storage slang_ir_storage;
|
||||
typedef struct slang_ir_storage_ slang_ir_storage;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -199,6 +228,11 @@ extern const slang_ir_info *
|
|||
_slang_ir_info(slang_ir_opcode opcode);
|
||||
|
||||
|
||||
extern void
|
||||
_slang_init_ir_storage(slang_ir_storage *st,
|
||||
enum register_file file, GLint index, GLint size,
|
||||
GLuint swizzle);
|
||||
|
||||
extern slang_ir_storage *
|
||||
_slang_new_ir_storage(enum register_file file, GLint index, GLint size);
|
||||
|
||||
|
|
@ -212,6 +246,17 @@ _slang_new_ir_storage_relative(GLint index, GLint size,
|
|||
slang_ir_storage *parent);
|
||||
|
||||
|
||||
extern slang_ir_storage *
|
||||
_slang_new_ir_storage_indirect(enum register_file file,
|
||||
GLint index,
|
||||
GLint size,
|
||||
enum register_file indirectFile,
|
||||
GLint indirectIndex,
|
||||
GLuint indirectSwizzle);
|
||||
|
||||
extern void
|
||||
_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src);
|
||||
|
||||
|
||||
extern void
|
||||
_slang_free_ir_tree(slang_ir_node *n);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#ifndef SLANG_VARTABLE_H
|
||||
#define SLANG_VARTABLE_H
|
||||
|
||||
struct _slang_ir_storage;
|
||||
struct slang_ir_storage_;
|
||||
|
||||
typedef struct slang_var_table_ slang_var_table;
|
||||
|
||||
|
|
@ -27,16 +27,16 @@ extern struct slang_variable_ *
|
|||
_slang_find_variable(const slang_var_table *t, slang_atom name);
|
||||
|
||||
extern GLboolean
|
||||
_slang_alloc_var(slang_var_table *t, struct _slang_ir_storage *store);
|
||||
_slang_alloc_var(slang_var_table *t, struct slang_ir_storage_ *store);
|
||||
|
||||
extern GLboolean
|
||||
_slang_alloc_temp(slang_var_table *t, struct _slang_ir_storage *store);
|
||||
_slang_alloc_temp(slang_var_table *t, struct slang_ir_storage_ *store);
|
||||
|
||||
extern void
|
||||
_slang_free_temp(slang_var_table *t, struct _slang_ir_storage *store);
|
||||
_slang_free_temp(slang_var_table *t, struct slang_ir_storage_ *store);
|
||||
|
||||
extern GLboolean
|
||||
_slang_is_temp(const slang_var_table *t, const struct _slang_ir_storage *store);
|
||||
_slang_is_temp(const slang_var_table *t, const struct slang_ir_storage_ *store);
|
||||
|
||||
|
||||
#endif /* SLANG_VARTABLE_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue