Compare commits
6 Commits
mesa-24.1.
...
useful
Author | SHA1 | Date | |
---|---|---|---|
|
d6db9143b6 | ||
|
9c0b233c44 | ||
|
364aa72824 | ||
|
d290ec228b | ||
|
c0906e06ee | ||
|
b6c49104ce |
@@ -63,6 +63,9 @@ const glsl_type glsl_type::builtin_core_types[] = {
|
||||
};
|
||||
|
||||
const glsl_type *const glsl_type::bool_type = & builtin_core_types[0];
|
||||
const glsl_type *const glsl_type::bvec2_type = & builtin_core_types[1];
|
||||
const glsl_type *const glsl_type::bvec3_type = & builtin_core_types[2];
|
||||
const glsl_type *const glsl_type::bvec4_type = & builtin_core_types[3];
|
||||
const glsl_type *const glsl_type::int_type = & builtin_core_types[4];
|
||||
const glsl_type *const glsl_type::ivec4_type = & builtin_core_types[7];
|
||||
const glsl_type *const glsl_type::float_type = & builtin_core_types[8];
|
||||
|
@@ -450,6 +450,125 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert sampler type attributes into an index in the sampler_types array
|
||||
*/
|
||||
#define SAMPLER_TYPE_INDEX(dim, sample_type, array, shadow) \
|
||||
((unsigned(dim) * 12) | (sample_type * 4) | (unsigned(array) * 2) \
|
||||
| unsigned(shadow))
|
||||
|
||||
/**
|
||||
* \note
|
||||
* Arrays like this are \b the argument for C99-style designated initializers.
|
||||
* Too bad C++ and VisualStudio are too cool for that sort of useful
|
||||
* functionality.
|
||||
*/
|
||||
const glsl_type *const glsl_type::sampler_types[] = {
|
||||
/* GLSL_SAMPLER_DIM_1D */
|
||||
&builtin_130_types[10], /* uint */
|
||||
NULL, /* uint, shadow */
|
||||
&builtin_130_types[5], /* uint, array */
|
||||
NULL, /* uint, array, shadow */
|
||||
&builtin_130_types[9], /* int */
|
||||
NULL, /* int, shadow */
|
||||
&builtin_130_types[4], /* int, array */
|
||||
NULL, /* int, array, shadow */
|
||||
&builtin_110_types[0], /* float */
|
||||
&builtin_110_types[1], /* float, shadow */
|
||||
&builtin_EXT_texture_array_types[0], /* float, array */
|
||||
&builtin_EXT_texture_array_types[2], /* float, array, shadow */
|
||||
|
||||
/* GLSL_SAMPLER_DIM_2D */
|
||||
&builtin_130_types[12], /* uint */
|
||||
NULL, /* uint, shadow */
|
||||
&builtin_130_types[7], /* uint, array */
|
||||
NULL, /* uint, array, shadow */
|
||||
&builtin_130_types[11], /* int */
|
||||
NULL, /* int, shadow */
|
||||
&builtin_130_types[6], /* int, array */
|
||||
NULL, /* int, array, shadow */
|
||||
&builtin_core_types[15], /* float */
|
||||
&builtin_110_types[2], /* float, shadow */
|
||||
&builtin_EXT_texture_array_types[1], /* float, array */
|
||||
&builtin_EXT_texture_array_types[3], /* float, array, shadow */
|
||||
|
||||
/* GLSL_SAMPLER_DIM_3D */
|
||||
&builtin_130_types[14], /* uint */
|
||||
NULL, /* uint, shadow */
|
||||
NULL, /* uint, array */
|
||||
NULL, /* uint, array, shadow */
|
||||
&builtin_130_types[13], /* int */
|
||||
NULL, /* int, shadow */
|
||||
NULL, /* int, array */
|
||||
NULL, /* int, array, shadow */
|
||||
&builtin_110_types[3], /* float */
|
||||
NULL, /* float, shadow */
|
||||
NULL, /* float, array */
|
||||
NULL, /* float, array, shadow */
|
||||
|
||||
/* GLSL_SAMPLER_DIM_CUBE */
|
||||
&builtin_130_types[16], /* uint */
|
||||
NULL, /* uint, shadow */
|
||||
NULL, /* uint, array */
|
||||
NULL, /* uint, array, shadow */
|
||||
&builtin_130_types[15], /* int */
|
||||
NULL, /* int, shadow */
|
||||
NULL, /* int, array */
|
||||
NULL, /* int, array, shadow */
|
||||
&builtin_core_types[16], /* float */
|
||||
&builtin_130_types[8], /* float, shadow */
|
||||
NULL, /* float, array */
|
||||
NULL, /* float, array, shadow */
|
||||
|
||||
/* GLSL_SAMPLER_DIM_RECT */
|
||||
NULL, /* uint */
|
||||
NULL, /* uint, shadow */
|
||||
NULL, /* uint, array */
|
||||
NULL, /* uint, array, shadow */
|
||||
NULL, /* int */
|
||||
NULL, /* int, shadow */
|
||||
NULL, /* int, array */
|
||||
NULL, /* int, array, shadow */
|
||||
&builtin_ARB_texture_rectangle_types[0], /* float */
|
||||
&builtin_ARB_texture_rectangle_types[1], /* float, shadow */
|
||||
NULL, /* float, array */
|
||||
NULL, /* float, array, shadow */
|
||||
|
||||
/* GLSL_SAMPLER_DIM_BUF */
|
||||
&builtin_EXT_texture_buffer_object_types[2], /* uint */
|
||||
NULL, /* uint, shadow */
|
||||
NULL, /* uint, array */
|
||||
NULL, /* uint, array, shadow */
|
||||
&builtin_EXT_texture_buffer_object_types[1], /* int */
|
||||
NULL, /* int, shadow */
|
||||
NULL, /* int, array */
|
||||
NULL, /* int, array, shadow */
|
||||
&builtin_EXT_texture_buffer_object_types[0], /* float */
|
||||
NULL, /* float, shadow */
|
||||
NULL, /* float, array */
|
||||
NULL, /* float, array, shadow */
|
||||
};
|
||||
|
||||
const glsl_type *
|
||||
glsl_type::get_sampler_instance(glsl_sampler_dim dim,
|
||||
bool shadow, bool array,
|
||||
unsigned sample_type)
|
||||
{
|
||||
const glsl_type *const t =
|
||||
sampler_types[SAMPLER_TYPE_INDEX(dim, sample_type, array, shadow)];
|
||||
|
||||
if (t == NULL)
|
||||
return NULL;
|
||||
|
||||
assert(t->base_type == GLSL_TYPE_SAMPLER);
|
||||
assert(t->sampler_dimensionality == dim);
|
||||
assert(t->sampler_shadow == shadow);
|
||||
assert(t->sampler_array == array);
|
||||
assert(t->sampler_type == sample_type);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
const glsl_type *
|
||||
glsl_type::field_type(const char *name) const
|
||||
|
@@ -155,6 +155,9 @@ struct glsl_type {
|
||||
static const glsl_type *const vec3_type;
|
||||
static const glsl_type *const vec4_type;
|
||||
static const glsl_type *const bool_type;
|
||||
static const glsl_type *const bvec2_type;
|
||||
static const glsl_type *const bvec3_type;
|
||||
static const glsl_type *const bvec4_type;
|
||||
static const glsl_type *const mat2_type;
|
||||
static const glsl_type *const mat2x3_type;
|
||||
static const glsl_type *const mat2x4_type;
|
||||
@@ -208,6 +211,13 @@ struct glsl_type {
|
||||
unsigned num_fields,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Get the instance of a sampler type
|
||||
*/
|
||||
static const glsl_type *get_sampler_instance(glsl_sampler_dim dim,
|
||||
bool shadow, bool array,
|
||||
unsigned sample_type);
|
||||
|
||||
/**
|
||||
* Query the total number of scalars that make up a scalar, vector or matrix
|
||||
*/
|
||||
@@ -439,6 +449,13 @@ private:
|
||||
static const glsl_type builtin_EXT_texture_buffer_object_types[];
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Table of sampler types used internally by get_sampler_instance
|
||||
*
|
||||
* \sa glsl_type::get_sampler_instance
|
||||
*/
|
||||
static const glsl_type *const sampler_types[];
|
||||
|
||||
/**
|
||||
* \name Methods to populate a symbol table with built-in types.
|
||||
*
|
||||
|
@@ -432,6 +432,7 @@ static const char *const operator_strs[] = {
|
||||
"dFdx",
|
||||
"dFdy",
|
||||
"noise",
|
||||
"lit",
|
||||
"+",
|
||||
"-",
|
||||
"*",
|
||||
|
@@ -822,10 +822,19 @@ enum ir_expression_operation {
|
||||
|
||||
ir_unop_noise,
|
||||
|
||||
/**
|
||||
* Calculate lighting coefficients
|
||||
*
|
||||
* Like this noise opcode, this opcode really shouldn't exist. The
|
||||
* only reason it exists is to facilitate translation of assembly
|
||||
* shaders to IR.
|
||||
*/
|
||||
ir_unop_lit,
|
||||
|
||||
/**
|
||||
* A sentinel marking the last of the unary operations.
|
||||
*/
|
||||
ir_last_unop = ir_unop_noise,
|
||||
ir_last_unop = ir_unop_lit,
|
||||
|
||||
ir_binop_add,
|
||||
ir_binop_sub,
|
||||
|
@@ -29,12 +29,14 @@
|
||||
*/
|
||||
|
||||
/* Operations for lower_instructions() */
|
||||
#define SUB_TO_ADD_NEG 0x01
|
||||
#define DIV_TO_MUL_RCP 0x02
|
||||
#define EXP_TO_EXP2 0x04
|
||||
#define POW_TO_EXP2 0x08
|
||||
#define LOG_TO_LOG2 0x10
|
||||
#define MOD_TO_FRACT 0x20
|
||||
#define SUB_TO_ADD_NEG (1U << 0)
|
||||
#define DIV_TO_MUL_RCP (1U << 1)
|
||||
#define EXP_TO_EXP2 (1U << 2)
|
||||
#define EXP_TO_POW (1U << 3)
|
||||
#define POW_TO_EXP2 (1U << 4)
|
||||
#define LOG_TO_LOG2 (1U << 5)
|
||||
#define MOD_TO_FRACT (1U << 6)
|
||||
#define LIT_TO_POW_FLAT (1U << 7)
|
||||
|
||||
bool do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations);
|
||||
|
||||
|
@@ -301,6 +301,11 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
assert(ir->operands[0]->type == ir->type);
|
||||
break;
|
||||
|
||||
case ir_unop_lit:
|
||||
assert(ir->type == glsl_type::vec4_type);
|
||||
assert(ir->operands[0]->type == glsl_type::vec4_type);
|
||||
break;
|
||||
|
||||
case ir_unop_noise:
|
||||
/* XXX what can we assert here? */
|
||||
break;
|
||||
|
@@ -33,9 +33,11 @@
|
||||
* - SUB_TO_ADD_NEG
|
||||
* - DIV_TO_MUL_RCP
|
||||
* - EXP_TO_EXP2
|
||||
* - EXP_TO_POW
|
||||
* - POW_TO_EXP2
|
||||
* - LOG_TO_LOG2
|
||||
* - MOD_TO_FRACT
|
||||
* - LIT_TO_POW_FLAT
|
||||
*
|
||||
* SUB_TO_ADD_NEG:
|
||||
* ---------------
|
||||
@@ -62,6 +64,12 @@
|
||||
* do have base 2 versions, so this pass converts exp and log to exp2
|
||||
* and log2 operations.
|
||||
*
|
||||
* EXP_TO_POW:
|
||||
* -----------
|
||||
* Few if any GPUs have an instruction for e**x, but they may have an x**y
|
||||
* instruction. For these GPUs, convert \c ir_unop_exp to a \c ir_binop_pow
|
||||
* with an immediate value of e for the first parameter.
|
||||
*
|
||||
* POW_TO_EXP2:
|
||||
* -----------
|
||||
* Many older GPUs don't have an x**y instruction. For these GPUs, convert
|
||||
@@ -74,6 +82,17 @@
|
||||
* Many GPUs don't have a MOD instruction (945 and 965 included), and
|
||||
* if we have to break it down like this anyway, it gives an
|
||||
* opportunity to do things like constant fold the (1.0 / op1) easily.
|
||||
*
|
||||
* LIT_TO_POW_FLAT:
|
||||
* ----------------
|
||||
* Lower the LIT instruction into a sequence of equivalent instructions.
|
||||
*
|
||||
* New GPUs have removed support for the CISC-like LIT instruction. Instead,
|
||||
* this must be implemented using a sequence of simpler instructions. Even some
|
||||
* older GPUs, such as i915, lack support for a LIT instruction. This version
|
||||
* of the lowering pass lowers \c ir_unop_lit to a sequence of IR that does
|
||||
* \b not include an if-statement. In the future it may be beneficial to add
|
||||
* a version of the lowering pass that generates an if-statement.
|
||||
*/
|
||||
|
||||
#include "main/core.h" /* for M_LOG2E */
|
||||
@@ -97,8 +116,10 @@ private:
|
||||
void div_to_mul_rcp(ir_expression *);
|
||||
void mod_to_fract(ir_expression *);
|
||||
void exp_to_exp2(ir_expression *);
|
||||
void exp_to_pow(ir_expression *);
|
||||
void pow_to_exp2(ir_expression *);
|
||||
void log_to_log2(ir_expression *);
|
||||
void lit_to_pow_flat(ir_expression *ir);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -187,6 +208,15 @@ lower_instructions_visitor::exp_to_exp2(ir_expression *ir)
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::exp_to_pow(ir_expression *ir)
|
||||
{
|
||||
ir->operation = ir_binop_pow;
|
||||
ir->operands[1] = ir->operands[0];
|
||||
ir->operands[0] = new(ir) ir_constant(float(M_E));
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::pow_to_exp2(ir_expression *ir)
|
||||
{
|
||||
@@ -246,10 +276,130 @@ lower_instructions_visitor::mod_to_fract(ir_expression *ir)
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::lit_to_pow_flat(ir_expression *ir)
|
||||
{
|
||||
ir_instruction *inst;
|
||||
|
||||
/* The ARB_vertex_program spec says that LIT does:
|
||||
*
|
||||
* tmp = VectorLoad(op0);
|
||||
* if (tmp.x < 0) tmp.x = 0;
|
||||
* if (tmp.y < 0) tmp.y = 0;
|
||||
* if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
|
||||
* else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
|
||||
* result.x = 1.0;
|
||||
* result.y = tmp.x;
|
||||
* result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
|
||||
* result.w = 1.0;
|
||||
*
|
||||
* This can be lowered to:
|
||||
*
|
||||
* tmp.yzw = max(vec3(0.0, 0.0, -(128.0 - epsilon)), op0.xyw);
|
||||
* tmp.w = min(128.0 - epsilon, tmp.w);
|
||||
* tmp.z = pow(tmp.z, tmp.w);
|
||||
* tmp.xw = vec2(1.0, 1.0);
|
||||
* if (tmp.y <= 0)
|
||||
* tmp.z = 0;
|
||||
*/
|
||||
|
||||
ir_variable *const tmp_var =
|
||||
new(ir) ir_variable(glsl_type::vec4_type, "lit_tmp", ir_var_temporary);
|
||||
this->base_ir->insert_before(tmp_var);
|
||||
|
||||
/* Generate 'tmp.yzw = max(vec3(0.0, 0.0, -(128.0 - epsilon)), op0.xyw);'
|
||||
* The "other" API defined the minimum and maximum values used here as the
|
||||
* values that can be represented in an 8.8 fixed-point value.
|
||||
*/
|
||||
ir_constant_data clamp_data = { { 0 } };
|
||||
clamp_data.f[2] = (float) -(double(0x7fff) / 256.0);
|
||||
|
||||
ir_expression *const max_expr =
|
||||
new(ir) ir_expression(ir_binop_max, glsl_type::vec3_type,
|
||||
new(ir) ir_constant(glsl_type::vec3_type,
|
||||
&clamp_data),
|
||||
new(ir) ir_swizzle(ir->operands[0], 0, 1, 3, 0, 3));
|
||||
inst = new(ir) ir_assignment(new(ir) ir_dereference_variable(tmp_var),
|
||||
max_expr, NULL, 0x0E);
|
||||
this->base_ir->insert_before(inst);
|
||||
|
||||
/* Generate 'tmp.w = min(128.0 - epsilon, tmp.w);'
|
||||
*/
|
||||
ir_rvalue *const tmp_w =
|
||||
new(ir) ir_swizzle(new(ir) ir_dereference_variable(tmp_var),
|
||||
3, 3, 3, 3, 1);
|
||||
ir_expression *const min_expr =
|
||||
new(ir) ir_expression(ir_binop_min, glsl_type::float_type,
|
||||
new(ir) ir_constant(-clamp_data.f[2]),
|
||||
tmp_w);
|
||||
inst = new(ir) ir_assignment(new(ir) ir_dereference_variable(tmp_var),
|
||||
min_expr, NULL, (1U << 3));
|
||||
this->base_ir->insert_before(inst);
|
||||
|
||||
/* Generate 'tmp.z = pow(tmp.z, tmp.w);'
|
||||
*/
|
||||
ir_rvalue *const tmp_z =
|
||||
new(ir) ir_swizzle(new(ir) ir_dereference_variable(tmp_var),
|
||||
2, 2, 2, 2, 1);
|
||||
ir_expression *const pow_expr =
|
||||
new(ir) ir_expression(ir_binop_pow, glsl_type::float_type,
|
||||
tmp_z, tmp_w->clone(ir, NULL));
|
||||
|
||||
inst = new(ir) ir_assignment(new(ir) ir_dereference_variable(tmp_var),
|
||||
pow_expr,
|
||||
NULL,
|
||||
(1U << 2));
|
||||
this->base_ir->insert_before(inst);
|
||||
|
||||
/* Generate 'tmp.xw = vec2(1.0, 1.0);'
|
||||
*/
|
||||
ir_constant_data output_data = { { 0 } };
|
||||
output_data.f[0] = 1.0F;
|
||||
output_data.f[1] = 1.0F;
|
||||
|
||||
inst = new(ir) ir_assignment(new(ir) ir_dereference_variable(tmp_var),
|
||||
new(ir) ir_constant(glsl_type::vec2_type,
|
||||
&output_data),
|
||||
NULL,
|
||||
0x09);
|
||||
this->base_ir->insert_before(inst);
|
||||
|
||||
/* Generate 'if (tmp.y <= 0) tmp.z = 0;'
|
||||
*/
|
||||
ir_rvalue *const tmp_y =
|
||||
new(ir) ir_swizzle(new(ir) ir_dereference_variable(tmp_var),
|
||||
1, 1, 1, 1, 1);
|
||||
ir_expression *const cmp_expr =
|
||||
new(ir) ir_expression(ir_binop_lequal,
|
||||
glsl_type::bool_type,
|
||||
tmp_y,
|
||||
new(ir) ir_constant(0.0F));
|
||||
|
||||
inst = new(ir) ir_assignment(new(ir) ir_dereference_variable(tmp_var),
|
||||
new(ir) ir_constant(0.0F),
|
||||
cmp_expr,
|
||||
(1U << 2));
|
||||
this->base_ir->insert_before(inst);
|
||||
|
||||
/* FINISHME: Convert lower_instructions_visitor to an ir_rvalue_visitor so
|
||||
* FINISHME: that this ugly hack can be removed.
|
||||
*/
|
||||
ir->operation = ir_binop_add;
|
||||
ir->operands[0] = new(ir) ir_dereference_variable(tmp_var);
|
||||
ir->operands[1] = ir_constant::zero(ir, glsl_type::vec4_type);
|
||||
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
lower_instructions_visitor::visit_leave(ir_expression *ir)
|
||||
{
|
||||
switch (ir->operation) {
|
||||
case ir_unop_lit:
|
||||
if (lowering(LIT_TO_POW_FLAT))
|
||||
lit_to_pow_flat(ir);
|
||||
break;
|
||||
|
||||
case ir_binop_sub:
|
||||
if (lowering(SUB_TO_ADD_NEG))
|
||||
sub_to_add_neg(ir);
|
||||
@@ -261,7 +411,9 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
|
||||
break;
|
||||
|
||||
case ir_unop_exp:
|
||||
if (lowering(EXP_TO_EXP2))
|
||||
if (lowering(EXP_TO_POW))
|
||||
exp_to_pow(ir);
|
||||
else if (lowering(EXP_TO_EXP2))
|
||||
exp_to_exp2(ir);
|
||||
break;
|
||||
|
||||
|
@@ -74,10 +74,10 @@ main/api_exec_es1.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py m
|
||||
main/api_exec_es2.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py main/APIspec.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) main/es_generator.py -S main/APIspec.xml -V GLES2.0 > $@
|
||||
|
||||
program/program_parse.tab.c program/program_parse.tab.h: program/program_parse.y
|
||||
bison -v -d --output=program/program_parse.tab.c $<
|
||||
program/program_parse.cpp program/program_parse.tab.h: program/program_parse.y
|
||||
bison -v -o program/program_parse.cpp --defines=program/program_parse.tab.h $<
|
||||
|
||||
program/lex.yy.c: program/program_lexer.l
|
||||
program/program_lexer.cpp: program/program_lexer.l
|
||||
flex --never-interactive --outfile=$@ $<
|
||||
|
||||
######################################################################
|
||||
|
@@ -100,7 +100,8 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
DIV_TO_MUL_RCP |
|
||||
SUB_TO_ADD_NEG |
|
||||
EXP_TO_EXP2 |
|
||||
LOG_TO_LOG2);
|
||||
LOG_TO_LOG2 |
|
||||
LIT_TO_POW_FLAT);
|
||||
|
||||
/* Pre-gen6 HW can only nest if-statements 16 deep. Beyond this,
|
||||
* if-statements need to be flattened.
|
||||
|
@@ -1195,6 +1195,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||
break;
|
||||
}
|
||||
|
||||
case ir_unop_lit:
|
||||
emit(ir, OPCODE_LIT, result_dst, op[0]);
|
||||
break;
|
||||
|
||||
case ir_binop_add:
|
||||
emit(ir, OPCODE_ADD, result_dst, op[0], op[1]);
|
||||
break;
|
||||
|
@@ -21,11 +21,17 @@
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "main/glheader.h"
|
||||
#include "main/imports.h"
|
||||
#include "program/prog_instruction.h"
|
||||
#include "program/prog_statevars.h"
|
||||
#include "program/symbol_table.h"
|
||||
};
|
||||
|
||||
#include "glsl_types.h"
|
||||
#include "ir.h"
|
||||
#include "program/program_parser.h"
|
||||
#include "program/program_parse.tab.h"
|
||||
|
||||
@@ -60,19 +66,34 @@
|
||||
} while (0)
|
||||
|
||||
|
||||
#define return_opcode(condition, token, opcode, len) \
|
||||
#define return_opcode(condition, token, len) \
|
||||
do { \
|
||||
if (condition && \
|
||||
_mesa_parse_instruction_suffix(yyextra, \
|
||||
yytext + len, \
|
||||
& yylval->temp_inst)) { \
|
||||
yylval->temp_inst.Opcode = OPCODE_ ## opcode; \
|
||||
& yylval->opcode)) { \
|
||||
yylval->opcode.opcode = 0; \
|
||||
return token; \
|
||||
} else { \
|
||||
return handle_ident(yyextra, yytext, yylval); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define return_common(condition, token, _opcode, len) \
|
||||
do { \
|
||||
if (condition && \
|
||||
_mesa_parse_instruction_suffix(yyextra, \
|
||||
yytext + len, \
|
||||
& yylval->opcode)) { \
|
||||
yylval->opcode.opcode = _opcode; \
|
||||
return token; \
|
||||
} else { \
|
||||
return handle_ident(yyextra, yytext, yylval); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
|
||||
SWIZZLE_NIL, SWIZZLE_NIL)
|
||||
|
||||
@@ -182,74 +203,76 @@ OUTPUT { return OUTPUT; }
|
||||
PARAM { return PARAM; }
|
||||
TEMP { yylval->integer = at_temp; return TEMP; }
|
||||
|
||||
ABS{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, ABS, 3); }
|
||||
ADD{sz}{cc}{sat} { return_opcode( 1, BIN_OP, ADD, 3); }
|
||||
ARL { return_opcode(require_ARB_vp, ARL, ARL, 3); }
|
||||
ABS{sz}{cc}{sat} { return_common( true, VECTOR_OP, ir_unop_abs, 3); }
|
||||
ADD{sz}{cc}{sat} { return_common( true, BIN_OP, ir_binop_add, 3); }
|
||||
ARL { return_opcode(require_ARB_vp, ARL, 3); }
|
||||
|
||||
CMP{sat} { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); }
|
||||
COS{szf}{cc}{sat} { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); }
|
||||
CMP{sat} { return_opcode(require_ARB_fp, CMP_OP, 3); }
|
||||
COS{szf}{cc}{sat} { return_common(require_ARB_fp, SCALAR_OP, ir_unop_cos, 3); }
|
||||
|
||||
DDX{szf}{cc}{sat} { return_opcode(require_NV_fp, VECTOR_OP, DDX, 3); }
|
||||
DDY{szf}{cc}{sat} { return_opcode(require_NV_fp, VECTOR_OP, DDY, 3); }
|
||||
DP3{sz}{cc}{sat} { return_opcode( 1, BIN_OP, DP3, 3); }
|
||||
DP4{sz}{cc}{sat} { return_opcode( 1, BIN_OP, DP4, 3); }
|
||||
DPH{sz}{cc}{sat} { return_opcode( 1, BIN_OP, DPH, 3); }
|
||||
DST{szf}{cc}{sat} { return_opcode( 1, BIN_OP, DST, 3); }
|
||||
DDX{szf}{cc}{sat} { return_common(require_NV_fp, VECTOR_OP, ir_unop_dFdx, 3); }
|
||||
DDY{szf}{cc}{sat} { return_common(require_NV_fp, VECTOR_OP, ir_unop_dFdy, 3); }
|
||||
DP3{sz}{cc}{sat} { return_opcode( true, DP3_OP, 3); }
|
||||
DP4{sz}{cc}{sat} { return_opcode( true, DP4_OP, 3); }
|
||||
DPH{sz}{cc}{sat} { return_opcode( true, DPH_OP, 3); }
|
||||
DST{szf}{cc}{sat} { return_opcode( true, DST_OP, 3); }
|
||||
|
||||
EX2{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, EX2, 3); }
|
||||
EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); }
|
||||
EX2{szf}{cc}{sat} { return_common( true, SCALAR_OP, ir_unop_exp, 3); }
|
||||
/* FINISHME: Somehow communicate that this is the low precision version. */
|
||||
EXP { return_common(require_ARB_vp, SCALAR_OP, ir_unop_exp, 3); }
|
||||
|
||||
FLR{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, FLR, 3); }
|
||||
FRC{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, FRC, 3); }
|
||||
FLR{sz}{cc}{sat} { return_common( true, VECTOR_OP, ir_unop_floor, 3); }
|
||||
FRC{sz}{cc}{sat} { return_common( true, VECTOR_OP, ir_unop_fract, 3); }
|
||||
|
||||
KIL { return_opcode(require_ARB_fp, KIL, KIL, 3); }
|
||||
KIL { return_opcode(require_ARB_fp, KIL, 3); }
|
||||
|
||||
LIT{szf}{cc}{sat} { return_opcode( 1, VECTOR_OP, LIT, 3); }
|
||||
LG2{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, LG2, 3); }
|
||||
LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); }
|
||||
LRP{sz}{cc}{sat} { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); }
|
||||
LIT{szf}{cc}{sat} { return_common( true, VECTOR_OP, ir_unop_lit, 3); }
|
||||
LG2{szf}{cc}{sat} { return_common( true, SCALAR_OP, ir_unop_log, 3); }
|
||||
/* FINISHME: Somehow communicate that this is the low precision version. */
|
||||
LOG { return_common(require_ARB_vp, SCALAR_OP, ir_unop_log, 3); }
|
||||
LRP{sz}{cc}{sat} { return_opcode(require_ARB_fp, LRP_OP, 3); }
|
||||
|
||||
MAD{sz}{cc}{sat} { return_opcode( 1, TRI_OP, MAD, 3); }
|
||||
MAX{sz}{cc}{sat} { return_opcode( 1, BIN_OP, MAX, 3); }
|
||||
MIN{sz}{cc}{sat} { return_opcode( 1, BIN_OP, MIN, 3); }
|
||||
MOV{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, MOV, 3); }
|
||||
MUL{sz}{cc}{sat} { return_opcode( 1, BIN_OP, MUL, 3); }
|
||||
MAD{sz}{cc}{sat} { return_common( true, MAD_OP, ir_binop_mul, 3); }
|
||||
MAX{sz}{cc}{sat} { return_common( true, BIN_OP, ir_binop_max, 3); }
|
||||
MIN{sz}{cc}{sat} { return_common( true, BIN_OP, ir_binop_min, 3); }
|
||||
MOV{sz}{cc}{sat} { return_common( true, MOV_OP, ir_binop_add, 3); }
|
||||
MUL{sz}{cc}{sat} { return_common( true, BIN_OP, ir_binop_mul, 3); }
|
||||
|
||||
PK2H { return_opcode(require_NV_fp, VECTOR_OP, PK2H, 4); }
|
||||
PK2US { return_opcode(require_NV_fp, VECTOR_OP, PK2US, 5); }
|
||||
PK4B { return_opcode(require_NV_fp, VECTOR_OP, PK4B, 4); }
|
||||
PK4UB { return_opcode(require_NV_fp, VECTOR_OP, PK4UB, 5); }
|
||||
POW{szf}{cc}{sat} { return_opcode( 1, BINSC_OP, POW, 3); }
|
||||
PK2H { return_opcode(require_NV_fp, PACK_OP, 4); }
|
||||
PK2US { return_opcode(require_NV_fp, PACK_OP, 5); }
|
||||
PK4B { return_opcode(require_NV_fp, PACK_OP, 4); }
|
||||
PK4UB { return_opcode(require_NV_fp, PACK_OP, 5); }
|
||||
POW{szf}{cc}{sat} { return_common( true, BINSC_OP, ir_binop_pow, 3); }
|
||||
|
||||
RCP{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, RCP, 3); }
|
||||
RFL{szf}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, RFL, 3); }
|
||||
RSQ{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, RSQ, 3); }
|
||||
RCP{szf}{cc}{sat} { return_common( true, SCALAR_OP, ir_unop_rcp, 3); }
|
||||
RFL{szf}{cc}{sat} { return_opcode(require_NV_fp, RFL_OP, 3); }
|
||||
RSQ{szf}{cc}{sat} { return_common( true, SCALAR_OP, ir_unop_rsq, 3); }
|
||||
|
||||
SCS{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); }
|
||||
SEQ{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SEQ, 3); }
|
||||
SFL{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SFL, 3); }
|
||||
SGE{sz}{cc}{sat} { return_opcode( 1, BIN_OP, SGE, 3); }
|
||||
SGT{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SGT, 3); }
|
||||
SIN{szf}{cc}{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); }
|
||||
SLE{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SLE, 3); }
|
||||
SLT{sz}{cc}{sat} { return_opcode( 1, BIN_OP, SLT, 3); }
|
||||
SNE{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SNE, 3); }
|
||||
STR{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, STR, 3); }
|
||||
SUB{sz}{cc}{sat} { return_opcode( 1, BIN_OP, SUB, 3); }
|
||||
SWZ{sat} { return_opcode( 1, SWZ, SWZ, 3); }
|
||||
SCS{sat} { return_opcode(require_ARB_fp, SCS_OP, 3); }
|
||||
SEQ{sz}{cc}{sat} { return_common(require_NV_fp, SET_OP, ir_binop_equal, 3); }
|
||||
SFL{sz}{cc}{sat} { return_opcode(require_NV_fp, SFL_OP, 3); }
|
||||
SGE{sz}{cc}{sat} { return_common( true, SET_OP, ir_binop_gequal, 3); }
|
||||
SGT{sz}{cc}{sat} { return_common(require_NV_fp, SET_OP, ir_binop_greater, 3); }
|
||||
SIN{szf}{cc}{sat} { return_common(require_ARB_fp, SCALAR_OP, ir_unop_sin, 3); }
|
||||
SLE{sz}{cc}{sat} { return_common(require_NV_fp, SET_OP, ir_binop_lequal, 3); }
|
||||
SLT{sz}{cc}{sat} { return_common( true, SET_OP, ir_binop_less, 3); }
|
||||
SNE{sz}{cc}{sat} { return_common(require_NV_fp, SET_OP, ir_binop_nequal, 3); }
|
||||
STR{sz}{cc}{sat} { return_opcode(require_NV_fp, STR_OP, 3); }
|
||||
SUB{sz}{cc}{sat} { return_common( true, BIN_OP, ir_binop_sub, 3); }
|
||||
SWZ{sat} { return_opcode( true, SWZ_OP, 3); }
|
||||
|
||||
TEX{cc}{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); }
|
||||
TXB{cc}{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); }
|
||||
TXD{cc}{sat} { return_opcode(require_NV_fp, TXD_OP, TXD, 3); }
|
||||
TXP{cc}{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); }
|
||||
TEX{cc}{sat} { return_opcode(require_ARB_fp, TEX_OP, 3); }
|
||||
TXB{cc}{sat} { return_opcode(require_ARB_fp, TXB_OP, 3); }
|
||||
TXD{cc}{sat} { return_opcode(require_NV_fp, TXD_OP, 3); }
|
||||
TXP{cc}{sat} { return_opcode(require_ARB_fp, TXP_OP, 3); }
|
||||
|
||||
UP2H{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP2H, 4); }
|
||||
UP2US{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP2US, 5); }
|
||||
UP4B{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP4B, 4); }
|
||||
UP4UB{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP4UB, 5); }
|
||||
UP2H{cc}{sat} { return_opcode(require_NV_fp, UNPACK_OP, 4); }
|
||||
UP2US{cc}{sat} { return_opcode(require_NV_fp, UNPACK_OP, 5); }
|
||||
UP4B{cc}{sat} { return_opcode(require_NV_fp, UNPACK_OP, 4); }
|
||||
UP4UB{cc}{sat} { return_opcode(require_NV_fp, UNPACK_OP, 5); }
|
||||
|
||||
X2D{szf}{cc}{sat} { return_opcode(require_NV_fp, TRI_OP, X2D, 3); }
|
||||
XPD{sat} { return_opcode( 1, BIN_OP, XPD, 3); }
|
||||
X2D{szf}{cc}{sat} { return_opcode(require_NV_fp, X2D_OP, 3); }
|
||||
XPD{sat} { return_opcode( true, XPD_OP, 3); }
|
||||
|
||||
vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
|
||||
fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -36,12 +36,12 @@
|
||||
int
|
||||
_mesa_parse_instruction_suffix(const struct asm_parser_state *state,
|
||||
const char *suffix,
|
||||
struct prog_instruction *inst)
|
||||
struct asm_opcode *inst)
|
||||
{
|
||||
inst->CondUpdate = 0;
|
||||
inst->CondDst = 0;
|
||||
inst->SaturateMode = SATURATE_OFF;
|
||||
inst->Precision = FLOAT32;
|
||||
inst->cond_update = 0;
|
||||
inst->cond_dst = 0;
|
||||
inst->saturate_mode = SATURATE_OFF;
|
||||
inst->precision = FLOAT32;
|
||||
|
||||
|
||||
/* The first possible suffix element is the precision specifier from
|
||||
@@ -50,15 +50,15 @@ _mesa_parse_instruction_suffix(const struct asm_parser_state *state,
|
||||
if (state->option.NV_fragment) {
|
||||
switch (suffix[0]) {
|
||||
case 'H':
|
||||
inst->Precision = FLOAT16;
|
||||
inst->precision = FLOAT16;
|
||||
suffix++;
|
||||
break;
|
||||
case 'R':
|
||||
inst->Precision = FLOAT32;
|
||||
inst->precision = FLOAT32;
|
||||
suffix++;
|
||||
break;
|
||||
case 'X':
|
||||
inst->Precision = FIXED12;
|
||||
inst->precision = FIXED12;
|
||||
suffix++;
|
||||
break;
|
||||
default:
|
||||
@@ -71,7 +71,7 @@ _mesa_parse_instruction_suffix(const struct asm_parser_state *state,
|
||||
*/
|
||||
if (state->option.NV_fragment) {
|
||||
if (suffix[0] == 'C') {
|
||||
inst->CondUpdate = 1;
|
||||
inst->cond_update = 1;
|
||||
suffix++;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ _mesa_parse_instruction_suffix(const struct asm_parser_state *state,
|
||||
*/
|
||||
if (state->mode == ARB_fragment) {
|
||||
if (strcmp(suffix, "_SAT") == 0) {
|
||||
inst->SaturateMode = SATURATE_ZERO_ONE;
|
||||
inst->saturate_mode = SATURATE_ZERO_ONE;
|
||||
suffix += 4;
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,10 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "main/config.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "list.h"
|
||||
|
||||
struct gl_context;
|
||||
|
||||
@@ -45,7 +48,7 @@ struct asm_symbol {
|
||||
/**
|
||||
* One of PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM, or PROGRAM_ENV_PARAM.
|
||||
*/
|
||||
unsigned param_binding_type;
|
||||
gl_register_file param_binding_type;
|
||||
|
||||
/**
|
||||
* Offset into the program_parameter_list where the tokens representing our
|
||||
@@ -120,6 +123,60 @@ struct asm_src_register {
|
||||
};
|
||||
|
||||
|
||||
struct asm_opcode {
|
||||
/**
|
||||
* This should be 'enum ir_expression_operation', but it can't be. This
|
||||
* file is included in C source, and the enum comes from a C++ header. The
|
||||
* rules for enums in C and C++ are so broken that you can't declare an
|
||||
* enum varaible without having seen the full enum declaration. Even after
|
||||
* seeing it, the compiler is just going to allocate an int, so WTF?
|
||||
*/
|
||||
unsigned opcode;
|
||||
|
||||
/**
|
||||
* Indicates that the instruction should update the condition code
|
||||
* register.
|
||||
*
|
||||
* \since
|
||||
* NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
|
||||
* NV_vertex_program2_option.
|
||||
*/
|
||||
unsigned cond_update:1;
|
||||
|
||||
/**
|
||||
* If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the
|
||||
* condition code register that is to be updated.
|
||||
*
|
||||
* In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition
|
||||
* code register 0 is available. In GL_NV_vertex_program3 mode, condition
|
||||
* code registers 0 and 1 are available.
|
||||
*
|
||||
* \since
|
||||
* NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
|
||||
* NV_vertex_program2_option.
|
||||
*/
|
||||
unsigned cond_dst:1;
|
||||
|
||||
/**
|
||||
* Saturate each value of the vectored result to the range [0,1] or the
|
||||
* range [-1,1]. \c SSAT mode (i.e., saturation to the range [-1,1]) is
|
||||
* only available in NV_fragment_program2 mode.
|
||||
* Value is one of the SATURATE_* tokens.
|
||||
*
|
||||
* \since
|
||||
* NV_fragment_program, NV_fragment_program_option, NV_vertex_program3.
|
||||
*/
|
||||
unsigned saturate_mode:2;
|
||||
|
||||
/**
|
||||
* Per-instruction selectable precision: FLOAT32, FLOAT16, FIXED12.
|
||||
*
|
||||
* \since
|
||||
* NV_fragment_program, NV_fragment_program_option.
|
||||
*/
|
||||
unsigned precision:3;
|
||||
};
|
||||
|
||||
struct asm_instruction {
|
||||
struct prog_instruction Base;
|
||||
struct asm_instruction *next;
|
||||
@@ -127,9 +184,16 @@ struct asm_instruction {
|
||||
};
|
||||
|
||||
|
||||
enum asm_program_target {
|
||||
invalid_mode = 0,
|
||||
ARB_vertex,
|
||||
ARB_fragment
|
||||
};
|
||||
|
||||
struct asm_parser_state {
|
||||
struct gl_context *ctx;
|
||||
struct gl_program *prog;
|
||||
struct exec_list ir;
|
||||
|
||||
/**
|
||||
* Per-program target limits
|
||||
@@ -191,11 +255,7 @@ struct asm_parser_state {
|
||||
*/
|
||||
unsigned InputsBound;
|
||||
|
||||
enum {
|
||||
invalid_mode = 0,
|
||||
ARB_vertex,
|
||||
ARB_fragment
|
||||
} mode;
|
||||
enum asm_program_target mode;
|
||||
|
||||
struct {
|
||||
unsigned PositionInvariant:1;
|
||||
@@ -233,6 +293,9 @@ typedef struct YYLTYPE {
|
||||
#define YYLTYPE_IS_DECLARED 1
|
||||
#define YYLTYPE_IS_TRIVIAL 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern GLboolean _mesa_parse_arb_program(struct gl_context *ctx, GLenum target,
|
||||
const GLubyte *str, GLsizei len, struct asm_parser_state *state);
|
||||
@@ -281,7 +344,7 @@ extern int _mesa_ARBfp_parse_option(struct asm_parser_state *state,
|
||||
* Non-zero on success, zero on failure.
|
||||
*/
|
||||
extern int _mesa_parse_instruction_suffix(const struct asm_parser_state *state,
|
||||
const char *suffix, struct prog_instruction *inst);
|
||||
const char *suffix, struct asm_opcode *inst);
|
||||
|
||||
/**
|
||||
* Parses a condition code name
|
||||
@@ -296,4 +359,8 @@ extern int _mesa_parse_instruction_suffix(const struct asm_parser_state *state,
|
||||
*/
|
||||
extern int _mesa_parse_cc(const char *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
@@ -240,11 +240,9 @@ STATETRACKER_SOURCES = \
|
||||
PROGRAM_SOURCES = \
|
||||
program/arbprogparse.c \
|
||||
program/hash_table.c \
|
||||
program/lex.yy.c \
|
||||
program/nvfragparse.c \
|
||||
program/nvvertparse.c \
|
||||
program/program.c \
|
||||
program/program_parse.tab.c \
|
||||
program/program_parse_extra.c \
|
||||
program/prog_cache.c \
|
||||
program/prog_execute.c \
|
||||
@@ -262,6 +260,8 @@ PROGRAM_SOURCES = \
|
||||
|
||||
|
||||
SHADER_CXX_SOURCES = \
|
||||
program/program_lexer.cpp \
|
||||
program/program_parse.cpp \
|
||||
program/ir_to_mesa.cpp \
|
||||
program/sampler.cpp
|
||||
|
||||
|
Reference in New Issue
Block a user