📄 slang_codegen.c
字号:
/* * Mesa 3-D graphics library * Version: 7.1 * * Copyright (C) 2005-2007 Brian Paul 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, sublicense, * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL 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. *//** * \file slang_codegen.c * Generate IR tree from AST. * \author Brian Paul *//*** *** NOTES: *** The new_() functions return a new instance of a simple IR node. *** The gen_() functions generate larger IR trees from the simple nodes. ***/#include "main/imports.h"#include "main/macros.h"#include "main/mtypes.h"#include "shader/program.h"#include "shader/prog_instruction.h"#include "shader/prog_parameter.h"#include "shader/prog_print.h"#include "shader/prog_statevars.h"#include "slang_typeinfo.h"#include "slang_codegen.h"#include "slang_compile.h"#include "slang_label.h"#include "slang_mem.h"#include "slang_simplify.h"#include "slang_emit.h"#include "slang_vartable.h"#include "slang_ir.h"#include "slang_print.h"static slang_ir_node *_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);static GLbooleanis_sampler_type(const slang_fully_specified_type *t){ switch (t->specifier.type) { case SLANG_SPEC_SAMPLER1D: case SLANG_SPEC_SAMPLER2D: case SLANG_SPEC_SAMPLER3D: case SLANG_SPEC_SAMPLERCUBE: case SLANG_SPEC_SAMPLER1DSHADOW: case SLANG_SPEC_SAMPLER2DSHADOW: case SLANG_SPEC_SAMPLER2DRECT: case SLANG_SPEC_SAMPLER2DRECTSHADOW: return GL_TRUE; default: return GL_FALSE; }}/** * Return the offset (in floats or ints) of the named field within * the given struct. Return -1 if field not found. * If field is NULL, return the size of the struct instead. */static GLint_slang_field_offset(const slang_type_specifier *spec, slang_atom field){ GLint offset = 0; GLuint i; for (i = 0; i < spec->_struct->fields->num_variables; i++) { const slang_variable *v = spec->_struct->fields->variables[i]; const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier); if (sz > 1) { /* types larger than 1 float are register (4-float) aligned */ offset = (offset + 3) & ~3; } if (field && v->a_name == field) { return offset; } offset += sz; } if (field) return -1; /* field not found */ else return offset; /* struct size */}/** * Return the size (in floats) of the given type specifier. * If the size is greater than 4, the size should be a multiple of 4 * so that the correct number of 4-float registers are allocated. * For example, a mat3x2 is size 12 because we want to store the * 3 columns in 3 float[4] registers. */GLuint_slang_sizeof_type_specifier(const slang_type_specifier *spec){ GLuint sz; switch (spec->type) { case SLANG_SPEC_VOID: sz = 0; break; case SLANG_SPEC_BOOL: sz = 1; break; case SLANG_SPEC_BVEC2: sz = 2; break; case SLANG_SPEC_BVEC3: sz = 3; break; case SLANG_SPEC_BVEC4: sz = 4; break; case SLANG_SPEC_INT: sz = 1; break; case SLANG_SPEC_IVEC2: sz = 2; break; case SLANG_SPEC_IVEC3: sz = 3; break; case SLANG_SPEC_IVEC4: sz = 4; break; case SLANG_SPEC_FLOAT: sz = 1; break; case SLANG_SPEC_VEC2: sz = 2; break; case SLANG_SPEC_VEC3: sz = 3; break; case SLANG_SPEC_VEC4: sz = 4; break; case SLANG_SPEC_MAT2: sz = 2 * 4; /* 2 columns (regs) */ break; case SLANG_SPEC_MAT3: sz = 3 * 4; break; case SLANG_SPEC_MAT4: sz = 4 * 4; break; case SLANG_SPEC_MAT23: sz = 2 * 4; /* 2 columns (regs) */ break; case SLANG_SPEC_MAT32: sz = 3 * 4; /* 3 columns (regs) */ break; case SLANG_SPEC_MAT24: sz = 2 * 4; break; case SLANG_SPEC_MAT42: sz = 4 * 4; /* 4 columns (regs) */ break; case SLANG_SPEC_MAT34: sz = 3 * 4; break; case SLANG_SPEC_MAT43: sz = 4 * 4; /* 4 columns (regs) */ break; case SLANG_SPEC_SAMPLER1D: case SLANG_SPEC_SAMPLER2D: case SLANG_SPEC_SAMPLER3D: case SLANG_SPEC_SAMPLERCUBE: case SLANG_SPEC_SAMPLER1DSHADOW: case SLANG_SPEC_SAMPLER2DSHADOW: case SLANG_SPEC_SAMPLER2DRECT: case SLANG_SPEC_SAMPLER2DRECTSHADOW: sz = 1; /* a sampler is basically just an integer index */ break; case SLANG_SPEC_STRUCT: sz = _slang_field_offset(spec, 0); /* special use */ if (sz > 4) { sz = (sz + 3) & ~0x3; /* round up to multiple of four */ } break; case SLANG_SPEC_ARRAY: sz = _slang_sizeof_type_specifier(spec->_array); break; default: _mesa_problem(NULL, "Unexpected type in _slang_sizeof_type_specifier()"); sz = 0; } if (sz > 4) { /* if size is > 4, it should be a multiple of four */ assert((sz & 0x3) == 0); } return sz;}/** * Establish the binding between a slang_ir_node and a slang_variable. * Then, allocate/attach a slang_ir_storage object to the IR node if needed. * The IR node must be a IR_VAR or IR_VAR_DECL node. * \param n the IR node * \param var the variable to associate with the IR node */static void_slang_attach_storage(slang_ir_node *n, slang_variable *var){ assert(n); assert(var); assert(n->Opcode == IR_VAR || n->Opcode == IR_VAR_DECL); assert(!n->Var || n->Var == var); n->Var = var; if (!n->Store) { /* need to setup storage */ if (n->Var && n->Var->aux) { /* node storage info = var storage info */ n->Store = (slang_ir_storage *) n->Var->aux; } else { /* alloc new storage info */ n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -7, -5);#if 0 printf("%s var=%s Store=%p Size=%d\n", __FUNCTION__, (char*) var->a_name, (void*) n->Store, n->Store->Size);#endif if (n->Var) n->Var->aux = n->Store; assert(n->Var->aux); } }}/** * Return the TEXTURE_*_INDEX value that corresponds to a sampler type, * or -1 if the type is not a sampler. */static GLintsampler_to_texture_index(const slang_type_specifier_type type){ switch (type) { case SLANG_SPEC_SAMPLER1D: return TEXTURE_1D_INDEX; case SLANG_SPEC_SAMPLER2D: return TEXTURE_2D_INDEX; case SLANG_SPEC_SAMPLER3D: return TEXTURE_3D_INDEX; case SLANG_SPEC_SAMPLERCUBE: return TEXTURE_CUBE_INDEX; case SLANG_SPEC_SAMPLER1DSHADOW: return TEXTURE_1D_INDEX; /* XXX fix */ case SLANG_SPEC_SAMPLER2DSHADOW: return TEXTURE_2D_INDEX; /* XXX fix */ case SLANG_SPEC_SAMPLER2DRECT: return TEXTURE_RECT_INDEX; case SLANG_SPEC_SAMPLER2DRECTSHADOW: return TEXTURE_RECT_INDEX; /* XXX fix */ default: return -1; }}#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)/** * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to * a vertex or fragment program input variable. Return -1 if the input * name is invalid. * XXX return size too */static GLint_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut){ struct input_info { const char *Name; GLuint Attrib; GLuint Swizzle; }; static const struct input_info vertInputs[] = { { "gl_Vertex", VERT_ATTRIB_POS, SWIZZLE_NOOP }, { "gl_Normal", VERT_ATTRIB_NORMAL, SWIZZLE_NOOP }, { "gl_Color", VERT_ATTRIB_COLOR0, SWIZZLE_NOOP }, { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, SWIZZLE_NOOP }, { "gl_FogCoord", VERT_ATTRIB_FOG, SWIZZLE_XXXX }, { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, SWIZZLE_NOOP }, { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, SWIZZLE_NOOP }, { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, SWIZZLE_NOOP }, { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, SWIZZLE_NOOP }, { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, SWIZZLE_NOOP }, { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, SWIZZLE_NOOP }, { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, SWIZZLE_NOOP }, { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, SWIZZLE_NOOP }, { NULL, 0, SWIZZLE_NOOP } }; static const struct input_info fragInputs[] = { { "gl_FragCoord", FRAG_ATTRIB_WPOS, SWIZZLE_NOOP }, { "gl_Color", FRAG_ATTRIB_COL0, SWIZZLE_NOOP }, { "gl_SecondaryColor", FRAG_ATTRIB_COL1, SWIZZLE_NOOP }, { "gl_TexCoord", FRAG_ATTRIB_TEX0, SWIZZLE_NOOP }, /* note: we're packing several quantities into the fogcoord vector */ { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, SWIZZLE_XXXX }, { "gl_FrontFacing", FRAG_ATTRIB_FOGC, SWIZZLE_YYYY }, /*XXX*/ { "gl_PointCoord", FRAG_ATTRIB_FOGC, SWIZZLE_ZWWW }, { NULL, 0, SWIZZLE_NOOP } }; GLuint i; const struct input_info *inputs = (target == GL_VERTEX_PROGRAM_ARB) ? vertInputs : fragInputs; ASSERT(MAX_TEXTURE_UNITS == 8); /* if this fails, fix vertInputs above */ for (i = 0; inputs[i].Name; i++) { if (strcmp(inputs[i].Name, name) == 0) { /* found */ *swizzleOut = inputs[i].Swizzle; return inputs[i].Attrib; } } return -1;}/** * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to * a vertex or fragment program output variable. Return -1 for an invalid * output name. */static GLint_slang_output_index(const char *name, GLenum target){ struct output_info { const char *Name; GLuint Attrib; }; static const struct output_info vertOutputs[] = { { "gl_Position", VERT_RESULT_HPOS }, { "gl_FrontColor", VERT_RESULT_COL0 }, { "gl_BackColor", VERT_RESULT_BFC0 }, { "gl_FrontSecondaryColor", VERT_RESULT_COL1 }, { "gl_BackSecondaryColor", VERT_RESULT_BFC1 }, { "gl_TexCoord", VERT_RESULT_TEX0 }, { "gl_FogFragCoord", VERT_RESULT_FOGC }, { "gl_PointSize", VERT_RESULT_PSIZ }, { NULL, 0 } }; static const struct output_info fragOutputs[] = { { "gl_FragColor", FRAG_RESULT_COLR }, { "gl_FragDepth", FRAG_RESULT_DEPR }, { "gl_FragData", FRAG_RESULT_DATA0 }, { NULL, 0 } }; GLuint i; const struct output_info *outputs = (target == GL_VERTEX_PROGRAM_ARB) ? vertOutputs : fragOutputs; for (i = 0; outputs[i].Name; i++) { if (strcmp(outputs[i].Name, name) == 0) { /* found */ return outputs[i].Attrib; } } return -1;}/**********************************************************************//** * Map "_asm foo" to IR_FOO, etc. */typedef struct{ const char *Name; slang_ir_opcode Opcode; GLuint HaveRetValue, NumParams;} slang_asm_info;static slang_asm_info AsmInfo[] = { /* vec4 binary op */ { "vec4_add", IR_ADD, 1, 2 }, { "vec4_subtract", IR_SUB, 1, 2 }, { "vec4_multiply", IR_MUL, 1, 2 }, { "vec4_dot", IR_DOT4, 1, 2 }, { "vec3_dot", IR_DOT3, 1, 2 }, { "vec3_cross", IR_CROSS, 1, 2 }, { "vec4_lrp", IR_LRP, 1, 3 }, { "vec4_min", IR_MIN, 1, 2 }, { "vec4_max", IR_MAX, 1, 2 }, { "vec4_clamp", IR_CLAMP, 1, 3 }, { "vec4_seq", IR_SEQUAL, 1, 2 }, { "vec4_sne", IR_SNEQUAL, 1, 2 }, { "vec4_sge", IR_SGE, 1, 2 }, { "vec4_sgt", IR_SGT, 1, 2 }, { "vec4_sle", IR_SLE, 1, 2 }, { "vec4_slt", IR_SLT, 1, 2 }, /* vec4 unary */ { "vec4_move", IR_MOVE, 1, 1 }, { "vec4_floor", IR_FLOOR, 1, 1 }, { "vec4_frac", IR_FRAC, 1, 1 }, { "vec4_abs", IR_ABS, 1, 1 }, { "vec4_negate", IR_NEG, 1, 1 }, { "vec4_ddx", IR_DDX, 1, 1 }, { "vec4_ddy", IR_DDY, 1, 1 }, /* float binary op */ { "float_power", IR_POW, 1, 2 }, /* texture / sampler */ { "vec4_tex1d", IR_TEX, 1, 2 }, { "vec4_texb1d", IR_TEXB, 1, 2 }, /* 1d w/ bias */ { "vec4_texp1d", IR_TEXP, 1, 2 }, /* 1d w/ projection */ { "vec4_tex2d", IR_TEX, 1, 2 }, { "vec4_texb2d", IR_TEXB, 1, 2 }, /* 2d w/ bias */ { "vec4_texp2d", IR_TEXP, 1, 2 }, /* 2d w/ projection */ { "vec4_tex3d", IR_TEX, 1, 2 }, { "vec4_texb3d", IR_TEXB, 1, 2 }, /* 3d w/ bias */ { "vec4_texp3d", IR_TEXP, 1, 2 }, /* 3d w/ projection */ { "vec4_texcube", IR_TEX, 1, 2 }, /* cubemap */ { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */ { "vec4_texp_rect", IR_TEX, 1, 2 },/* rectangle w/ projection */ /* unary op */ { "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */ { "vec4_to_ivec4", IR_F_TO_I, 1, 1 }, /* float[4] to int[4] */ { "float_exp", IR_EXP, 1, 1 }, { "float_exp2", IR_EXP2, 1, 1 }, { "float_log2", IR_LOG2, 1, 1 }, { "float_rsq", IR_RSQ, 1, 1 }, { "float_rcp", IR_RCP, 1, 1 }, { "float_sine", IR_SIN, 1, 1 },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -