#include "st_format.h"
#include "st_glsl_types.h"
#include "st_nir.h"
+#include "st_shader_cache.h"
#include <algorithm>
bool have_sqrt;
bool have_fma;
bool use_shared_memory;
+ bool has_tex_txf_lz;
variable_storage *find_variable_storage(ir_variable *var);
emit_scalar(ir, TGSI_OPCODE_EX2, result_dst, op[0]);
break;
case ir_unop_exp:
+ assert(!"not reached: should be handled by exp_to_exp2");
+ break;
case ir_unop_log:
- assert(!"not reached: should be handled by ir_explog_to_explog2");
+ assert(!"not reached: should be handled by log_to_log2");
break;
case ir_unop_log2:
emit_scalar(ir, TGSI_OPCODE_LG2, result_dst, op[0]);
break;
}
case ir_binop_lshift:
- if (native_integers) {
- emit_asm(ir, TGSI_OPCODE_SHL, result_dst, op[0], op[1]);
- break;
- }
case ir_binop_rshift:
if (native_integers) {
- emit_asm(ir, TGSI_OPCODE_ISHR, result_dst, op[0], op[1]);
+ unsigned opcode = ir->operation == ir_binop_lshift ? TGSI_OPCODE_SHL
+ : TGSI_OPCODE_ISHR;
+ st_src_reg count;
+
+ if (glsl_base_type_is_64bit(op[0].type)) {
+ /* GLSL shift operations have 32-bit shift counts, but TGSI uses
+ * 64 bits.
+ */
+ count = get_temp(glsl_type::u64vec(ir->operands[1]->type->components()));
+ emit_asm(ir, TGSI_OPCODE_U2I64, st_dst_reg(count), op[1]);
+ } else {
+ count = op[1];
+ }
+
+ emit_asm(ir, opcode, result_dst, op[0], count);
break;
}
case ir_binop_bit_and:
const_offset % 16 / 4,
const_offset % 16 / 4);
- if (ir->type->base_type == GLSL_TYPE_BOOL) {
+ if (ir->type->is_boolean()) {
emit_asm(ir, TGSI_OPCODE_USNE, result_dst, cbuf, st_src_reg_for_int(0));
} else {
emit_asm(ir, TGSI_OPCODE_MOV, result_dst, cbuf);
break;
case ir_binop_ldexp:
- if (ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE) {
+ if (ir->operands[0]->type->is_double()) {
emit_asm(ir, TGSI_OPCODE_DLDEXP, result_dst, op[0], op[1]);
} else {
assert(!"Invalid ldexp for non-double opcode in glsl_to_tgsi_visitor::visit()");
case ir_unop_vote_eq:
emit_asm(ir, TGSI_OPCODE_VOTE_EQ, result_dst, op[0]);
break;
+ case ir_unop_ballot:
+ emit_asm(ir, TGSI_OPCODE_BALLOT, result_dst, op[0]);
+ break;
+ case ir_unop_read_first_invocation:
+ emit_asm(ir, TGSI_OPCODE_READ_FIRST, result_dst, op[0]);
+ break;
+ case ir_binop_read_invocation:
+ emit_asm(ir, TGSI_OPCODE_READ_INVOC, result_dst, op[0], op[1]);
+ break;
case ir_unop_u2i64:
case ir_unop_u2u64:
case ir_unop_b2i64: {
st_dst_reg *l, st_src_reg *r,
st_src_reg *cond, bool cond_swap)
{
- if (type->base_type == GLSL_TYPE_STRUCT) {
+ if (type->is_record()) {
for (unsigned int i = 0; i < type->length; i++) {
emit_block_mov(ir, type->fields.structure[i].type, l, r,
cond, cond_swap);
* aggregate constant and move each constant value into it. If we
* get lucky, copy propagation will eliminate the extra moves.
*/
- if (ir->type->base_type == GLSL_TYPE_STRUCT) {
+ if (ir->type->is_record()) {
st_src_reg temp_base = get_temp(ir->type);
st_dst_reg temp = st_dst_reg(temp_base);
inst->resource = buffer;
if (access)
inst->buffer_access = access->value.u[0];
+
+ if (inst == this->instructions.get_head_raw())
+ break;
inst = (glsl_to_tgsi_instruction *)inst->get_prev();
- if (inst->op == TGSI_OPCODE_UADD)
+
+ if (inst->op == TGSI_OPCODE_UADD) {
+ if (inst == this->instructions.get_head_raw())
+ break;
inst = (glsl_to_tgsi_instruction *)inst->get_prev();
- } while (inst && inst->op == op && inst->resource.file == PROGRAM_UNDEFINED);
+ }
+ } while (inst->op == op && inst->resource.file == PROGRAM_UNDEFINED);
}
void
inst->sampler_array_size = sampler_array_size;
inst->sampler_base = sampler_base;
- switch (type->sampler_dimensionality) {
- case GLSL_SAMPLER_DIM_1D:
- inst->tex_target = (type->sampler_array)
- ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_2D:
- inst->tex_target = (type->sampler_array)
- ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_3D:
- inst->tex_target = TEXTURE_3D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_CUBE:
- inst->tex_target = (type->sampler_array)
- ? TEXTURE_CUBE_ARRAY_INDEX : TEXTURE_CUBE_INDEX;
- break;
- case GLSL_SAMPLER_DIM_RECT:
- inst->tex_target = TEXTURE_RECT_INDEX;
- break;
- case GLSL_SAMPLER_DIM_BUF:
- inst->tex_target = TEXTURE_BUFFER_INDEX;
- break;
- case GLSL_SAMPLER_DIM_EXTERNAL:
- inst->tex_target = TEXTURE_EXTERNAL_INDEX;
- break;
- case GLSL_SAMPLER_DIM_MS:
- inst->tex_target = (type->sampler_array)
- ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
- break;
- default:
- assert(!"Should not get here.");
- }
-
+ inst->tex_target = type->sampler_index();
inst->image_format = st_mesa_format_to_pipe_format(st_context(ctx),
_mesa_get_shader_image_format(imgvar->data.image_format));
visit_image_intrinsic(ir);
return;
+ case ir_intrinsic_shader_clock: {
+ ir->return_deref->accept(this);
+
+ st_dst_reg dst = st_dst_reg(this->result);
+ dst.writemask = TGSI_WRITEMASK_XY;
+
+ emit_asm(ir, TGSI_OPCODE_CLOCK, dst);
+ return;
+ }
+
case ir_intrinsic_invalid:
case ir_intrinsic_generic_load:
case ir_intrinsic_generic_store:
case ir_intrinsic_generic_atomic_max:
case ir_intrinsic_generic_atomic_exchange:
case ir_intrinsic_generic_atomic_comp_swap:
- case ir_intrinsic_shader_clock:
unreachable("Invalid intrinsic");
}
}
const glsl_type *sampler_type = ir->sampler->type;
unsigned sampler_array_size = 1, sampler_base = 0;
uint16_t sampler_index = 0;
- bool is_cube_array = false;
+ bool is_cube_array = false, is_cube_shadow = false;
unsigned i;
- /* if we are a cube array sampler */
- if ((sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
- sampler_type->sampler_array)) {
- is_cube_array = true;
+ /* if we are a cube array sampler or a cube shadow */
+ if (sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) {
+ is_cube_array = sampler_type->sampler_array;
+ is_cube_shadow = sampler_type->sampler_shadow;
}
if (ir->coordinate) {
*/
result_src = get_temp(ir->type);
result_dst = st_dst_reg(result_src);
+ result_dst.writemask = (1 << ir->type->vector_elements) - 1;
switch (ir->op) {
case ir_tex:
}
break;
case ir_txb:
- if (is_cube_array ||
- sampler_type == glsl_type::samplerCubeShadow_type) {
+ if (is_cube_array || is_cube_shadow) {
opcode = TGSI_OPCODE_TXB2;
}
else {
}
break;
case ir_txl:
- opcode = is_cube_array ? TGSI_OPCODE_TXL2 : TGSI_OPCODE_TXL;
- ir->lod_info.lod->accept(this);
- lod_info = this->result;
+ if (this->has_tex_txf_lz && ir->lod_info.lod->is_zero()) {
+ opcode = TGSI_OPCODE_TEX_LZ;
+ } else {
+ opcode = is_cube_array ? TGSI_OPCODE_TXL2 : TGSI_OPCODE_TXL;
+ ir->lod_info.lod->accept(this);
+ lod_info = this->result;
+ }
if (ir->offset) {
ir->offset->accept(this);
offset[0] = this->result;
levels_src = get_temp(ir->type);
break;
case ir_txf:
- opcode = TGSI_OPCODE_TXF;
- ir->lod_info.lod->accept(this);
- lod_info = this->result;
+ if (this->has_tex_txf_lz && ir->lod_info.lod->is_zero()) {
+ opcode = TGSI_OPCODE_TXF_LZ;
+ } else {
+ opcode = TGSI_OPCODE_TXF;
+ ir->lod_info.lod->accept(this);
+ lod_info = this->result;
+ }
if (ir->offset) {
ir->offset->accept(this);
offset[0] = this->result;
component = this->result;
if (ir->offset) {
ir->offset->accept(this);
- if (ir->offset->type->base_type == GLSL_TYPE_ARRAY) {
+ if (ir->offset->type->is_array()) {
const glsl_type *elt_type = ir->offset->type->fields.array;
for (i = 0; i < ir->offset->type->length; i++) {
offset[i] = this->result;
inst = emit_asm(ir, opcode, result_dst, lod_info);
} else if (opcode == TGSI_OPCODE_TXQS) {
inst = emit_asm(ir, opcode, result_dst);
- } else if (opcode == TGSI_OPCODE_TXF) {
- inst = emit_asm(ir, opcode, result_dst, coord);
} else if (opcode == TGSI_OPCODE_TXL2 || opcode == TGSI_OPCODE_TXB2) {
inst = emit_asm(ir, opcode, result_dst, coord, lod_info);
} else if (opcode == TGSI_OPCODE_TEX2) {
inst->tex_offset_num_offset = i;
}
- switch (sampler_type->sampler_dimensionality) {
- case GLSL_SAMPLER_DIM_1D:
- inst->tex_target = (sampler_type->sampler_array)
- ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_2D:
- inst->tex_target = (sampler_type->sampler_array)
- ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_3D:
- inst->tex_target = TEXTURE_3D_INDEX;
- break;
- case GLSL_SAMPLER_DIM_CUBE:
- inst->tex_target = (sampler_type->sampler_array)
- ? TEXTURE_CUBE_ARRAY_INDEX : TEXTURE_CUBE_INDEX;
- break;
- case GLSL_SAMPLER_DIM_RECT:
- inst->tex_target = TEXTURE_RECT_INDEX;
- break;
- case GLSL_SAMPLER_DIM_BUF:
- inst->tex_target = TEXTURE_BUFFER_INDEX;
- break;
- case GLSL_SAMPLER_DIM_EXTERNAL:
- inst->tex_target = TEXTURE_EXTERNAL_INDEX;
- break;
- case GLSL_SAMPLER_DIM_MS:
- inst->tex_target = (sampler_type->sampler_array)
- ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
- break;
- default:
- assert(!"Should not get here.");
- }
-
+ inst->tex_target = sampler_type->sampler_index();
inst->tex_type = ir->type->base_type;
this->result = result_src;
have_sqrt = false;
have_fma = false;
use_shared_memory = false;
+ has_tex_txf_lz = false;
}
glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor()
case SYSTEM_VALUE_LOCAL_GROUP_SIZE:
return TGSI_SEMANTIC_BLOCK_SIZE;
+ /* ARB_shader_ballot */
+ case SYSTEM_VALUE_SUBGROUP_SIZE:
+ return TGSI_SEMANTIC_SUBGROUP_SIZE;
+ case SYSTEM_VALUE_SUBGROUP_INVOCATION:
+ return TGSI_SEMANTIC_SUBGROUP_INVOCATION;
+ case SYSTEM_VALUE_SUBGROUP_EQ_MASK:
+ return TGSI_SEMANTIC_SUBGROUP_EQ_MASK;
+ case SYSTEM_VALUE_SUBGROUP_GE_MASK:
+ return TGSI_SEMANTIC_SUBGROUP_GE_MASK;
+ case SYSTEM_VALUE_SUBGROUP_GT_MASK:
+ return TGSI_SEMANTIC_SUBGROUP_GT_MASK;
+ case SYSTEM_VALUE_SUBGROUP_LE_MASK:
+ return TGSI_SEMANTIC_SUBGROUP_LE_MASK;
+ case SYSTEM_VALUE_SUBGROUP_LT_MASK:
+ return TGSI_SEMANTIC_SUBGROUP_LT_MASK;
+
/* Unhandled */
case SYSTEM_VALUE_LOCAL_INVOCATION_INDEX:
case SYSTEM_VALUE_GLOBAL_INVOCATION_ID:
return;
case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TEX_LZ:
case TGSI_OPCODE_TXB:
case TGSI_OPCODE_TXD:
case TGSI_OPCODE_TXL:
case TGSI_OPCODE_TXQ:
case TGSI_OPCODE_TXQS:
case TGSI_OPCODE_TXF:
+ case TGSI_OPCODE_TXF_LZ:
case TGSI_OPCODE_TEX2:
case TGSI_OPCODE_TXB2:
case TGSI_OPCODE_TXL2:
PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED);
v->have_fma = pscreen->get_shader_param(pscreen, ptarget,
PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED);
+ v->has_tex_txf_lz = pscreen->get_param(pscreen,
+ PIPE_CAP_TGSI_TEX_TXF_LZ);
_mesa_generate_parameters_list_for_uniforms(shader_program, shader,
prog->Parameters);
* prog->ParameterValues to get reallocated (e.g., anything that adds a
* program constant) has to happen before creating this linkage.
*/
- _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters);
+ _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters,
+ true);
if (!shader_program->data->LinkStatus) {
free_glsl_to_tgsi_visitor(v);
_mesa_reference_program(ctx, &shader->Program, NULL);
GLboolean
st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
{
+ /* Return early if we are loading the shader from on-disk cache */
+ if (st_load_tgsi_from_disk_cache(ctx, prog)) {
+ return GL_TRUE;
+ }
+
struct pipe_screen *pscreen = ctx->st->pipe->screen;
assert(prog->data->LinkStatus);
(options->EmitNoPow ? POW_TO_EXP2 : 0) |
(!ctx->Const.NativeIntegers ? INT_DIV_TO_MUL_RCP : 0) |
(options->EmitNoSat ? SAT_TO_CLAMP : 0) |
+ (ctx->Const.ForceGLSLAbsSqrt ? SQRT_TO_ABS_SQRT : 0) |
/* Assume that if ARB_gpu_shader5 is not supported
* then all of the extended integer functions need
* lowering. It may be necessary to add some caps