#include "main/compiler.h"
#include "ir.h"
#include "ir_visitor.h"
-#include "ir_print_visitor.h"
#include "ir_expression_flattening.h"
#include "ir_uniform.h"
#include "glsl_types.h"
#include "main/mtypes.h"
#include "main/shaderobj.h"
+#include "main/uniforms.h"
#include "program/hash_table.h"
extern "C" {
#include "main/shaderapi.h"
-#include "main/uniforms.h"
#include "program/prog_instruction.h"
#include "program/prog_optimize.h"
#include "program/prog_print.h"
#include "program/sampler.h"
}
+static int swizzle_for_size(int size);
+
+namespace {
+
class src_reg;
class dst_reg;
-static int swizzle_for_size(int size);
-
/**
* This struct is a corresponding struct to Mesa prog_src_register, with
* wider fields.
explicit src_reg(dst_reg reg);
gl_register_file file; /**< PROGRAM_* from Mesa */
- int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ int index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */
GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
int negate; /**< NEGATE_XYZW mask from mesa */
/** Register index should be offset by the integer in this reg. */
explicit dst_reg(src_reg reg);
gl_register_file file; /**< PROGRAM_* from Mesa */
- int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+ int index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */
int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
GLuint cond_mask:4;
/** Register index should be offset by the integer in this reg. */
src_reg *reladdr;
};
+} /* anonymous namespace */
+
src_reg::src_reg(dst_reg reg)
{
this->file = reg.file;
this->reladdr = reg.reladdr;
}
+namespace {
+
class ir_to_mesa_instruction : public exec_node {
public:
- /* Callers of this ralloc-based new need not call delete. It's
- * easier to just ralloc_free 'ctx' (or any of its ancestors). */
- static void* operator new(size_t size, void *ctx)
- {
- void *node;
-
- node = rzalloc_size(ctx, size);
- assert(node != NULL);
-
- return node;
- }
+ DECLARE_RALLOC_CXX_OPERATORS(ir_to_mesa_instruction)
enum prog_opcode op;
dst_reg dst;
virtual void visit(ir_discard *);
virtual void visit(ir_texture *);
virtual void visit(ir_if *);
+ virtual void visit(ir_emit_vertex *);
+ virtual void visit(ir_end_primitive *);
/*@}*/
src_reg result;
void *mem_ctx;
};
+} /* anonymous namespace */
+
static src_reg undef_src = src_reg(PROGRAM_UNDEFINED, 0, NULL);
static dst_reg undef_dst = dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP);
* at link time.
*/
return 1;
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
+ case GLSL_TYPE_INTERFACE:
assert(!"Invalid type in type_size");
break;
}
const ir_function_signature *sig;
exec_list empty;
- sig = ir->matching_signature(&empty);
+ sig = ir->matching_signature(NULL, &empty);
assert(sig);
this->result.file = PROGRAM_UNDEFINED;
deref->accept(this);
if (this->result.file == PROGRAM_UNDEFINED) {
- ir_print_visitor v;
printf("Failed to get tree for expression operand:\n");
- deref->accept(&v);
+ deref->print();
+ printf("\n");
exit(1);
}
this->result.file = PROGRAM_UNDEFINED;
ir->operands[operand]->accept(this);
if (this->result.file == PROGRAM_UNDEFINED) {
- ir_print_visitor v;
printf("Failed to get tree for expression operand:\n");
- ir->operands[operand]->accept(&v);
+ ir->operands[operand]->print();
+ printf("\n");
exit(1);
}
op[operand] = this->result;
emit(ir, OPCODE_FRC, result_dst, op[0]);
break;
case ir_unop_pack_snorm_2x16:
+ case ir_unop_pack_snorm_4x8:
case ir_unop_pack_unorm_2x16:
+ case ir_unop_pack_unorm_4x8:
case ir_unop_pack_half_2x16:
case ir_unop_unpack_snorm_2x16:
+ case ir_unop_unpack_snorm_4x8:
case ir_unop_unpack_unorm_2x16:
+ case ir_unop_unpack_unorm_4x8:
case ir_unop_unpack_half_2x16:
case ir_unop_unpack_half_2x16_split_x:
case ir_unop_unpack_half_2x16_split_y:
case ir_binop_pack_half_2x16_split:
+ case ir_unop_bitfield_reverse:
+ case ir_unop_bit_count:
+ case ir_unop_find_msb:
+ case ir_unop_find_lsb:
assert(!"not supported");
break;
case ir_binop_min:
assert(!"not supported");
break;
+ case ir_triop_lrp:
+ /* ir_triop_lrp operands are (x, y, a) while
+ * OPCODE_LRP operands are (a, y, x) to match ARB_fragment_program.
+ */
+ emit(ir, OPCODE_LRP, result_dst, op[2], op[1], op[0]);
+ break;
+
+ case ir_binop_vector_extract:
+ case ir_binop_bfm:
+ case ir_triop_fma:
+ case ir_triop_bfi:
+ case ir_triop_bitfield_extract:
+ case ir_triop_vector_insert:
+ case ir_quadop_bitfield_insert:
+ case ir_binop_ldexp:
+ case ir_triop_csel:
+ case ir_binop_carry:
+ case ir_binop_borrow:
+ case ir_binop_imul_high:
+ assert(!"not supported");
+ break;
+
case ir_quadop_vector:
/* This operation should have already been handled.
*/
ir->lod_info.grad.dPdy->accept(this);
dy = this->result;
break;
+ case ir_txf_ms:
+ assert(!"Unexpected ir_txf_ms opcode");
+ break;
+ case ir_lod:
+ assert(!"Unexpected ir_lod opcode");
+ break;
+ case ir_tg4:
+ assert(!"Unexpected ir_tg4 opcode");
+ break;
+ case ir_query_levels:
+ assert(!"Unexpected ir_query_levels opcode");
+ break;
}
const glsl_type *sampler_type = ir->sampler->type;
visit_exec_list(&ir->else_instructions, this);
}
- if_inst = emit(ir->condition, OPCODE_ENDIF);
+ emit(ir->condition, OPCODE_ENDIF);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_emit_vertex *ir)
+{
+ assert(!"Geometry shaders not supported.");
+}
+
+void
+ir_to_mesa_visitor::visit(ir_end_primitive *ir)
+{
+ assert(!"Geometry shaders not supported.");
}
ir_to_mesa_visitor::ir_to_mesa_visitor()
}
}
-class add_uniform_to_shader : public uniform_field_visitor {
+namespace {
+
+class add_uniform_to_shader : public program_resource_visitor {
public:
add_uniform_to_shader(struct gl_shader_program *shader_program,
- struct gl_program_parameter_list *params)
- : shader_program(shader_program), params(params), idx(-1)
+ struct gl_program_parameter_list *params,
+ gl_shader_type shader_type)
+ : shader_program(shader_program), params(params), idx(-1),
+ shader_type(shader_type)
{
/* empty */
}
void process(ir_variable *var)
{
this->idx = -1;
- this->uniform_field_visitor::process(var);
+ this->program_resource_visitor::process(var);
var->location = this->idx;
}
private:
- virtual void visit_field(const glsl_type *type, const char *name);
+ virtual void visit_field(const glsl_type *type, const char *name,
+ bool row_major);
struct gl_shader_program *shader_program;
struct gl_program_parameter_list *params;
int idx;
+ gl_shader_type shader_type;
};
+} /* anonymous namespace */
+
void
-add_uniform_to_shader::visit_field(const glsl_type *type, const char *name)
+add_uniform_to_shader::visit_field(const glsl_type *type, const char *name,
+ bool row_major)
{
unsigned int size;
+ (void) row_major;
+
if (type->is_vector() || type->is_scalar()) {
size = type->vector_elements;
} else {
struct gl_uniform_storage *storage =
&this->shader_program->UniformStorage[location];
+ assert(storage->sampler[shader_type].active);
+
for (unsigned int j = 0; j < size / 4; j++)
- params->ParameterValues[index + j][0].f = storage->sampler + j;
+ params->ParameterValues[index + j][0].f =
+ storage->sampler[shader_type].index + j;
}
}
struct gl_program_parameter_list
*params)
{
- add_uniform_to_shader add(shader_program, params);
+ add_uniform_to_shader add(shader_program, params,
+ _mesa_shader_type_to_index(sh->Type));
foreach_list(node, sh->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
if ((var == NULL) || (var->mode != ir_var_uniform)
- || var->uniform_block != -1 || (strncmp(var->name, "gl_", 3) == 0))
+ || var->is_in_uniform_block() || (strncmp(var->name, "gl_", 3) == 0))
continue;
add.process(var);
format = uniform_native;
columns = 1;
break;
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_ARRAY:
case GLSL_TYPE_VOID:
case GLSL_TYPE_STRUCT:
case GLSL_TYPE_ERROR:
+ case GLSL_TYPE_INTERFACE:
assert(!"Should not get here.");
break;
}
/* If this is a copy, add it to the ACP. */
if (inst->op == OPCODE_MOV &&
inst->dst.file == PROGRAM_TEMPORARY &&
+ !(inst->dst.file == inst->src[0].file &&
+ inst->dst.index == inst->src[0].index) &&
!inst->dst.reladdr &&
!inst->saturate &&
!inst->src[0].reladdr &&
int i;
struct gl_program *prog;
GLenum target;
- const char *target_string;
+ const char *target_string = _mesa_glsl_shader_target_name(shader->Type);
struct gl_shader_compiler_options *options =
&ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader->Type)];
switch (shader->Type) {
case GL_VERTEX_SHADER:
target = GL_VERTEX_PROGRAM_ARB;
- target_string = "vertex";
break;
case GL_FRAGMENT_SHADER:
target = GL_FRAGMENT_PROGRAM_ARB;
- target_string = "fragment";
break;
case GL_GEOMETRY_SHADER:
target = GL_GEOMETRY_PROGRAM_NV;
- target_string = "geometry";
break;
default:
assert(!"should not be reached");
*/
mesa_instructions = NULL;
- do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER);
+ do_set_program_inouts(shader->ir, prog, shader->Type);
prog->SamplersUsed = shader->active_samplers;
prog->ShadowSamplers = shader->shadow_samplers;
progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
progress = do_common_optimization(ir, true, true,
- options->MaxUnrollIterations)
+ options->MaxUnrollIterations,
+ options)
|| progress;
progress = lower_quadop_vector(ir, true) || progress;
|| progress;
progress = do_vec_index_to_cond_assign(ir) || progress;
+ progress = lower_vector_insert(ir, true) || progress;
} while (progress);
validate_ir_tree(ir);
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
if (linked_prog) {
- static const GLenum targets[] = {
- GL_VERTEX_PROGRAM_ARB,
- GL_FRAGMENT_PROGRAM_ARB,
- GL_GEOMETRY_PROGRAM_NV
- };
-
- if (i == MESA_SHADER_VERTEX) {
- ((struct gl_vertex_program *)linked_prog)->UsesClipDistance
- = prog->Vert.UsesClipDistance;
- }
+ _mesa_copy_linked_program_data((gl_shader_type) i, prog, linked_prog);
_mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program,
linked_prog);
- if (!ctx->Driver.ProgramStringNotify(ctx, targets[i], linked_prog)) {
+ if (!ctx->Driver.ProgramStringNotify(ctx,
+ _mesa_program_index_to_target(i),
+ linked_prog)) {
return GL_FALSE;
}
}
return prog->LinkStatus;
}
-
-/**
- * Compile a GLSL shader. Called via glCompileShader().
- */
-void
-_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
-{
- struct _mesa_glsl_parse_state *state =
- new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
-
- const char *source = shader->Source;
- /* Check if the user called glCompileShader without first calling
- * glShaderSource. This should fail to compile, but not raise a GL_ERROR.
- */
- if (source == NULL) {
- shader->CompileStatus = GL_FALSE;
- return;
- }
-
- state->error = glcpp_preprocess(state, &source, &state->info_log,
- &ctx->Extensions, ctx);
-
- if (ctx->Shader.Flags & GLSL_DUMP) {
- printf("GLSL source for %s shader %d:\n",
- _mesa_glsl_shader_target_name(state->target), shader->Name);
- printf("%s\n", shader->Source);
- }
-
- if (!state->error) {
- _mesa_glsl_lexer_ctor(state, source);
- _mesa_glsl_parse(state);
- _mesa_glsl_lexer_dtor(state);
- }
-
- ralloc_free(shader->ir);
- shader->ir = new(shader) exec_list;
- if (!state->error && !state->translation_unit.is_empty())
- _mesa_ast_to_hir(shader->ir, state);
-
- if (!state->error && !shader->ir->is_empty()) {
- validate_ir_tree(shader->ir);
-
- /* Do some optimization at compile time to reduce shader IR size
- * and reduce later work if the same shader is linked multiple times
- */
- while (do_common_optimization(shader->ir, false, false, 32))
- ;
-
- validate_ir_tree(shader->ir);
- }
-
- shader->symbols = state->symbols;
-
- shader->CompileStatus = !state->error;
- shader->InfoLog = state->info_log;
- shader->Version = state->language_version;
- memcpy(shader->builtins_to_link, state->builtins_to_link,
- sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
- shader->num_builtins_to_link = state->num_builtins_to_link;
-
- if (ctx->Shader.Flags & GLSL_LOG) {
- _mesa_write_shader_to_file(shader);
- }
-
- if (ctx->Shader.Flags & GLSL_DUMP) {
- if (shader->CompileStatus) {
- printf("GLSL IR for shader %d:\n", shader->Name);
- _mesa_print_ir(shader->ir, NULL);
- printf("\n\n");
- } else {
- printf("GLSL shader %d failed to compile.\n", shader->Name);
- }
- if (shader->InfoLog && shader->InfoLog[0] != 0) {
- printf("GLSL shader %d info log:\n", shader->Name);
- printf("%s\n", shader->InfoLog);
- }
- }
-
- if (shader->UniformBlocks)
- ralloc_free(shader->UniformBlocks);
- shader->NumUniformBlocks = state->num_uniform_blocks;
- shader->UniformBlocks = state->uniform_blocks;
- ralloc_steal(shader, shader->UniformBlocks);
-
- /* Retain any live IR, but trash the rest. */
- reparent_ir(shader->ir, shader->ir);
-
- ralloc_free(state);
-}
-
-
/**
* Link a GLSL shader program. Called via glLinkProgram().
*/
for (i = 0; i < prog->NumShaders; i++) {
if (!prog->Shaders[i]->CompileStatus) {
linker_error(prog, "linking with uncompiled shader");
- prog->LinkStatus = GL_FALSE;
}
}