2010-03-10 13:58:12 -08:00
|
|
|
/* -*- c++ -*- */
|
2010-02-22 13:19:34 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2010 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* 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 (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2010-03-15 15:20:15 -07:00
|
|
|
#pragma once
|
|
|
|
|
#ifndef IR_H
|
|
|
|
|
#define IR_H
|
|
|
|
|
|
2011-02-10 10:26:42 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2010-06-22 10:38:52 -07:00
|
|
|
|
2011-01-21 14:32:31 -08:00
|
|
|
#include "ralloc.h"
|
2010-11-16 12:01:42 -08:00
|
|
|
#include "glsl_types.h"
|
2010-03-08 23:44:00 -08:00
|
|
|
#include "list.h"
|
2010-03-09 16:23:37 -08:00
|
|
|
#include "ir_visitor.h"
|
2010-05-14 12:39:23 -07:00
|
|
|
#include "ir_hierarchical_visitor.h"
|
2011-10-25 18:06:37 -07:00
|
|
|
#include "main/mtypes.h"
|
2010-03-08 23:44:00 -08:00
|
|
|
|
2013-03-22 13:29:55 -07:00
|
|
|
#ifdef __cplusplus
|
|
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* \defgroup IR Intermediate representation nodes
|
|
|
|
|
*
|
|
|
|
|
* @{
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Class tags
|
|
|
|
|
*
|
|
|
|
|
* Each concrete class derived from \c ir_instruction has a value in this
|
|
|
|
|
* enumerant. The value for the type is stored in \c ir_instruction::ir_type
|
|
|
|
|
* by the constructor. While using type tags is not very C++, it is extremely
|
|
|
|
|
* convenient. For example, during debugging you can simply inspect
|
|
|
|
|
* \c ir_instruction::ir_type to find out the actual type of the object.
|
|
|
|
|
*
|
|
|
|
|
* In addition, it is possible to use a switch-statement based on \c
|
|
|
|
|
* \c ir_instruction::ir_type to select different behavior for different object
|
|
|
|
|
* types. For functions that have only slight differences for several object
|
|
|
|
|
* types, this allows writing very straightforward, readable code.
|
|
|
|
|
*/
|
2010-07-19 09:05:42 -07:00
|
|
|
enum ir_node_type {
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Zero is unused so that the IR validator can detect cases where
|
|
|
|
|
* \c ir_instruction::ir_type has not been initialized.
|
|
|
|
|
*/
|
2010-07-19 09:05:42 -07:00
|
|
|
ir_type_unset,
|
|
|
|
|
ir_type_variable,
|
|
|
|
|
ir_type_assignment,
|
|
|
|
|
ir_type_call,
|
|
|
|
|
ir_type_constant,
|
|
|
|
|
ir_type_dereference_array,
|
|
|
|
|
ir_type_dereference_record,
|
|
|
|
|
ir_type_dereference_variable,
|
|
|
|
|
ir_type_discard,
|
|
|
|
|
ir_type_expression,
|
|
|
|
|
ir_type_function,
|
|
|
|
|
ir_type_function_signature,
|
|
|
|
|
ir_type_if,
|
|
|
|
|
ir_type_loop,
|
|
|
|
|
ir_type_loop_jump,
|
|
|
|
|
ir_type_return,
|
|
|
|
|
ir_type_swizzle,
|
|
|
|
|
ir_type_texture,
|
2013-02-15 09:26:35 -06:00
|
|
|
ir_type_emit_vertex,
|
|
|
|
|
ir_type_end_primitive,
|
2010-08-11 13:59:28 -06:00
|
|
|
ir_type_max /**< maximum ir_type enum number, for validation */
|
2010-07-19 09:05:42 -07:00
|
|
|
};
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
/**
|
|
|
|
|
* Base class of all IR instructions
|
|
|
|
|
*/
|
2010-03-08 23:44:00 -08:00
|
|
|
class ir_instruction : public exec_node {
|
2010-02-22 13:19:34 -08:00
|
|
|
public:
|
2010-07-19 09:05:42 -07:00
|
|
|
enum ir_node_type ir_type;
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2012-05-14 16:48:47 -07:00
|
|
|
/**
|
|
|
|
|
* GCC 4.7+ and clang warn when deleting an ir_instruction unless
|
|
|
|
|
* there's a virtual destructor present. Because we almost
|
|
|
|
|
* universally use ralloc for our memory management of
|
|
|
|
|
* ir_instructions, the destructor doesn't need to do any work.
|
|
|
|
|
*/
|
|
|
|
|
virtual ~ir_instruction()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-22 12:09:21 -07:00
|
|
|
/** ir_print_visitor helper for debugging. */
|
2010-06-23 11:37:12 -07:00
|
|
|
void print(void) const;
|
2010-06-22 12:09:21 -07:00
|
|
|
|
2010-03-09 16:23:37 -08:00
|
|
|
virtual void accept(ir_visitor *) = 0;
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_instruction *clone(void *mem_ctx,
|
|
|
|
|
struct hash_table *ht) const = 0;
|
2010-03-09 16:23:37 -08:00
|
|
|
|
2010-03-25 23:30:28 -07:00
|
|
|
/**
|
|
|
|
|
* \name IR instruction downcast functions
|
|
|
|
|
*
|
|
|
|
|
* These functions either cast the object to a derived class or return
|
|
|
|
|
* \c NULL if the object's type does not match the specified derived class.
|
|
|
|
|
* Additional downcast functions will be added as needed.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
virtual class ir_variable * as_variable() { return NULL; }
|
2010-04-21 16:02:15 -07:00
|
|
|
virtual class ir_function * as_function() { return NULL; }
|
2010-03-25 23:30:28 -07:00
|
|
|
virtual class ir_dereference * as_dereference() { return NULL; }
|
2010-05-11 11:31:09 -07:00
|
|
|
virtual class ir_dereference_array * as_dereference_array() { return NULL; }
|
2010-06-29 14:16:11 -07:00
|
|
|
virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }
|
2013-03-09 17:12:09 -08:00
|
|
|
virtual class ir_dereference_record *as_dereference_record() { return NULL; }
|
2010-07-12 11:04:07 -07:00
|
|
|
virtual class ir_expression * as_expression() { return NULL; }
|
2010-03-26 00:25:36 -07:00
|
|
|
virtual class ir_rvalue * as_rvalue() { return NULL; }
|
2010-04-05 17:13:14 -07:00
|
|
|
virtual class ir_loop * as_loop() { return NULL; }
|
2010-04-07 11:46:26 -07:00
|
|
|
virtual class ir_assignment * as_assignment() { return NULL; }
|
|
|
|
|
virtual class ir_call * as_call() { return NULL; }
|
|
|
|
|
virtual class ir_return * as_return() { return NULL; }
|
2010-04-14 17:03:03 -07:00
|
|
|
virtual class ir_if * as_if() { return NULL; }
|
2010-04-16 16:43:47 -07:00
|
|
|
virtual class ir_swizzle * as_swizzle() { return NULL; }
|
2010-05-04 13:04:40 -07:00
|
|
|
virtual class ir_constant * as_constant() { return NULL; }
|
2010-11-24 21:33:07 -08:00
|
|
|
virtual class ir_discard * as_discard() { return NULL; }
|
2013-04-22 13:59:17 -07:00
|
|
|
virtual class ir_jump * as_jump() { return NULL; }
|
2010-03-25 23:30:28 -07:00
|
|
|
/*@}*/
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
protected:
|
2010-03-25 23:30:28 -07:00
|
|
|
ir_instruction()
|
2010-03-11 14:23:41 -08:00
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
ir_type = ir_type_unset;
|
2010-03-11 14:23:41 -08:00
|
|
|
}
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2011-09-22 15:04:56 -07:00
|
|
|
/**
|
|
|
|
|
* The base class for all "values"/expression trees.
|
|
|
|
|
*/
|
2010-03-26 00:25:36 -07:00
|
|
|
class ir_rvalue : public ir_instruction {
|
|
|
|
|
public:
|
2011-09-20 17:58:45 -07:00
|
|
|
const struct glsl_type *type;
|
|
|
|
|
|
2011-09-22 15:04:56 -07:00
|
|
|
virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const;
|
2010-07-06 17:41:02 -07:00
|
|
|
|
2011-09-22 15:04:56 -07:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
virtual ir_rvalue * as_rvalue()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-19 18:27:41 +08:00
|
|
|
ir_rvalue *as_rvalue_to_saturate();
|
|
|
|
|
|
2011-08-02 15:22:25 -07:00
|
|
|
virtual bool is_lvalue() const
|
2010-03-26 00:25:36 -07:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 17:35:42 -07:00
|
|
|
/**
|
|
|
|
|
* Get the variable that is ultimately referenced by an r-value
|
|
|
|
|
*/
|
2011-08-02 15:22:25 -07:00
|
|
|
virtual ir_variable *variable_referenced() const
|
2010-05-14 17:35:42 -07:00
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-26 11:32:52 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If an r-value is a reference to a whole variable, get that variable
|
|
|
|
|
*
|
|
|
|
|
* \return
|
|
|
|
|
* Pointer to a variable that is completely dereferenced by the r-value. If
|
|
|
|
|
* the r-value is not a dereference or the dereference does not access the
|
|
|
|
|
* entire variable (i.e., it's just one array element, struct field), \c NULL
|
|
|
|
|
* is returned.
|
|
|
|
|
*/
|
|
|
|
|
virtual ir_variable *whole_variable_referenced()
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-18 17:11:17 -08:00
|
|
|
/**
|
|
|
|
|
* Determine if an r-value has the value zero
|
|
|
|
|
*
|
|
|
|
|
* The base implementation of this function always returns \c false. The
|
|
|
|
|
* \c ir_constant class over-rides this function to return \c true \b only
|
|
|
|
|
* for vector and scalar types that have all elements set to the value
|
|
|
|
|
* zero (or \c false for booleans).
|
|
|
|
|
*
|
2012-06-04 16:26:32 -04:00
|
|
|
* \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one,
|
|
|
|
|
* ir_constant::is_basis
|
2010-11-18 17:11:17 -08:00
|
|
|
*/
|
|
|
|
|
virtual bool is_zero() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Determine if an r-value has the value one
|
|
|
|
|
*
|
|
|
|
|
* The base implementation of this function always returns \c false. The
|
|
|
|
|
* \c ir_constant class over-rides this function to return \c true \b only
|
|
|
|
|
* for vector and scalar types that have all elements set to the value
|
|
|
|
|
* one (or \c true for booleans).
|
|
|
|
|
*
|
2012-06-04 16:26:32 -04:00
|
|
|
* \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one,
|
|
|
|
|
* ir_constant::is_basis
|
2010-11-18 17:11:17 -08:00
|
|
|
*/
|
|
|
|
|
virtual bool is_one() const;
|
|
|
|
|
|
2010-11-16 11:59:22 -08:00
|
|
|
/**
|
|
|
|
|
* Determine if an r-value has the value negative one
|
|
|
|
|
*
|
|
|
|
|
* The base implementation of this function always returns \c false. The
|
|
|
|
|
* \c ir_constant class over-rides this function to return \c true \b only
|
|
|
|
|
* for vector and scalar types that have all elements set to the value
|
2012-06-04 16:26:32 -04:00
|
|
|
* negative one. For boolean types, the result is always \c false.
|
2010-11-16 11:59:22 -08:00
|
|
|
*
|
|
|
|
|
* \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one
|
2012-06-04 16:26:32 -04:00
|
|
|
* ir_constant::is_basis
|
2010-11-16 11:59:22 -08:00
|
|
|
*/
|
|
|
|
|
virtual bool is_negative_one() const;
|
|
|
|
|
|
2012-06-04 16:26:32 -04:00
|
|
|
/**
|
|
|
|
|
* Determine if an r-value is a basis vector
|
|
|
|
|
*
|
|
|
|
|
* The base implementation of this function always returns \c false. The
|
|
|
|
|
* \c ir_constant class over-rides this function to return \c true \b only
|
|
|
|
|
* for vector and scalar types that have one element set to the value one,
|
|
|
|
|
* and the other elements set to the value zero. For boolean types, the
|
|
|
|
|
* result is always \c false.
|
|
|
|
|
*
|
|
|
|
|
* \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one,
|
|
|
|
|
* is_constant::is_negative_one
|
|
|
|
|
*/
|
|
|
|
|
virtual bool is_basis() const;
|
|
|
|
|
|
2011-09-22 15:04:56 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return a generic value of error_type.
|
|
|
|
|
*
|
|
|
|
|
* Allocation will be performed with 'mem_ctx' as ralloc owner.
|
|
|
|
|
*/
|
|
|
|
|
static ir_rvalue *error_value(void *mem_ctx);
|
|
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
protected:
|
2010-07-22 16:45:37 -07:00
|
|
|
ir_rvalue();
|
2010-03-26 00:25:36 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Variable storage classes
|
|
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
enum ir_variable_mode {
|
2010-09-18 16:08:38 +02:00
|
|
|
ir_var_auto = 0, /**< Function local variables and globals. */
|
|
|
|
|
ir_var_uniform, /**< Variable declared as a uniform. */
|
2013-01-11 14:39:32 -08:00
|
|
|
ir_var_shader_in,
|
|
|
|
|
ir_var_shader_out,
|
|
|
|
|
ir_var_function_in,
|
|
|
|
|
ir_var_function_out,
|
|
|
|
|
ir_var_function_inout,
|
2011-01-12 15:37:37 -08:00
|
|
|
ir_var_const_in, /**< "in" param that must be a constant expression */
|
2010-12-08 18:25:38 -07:00
|
|
|
ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
|
2013-04-09 10:03:11 -07:00
|
|
|
ir_var_temporary, /**< Temporary variable generated during compilation. */
|
|
|
|
|
ir_var_mode_count /**< Number of variable modes */
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
2011-01-27 01:40:22 -08:00
|
|
|
/**
|
|
|
|
|
* \brief Layout qualifiers for gl_FragDepth.
|
|
|
|
|
*
|
2011-08-09 10:53:29 -07:00
|
|
|
* The AMD/ARB_conservative_depth extensions allow gl_FragDepth to be redeclared
|
2011-01-27 01:40:22 -08:00
|
|
|
* with a layout qualifier.
|
|
|
|
|
*/
|
|
|
|
|
enum ir_depth_layout {
|
|
|
|
|
ir_depth_layout_none, /**< No depth layout is specified. */
|
|
|
|
|
ir_depth_layout_any,
|
|
|
|
|
ir_depth_layout_greater,
|
|
|
|
|
ir_depth_layout_less,
|
|
|
|
|
ir_depth_layout_unchanged
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Convert depth layout qualifier to string.
|
|
|
|
|
*/
|
|
|
|
|
const char*
|
|
|
|
|
depth_layout_string(ir_depth_layout layout);
|
2010-03-26 00:25:36 -07:00
|
|
|
|
2011-01-25 10:41:20 -08:00
|
|
|
/**
|
|
|
|
|
* Description of built-in state associated with a uniform
|
|
|
|
|
*
|
|
|
|
|
* \sa ir_variable::state_slots
|
|
|
|
|
*/
|
|
|
|
|
struct ir_state_slot {
|
|
|
|
|
int tokens[5];
|
|
|
|
|
int swizzle;
|
|
|
|
|
};
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
class ir_variable : public ir_instruction {
|
|
|
|
|
public:
|
2010-07-19 17:12:42 -07:00
|
|
|
ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-03-25 23:30:28 -07:00
|
|
|
virtual ir_variable *as_variable()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-09 16:23:37 -08:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-03-31 17:52:44 -07:00
|
|
|
|
2010-06-18 19:00:28 -07:00
|
|
|
/**
|
|
|
|
|
* Get the string value for the interpolation qualifier
|
|
|
|
|
*
|
2010-08-04 20:33:57 -07:00
|
|
|
* \return The string that would be used in a shader to specify \c
|
|
|
|
|
* mode will be returned.
|
|
|
|
|
*
|
glsl: Distinguish between no interpolation qualifier and 'smooth'
Previously, we treated the 'smooth' qualifier as equivalent to no
qualifier at all. However, this is incorrect for the built-in color
variables (gl_FrontColor, gl_BackColor, gl_FrontSecondaryColor, and
gl_BackSecondaryColor). For those variables, if there is no qualifier
at all, interpolation should be flat if the shade model is GL_FLAT,
and smooth if the shade model is GL_SMOOTH.
To make this possible, I added a new value to the
glsl_interp_qualifier enum, INTERP_QUALIFIER_NONE.
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
2011-10-21 07:40:37 -07:00
|
|
|
* This function is used to generate error messages of the form "shader
|
|
|
|
|
* uses %s interpolation qualifier", so in the case where there is no
|
|
|
|
|
* interpolation qualifier, it returns "no".
|
|
|
|
|
*
|
2010-08-04 20:33:57 -07:00
|
|
|
* This function should only be used on a shader input or output variable.
|
2010-06-18 19:00:28 -07:00
|
|
|
*/
|
|
|
|
|
const char *interpolation_string() const;
|
|
|
|
|
|
2011-10-21 07:55:48 -07:00
|
|
|
/**
|
|
|
|
|
* Determine how this variable should be interpolated based on its
|
|
|
|
|
* interpolation qualifier (if present), whether it is gl_Color or
|
|
|
|
|
* gl_SecondaryColor, and whether flatshading is enabled in the current GL
|
|
|
|
|
* state.
|
|
|
|
|
*
|
|
|
|
|
* The return value will always be either INTERP_QUALIFIER_SMOOTH,
|
|
|
|
|
* INTERP_QUALIFIER_NOPERSPECTIVE, or INTERP_QUALIFIER_FLAT.
|
|
|
|
|
*/
|
|
|
|
|
glsl_interp_qualifier determine_interpolation_mode(bool flat_shade);
|
|
|
|
|
|
2012-12-14 12:00:14 -08:00
|
|
|
/**
|
|
|
|
|
* Determine whether or not a variable is part of a uniform block.
|
|
|
|
|
*/
|
|
|
|
|
inline bool is_in_uniform_block() const
|
|
|
|
|
{
|
2013-01-21 21:51:15 -05:00
|
|
|
return this->mode == ir_var_uniform && this->interface_type != NULL;
|
2012-12-14 12:00:14 -08:00
|
|
|
}
|
|
|
|
|
|
2013-01-21 22:18:16 -05:00
|
|
|
/**
|
|
|
|
|
* Determine whether or not a variable is the declaration of an interface
|
|
|
|
|
* block
|
|
|
|
|
*
|
|
|
|
|
* For the first declaration below, there will be an \c ir_variable named
|
|
|
|
|
* "instance" whose type and whose instance_type will be the same
|
|
|
|
|
* \cglsl_type. For the second declaration, there will be an \c ir_variable
|
|
|
|
|
* named "f" whose type is float and whose instance_type is B2.
|
|
|
|
|
*
|
|
|
|
|
* "instance" is an interface instance variable, but "f" is not.
|
|
|
|
|
*
|
|
|
|
|
* uniform B1 {
|
|
|
|
|
* float f;
|
|
|
|
|
* } instance;
|
|
|
|
|
*
|
|
|
|
|
* uniform B2 {
|
|
|
|
|
* float f;
|
|
|
|
|
* };
|
|
|
|
|
*/
|
|
|
|
|
inline bool is_interface_instance() const
|
|
|
|
|
{
|
|
|
|
|
const glsl_type *const t = this->type;
|
|
|
|
|
|
|
|
|
|
return (t == this->interface_type)
|
|
|
|
|
|| (t->is_array() && t->fields.array == this->interface_type);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-24 14:30:29 -07:00
|
|
|
/**
|
|
|
|
|
* Set this->interface_type on a newly created variable.
|
|
|
|
|
*/
|
|
|
|
|
void init_interface_type(const struct glsl_type *type)
|
|
|
|
|
{
|
|
|
|
|
assert(this->interface_type == NULL);
|
|
|
|
|
this->interface_type = type;
|
2013-09-18 14:15:36 -07:00
|
|
|
if (this->is_interface_instance()) {
|
|
|
|
|
this->max_ifc_array_access =
|
|
|
|
|
rzalloc_array(this, unsigned, type->length);
|
|
|
|
|
}
|
2013-09-24 14:30:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const glsl_type *get_interface_type() const
|
|
|
|
|
{
|
|
|
|
|
return this->interface_type;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-20 17:58:45 -07:00
|
|
|
/**
|
|
|
|
|
* Declared type of the variable
|
|
|
|
|
*/
|
|
|
|
|
const struct glsl_type *type;
|
|
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
2012-06-26 09:45:29 -06:00
|
|
|
* Declared name of the variable
|
2010-09-18 16:08:38 +02:00
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
const char *name;
|
|
|
|
|
|
2010-04-01 18:31:11 -07:00
|
|
|
/**
|
|
|
|
|
* Highest element accessed with a constant expression array index
|
|
|
|
|
*
|
|
|
|
|
* Not used for non-array variables.
|
|
|
|
|
*/
|
|
|
|
|
unsigned max_array_access;
|
2013-09-18 14:15:36 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* For variables which satisfy the is_interface_instance() predicate, this
|
|
|
|
|
* points to an array of integers such that if the ith member of the
|
|
|
|
|
* interface block is an array, max_ifc_array_access[i] is the maximum
|
|
|
|
|
* array element of that member that has been accessed. If the ith member
|
|
|
|
|
* of the interface block is not an array, max_ifc_array_access[i] is
|
|
|
|
|
* unused.
|
|
|
|
|
*
|
|
|
|
|
* For variables whose type is not an interface block, this pointer is
|
|
|
|
|
* NULL.
|
|
|
|
|
*/
|
|
|
|
|
unsigned *max_ifc_array_access;
|
2010-04-01 18:31:11 -07:00
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Is the variable read-only?
|
|
|
|
|
*
|
|
|
|
|
* This is set for variables declared as \c const, shader inputs,
|
|
|
|
|
* and uniforms.
|
|
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
unsigned read_only:1;
|
|
|
|
|
unsigned centroid:1;
|
|
|
|
|
unsigned invariant:1;
|
|
|
|
|
|
2011-01-07 18:34:58 -08:00
|
|
|
/**
|
|
|
|
|
* Has this variable been used for reading or writing?
|
|
|
|
|
*
|
|
|
|
|
* Several GLSL semantic checks require knowledge of whether or not a
|
|
|
|
|
* variable has been used. For example, it is an error to redeclare a
|
|
|
|
|
* variable as invariant after it has been used.
|
2012-03-29 17:02:15 -07:00
|
|
|
*
|
|
|
|
|
* This is only maintained in the ast_to_hir.cpp path, not in
|
|
|
|
|
* Mesa's fixed function or ARB program paths.
|
2011-01-07 18:34:58 -08:00
|
|
|
*/
|
|
|
|
|
unsigned used:1;
|
|
|
|
|
|
2012-03-29 17:02:15 -07:00
|
|
|
/**
|
|
|
|
|
* Has this variable been statically assigned?
|
|
|
|
|
*
|
|
|
|
|
* This answers whether the variable was assigned in any path of
|
|
|
|
|
* the shader during ast_to_hir. This doesn't answer whether it is
|
|
|
|
|
* still written after dead code removal, nor is it maintained in
|
|
|
|
|
* non-ast_to_hir.cpp (GLSL parsing) paths.
|
|
|
|
|
*/
|
|
|
|
|
unsigned assigned:1;
|
|
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Storage class of the variable.
|
|
|
|
|
*
|
|
|
|
|
* \sa ir_variable_mode
|
|
|
|
|
*/
|
2013-01-11 14:39:32 -08:00
|
|
|
unsigned mode:4;
|
2010-09-18 16:08:38 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Interpolation mode for shader inputs / outputs
|
|
|
|
|
*
|
|
|
|
|
* \sa ir_variable_interpolation
|
|
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
unsigned interpolation:2;
|
2010-04-02 17:17:47 -07:00
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* \name ARB_fragment_coord_conventions
|
|
|
|
|
* @{
|
|
|
|
|
*/
|
2010-07-28 14:41:51 -07:00
|
|
|
unsigned origin_upper_left:1;
|
|
|
|
|
unsigned pixel_center_integer:1;
|
2010-09-18 16:08:38 +02:00
|
|
|
/*@}*/
|
2010-07-28 14:41:51 -07:00
|
|
|
|
2010-10-07 15:13:38 -07:00
|
|
|
/**
|
|
|
|
|
* Was the location explicitly set in the shader?
|
|
|
|
|
*
|
|
|
|
|
* If the location is explicitly set in the shader, it \b cannot be changed
|
|
|
|
|
* by the linker or by the API (e.g., calls to \c glBindAttribLocation have
|
|
|
|
|
* no effect).
|
|
|
|
|
*/
|
|
|
|
|
unsigned explicit_location:1;
|
glsl: add support for ARB_blend_func_extended (v3)
This adds index support to the GLSL compiler.
I'm not 100% sure of my approach here, esp without how output ordering
happens wrt location, index pairs, in the "mark" function.
Since current hw doesn't ever have a location > 0 with an index > 0,
we don't have to work out if the output ordering the hw requires is
location, index, location, index or location, location, index, index.
But we have no hw to know, so punt on it for now.
v2: index requires layout - catch and error
setup explicit index properly.
v3: drop idx_offset stuff, assume index follow location
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-03-24 13:33:41 +00:00
|
|
|
unsigned explicit_index:1;
|
2010-10-07 15:13:38 -07:00
|
|
|
|
2013-07-18 15:10:49 -07:00
|
|
|
/**
|
|
|
|
|
* Was an initial binding explicitly set in the shader?
|
|
|
|
|
*
|
|
|
|
|
* If so, constant_value contains an integer ir_constant representing the
|
|
|
|
|
* initial binding point.
|
|
|
|
|
*/
|
|
|
|
|
unsigned explicit_binding:1;
|
|
|
|
|
|
2011-10-31 14:31:07 -07:00
|
|
|
/**
|
|
|
|
|
* Does this variable have an initializer?
|
|
|
|
|
*
|
|
|
|
|
* This is used by the linker to cross-validiate initializers of global
|
|
|
|
|
* variables.
|
|
|
|
|
*/
|
|
|
|
|
unsigned has_initializer:1;
|
|
|
|
|
|
2012-12-04 15:17:01 -08:00
|
|
|
/**
|
|
|
|
|
* Is this variable a generic output or input that has not yet been matched
|
|
|
|
|
* up to a variable in another stage of the pipeline?
|
|
|
|
|
*
|
|
|
|
|
* This is used by the linker as scratch storage while assigning locations
|
|
|
|
|
* to generic inputs and outputs.
|
|
|
|
|
*/
|
|
|
|
|
unsigned is_unmatched_generic_inout:1;
|
|
|
|
|
|
2012-12-05 10:47:55 -08:00
|
|
|
/**
|
|
|
|
|
* If non-zero, then this variable may be packed along with other variables
|
|
|
|
|
* into a single varying slot, so this offset should be applied when
|
|
|
|
|
* accessing components. For example, an offset of 1 means that the x
|
|
|
|
|
* component of this variable is actually stored in component y of the
|
|
|
|
|
* location specified by \c location.
|
|
|
|
|
*/
|
|
|
|
|
unsigned location_frac:2;
|
|
|
|
|
|
2011-10-31 14:04:10 -07:00
|
|
|
/**
|
|
|
|
|
* \brief Layout qualifier for gl_FragDepth.
|
|
|
|
|
*
|
|
|
|
|
* This is not equal to \c ir_depth_layout_none if and only if this
|
|
|
|
|
* variable is \c gl_FragDepth and a layout qualifier is specified.
|
|
|
|
|
*/
|
|
|
|
|
ir_depth_layout depth_layout;
|
|
|
|
|
|
2010-06-21 11:42:02 -07:00
|
|
|
/**
|
|
|
|
|
* Storage location of the base of this variable
|
|
|
|
|
*
|
|
|
|
|
* The precise meaning of this field depends on the nature of the variable.
|
|
|
|
|
*
|
|
|
|
|
* - Vertex shader input: one of the values from \c gl_vert_attrib.
|
2013-02-23 07:22:01 -08:00
|
|
|
* - Vertex shader output: one of the values from \c gl_varying_slot.
|
2013-02-15 09:26:35 -06:00
|
|
|
* - Geometry shader input: one of the values from \c gl_varying_slot.
|
|
|
|
|
* - Geometry shader output: one of the values from \c gl_varying_slot.
|
2013-02-23 09:00:58 -08:00
|
|
|
* - Fragment shader input: one of the values from \c gl_varying_slot.
|
2010-06-21 11:42:02 -07:00
|
|
|
* - Fragment shader output: one of the values from \c gl_frag_result.
|
2012-04-26 18:21:43 -07:00
|
|
|
* - Uniforms: Per-stage uniform slot number for default uniform block.
|
|
|
|
|
* - Uniforms: Index within the uniform block definition for UBO members.
|
2010-06-21 11:42:02 -07:00
|
|
|
* - Other: This field is not currently used.
|
|
|
|
|
*
|
|
|
|
|
* If the variable is a uniform, shader input, or shader output, and the
|
|
|
|
|
* slot has not been assigned, the value will be -1.
|
|
|
|
|
*/
|
|
|
|
|
int location;
|
|
|
|
|
|
2012-03-24 13:33:00 +00:00
|
|
|
/**
|
|
|
|
|
* output index for dual source blending.
|
|
|
|
|
*/
|
|
|
|
|
int index;
|
|
|
|
|
|
2013-07-18 15:10:49 -07:00
|
|
|
/**
|
|
|
|
|
* Initial binding point for a sampler or UBO.
|
|
|
|
|
*
|
|
|
|
|
* For array types, this represents the binding point for the first element.
|
|
|
|
|
*/
|
|
|
|
|
int binding;
|
|
|
|
|
|
2011-01-25 10:41:20 -08:00
|
|
|
/**
|
|
|
|
|
* Built-in state that backs this uniform
|
|
|
|
|
*
|
|
|
|
|
* Once set at variable creation, \c state_slots must remain invariant.
|
|
|
|
|
* This is because, ideally, this array would be shared by all clones of
|
|
|
|
|
* this variable in the IR tree. In other words, we'd really like for it
|
|
|
|
|
* to be a fly-weight.
|
|
|
|
|
*
|
|
|
|
|
* If the variable is not a uniform, \c num_state_slots will be zero and
|
|
|
|
|
* \c state_slots will be \c NULL.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
unsigned num_state_slots; /**< Number of state slots used */
|
|
|
|
|
ir_state_slot *state_slots; /**< State descriptors. */
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2010-04-07 16:53:54 -07:00
|
|
|
/**
|
|
|
|
|
* Emit a warning if this variable is accessed.
|
|
|
|
|
*/
|
|
|
|
|
const char *warn_extension;
|
|
|
|
|
|
2010-04-06 10:30:54 -07:00
|
|
|
/**
|
|
|
|
|
* Value assigned in the initializer of a variable declared "const"
|
|
|
|
|
*/
|
|
|
|
|
ir_constant *constant_value;
|
2011-10-31 14:31:07 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constant expression assigned in the initializer of the variable
|
|
|
|
|
*
|
|
|
|
|
* \warning
|
|
|
|
|
* This field and \c ::constant_value are distinct. Even if the two fields
|
|
|
|
|
* refer to constants with the same value, they must point to separate
|
|
|
|
|
* objects.
|
|
|
|
|
*/
|
|
|
|
|
ir_constant *constant_initializer;
|
2013-01-21 21:51:15 -05:00
|
|
|
|
2013-09-24 14:30:29 -07:00
|
|
|
private:
|
2013-01-21 21:51:15 -05:00
|
|
|
/**
|
|
|
|
|
* For variables that are in an interface block or are an instance of an
|
|
|
|
|
* interface block, this is the \c GLSL_TYPE_INTERFACE type for that block.
|
|
|
|
|
*
|
|
|
|
|
* \sa ir_variable::location
|
|
|
|
|
*/
|
|
|
|
|
const glsl_type *interface_type;
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
glsl: Store a predicate for whether a built-in signature is available.
For the upcoming built-in function rewrite, we'll need to be able to
answer "Is this built-in function signature available?".
This is actually a somewhat complex question, since it depends on the
language version, GLSL vs. GLSL ES, enabled extensions, and the current
shader stage.
Storing such a set of constraints in a structure would be painful, so
instead we store a function pointer. When creating a signature, we
simply point to a predicate that inspects _mesa_glsl_parse_state and
answers whether the signature is available in the current shader.
Unfortunately, IR reader doesn't actually know when built-in functions
are available, so this patch makes it lie and say that they're always
present. This allows us to hook up the new functionality; it just won't
be useful until real data is populated. In the meantime, the existing
profile mechanism ensures built-ins are available in the right places.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
2013-08-30 16:00:43 -07:00
|
|
|
/**
|
|
|
|
|
* A function that returns whether a built-in function is available in the
|
|
|
|
|
* current shading language (based on version, ES or desktop, and extensions).
|
|
|
|
|
*/
|
|
|
|
|
typedef bool (*builtin_available_predicate)(const _mesa_glsl_parse_state *);
|
2010-02-22 13:19:34 -08:00
|
|
|
|
|
|
|
|
/*@{*/
|
2010-04-21 12:30:22 -07:00
|
|
|
/**
|
|
|
|
|
* The representation of a function instance; may be the full definition or
|
|
|
|
|
* simply a prototype.
|
|
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
class ir_function_signature : public ir_instruction {
|
2010-04-07 13:19:11 -07:00
|
|
|
/* An ir_function_signature will be part of the list of signatures in
|
|
|
|
|
* an ir_function.
|
|
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
public:
|
glsl: Store a predicate for whether a built-in signature is available.
For the upcoming built-in function rewrite, we'll need to be able to
answer "Is this built-in function signature available?".
This is actually a somewhat complex question, since it depends on the
language version, GLSL vs. GLSL ES, enabled extensions, and the current
shader stage.
Storing such a set of constraints in a structure would be painful, so
instead we store a function pointer. When creating a signature, we
simply point to a predicate that inspects _mesa_glsl_parse_state and
answers whether the signature is available in the current shader.
Unfortunately, IR reader doesn't actually know when built-in functions
are available, so this patch makes it lie and say that they're always
present. This allows us to hook up the new functionality; it just won't
be useful until real data is populated. In the meantime, the existing
profile mechanism ensures built-ins are available in the right places.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
2013-08-30 16:00:43 -07:00
|
|
|
ir_function_signature(const glsl_type *return_type,
|
2013-09-09 14:53:22 -07:00
|
|
|
builtin_available_predicate builtin_avail = NULL);
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_function_signature *clone(void *mem_ctx,
|
|
|
|
|
struct hash_table *ht) const;
|
2010-11-11 12:21:27 -08:00
|
|
|
ir_function_signature *clone_prototype(void *mem_ctx,
|
|
|
|
|
struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-03-09 16:23:37 -08:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2011-09-20 00:14:05 -07:00
|
|
|
/**
|
2012-05-02 23:11:38 +02:00
|
|
|
* Attempt to evaluate this function as a constant expression,
|
|
|
|
|
* given a list of the actual parameters and the variable context.
|
|
|
|
|
* Returns NULL for non-built-ins.
|
2011-09-20 00:14:05 -07:00
|
|
|
*/
|
2012-05-02 23:11:38 +02:00
|
|
|
ir_constant *constant_expression_value(exec_list *actual_parameters, struct hash_table *variable_context);
|
2011-09-20 00:14:05 -07:00
|
|
|
|
2010-03-31 16:44:12 -07:00
|
|
|
/**
|
|
|
|
|
* Get the name of the function for which this is a signature
|
|
|
|
|
*/
|
|
|
|
|
const char *function_name() const;
|
|
|
|
|
|
2010-07-02 13:28:32 -07:00
|
|
|
/**
|
|
|
|
|
* Get a handle to the function for which this is a signature
|
|
|
|
|
*
|
|
|
|
|
* There is no setter function, this function returns a \c const pointer,
|
|
|
|
|
* and \c ir_function_signature::_function is private for a reason. The
|
|
|
|
|
* only way to make a connection between a function and function signature
|
|
|
|
|
* is via \c ir_function::add_signature. This helps ensure that certain
|
|
|
|
|
* invariants (i.e., a function signature is in the list of signatures for
|
|
|
|
|
* its \c _function) are met.
|
|
|
|
|
*
|
|
|
|
|
* \sa ir_function::add_signature
|
|
|
|
|
*/
|
|
|
|
|
inline const class ir_function *function() const
|
|
|
|
|
{
|
|
|
|
|
return this->_function;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-28 11:49:12 -07:00
|
|
|
/**
|
|
|
|
|
* Check whether the qualifiers match between this signature's parameters
|
|
|
|
|
* and the supplied parameter list. If not, returns the name of the first
|
|
|
|
|
* parameter with mismatched qualifiers (for use in error messages).
|
|
|
|
|
*/
|
|
|
|
|
const char *qualifiers_match(exec_list *params);
|
|
|
|
|
|
2010-04-28 12:44:24 -07:00
|
|
|
/**
|
|
|
|
|
* Replace the current parameter list with the given one. This is useful
|
|
|
|
|
* if the current information came from a prototype, and either has invalid
|
|
|
|
|
* or missing parameter names.
|
|
|
|
|
*/
|
|
|
|
|
void replace_parameters(exec_list *new_params);
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
/**
|
|
|
|
|
* Function return type.
|
|
|
|
|
*
|
|
|
|
|
* \note This discards the optional precision qualifier.
|
|
|
|
|
*/
|
|
|
|
|
const struct glsl_type *return_type;
|
|
|
|
|
|
|
|
|
|
/**
|
2010-04-07 12:35:34 -07:00
|
|
|
* List of ir_variable of function parameters.
|
|
|
|
|
*
|
|
|
|
|
* This represents the storage. The paramaters passed in a particular
|
|
|
|
|
* call will be in ir_call::actual_paramaters.
|
2010-02-22 13:19:34 -08:00
|
|
|
*/
|
2010-03-08 23:44:00 -08:00
|
|
|
struct exec_list parameters;
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2010-04-21 12:30:22 -07:00
|
|
|
/** Whether or not this function has a body (which may be empty). */
|
|
|
|
|
unsigned is_defined:1;
|
2010-03-31 16:37:10 -07:00
|
|
|
|
2010-09-05 01:48:11 -07:00
|
|
|
/** Whether or not this function signature is a built-in. */
|
2013-08-30 16:12:55 -07:00
|
|
|
bool is_builtin() const;
|
2010-09-05 01:48:11 -07:00
|
|
|
|
2013-08-30 00:06:30 -07:00
|
|
|
/** Whether or not a built-in is available for this shader. */
|
|
|
|
|
bool is_builtin_available(const _mesa_glsl_parse_state *state) const;
|
|
|
|
|
|
2010-04-07 13:19:11 -07:00
|
|
|
/** Body of instructions in the function. */
|
|
|
|
|
struct exec_list body;
|
|
|
|
|
|
2010-03-31 16:37:10 -07:00
|
|
|
private:
|
glsl: Store a predicate for whether a built-in signature is available.
For the upcoming built-in function rewrite, we'll need to be able to
answer "Is this built-in function signature available?".
This is actually a somewhat complex question, since it depends on the
language version, GLSL vs. GLSL ES, enabled extensions, and the current
shader stage.
Storing such a set of constraints in a structure would be painful, so
instead we store a function pointer. When creating a signature, we
simply point to a predicate that inspects _mesa_glsl_parse_state and
answers whether the signature is available in the current shader.
Unfortunately, IR reader doesn't actually know when built-in functions
are available, so this patch makes it lie and say that they're always
present. This allows us to hook up the new functionality; it just won't
be useful until real data is populated. In the meantime, the existing
profile mechanism ensures built-ins are available in the right places.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
2013-08-30 16:00:43 -07:00
|
|
|
/**
|
|
|
|
|
* A function pointer to a predicate that answers whether a built-in
|
|
|
|
|
* function is available in the current shader. NULL if not a built-in.
|
|
|
|
|
*/
|
2013-09-09 14:53:22 -07:00
|
|
|
builtin_available_predicate builtin_avail;
|
glsl: Store a predicate for whether a built-in signature is available.
For the upcoming built-in function rewrite, we'll need to be able to
answer "Is this built-in function signature available?".
This is actually a somewhat complex question, since it depends on the
language version, GLSL vs. GLSL ES, enabled extensions, and the current
shader stage.
Storing such a set of constraints in a structure would be painful, so
instead we store a function pointer. When creating a signature, we
simply point to a predicate that inspects _mesa_glsl_parse_state and
answers whether the signature is available in the current shader.
Unfortunately, IR reader doesn't actually know when built-in functions
are available, so this patch makes it lie and say that they're always
present. This allows us to hook up the new functionality; it just won't
be useful until real data is populated. In the meantime, the existing
profile mechanism ensures built-ins are available in the right places.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
2013-08-30 16:00:43 -07:00
|
|
|
|
2010-03-31 16:37:10 -07:00
|
|
|
/** Function of which this signature is one overload. */
|
2010-07-02 13:28:32 -07:00
|
|
|
class ir_function *_function;
|
2010-03-31 16:37:10 -07:00
|
|
|
|
2012-05-02 23:11:41 +02:00
|
|
|
/** Function signature of which this one is a prototype clone */
|
|
|
|
|
const ir_function_signature *origin;
|
|
|
|
|
|
2010-03-31 16:37:10 -07:00
|
|
|
friend class ir_function;
|
2012-05-02 23:11:42 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper function to run a list of instructions for constant
|
|
|
|
|
* expression evaluation.
|
|
|
|
|
*
|
|
|
|
|
* The hash table represents the values of the visible variables.
|
|
|
|
|
* There are no scoping issues because the table is indexed on
|
|
|
|
|
* ir_variable pointers, not variable names.
|
|
|
|
|
*
|
|
|
|
|
* Returns false if the expression is not constant, true otherwise,
|
|
|
|
|
* and the value in *result if result is non-NULL.
|
|
|
|
|
*/
|
|
|
|
|
bool constant_expression_evaluate_expression_list(const struct exec_list &body,
|
|
|
|
|
struct hash_table *variable_context,
|
|
|
|
|
ir_constant **result);
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2010-04-21 12:30:22 -07:00
|
|
|
* Header for tracking multiple overloaded functions with the same name.
|
|
|
|
|
* Contains a list of ir_function_signatures representing each of the
|
|
|
|
|
* actual functions.
|
2010-02-22 13:19:34 -08:00
|
|
|
*/
|
|
|
|
|
class ir_function : public ir_instruction {
|
|
|
|
|
public:
|
2010-03-23 17:42:04 -07:00
|
|
|
ir_function(const char *name);
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-04-21 16:02:15 -07:00
|
|
|
virtual ir_function *as_function()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-09 16:23:37 -08:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-03-31 16:37:10 -07:00
|
|
|
void add_signature(ir_function_signature *sig)
|
|
|
|
|
{
|
2010-07-02 13:28:32 -07:00
|
|
|
sig->_function = this;
|
|
|
|
|
this->signatures.push_tail(sig);
|
2010-03-31 16:37:10 -07:00
|
|
|
}
|
|
|
|
|
|
2010-03-31 16:40:26 -07:00
|
|
|
/**
|
|
|
|
|
* Get an iterator for the set of function signatures
|
|
|
|
|
*/
|
|
|
|
|
exec_list_iterator iterator()
|
|
|
|
|
{
|
|
|
|
|
return signatures.iterator();
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-11 00:48:14 -08:00
|
|
|
/**
|
|
|
|
|
* Find a signature that matches a set of actual parameters, taking implicit
|
|
|
|
|
* conversions into account. Also flags whether the match was exact.
|
|
|
|
|
*/
|
2013-08-30 23:11:55 -07:00
|
|
|
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
|
|
|
|
|
const exec_list *actual_param,
|
2011-11-11 00:48:14 -08:00
|
|
|
bool *match_is_exact);
|
|
|
|
|
|
2010-03-11 14:50:30 -08:00
|
|
|
/**
|
2010-04-28 12:04:23 -07:00
|
|
|
* Find a signature that matches a set of actual parameters, taking implicit
|
|
|
|
|
* conversions into account.
|
2010-03-11 14:50:30 -08:00
|
|
|
*/
|
2013-08-30 23:11:55 -07:00
|
|
|
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
|
|
|
|
|
const exec_list *actual_param);
|
2010-03-11 14:50:30 -08:00
|
|
|
|
2010-04-28 12:04:23 -07:00
|
|
|
/**
|
|
|
|
|
* Find a signature that exactly matches a set of actual parameters without
|
|
|
|
|
* any implicit type conversions.
|
|
|
|
|
*/
|
2013-08-30 23:11:55 -07:00
|
|
|
ir_function_signature *exact_matching_signature(_mesa_glsl_parse_state *state,
|
|
|
|
|
const exec_list *actual_ps);
|
2010-04-28 12:04:23 -07:00
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
/**
|
|
|
|
|
* Name of the function.
|
|
|
|
|
*/
|
|
|
|
|
const char *name;
|
|
|
|
|
|
2010-09-16 02:52:25 -07:00
|
|
|
/** Whether or not this function has a signature that isn't a built-in. */
|
|
|
|
|
bool has_user_signature();
|
2010-08-20 20:04:39 -07:00
|
|
|
|
2010-03-11 14:50:30 -08:00
|
|
|
/**
|
2010-04-07 12:35:34 -07:00
|
|
|
* List of ir_function_signature for each overloaded function with this name.
|
2010-03-11 14:50:30 -08:00
|
|
|
*/
|
2010-03-08 23:44:00 -08:00
|
|
|
struct exec_list signatures;
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
2010-03-31 16:44:12 -07:00
|
|
|
|
|
|
|
|
inline const char *ir_function_signature::function_name() const
|
|
|
|
|
{
|
2010-07-02 13:28:32 -07:00
|
|
|
return this->_function->name;
|
2010-03-31 16:44:12 -07:00
|
|
|
}
|
2010-02-22 13:19:34 -08:00
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
|
2010-03-29 14:11:25 -07:00
|
|
|
/**
|
|
|
|
|
* IR instruction representing high-level if-statements
|
|
|
|
|
*/
|
|
|
|
|
class ir_if : public ir_instruction {
|
|
|
|
|
public:
|
|
|
|
|
ir_if(ir_rvalue *condition)
|
|
|
|
|
: condition(condition)
|
|
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
ir_type = ir_type_if;
|
2010-03-29 14:11:25 -07:00
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-04-14 17:03:03 -07:00
|
|
|
virtual ir_if *as_if()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 14:11:25 -07:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-03-29 14:11:25 -07:00
|
|
|
ir_rvalue *condition;
|
2010-04-07 12:35:34 -07:00
|
|
|
/** List of ir_instruction for the body of the then branch */
|
2010-03-29 14:11:25 -07:00
|
|
|
exec_list then_instructions;
|
2010-04-07 12:35:34 -07:00
|
|
|
/** List of ir_instruction for the body of the else branch */
|
2010-03-29 14:11:25 -07:00
|
|
|
exec_list else_instructions;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-04-05 16:16:07 -07:00
|
|
|
/**
|
|
|
|
|
* IR instruction representing a high-level loop structure.
|
|
|
|
|
*/
|
|
|
|
|
class ir_loop : public ir_instruction {
|
|
|
|
|
public:
|
2010-08-26 15:11:26 -07:00
|
|
|
ir_loop();
|
2010-04-05 16:16:07 -07:00
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_loop *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-04-05 16:16:07 -07:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-04-05 17:13:14 -07:00
|
|
|
virtual ir_loop *as_loop()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-05 16:16:07 -07:00
|
|
|
/**
|
|
|
|
|
* Get an iterator for the instructions of the loop body
|
|
|
|
|
*/
|
|
|
|
|
exec_list_iterator iterator()
|
|
|
|
|
{
|
|
|
|
|
return body_instructions.iterator();
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-07 12:35:34 -07:00
|
|
|
/** List of ir_instruction that make up the body of the loop. */
|
2010-04-05 16:16:07 -07:00
|
|
|
exec_list body_instructions;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \name Loop counter and controls
|
2010-08-26 15:11:26 -07:00
|
|
|
*
|
|
|
|
|
* Represents a loop like a FORTRAN \c do-loop.
|
|
|
|
|
*
|
|
|
|
|
* \note
|
|
|
|
|
* If \c from and \c to are the same value, the loop will execute once.
|
2010-04-05 16:16:07 -07:00
|
|
|
*/
|
|
|
|
|
/*@{*/
|
2010-08-26 15:11:26 -07:00
|
|
|
ir_rvalue *from; /** Value of the loop counter on the first
|
|
|
|
|
* iteration of the loop.
|
|
|
|
|
*/
|
|
|
|
|
ir_rvalue *to; /** Value of the loop counter on the last
|
|
|
|
|
* iteration of the loop.
|
|
|
|
|
*/
|
2010-04-05 16:16:07 -07:00
|
|
|
ir_rvalue *increment;
|
|
|
|
|
ir_variable *counter;
|
2010-08-26 15:11:26 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Comparison operation in the loop terminator.
|
|
|
|
|
*
|
|
|
|
|
* If any of the loop control fields are non-\c NULL, this field must be
|
|
|
|
|
* one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal,
|
|
|
|
|
* \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal.
|
|
|
|
|
*/
|
|
|
|
|
int cmp;
|
2010-04-05 16:16:07 -07:00
|
|
|
/*@}*/
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-07-22 16:40:35 -07:00
|
|
|
class ir_assignment : public ir_instruction {
|
2010-02-22 13:19:34 -08:00
|
|
|
public:
|
2011-06-24 13:17:07 -07:00
|
|
|
ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition = NULL);
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2010-08-02 18:48:25 -07:00
|
|
|
/**
|
|
|
|
|
* Construct an assignment with an explicit write mask
|
|
|
|
|
*
|
|
|
|
|
* \note
|
|
|
|
|
* Since a write mask is supplied, the LHS must already be a bare
|
|
|
|
|
* \c ir_dereference. The cannot be any swizzles in the LHS.
|
|
|
|
|
*/
|
|
|
|
|
ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition,
|
|
|
|
|
unsigned write_mask);
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-03-09 16:23:37 -08:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-04-07 11:46:26 -07:00
|
|
|
virtual ir_assignment * as_assignment()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-02 18:48:25 -07:00
|
|
|
/**
|
|
|
|
|
* Get a whole variable written by an assignment
|
|
|
|
|
*
|
|
|
|
|
* If the LHS of the assignment writes a whole variable, the variable is
|
|
|
|
|
* returned. Otherwise \c NULL is returned. Examples of whole-variable
|
|
|
|
|
* assignment are:
|
|
|
|
|
*
|
|
|
|
|
* - Assigning to a scalar
|
|
|
|
|
* - Assigning to all components of a vector
|
|
|
|
|
* - Whole array (or matrix) assignment
|
|
|
|
|
* - Whole structure assignment
|
|
|
|
|
*/
|
|
|
|
|
ir_variable *whole_variable_written();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the LHS of an assignment
|
|
|
|
|
*/
|
|
|
|
|
void set_lhs(ir_rvalue *lhs);
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
/**
|
|
|
|
|
* Left-hand side of the assignment.
|
2010-08-02 18:48:25 -07:00
|
|
|
*
|
|
|
|
|
* This should be treated as read only. If you need to set the LHS of an
|
|
|
|
|
* assignment, use \c ir_assignment::set_lhs.
|
2010-02-22 13:19:34 -08:00
|
|
|
*/
|
2010-08-02 18:48:25 -07:00
|
|
|
ir_dereference *lhs;
|
2010-02-22 13:19:34 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Value being assigned
|
|
|
|
|
*/
|
2010-03-26 00:25:36 -07:00
|
|
|
ir_rvalue *rhs;
|
2010-02-22 13:19:34 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Optional condition for the assignment.
|
|
|
|
|
*/
|
2010-03-26 00:25:36 -07:00
|
|
|
ir_rvalue *condition;
|
2010-08-02 18:48:25 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Component mask written
|
|
|
|
|
*
|
|
|
|
|
* For non-vector types in the LHS, this field will be zero. For vector
|
|
|
|
|
* types, a bit will be set for each component that is written. Note that
|
|
|
|
|
* for \c vec2 and \c vec3 types only the lower bits will ever be set.
|
2010-09-22 11:47:03 -07:00
|
|
|
*
|
|
|
|
|
* A partially-set write mask means that each enabled channel gets
|
|
|
|
|
* the value from a consecutive channel of the rhs. For example,
|
|
|
|
|
* to write just .xyw of gl_FrontColor with color:
|
|
|
|
|
*
|
|
|
|
|
* (assign (constant bool (1)) (xyw)
|
|
|
|
|
* (var_ref gl_FragColor)
|
|
|
|
|
* (swiz xyw (var_ref color)))
|
2010-08-02 18:48:25 -07:00
|
|
|
*/
|
|
|
|
|
unsigned write_mask:4;
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
2013-01-08 08:26:34 -08:00
|
|
|
/* Update ir_expression::get_num_operands() and operator_strs when
|
2010-04-01 18:07:08 -10:00
|
|
|
* updating this list.
|
2010-04-07 17:18:29 -07:00
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
enum ir_expression_operation {
|
|
|
|
|
ir_unop_bit_not,
|
|
|
|
|
ir_unop_logic_not,
|
|
|
|
|
ir_unop_neg,
|
|
|
|
|
ir_unop_abs,
|
2010-05-03 20:05:57 -07:00
|
|
|
ir_unop_sign,
|
2010-02-22 13:19:34 -08:00
|
|
|
ir_unop_rcp,
|
|
|
|
|
ir_unop_rsq,
|
2010-03-27 13:01:51 -07:00
|
|
|
ir_unop_sqrt,
|
2012-05-08 20:40:32 +02:00
|
|
|
ir_unop_exp, /**< Log base e on gentype */
|
|
|
|
|
ir_unop_log, /**< Natural log on gentype */
|
2010-03-27 13:56:35 -07:00
|
|
|
ir_unop_exp2,
|
|
|
|
|
ir_unop_log2,
|
2012-05-08 20:40:32 +02:00
|
|
|
ir_unop_f2i, /**< Float-to-integer conversion. */
|
2012-06-13 15:47:45 -07:00
|
|
|
ir_unop_f2u, /**< Float-to-unsigned conversion. */
|
2012-05-08 20:40:32 +02:00
|
|
|
ir_unop_i2f, /**< Integer-to-float conversion. */
|
|
|
|
|
ir_unop_f2b, /**< Float-to-boolean conversion */
|
|
|
|
|
ir_unop_b2f, /**< Boolean-to-float conversion */
|
|
|
|
|
ir_unop_i2b, /**< int-to-boolean conversion */
|
|
|
|
|
ir_unop_b2i, /**< Boolean-to-int conversion */
|
|
|
|
|
ir_unop_u2f, /**< Unsigned-to-float conversion. */
|
|
|
|
|
ir_unop_i2u, /**< Integer-to-unsigned conversion. */
|
|
|
|
|
ir_unop_u2i, /**< Unsigned-to-integer conversion. */
|
|
|
|
|
ir_unop_bitcast_i2f, /**< Bit-identical int-to-float "conversion" */
|
|
|
|
|
ir_unop_bitcast_f2i, /**< Bit-identical float-to-int "conversion" */
|
|
|
|
|
ir_unop_bitcast_u2f, /**< Bit-identical uint-to-float "conversion" */
|
|
|
|
|
ir_unop_bitcast_f2u, /**< Bit-identical float-to-uint "conversion" */
|
2010-08-23 12:21:33 -07:00
|
|
|
ir_unop_any,
|
2010-02-22 13:19:34 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \name Unary floating-point rounding operations.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_unop_trunc,
|
|
|
|
|
ir_unop_ceil,
|
|
|
|
|
ir_unop_floor,
|
2010-07-01 10:37:11 -07:00
|
|
|
ir_unop_fract,
|
2010-10-14 13:37:03 -07:00
|
|
|
ir_unop_round_even,
|
2010-02-22 13:19:34 -08:00
|
|
|
/*@}*/
|
|
|
|
|
|
2010-05-03 22:11:17 -07:00
|
|
|
/**
|
|
|
|
|
* \name Trigonometric operations.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_unop_sin,
|
|
|
|
|
ir_unop_cos,
|
2010-11-18 11:05:32 -08:00
|
|
|
ir_unop_sin_reduced, /**< Reduced range sin. [-pi, pi] */
|
|
|
|
|
ir_unop_cos_reduced, /**< Reduced range cos. [-pi, pi] */
|
2010-05-03 22:11:17 -07:00
|
|
|
/*@}*/
|
|
|
|
|
|
2010-06-09 14:42:41 -07:00
|
|
|
/**
|
|
|
|
|
* \name Partial derivatives.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_unop_dFdx,
|
|
|
|
|
ir_unop_dFdy,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2012-11-19 10:48:25 -08:00
|
|
|
/**
|
|
|
|
|
* \name Floating point pack and unpack operations.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_unop_pack_snorm_2x16,
|
2013-01-21 14:12:37 -08:00
|
|
|
ir_unop_pack_snorm_4x8,
|
2012-11-19 10:48:25 -08:00
|
|
|
ir_unop_pack_unorm_2x16,
|
2013-01-21 14:12:37 -08:00
|
|
|
ir_unop_pack_unorm_4x8,
|
2012-11-19 10:48:25 -08:00
|
|
|
ir_unop_pack_half_2x16,
|
|
|
|
|
ir_unop_unpack_snorm_2x16,
|
2013-01-21 14:12:37 -08:00
|
|
|
ir_unop_unpack_snorm_4x8,
|
2012-11-19 10:48:25 -08:00
|
|
|
ir_unop_unpack_unorm_2x16,
|
2013-01-21 14:12:37 -08:00
|
|
|
ir_unop_unpack_unorm_4x8,
|
2012-11-19 10:48:25 -08:00
|
|
|
ir_unop_unpack_half_2x16,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \name Lowered floating point unpacking operations.
|
|
|
|
|
*
|
|
|
|
|
* \see lower_packing_builtins_visitor::split_unpack_half_2x16
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_unop_unpack_half_2x16_split_x,
|
|
|
|
|
ir_unop_unpack_half_2x16_split_y,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2013-04-09 17:45:12 -07:00
|
|
|
/**
|
|
|
|
|
* \name Bit operations, part of ARB_gpu_shader5.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_unop_bitfield_reverse,
|
|
|
|
|
ir_unop_bit_count,
|
|
|
|
|
ir_unop_find_msb,
|
|
|
|
|
ir_unop_find_lsb,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2010-09-01 21:12:10 -07:00
|
|
|
ir_unop_noise,
|
|
|
|
|
|
2010-11-17 15:31:35 -08:00
|
|
|
/**
|
|
|
|
|
* A sentinel marking the last of the unary operations.
|
|
|
|
|
*/
|
|
|
|
|
ir_last_unop = ir_unop_noise,
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
ir_binop_add,
|
|
|
|
|
ir_binop_sub,
|
2013-09-17 21:34:15 -07:00
|
|
|
ir_binop_mul, /**< Floating-point or low 32-bit integer multiply. */
|
|
|
|
|
ir_binop_imul_high, /**< Calculates the high 32-bits of a 64-bit multiply. */
|
2010-02-22 13:19:34 -08:00
|
|
|
ir_binop_div,
|
2010-07-01 10:09:58 -07:00
|
|
|
|
2013-09-19 12:56:10 -07:00
|
|
|
/**
|
|
|
|
|
* Returns the carry resulting from the addition of the two arguments.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_binop_carry,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the borrow resulting from the subtraction of the second argument
|
|
|
|
|
* from the first argument.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_binop_borrow,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2010-07-01 10:09:58 -07:00
|
|
|
/**
|
|
|
|
|
* Takes one of two combinations of arguments:
|
|
|
|
|
*
|
|
|
|
|
* - mod(vecN, vecN)
|
|
|
|
|
* - mod(vecN, float)
|
|
|
|
|
*
|
|
|
|
|
* Does not take integer types.
|
|
|
|
|
*/
|
2010-02-22 13:19:34 -08:00
|
|
|
ir_binop_mod,
|
|
|
|
|
|
|
|
|
|
/**
|
2010-09-19 04:50:28 +02:00
|
|
|
* \name Binary comparison operators which return a boolean vector.
|
|
|
|
|
* The type of both operands must be equal.
|
2010-02-22 13:19:34 -08:00
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_binop_less,
|
|
|
|
|
ir_binop_greater,
|
|
|
|
|
ir_binop_lequal,
|
|
|
|
|
ir_binop_gequal,
|
2010-09-08 01:31:39 +02:00
|
|
|
ir_binop_equal,
|
|
|
|
|
ir_binop_nequal,
|
2010-07-26 22:50:29 -07:00
|
|
|
/**
|
|
|
|
|
* Returns single boolean for whether all components of operands[0]
|
|
|
|
|
* equal the components of operands[1].
|
|
|
|
|
*/
|
2010-09-08 01:31:39 +02:00
|
|
|
ir_binop_all_equal,
|
2010-07-26 22:50:29 -07:00
|
|
|
/**
|
|
|
|
|
* Returns single boolean for whether any component of operands[0]
|
|
|
|
|
* is not equal to the corresponding component of operands[1].
|
|
|
|
|
*/
|
2010-09-08 01:31:39 +02:00
|
|
|
ir_binop_any_nequal,
|
2010-02-22 13:19:34 -08:00
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \name Bit-wise binary operations.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_binop_lshift,
|
|
|
|
|
ir_binop_rshift,
|
|
|
|
|
ir_binop_bit_and,
|
|
|
|
|
ir_binop_bit_xor,
|
|
|
|
|
ir_binop_bit_or,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
ir_binop_logic_and,
|
|
|
|
|
ir_binop_logic_xor,
|
|
|
|
|
ir_binop_logic_or,
|
|
|
|
|
|
|
|
|
|
ir_binop_dot,
|
|
|
|
|
ir_binop_min,
|
|
|
|
|
ir_binop_max,
|
|
|
|
|
|
2010-11-17 15:31:35 -08:00
|
|
|
ir_binop_pow,
|
|
|
|
|
|
2012-11-19 10:48:25 -08:00
|
|
|
/**
|
|
|
|
|
* \name Lowered floating point packing operations.
|
|
|
|
|
*
|
|
|
|
|
* \see lower_packing_builtins_visitor::split_pack_half_2x16
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_binop_pack_half_2x16_split,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2013-04-09 22:43:05 -07:00
|
|
|
/**
|
|
|
|
|
* \name First half of a lowered bitfieldInsert() operation.
|
|
|
|
|
*
|
|
|
|
|
* \see lower_instructions::bitfield_insert_to_bfm_bfi
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_binop_bfm,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
glsl: Add a "ubo_load" expression type for fetches from UBOs.
Drivers will probably want to be able to take UBO references in a
shader like:
uniform ubo1 {
float a;
float b;
float c;
float d;
}
void main() {
gl_FragColor = vec4(a, b, c, d);
}
and generate a single aligned vec4 load out of the UBO. For intel,
this involves recognizing the shared offset of the aligned loads and
CSEing them out. Obviously that involves breaking things down to
loads from an offset from a particular UBO first. Thus, the driver
doesn't want to see
variable_ref(ir_variable("a")),
and even more so does it not want to see
array_ref(record_ref(variable_ref(ir_variable("a")),
"field1"), variable_ref(ir_variable("i"))).
where a.field1[i] is a row_major matrix.
Instead, we're going to make a lowering pass to break UBO references
down to expressions that are obvious to codegen, and amenable to
merging through CSE.
v2: Fix some partial thoughts in the ir_binop comment (review by Kenneth)
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2012-07-09 15:52:53 -07:00
|
|
|
/**
|
|
|
|
|
* Load a value the size of a given GLSL type from a uniform block.
|
|
|
|
|
*
|
|
|
|
|
* operand0 is the ir_constant uniform block index in the linked shader.
|
|
|
|
|
* operand1 is a byte offset within the uniform block.
|
|
|
|
|
*/
|
|
|
|
|
ir_binop_ubo_load,
|
|
|
|
|
|
2013-08-22 13:31:18 -07:00
|
|
|
/**
|
|
|
|
|
* \name Multiplies a number by two to a power, part of ARB_gpu_shader5.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_binop_ldexp,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2013-03-06 11:05:14 -08:00
|
|
|
/**
|
|
|
|
|
* Extract a scalar from a vector
|
|
|
|
|
*
|
|
|
|
|
* operand0 is the vector
|
|
|
|
|
* operand1 is the index of the field to read from operand0
|
|
|
|
|
*/
|
|
|
|
|
ir_binop_vector_extract,
|
|
|
|
|
|
2010-11-17 15:31:35 -08:00
|
|
|
/**
|
|
|
|
|
* A sentinel marking the last of the binary operations.
|
|
|
|
|
*/
|
2013-03-06 11:05:14 -08:00
|
|
|
ir_last_binop = ir_binop_vector_extract,
|
2010-11-17 15:31:35 -08:00
|
|
|
|
2013-04-23 17:19:06 -07:00
|
|
|
/**
|
|
|
|
|
* \name Fused floating-point multiply-add, part of ARB_gpu_shader5.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_triop_fma,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2012-12-01 23:49:26 -08:00
|
|
|
ir_triop_lrp,
|
|
|
|
|
|
2013-08-19 10:45:46 -07:00
|
|
|
/**
|
|
|
|
|
* \name Conditional Select
|
|
|
|
|
*
|
|
|
|
|
* A vector conditional select instruction (like ?:, but operating per-
|
|
|
|
|
* component on vectors).
|
|
|
|
|
*
|
|
|
|
|
* \see lower_instructions_visitor::ldexp_to_arith
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_triop_csel,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2013-04-09 22:43:05 -07:00
|
|
|
/**
|
|
|
|
|
* \name Second half of a lowered bitfieldInsert() operation.
|
|
|
|
|
*
|
|
|
|
|
* \see lower_instructions::bitfield_insert_to_bfm_bfi
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
ir_triop_bfi,
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2013-04-09 17:45:12 -07:00
|
|
|
ir_triop_bitfield_extract,
|
|
|
|
|
|
2013-03-12 12:42:51 -07:00
|
|
|
/**
|
|
|
|
|
* Generate a value with one field of a vector changed
|
|
|
|
|
*
|
|
|
|
|
* operand0 is the vector
|
|
|
|
|
* operand1 is the value to write into the vector result
|
|
|
|
|
* operand2 is the index in operand0 to be modified
|
|
|
|
|
*/
|
|
|
|
|
ir_triop_vector_insert,
|
|
|
|
|
|
2012-12-01 23:49:26 -08:00
|
|
|
/**
|
|
|
|
|
* A sentinel marking the last of the ternary operations.
|
|
|
|
|
*/
|
2013-03-12 12:42:51 -07:00
|
|
|
ir_last_triop = ir_triop_vector_insert,
|
2013-04-09 17:45:12 -07:00
|
|
|
|
|
|
|
|
ir_quadop_bitfield_insert,
|
2012-12-01 23:49:26 -08:00
|
|
|
|
2010-11-16 12:01:42 -08:00
|
|
|
ir_quadop_vector,
|
|
|
|
|
|
2013-04-09 17:45:12 -07:00
|
|
|
/**
|
|
|
|
|
* A sentinel marking the last of the ternary operations.
|
|
|
|
|
*/
|
|
|
|
|
ir_last_quadop = ir_quadop_vector,
|
|
|
|
|
|
2010-11-17 15:31:35 -08:00
|
|
|
/**
|
|
|
|
|
* A sentinel marking the last of all operations.
|
|
|
|
|
*/
|
2012-03-29 10:51:24 -07:00
|
|
|
ir_last_opcode = ir_quadop_vector
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
class ir_expression : public ir_rvalue {
|
2010-02-22 13:19:34 -08:00
|
|
|
public:
|
2012-12-01 23:40:42 -08:00
|
|
|
ir_expression(int op, const struct glsl_type *type,
|
|
|
|
|
ir_rvalue *op0, ir_rvalue *op1 = NULL,
|
|
|
|
|
ir_rvalue *op2 = NULL, ir_rvalue *op3 = NULL);
|
|
|
|
|
|
2010-11-09 14:19:10 -08:00
|
|
|
/**
|
|
|
|
|
* Constructor for unary operation expressions
|
|
|
|
|
*/
|
2010-11-03 10:21:07 -07:00
|
|
|
ir_expression(int op, ir_rvalue *);
|
2010-11-09 14:19:10 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor for binary operation expressions
|
|
|
|
|
*/
|
2010-11-03 10:21:07 -07:00
|
|
|
ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1);
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2013-09-03 11:52:40 -07:00
|
|
|
/**
|
|
|
|
|
* Constructor for ternary operation expressions
|
|
|
|
|
*/
|
|
|
|
|
ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2);
|
|
|
|
|
|
2010-07-12 11:04:07 -07:00
|
|
|
virtual ir_expression *as_expression()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Attempt to constant-fold the expression
|
|
|
|
|
*
|
2012-05-02 23:11:38 +02:00
|
|
|
* The "variable_context" hash table links ir_variable * to ir_constant *
|
|
|
|
|
* that represent the variables' values. \c NULL represents an empty
|
|
|
|
|
* context.
|
|
|
|
|
*
|
2010-09-18 16:08:38 +02:00
|
|
|
* If the expression cannot be constant folded, this method will return
|
|
|
|
|
* \c NULL.
|
|
|
|
|
*/
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Determine the number of operands used by an expression
|
|
|
|
|
*/
|
2010-04-07 16:56:57 -07:00
|
|
|
static unsigned int get_num_operands(ir_expression_operation);
|
2010-09-18 16:08:38 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Determine the number of operands used by an expression
|
|
|
|
|
*/
|
2010-06-23 11:37:12 -07:00
|
|
|
unsigned int get_num_operands() const
|
2010-04-07 16:56:57 -07:00
|
|
|
{
|
2010-11-16 12:01:42 -08:00
|
|
|
return (this->operation == ir_quadop_vector)
|
|
|
|
|
? this->type->vector_elements : get_num_operands(operation);
|
2010-04-07 16:56:57 -07:00
|
|
|
}
|
2010-04-01 18:07:08 -10:00
|
|
|
|
2010-04-07 17:18:29 -07:00
|
|
|
/**
|
|
|
|
|
* Return a string representing this expression's operator.
|
|
|
|
|
*/
|
|
|
|
|
const char *operator_string();
|
|
|
|
|
|
2010-08-27 13:53:25 -07:00
|
|
|
/**
|
|
|
|
|
* Return a string representing this expression's operator.
|
|
|
|
|
*/
|
|
|
|
|
static const char *operator_string(ir_expression_operation);
|
|
|
|
|
|
|
|
|
|
|
2010-04-07 17:18:29 -07:00
|
|
|
/**
|
|
|
|
|
* Do a reverse-lookup to translate the given string into an operator.
|
|
|
|
|
*/
|
|
|
|
|
static ir_expression_operation get_operator(const char *);
|
|
|
|
|
|
2010-03-09 16:23:37 -08:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
ir_expression_operation operation;
|
2010-11-16 12:01:42 -08:00
|
|
|
ir_rvalue *operands[4];
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-03-11 14:34:27 -08:00
|
|
|
/**
|
glsl: Convert ir_call to be a statement rather than a value.
Aside from ir_call, our IR is cleanly split into two classes:
- Statements (typeless; used for side effects, control flow)
- Values (deeply nestable, pure, typed expression trees)
Unfortunately, ir_call confused all this:
- For void functions, we placed ir_call directly in the instruction
stream, treating it as an untyped statement. Yet, it was a subclass
of ir_rvalue, and no other ir_rvalue could be used in this way.
- For functions with a return value, ir_call could be placed in
arbitrary expression trees. While this fit naturally with the source
language, it meant that expressions might not be pure, making it
difficult to transform and optimize them. To combat this, we always
emitted ir_call directly in the RHS of an ir_assignment, only using
a temporary variable in expression trees. Many passes relied on this
assumption; the acos and atan built-ins violated it.
This patch makes ir_call a statement (ir_instruction) rather than a
value (ir_rvalue). Non-void calls now take a ir_dereference of a
variable, and store the return value there---effectively a call and
assignment rolled into one. They cannot be embedded in expressions.
All expression trees are now pure, without exception.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-03-20 15:56:37 -07:00
|
|
|
* HIR instruction representing a high-level function call, containing a list
|
|
|
|
|
* of parameters and returning a value in the supplied temporary.
|
2010-03-11 14:34:27 -08:00
|
|
|
*/
|
glsl: Convert ir_call to be a statement rather than a value.
Aside from ir_call, our IR is cleanly split into two classes:
- Statements (typeless; used for side effects, control flow)
- Values (deeply nestable, pure, typed expression trees)
Unfortunately, ir_call confused all this:
- For void functions, we placed ir_call directly in the instruction
stream, treating it as an untyped statement. Yet, it was a subclass
of ir_rvalue, and no other ir_rvalue could be used in this way.
- For functions with a return value, ir_call could be placed in
arbitrary expression trees. While this fit naturally with the source
language, it meant that expressions might not be pure, making it
difficult to transform and optimize them. To combat this, we always
emitted ir_call directly in the RHS of an ir_assignment, only using
a temporary variable in expression trees. Many passes relied on this
assumption; the acos and atan built-ins violated it.
This patch makes ir_call a statement (ir_instruction) rather than a
value (ir_rvalue). Non-void calls now take a ir_dereference of a
variable, and store the return value there---effectively a call and
assignment rolled into one. They cannot be embedded in expressions.
All expression trees are now pure, without exception.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-03-20 15:56:37 -07:00
|
|
|
class ir_call : public ir_instruction {
|
2010-03-11 14:34:27 -08:00
|
|
|
public:
|
glsl: Convert ir_call to be a statement rather than a value.
Aside from ir_call, our IR is cleanly split into two classes:
- Statements (typeless; used for side effects, control flow)
- Values (deeply nestable, pure, typed expression trees)
Unfortunately, ir_call confused all this:
- For void functions, we placed ir_call directly in the instruction
stream, treating it as an untyped statement. Yet, it was a subclass
of ir_rvalue, and no other ir_rvalue could be used in this way.
- For functions with a return value, ir_call could be placed in
arbitrary expression trees. While this fit naturally with the source
language, it meant that expressions might not be pure, making it
difficult to transform and optimize them. To combat this, we always
emitted ir_call directly in the RHS of an ir_assignment, only using
a temporary variable in expression trees. Many passes relied on this
assumption; the acos and atan built-ins violated it.
This patch makes ir_call a statement (ir_instruction) rather than a
value (ir_rvalue). Non-void calls now take a ir_dereference of a
variable, and store the return value there---effectively a call and
assignment rolled into one. They cannot be embedded in expressions.
All expression trees are now pure, without exception.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-03-20 15:56:37 -07:00
|
|
|
ir_call(ir_function_signature *callee,
|
|
|
|
|
ir_dereference_variable *return_deref,
|
|
|
|
|
exec_list *actual_parameters)
|
|
|
|
|
: return_deref(return_deref), callee(callee)
|
2010-03-11 14:34:27 -08:00
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
ir_type = ir_type_call;
|
2010-03-23 12:21:18 -07:00
|
|
|
assert(callee->return_type != NULL);
|
2010-03-11 14:50:30 -08:00
|
|
|
actual_parameters->move_nodes_to(& this->actual_parameters);
|
2013-08-30 16:12:55 -07:00
|
|
|
this->use_builtin = callee->is_builtin();
|
2010-03-11 14:34:27 -08:00
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-04-07 11:46:26 -07:00
|
|
|
virtual ir_call *as_call()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-11 14:34:27 -08:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-03-26 17:19:47 -07:00
|
|
|
/**
|
|
|
|
|
* Get an iterator for the set of acutal parameters
|
|
|
|
|
*/
|
|
|
|
|
exec_list_iterator iterator()
|
|
|
|
|
{
|
|
|
|
|
return actual_parameters.iterator();
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-26 17:29:29 -07:00
|
|
|
/**
|
|
|
|
|
* Get the name of the function being called.
|
|
|
|
|
*/
|
|
|
|
|
const char *callee_name() const
|
|
|
|
|
{
|
2010-03-31 16:44:12 -07:00
|
|
|
return callee->function_name();
|
2010-03-26 17:29:29 -07:00
|
|
|
}
|
|
|
|
|
|
2010-04-07 11:46:26 -07:00
|
|
|
/**
|
|
|
|
|
* Generates an inline version of the function before @ir,
|
glsl: Convert ir_call to be a statement rather than a value.
Aside from ir_call, our IR is cleanly split into two classes:
- Statements (typeless; used for side effects, control flow)
- Values (deeply nestable, pure, typed expression trees)
Unfortunately, ir_call confused all this:
- For void functions, we placed ir_call directly in the instruction
stream, treating it as an untyped statement. Yet, it was a subclass
of ir_rvalue, and no other ir_rvalue could be used in this way.
- For functions with a return value, ir_call could be placed in
arbitrary expression trees. While this fit naturally with the source
language, it meant that expressions might not be pure, making it
difficult to transform and optimize them. To combat this, we always
emitted ir_call directly in the RHS of an ir_assignment, only using
a temporary variable in expression trees. Many passes relied on this
assumption; the acos and atan built-ins violated it.
This patch makes ir_call a statement (ir_instruction) rather than a
value (ir_rvalue). Non-void calls now take a ir_dereference of a
variable, and store the return value there---effectively a call and
assignment rolled into one. They cannot be embedded in expressions.
All expression trees are now pure, without exception.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-03-20 15:56:37 -07:00
|
|
|
* storing the return value in return_deref.
|
2010-04-07 11:46:26 -07:00
|
|
|
*/
|
glsl: Convert ir_call to be a statement rather than a value.
Aside from ir_call, our IR is cleanly split into two classes:
- Statements (typeless; used for side effects, control flow)
- Values (deeply nestable, pure, typed expression trees)
Unfortunately, ir_call confused all this:
- For void functions, we placed ir_call directly in the instruction
stream, treating it as an untyped statement. Yet, it was a subclass
of ir_rvalue, and no other ir_rvalue could be used in this way.
- For functions with a return value, ir_call could be placed in
arbitrary expression trees. While this fit naturally with the source
language, it meant that expressions might not be pure, making it
difficult to transform and optimize them. To combat this, we always
emitted ir_call directly in the RHS of an ir_assignment, only using
a temporary variable in expression trees. Many passes relied on this
assumption; the acos and atan built-ins violated it.
This patch makes ir_call a statement (ir_instruction) rather than a
value (ir_rvalue). Non-void calls now take a ir_dereference of a
variable, and store the return value there---effectively a call and
assignment rolled into one. They cannot be embedded in expressions.
All expression trees are now pure, without exception.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-03-20 15:56:37 -07:00
|
|
|
void generate_inline(ir_instruction *ir);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Storage for the function's return value.
|
|
|
|
|
* This must be NULL if the return type is void.
|
|
|
|
|
*/
|
|
|
|
|
ir_dereference_variable *return_deref;
|
2010-04-07 11:46:26 -07:00
|
|
|
|
2011-09-20 18:08:11 -07:00
|
|
|
/**
|
|
|
|
|
* The specific function signature being called.
|
|
|
|
|
*/
|
|
|
|
|
ir_function_signature *callee;
|
|
|
|
|
|
2010-07-13 17:34:02 -07:00
|
|
|
/* List of ir_rvalue of paramaters passed in this call. */
|
|
|
|
|
exec_list actual_parameters;
|
|
|
|
|
|
2011-06-29 14:52:10 -07:00
|
|
|
/** Should this call only bind to a built-in function? */
|
|
|
|
|
bool use_builtin;
|
2010-03-11 14:34:27 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-03-19 16:44:52 -07:00
|
|
|
/**
|
|
|
|
|
* \name Jump-like IR instructions.
|
|
|
|
|
*
|
|
|
|
|
* These include \c break, \c continue, \c return, and \c discard.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
class ir_jump : public ir_instruction {
|
|
|
|
|
protected:
|
|
|
|
|
ir_jump()
|
|
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
ir_type = ir_type_unset;
|
2010-03-19 16:44:52 -07:00
|
|
|
}
|
2013-04-22 13:59:17 -07:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
virtual ir_jump *as_jump()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2010-03-19 16:44:52 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class ir_return : public ir_jump {
|
|
|
|
|
public:
|
|
|
|
|
ir_return()
|
|
|
|
|
: value(NULL)
|
|
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
this->ir_type = ir_type_return;
|
2010-03-19 16:44:52 -07:00
|
|
|
}
|
|
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
ir_return(ir_rvalue *value)
|
2010-03-19 16:44:52 -07:00
|
|
|
: value(value)
|
|
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
this->ir_type = ir_type_return;
|
2010-03-19 16:44:52 -07:00
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-04-07 11:46:26 -07:00
|
|
|
virtual ir_return *as_return()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
ir_rvalue *get_value() const
|
2010-03-19 16:44:52 -07:00
|
|
|
{
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
ir_rvalue *value;
|
2010-03-19 16:44:52 -07:00
|
|
|
};
|
2010-04-05 16:28:15 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Jump instructions used inside loops
|
|
|
|
|
*
|
|
|
|
|
* These include \c break and \c continue. The \c break within a loop is
|
|
|
|
|
* different from the \c break within a switch-statement.
|
|
|
|
|
*
|
|
|
|
|
* \sa ir_switch_jump
|
|
|
|
|
*/
|
|
|
|
|
class ir_loop_jump : public ir_jump {
|
|
|
|
|
public:
|
|
|
|
|
enum jump_mode {
|
|
|
|
|
jump_break,
|
|
|
|
|
jump_continue
|
|
|
|
|
};
|
|
|
|
|
|
2010-06-23 11:37:12 -07:00
|
|
|
ir_loop_jump(jump_mode mode)
|
2010-04-05 16:28:15 -07:00
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
this->ir_type = ir_type_loop_jump;
|
2010-05-07 12:35:47 -07:00
|
|
|
this->mode = mode;
|
2010-04-05 16:28:15 -07:00
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2010-04-05 16:28:15 -07:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-04-05 16:28:15 -07:00
|
|
|
bool is_break() const
|
|
|
|
|
{
|
|
|
|
|
return mode == jump_break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool is_continue() const
|
|
|
|
|
{
|
|
|
|
|
return mode == jump_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Mode selector for the jump instruction. */
|
|
|
|
|
enum jump_mode mode;
|
|
|
|
|
};
|
2010-06-30 10:47:34 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* IR instruction representing discard statements.
|
|
|
|
|
*/
|
|
|
|
|
class ir_discard : public ir_jump {
|
|
|
|
|
public:
|
|
|
|
|
ir_discard()
|
|
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
this->ir_type = ir_type_discard;
|
2010-06-30 10:47:34 -07:00
|
|
|
this->condition = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_discard(ir_rvalue *cond)
|
|
|
|
|
{
|
2010-08-04 16:31:04 +02:00
|
|
|
this->ir_type = ir_type_discard;
|
2010-06-30 10:47:34 -07:00
|
|
|
this->condition = cond;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_discard *clone(void *mem_ctx, struct hash_table *ht) const;
|
2010-06-30 10:47:34 -07:00
|
|
|
|
|
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-11-24 21:33:07 -08:00
|
|
|
virtual ir_discard *as_discard()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-30 10:47:34 -07:00
|
|
|
ir_rvalue *condition;
|
|
|
|
|
};
|
2010-03-19 16:44:52 -07:00
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
|
2010-04-28 18:42:36 -07:00
|
|
|
/**
|
|
|
|
|
* Texture sampling opcodes used in ir_texture
|
|
|
|
|
*/
|
|
|
|
|
enum ir_texture_opcode {
|
2010-09-18 16:08:38 +02:00
|
|
|
ir_tex, /**< Regular texture look-up */
|
|
|
|
|
ir_txb, /**< Texture look-up with LOD bias */
|
|
|
|
|
ir_txl, /**< Texture look-up with explicit LOD */
|
|
|
|
|
ir_txd, /**< Texture look-up with partial derivatvies */
|
2011-02-25 14:45:33 -08:00
|
|
|
ir_txf, /**< Texel fetch with explicit LOD */
|
2012-12-21 21:33:37 +13:00
|
|
|
ir_txf_ms, /**< Multisample texture fetch */
|
2012-09-23 19:50:41 +10:00
|
|
|
ir_txs, /**< Texture size */
|
2012-12-24 00:57:37 +01:00
|
|
|
ir_lod, /**< Texture lod query */
|
2013-09-26 19:37:30 +12:00
|
|
|
ir_tg4, /**< Texture gather */
|
|
|
|
|
ir_query_levels /**< Texture levels query */
|
2010-04-28 18:42:36 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* IR instruction to sample a texture
|
|
|
|
|
*
|
|
|
|
|
* The specific form of the IR instruction depends on the \c mode value
|
|
|
|
|
* selected from \c ir_texture_opcodes. In the printed IR, these will
|
|
|
|
|
* appear as:
|
|
|
|
|
*
|
2011-02-25 14:29:36 -08:00
|
|
|
* Texel offset (0 or an expression)
|
|
|
|
|
* | Projection divisor
|
|
|
|
|
* | | Shadow comparitor
|
|
|
|
|
* | | |
|
|
|
|
|
* v v v
|
|
|
|
|
* (tex <type> <sampler> <coordinate> 0 1 ( ))
|
|
|
|
|
* (txb <type> <sampler> <coordinate> 0 1 ( ) <bias>)
|
|
|
|
|
* (txl <type> <sampler> <coordinate> 0 1 ( ) <lod>)
|
|
|
|
|
* (txd <type> <sampler> <coordinate> 0 1 ( ) (dPdx dPdy))
|
|
|
|
|
* (txf <type> <sampler> <coordinate> 0 <lod>)
|
2012-12-21 21:33:37 +13:00
|
|
|
* (txf_ms
|
|
|
|
|
* <type> <sampler> <coordinate> <sample_index>)
|
2011-02-25 14:45:33 -08:00
|
|
|
* (txs <type> <sampler> <lod>)
|
2012-09-23 19:50:41 +10:00
|
|
|
* (lod <type> <sampler> <coordinate>)
|
2013-10-05 18:26:56 +13:00
|
|
|
* (tg4 <type> <sampler> <coordinate> <offset> <component>)
|
2013-09-26 19:37:30 +12:00
|
|
|
* (query_levels <type> <sampler>)
|
2010-04-28 18:42:36 -07:00
|
|
|
*/
|
|
|
|
|
class ir_texture : public ir_rvalue {
|
|
|
|
|
public:
|
|
|
|
|
ir_texture(enum ir_texture_opcode op)
|
2013-02-11 22:35:01 -08:00
|
|
|
: op(op), sampler(NULL), coordinate(NULL), projector(NULL),
|
|
|
|
|
shadow_comparitor(NULL), offset(NULL)
|
2010-04-28 18:42:36 -07:00
|
|
|
{
|
2010-07-19 09:05:42 -07:00
|
|
|
this->ir_type = ir_type_texture;
|
2013-09-01 23:18:37 -07:00
|
|
|
memset(&lod_info, 0, sizeof(lod_info));
|
2010-04-28 18:42:36 -07:00
|
|
|
}
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-05-26 17:42:03 -07:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-05-26 16:41:47 -07:00
|
|
|
/**
|
|
|
|
|
* Return a string representing the ir_texture_opcode.
|
|
|
|
|
*/
|
|
|
|
|
const char *opcode_string();
|
|
|
|
|
|
2011-02-25 14:29:36 -08:00
|
|
|
/** Set the sampler and type. */
|
|
|
|
|
void set_sampler(ir_dereference *sampler, const glsl_type *type);
|
2010-06-03 15:07:34 -07:00
|
|
|
|
2010-05-26 16:41:47 -07:00
|
|
|
/**
|
|
|
|
|
* Do a reverse-lookup to translate a string into an ir_texture_opcode.
|
|
|
|
|
*/
|
|
|
|
|
static ir_texture_opcode get_opcode(const char *);
|
|
|
|
|
|
2010-04-28 18:42:36 -07:00
|
|
|
enum ir_texture_opcode op;
|
|
|
|
|
|
|
|
|
|
/** Sampler to use for the texture access. */
|
|
|
|
|
ir_dereference *sampler;
|
|
|
|
|
|
|
|
|
|
/** Texture coordinate to sample */
|
|
|
|
|
ir_rvalue *coordinate;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Value used for projective divide.
|
|
|
|
|
*
|
|
|
|
|
* If there is no projective divide (the common case), this will be
|
|
|
|
|
* \c NULL. Optimization passes should check for this to point to a constant
|
|
|
|
|
* of 1.0 and replace that with \c NULL.
|
|
|
|
|
*/
|
|
|
|
|
ir_rvalue *projector;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Coordinate used for comparison on shadow look-ups.
|
|
|
|
|
*
|
|
|
|
|
* If there is no shadow comparison, this will be \c NULL. For the
|
|
|
|
|
* \c ir_txf opcode, this *must* be \c NULL.
|
|
|
|
|
*/
|
|
|
|
|
ir_rvalue *shadow_comparitor;
|
|
|
|
|
|
2011-01-08 23:49:23 -08:00
|
|
|
/** Texel offset. */
|
|
|
|
|
ir_rvalue *offset;
|
2010-04-28 18:42:36 -07:00
|
|
|
|
|
|
|
|
union {
|
|
|
|
|
ir_rvalue *lod; /**< Floating point LOD */
|
|
|
|
|
ir_rvalue *bias; /**< Floating point LOD bias */
|
2012-12-21 21:33:37 +13:00
|
|
|
ir_rvalue *sample_index; /**< MSAA sample index */
|
2013-10-05 18:26:56 +13:00
|
|
|
ir_rvalue *component; /**< Gather component selector */
|
2010-04-28 18:42:36 -07:00
|
|
|
struct {
|
|
|
|
|
ir_rvalue *dPdx; /**< Partial derivative of coordinate wrt X */
|
|
|
|
|
ir_rvalue *dPdy; /**< Partial derivative of coordinate wrt Y */
|
|
|
|
|
} grad;
|
|
|
|
|
} lod_info;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
struct ir_swizzle_mask {
|
|
|
|
|
unsigned x:2;
|
|
|
|
|
unsigned y:2;
|
|
|
|
|
unsigned z:2;
|
|
|
|
|
unsigned w:2;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Number of components in the swizzle.
|
|
|
|
|
*/
|
2010-03-25 11:22:42 -07:00
|
|
|
unsigned num_components:3;
|
2010-02-22 13:19:34 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Does the swizzle contain duplicate components?
|
|
|
|
|
*
|
|
|
|
|
* L-value swizzles cannot contain duplicate components.
|
|
|
|
|
*/
|
|
|
|
|
unsigned has_duplicates:1;
|
|
|
|
|
};
|
|
|
|
|
|
2010-03-26 01:20:08 -07:00
|
|
|
|
|
|
|
|
class ir_swizzle : public ir_rvalue {
|
|
|
|
|
public:
|
|
|
|
|
ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
|
|
|
|
|
unsigned count);
|
2010-06-25 15:25:27 -07:00
|
|
|
|
|
|
|
|
ir_swizzle(ir_rvalue *val, const unsigned *components, unsigned count);
|
|
|
|
|
|
2010-05-03 17:08:01 -07:00
|
|
|
ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask);
|
2010-04-07 11:46:26 -07:00
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-04-16 16:43:47 -07:00
|
|
|
virtual ir_swizzle *as_swizzle()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-26 01:20:08 -07:00
|
|
|
/**
|
|
|
|
|
* Construct an ir_swizzle from the textual representation. Can fail.
|
|
|
|
|
*/
|
|
|
|
|
static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
|
|
|
|
|
|
|
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2011-08-02 15:22:25 -07:00
|
|
|
bool is_lvalue() const
|
2010-03-26 01:20:08 -07:00
|
|
|
{
|
2010-03-28 01:29:18 -07:00
|
|
|
return val->is_lvalue() && !mask.has_duplicates;
|
2010-03-26 01:20:08 -07:00
|
|
|
}
|
|
|
|
|
|
2010-05-14 17:35:42 -07:00
|
|
|
/**
|
|
|
|
|
* Get the variable that is ultimately referenced by an r-value
|
|
|
|
|
*/
|
2011-08-02 15:22:25 -07:00
|
|
|
virtual ir_variable *variable_referenced() const;
|
2010-05-14 17:35:42 -07:00
|
|
|
|
2010-03-26 01:20:08 -07:00
|
|
|
ir_rvalue *val;
|
|
|
|
|
ir_swizzle_mask mask;
|
2010-06-25 15:25:27 -07:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the mask component of a swizzle
|
|
|
|
|
*
|
|
|
|
|
* This is used by the \c ir_swizzle constructors.
|
|
|
|
|
*/
|
|
|
|
|
void init_mask(const unsigned *components, unsigned count);
|
2010-03-26 01:20:08 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
class ir_dereference : public ir_rvalue {
|
2010-02-22 13:19:34 -08:00
|
|
|
public:
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
|
2010-07-06 17:41:02 -07:00
|
|
|
|
2010-03-25 23:30:28 -07:00
|
|
|
virtual ir_dereference *as_dereference()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-02 15:22:25 -07:00
|
|
|
bool is_lvalue() const;
|
2010-03-26 00:25:36 -07:00
|
|
|
|
2010-05-14 17:35:42 -07:00
|
|
|
/**
|
|
|
|
|
* Get the variable that is ultimately referenced by an r-value
|
|
|
|
|
*/
|
2011-08-02 15:22:25 -07:00
|
|
|
virtual ir_variable *variable_referenced() const = 0;
|
2012-05-02 23:11:39 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the constant that is ultimately referenced by an r-value,
|
|
|
|
|
* in a constant expression evaluation context.
|
|
|
|
|
*
|
|
|
|
|
* The offset is used when the reference is to a specific column of
|
|
|
|
|
* a matrix.
|
|
|
|
|
*/
|
|
|
|
|
virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const = 0;
|
2010-05-19 11:37:35 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ir_dereference_variable : public ir_dereference {
|
|
|
|
|
public:
|
|
|
|
|
ir_dereference_variable(ir_variable *var);
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_dereference_variable *clone(void *mem_ctx,
|
|
|
|
|
struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-06-29 14:16:11 -07:00
|
|
|
virtual ir_dereference_variable *as_dereference_variable()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 11:37:35 +02:00
|
|
|
/**
|
|
|
|
|
* Get the variable that is ultimately referenced by an r-value
|
|
|
|
|
*/
|
2011-08-02 15:22:25 -07:00
|
|
|
virtual ir_variable *variable_referenced() const
|
2010-05-19 11:37:35 +02:00
|
|
|
{
|
2010-05-19 13:52:29 +02:00
|
|
|
return this->var;
|
2010-05-19 11:37:35 +02:00
|
|
|
}
|
2010-05-19 12:02:19 +02:00
|
|
|
|
2012-05-02 23:11:39 +02:00
|
|
|
/**
|
|
|
|
|
* Get the constant that is ultimately referenced by an r-value,
|
|
|
|
|
* in a constant expression evaluation context.
|
|
|
|
|
*
|
|
|
|
|
* The offset is used when the reference is to a specific column of
|
|
|
|
|
* a matrix.
|
|
|
|
|
*/
|
|
|
|
|
virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
|
|
|
|
|
|
2010-05-26 11:32:52 -07:00
|
|
|
virtual ir_variable *whole_variable_referenced()
|
|
|
|
|
{
|
|
|
|
|
/* ir_dereference_variable objects always dereference the entire
|
|
|
|
|
* variable. However, if this dereference is dereferenced by anything
|
|
|
|
|
* else, the complete deferefernce chain is not a whole-variable
|
|
|
|
|
* dereference. This method should only be called on the top most
|
|
|
|
|
* ir_rvalue in a dereference chain.
|
|
|
|
|
*/
|
|
|
|
|
return this->var;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 13:20:12 +02:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 12:02:19 +02:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
2010-05-19 13:52:29 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Object being dereferenced.
|
|
|
|
|
*/
|
|
|
|
|
ir_variable *var;
|
2010-05-19 11:37:35 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ir_dereference_array : public ir_dereference {
|
|
|
|
|
public:
|
|
|
|
|
ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index);
|
|
|
|
|
|
|
|
|
|
ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_dereference_array *clone(void *mem_ctx,
|
|
|
|
|
struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-05-11 11:31:09 -07:00
|
|
|
virtual ir_dereference_array *as_dereference_array()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 11:37:35 +02:00
|
|
|
/**
|
|
|
|
|
* Get the variable that is ultimately referenced by an r-value
|
|
|
|
|
*/
|
2011-08-02 15:22:25 -07:00
|
|
|
virtual ir_variable *variable_referenced() const
|
2010-05-19 11:37:35 +02:00
|
|
|
{
|
2010-05-19 13:52:29 +02:00
|
|
|
return this->array->variable_referenced();
|
2010-05-19 11:37:35 +02:00
|
|
|
}
|
|
|
|
|
|
2012-05-02 23:11:39 +02:00
|
|
|
/**
|
|
|
|
|
* Get the constant that is ultimately referenced by an r-value,
|
|
|
|
|
* in a constant expression evaluation context.
|
|
|
|
|
*
|
|
|
|
|
* The offset is used when the reference is to a specific column of
|
|
|
|
|
* a matrix.
|
|
|
|
|
*/
|
|
|
|
|
virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
|
|
|
|
|
|
2010-05-19 13:20:12 +02:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 12:02:19 +02:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
2010-05-19 11:37:35 +02:00
|
|
|
|
2010-05-19 13:52:29 +02:00
|
|
|
ir_rvalue *array;
|
|
|
|
|
ir_rvalue *array_index;
|
|
|
|
|
|
2010-05-19 11:37:35 +02:00
|
|
|
private:
|
|
|
|
|
void set_array(ir_rvalue *value);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ir_dereference_record : public ir_dereference {
|
|
|
|
|
public:
|
|
|
|
|
ir_dereference_record(ir_rvalue *value, const char *field);
|
|
|
|
|
|
|
|
|
|
ir_dereference_record(ir_variable *var, const char *field);
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_dereference_record *clone(void *mem_ctx,
|
|
|
|
|
struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2013-03-09 17:12:09 -08:00
|
|
|
virtual ir_dereference_record *as_dereference_record()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 11:37:35 +02:00
|
|
|
/**
|
|
|
|
|
* Get the variable that is ultimately referenced by an r-value
|
|
|
|
|
*/
|
2011-08-02 15:22:25 -07:00
|
|
|
virtual ir_variable *variable_referenced() const
|
2010-05-19 11:37:35 +02:00
|
|
|
{
|
2010-05-19 13:52:29 +02:00
|
|
|
return this->record->variable_referenced();
|
2010-05-19 11:37:35 +02:00
|
|
|
}
|
2010-05-19 12:02:19 +02:00
|
|
|
|
2012-05-02 23:11:39 +02:00
|
|
|
/**
|
|
|
|
|
* Get the constant that is ultimately referenced by an r-value,
|
|
|
|
|
* in a constant expression evaluation context.
|
|
|
|
|
*
|
|
|
|
|
* The offset is used when the reference is to a specific column of
|
|
|
|
|
* a matrix.
|
|
|
|
|
*/
|
|
|
|
|
virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
|
|
|
|
|
|
2010-05-19 13:20:12 +02:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 12:02:19 +02:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
2010-05-19 13:52:29 +02:00
|
|
|
|
|
|
|
|
ir_rvalue *record;
|
|
|
|
|
const char *field;
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-06-11 14:01:44 -07:00
|
|
|
/**
|
|
|
|
|
* Data stored in an ir_constant
|
|
|
|
|
*/
|
|
|
|
|
union ir_constant_data {
|
|
|
|
|
unsigned u[16];
|
|
|
|
|
int i[16];
|
|
|
|
|
float f[16];
|
|
|
|
|
bool b[16];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-03-26 00:25:36 -07:00
|
|
|
class ir_constant : public ir_rvalue {
|
2010-02-22 13:19:34 -08:00
|
|
|
public:
|
2010-06-11 16:57:47 -07:00
|
|
|
ir_constant(const struct glsl_type *type, const ir_constant_data *data);
|
2013-08-05 15:15:37 -07:00
|
|
|
ir_constant(bool b, unsigned vector_elements=1);
|
|
|
|
|
ir_constant(unsigned int u, unsigned vector_elements=1);
|
|
|
|
|
ir_constant(int i, unsigned vector_elements=1);
|
|
|
|
|
ir_constant(float f, unsigned vector_elements=1);
|
2010-02-22 13:19:34 -08:00
|
|
|
|
2010-06-04 16:34:38 -07:00
|
|
|
/**
|
|
|
|
|
* Construct an ir_constant from a list of ir_constant values
|
|
|
|
|
*/
|
|
|
|
|
ir_constant(const struct glsl_type *type, exec_list *values);
|
|
|
|
|
|
2010-06-04 16:13:35 -07:00
|
|
|
/**
|
|
|
|
|
* Construct an ir_constant from a scalar component of another ir_constant
|
|
|
|
|
*
|
|
|
|
|
* The new \c ir_constant inherits the type of the component from the
|
|
|
|
|
* source constant.
|
|
|
|
|
*
|
|
|
|
|
* \note
|
|
|
|
|
* In the case of a matrix constant, the new constant is a scalar, \b not
|
|
|
|
|
* a vector.
|
|
|
|
|
*/
|
|
|
|
|
ir_constant(const ir_constant *c, unsigned i);
|
|
|
|
|
|
2010-07-21 15:54:15 -07:00
|
|
|
/**
|
|
|
|
|
* Return a new ir_constant of the specified type containing all zeros.
|
|
|
|
|
*/
|
|
|
|
|
static ir_constant *zero(void *mem_ctx, const glsl_type *type);
|
|
|
|
|
|
2010-08-04 12:34:56 -07:00
|
|
|
virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
|
2010-06-23 11:37:12 -07:00
|
|
|
|
2012-05-02 23:11:38 +02:00
|
|
|
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
|
2010-07-15 10:09:09 -07:00
|
|
|
|
2010-05-04 13:04:40 -07:00
|
|
|
virtual ir_constant *as_constant()
|
|
|
|
|
{
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-09 16:23:37 -08:00
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-14 12:39:23 -07:00
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
|
2010-06-04 16:30:07 -07:00
|
|
|
/**
|
|
|
|
|
* Get a particular component of a constant as a specific type
|
|
|
|
|
*
|
|
|
|
|
* This is useful, for example, to get a value from an integer constant
|
|
|
|
|
* as a float or bool. This appears frequently when constructors are
|
|
|
|
|
* called with all constant parameters.
|
|
|
|
|
*/
|
|
|
|
|
/*@{*/
|
|
|
|
|
bool get_bool_component(unsigned i) const;
|
|
|
|
|
float get_float_component(unsigned i) const;
|
|
|
|
|
int get_int_component(unsigned i) const;
|
|
|
|
|
unsigned get_uint_component(unsigned i) const;
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
2010-07-20 01:06:33 -07:00
|
|
|
ir_constant *get_array_element(unsigned i) const;
|
|
|
|
|
|
2010-06-09 17:28:54 -07:00
|
|
|
ir_constant *get_record_field(const char *name);
|
|
|
|
|
|
2012-05-02 23:11:40 +02:00
|
|
|
/**
|
|
|
|
|
* Copy the values on another constant at a given offset.
|
|
|
|
|
*
|
|
|
|
|
* The offset is ignored for array or struct copies, it's only for
|
|
|
|
|
* scalars or vectors into vectors or matrices.
|
|
|
|
|
*
|
|
|
|
|
* With identical types on both sides and zero offset it's clone()
|
|
|
|
|
* without creating a new object.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void copy_offset(ir_constant *src, int offset);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Copy the values on another constant at a given offset and
|
|
|
|
|
* following an assign-like mask.
|
|
|
|
|
*
|
|
|
|
|
* The mask is ignored for scalars.
|
|
|
|
|
*
|
|
|
|
|
* Note that this function only handles what assign can handle,
|
|
|
|
|
* i.e. at most a vector as source and a column of a matrix as
|
|
|
|
|
* destination.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void copy_masked_offset(ir_constant *src, int offset, unsigned int mask);
|
|
|
|
|
|
2010-06-17 19:50:36 -07:00
|
|
|
/**
|
|
|
|
|
* Determine whether a constant has the same value as another constant
|
2010-11-12 10:19:08 -08:00
|
|
|
*
|
2010-11-16 11:59:22 -08:00
|
|
|
* \sa ir_constant::is_zero, ir_constant::is_one,
|
2012-06-04 16:26:32 -04:00
|
|
|
* ir_constant::is_negative_one, ir_constant::is_basis
|
2010-06-17 19:50:36 -07:00
|
|
|
*/
|
|
|
|
|
bool has_value(const ir_constant *) const;
|
|
|
|
|
|
2010-11-18 17:11:17 -08:00
|
|
|
virtual bool is_zero() const;
|
|
|
|
|
virtual bool is_one() const;
|
2010-11-16 11:59:22 -08:00
|
|
|
virtual bool is_negative_one() const;
|
2012-06-04 16:26:32 -04:00
|
|
|
virtual bool is_basis() const;
|
2010-11-12 10:19:08 -08:00
|
|
|
|
2010-02-22 13:19:34 -08:00
|
|
|
/**
|
|
|
|
|
* Value of the constant.
|
|
|
|
|
*
|
|
|
|
|
* The field used to back the values supplied by the constant is determined
|
|
|
|
|
* by the type associated with the \c ir_instruction. Constants may be
|
|
|
|
|
* scalars, vectors, or matrices.
|
|
|
|
|
*/
|
2010-06-11 14:01:44 -07:00
|
|
|
union ir_constant_data value;
|
2010-06-09 17:11:50 -07:00
|
|
|
|
2010-07-20 01:06:33 -07:00
|
|
|
/* Array elements */
|
|
|
|
|
ir_constant **array_elements;
|
|
|
|
|
|
|
|
|
|
/* Structure fields */
|
2010-06-09 17:11:50 -07:00
|
|
|
exec_list components;
|
2010-06-09 17:18:04 -07:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
/**
|
|
|
|
|
* Parameterless constructor only used by the clone method
|
|
|
|
|
*/
|
|
|
|
|
ir_constant(void);
|
2010-02-22 13:19:34 -08:00
|
|
|
};
|
|
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/*@}*/
|
|
|
|
|
|
2013-02-15 09:26:35 -06:00
|
|
|
/**
|
|
|
|
|
* IR instruction to emit a vertex in a geometry shader.
|
|
|
|
|
*/
|
|
|
|
|
class ir_emit_vertex : public ir_instruction {
|
|
|
|
|
public:
|
|
|
|
|
ir_emit_vertex()
|
|
|
|
|
{
|
|
|
|
|
ir_type = ir_type_emit_vertex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const
|
|
|
|
|
{
|
|
|
|
|
return new(mem_ctx) ir_emit_vertex();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* IR instruction to complete the current primitive and start a new one in a
|
|
|
|
|
* geometry shader.
|
|
|
|
|
*/
|
|
|
|
|
class ir_end_primitive : public ir_instruction {
|
|
|
|
|
public:
|
|
|
|
|
ir_end_primitive()
|
|
|
|
|
{
|
|
|
|
|
ir_type = ir_type_end_primitive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void accept(ir_visitor *v)
|
|
|
|
|
{
|
|
|
|
|
v->visit(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const
|
|
|
|
|
{
|
|
|
|
|
return new(mem_ctx) ir_end_primitive();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
|
|
|
|
|
};
|
|
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Apply a visitor to each IR node in a list
|
|
|
|
|
*/
|
2010-04-06 11:52:09 -07:00
|
|
|
void
|
|
|
|
|
visit_exec_list(exec_list *list, ir_visitor *visitor);
|
2010-03-10 10:43:16 -08:00
|
|
|
|
2010-09-18 16:08:38 +02:00
|
|
|
/**
|
|
|
|
|
* Validate invariants on each IR node in a list
|
|
|
|
|
*/
|
2010-06-22 12:07:21 -07:00
|
|
|
void validate_ir_tree(exec_list *instructions);
|
|
|
|
|
|
2011-07-11 10:46:01 -07:00
|
|
|
struct _mesa_glsl_parse_state;
|
|
|
|
|
struct gl_shader_program;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Detect whether an unlinked shader contains static recursion
|
|
|
|
|
*
|
|
|
|
|
* If the list of instructions is determined to contain static recursion,
|
|
|
|
|
* \c _mesa_glsl_error will be called to emit error messages for each function
|
|
|
|
|
* that is in the recursion cycle.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
detect_recursion_unlinked(struct _mesa_glsl_parse_state *state,
|
|
|
|
|
exec_list *instructions);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Detect whether a linked shader contains static recursion
|
|
|
|
|
*
|
|
|
|
|
* If the list of instructions is determined to contain static recursion,
|
|
|
|
|
* \c link_error_printf will be called to emit error messages for each function
|
|
|
|
|
* that is in the recursion cycle. In addition,
|
|
|
|
|
* \c gl_shader_program::LinkStatus will be set to false.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
detect_recursion_linked(struct gl_shader_program *prog,
|
|
|
|
|
exec_list *instructions);
|
|
|
|
|
|
2010-07-06 16:01:06 -07:00
|
|
|
/**
|
|
|
|
|
* Make a clone of each IR instruction in a list
|
|
|
|
|
*
|
|
|
|
|
* \param in List of IR instructions that are to be cloned
|
|
|
|
|
* \param out List to hold the cloned instructions
|
|
|
|
|
*/
|
|
|
|
|
void
|
2010-08-04 12:34:56 -07:00
|
|
|
clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in);
|
2010-07-06 16:01:06 -07:00
|
|
|
|
2010-03-10 10:43:16 -08:00
|
|
|
extern void
|
|
|
|
|
_mesa_glsl_initialize_variables(exec_list *instructions,
|
|
|
|
|
struct _mesa_glsl_parse_state *state);
|
2010-03-15 15:20:15 -07:00
|
|
|
|
2010-03-26 18:20:30 -07:00
|
|
|
extern void
|
2011-01-01 12:01:09 -08:00
|
|
|
_mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state);
|
2010-03-26 18:20:30 -07:00
|
|
|
|
2013-08-29 23:06:39 -07:00
|
|
|
extern void
|
|
|
|
|
_mesa_glsl_initialize_builtin_functions();
|
|
|
|
|
|
|
|
|
|
extern ir_function_signature *
|
|
|
|
|
_mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
|
|
|
|
|
const char *name, exec_list *actual_parameters);
|
|
|
|
|
|
2010-07-20 11:29:46 -07:00
|
|
|
extern void
|
|
|
|
|
_mesa_glsl_release_functions(void);
|
|
|
|
|
|
2013-08-29 23:06:39 -07:00
|
|
|
extern void
|
|
|
|
|
_mesa_glsl_release_builtin_functions(void);
|
|
|
|
|
|
2010-07-20 11:27:38 -07:00
|
|
|
extern void
|
|
|
|
|
reparent_ir(exec_list *list, void *mem_ctx);
|
|
|
|
|
|
2010-08-14 15:35:57 +01:00
|
|
|
struct glsl_symbol_table;
|
2010-07-20 11:28:31 -07:00
|
|
|
|
|
|
|
|
extern void
|
|
|
|
|
import_prototypes(const exec_list *source, exec_list *dest,
|
2010-08-14 15:35:57 +01:00
|
|
|
struct glsl_symbol_table *symbols, void *mem_ctx);
|
2010-07-20 11:28:31 -07:00
|
|
|
|
2010-08-05 12:10:31 -07:00
|
|
|
extern bool
|
|
|
|
|
ir_has_call(ir_instruction *ir);
|
|
|
|
|
|
2010-08-06 13:07:25 -07:00
|
|
|
extern void
|
2011-10-25 18:06:37 -07:00
|
|
|
do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
|
2013-07-30 20:49:56 -07:00
|
|
|
GLenum shader_type);
|
2010-08-06 13:07:25 -07:00
|
|
|
|
2011-07-08 10:34:38 -07:00
|
|
|
extern char *
|
|
|
|
|
prototype_string(const glsl_type *return_type, const char *name,
|
|
|
|
|
exec_list *parameters);
|
|
|
|
|
|
2013-06-12 16:10:33 -07:00
|
|
|
extern "C" {
|
2013-03-22 13:29:55 -07:00
|
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
2013-06-12 16:10:33 -07:00
|
|
|
extern void _mesa_print_ir(struct exec_list *instructions,
|
|
|
|
|
struct _mesa_glsl_parse_state *state);
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
} /* extern "C" */
|
|
|
|
|
#endif
|
|
|
|
|
|
2013-02-15 09:46:50 -06:00
|
|
|
unsigned
|
|
|
|
|
vertices_per_prim(GLenum prim);
|
|
|
|
|
|
2010-03-15 15:20:15 -07:00
|
|
|
#endif /* IR_H */
|