class immediate_storage : public exec_node {
public:
- immediate_storage(gl_constant_value *values, int size32, int type)
+ immediate_storage(gl_constant_value *values, int size32, GLenum type)
{
memcpy(this->values, values, size32 * sizeof(gl_constant_value));
this->size32 = size32;
/* doubles are stored across 2 gl_constant_values */
gl_constant_value values[4];
int size32; /**< Number of 32-bit components (1-4) */
- int type; /**< GL_DOUBLE, GL_FLOAT, GL_INT, GL_BOOL, or GL_UNSIGNED_INT */
+ GLenum type; /**< GL_DOUBLE, GL_FLOAT, GL_INT, GL_BOOL, or GL_UNSIGNED_INT */
};
static const st_src_reg undef_src = st_src_reg(PROGRAM_UNDEFINED, 0, GLSL_TYPE_ERROR);
return GLSL_TYPE_ERROR;
}
+struct hwatomic_decl {
+ unsigned location;
+ unsigned binding;
+ unsigned size;
+ unsigned array_id;
+};
+
struct glsl_to_tgsi_visitor : public ir_visitor {
public:
glsl_to_tgsi_visitor();
unsigned num_outputs;
unsigned num_output_arrays;
+ struct hwatomic_decl atomic_info[PIPE_MAX_HW_ATOMIC_BUFFERS];
+ unsigned num_atomics;
+ unsigned num_atomic_arrays;
int num_address_regs;
uint32_t samplers_used;
glsl_base_type sampler_types[PIPE_MAX_SAMPLERS];
- int sampler_targets[PIPE_MAX_SAMPLERS]; /**< One of TGSI_TEXTURE_* */
+ enum tgsi_texture_type sampler_targets[PIPE_MAX_SAMPLERS];
int images_used;
int image_targets[PIPE_MAX_SHADER_IMAGES];
- unsigned image_formats[PIPE_MAX_SHADER_IMAGES];
+ enum pipe_format image_formats[PIPE_MAX_SHADER_IMAGES];
bool indirect_addr_consts;
int wpos_transform_const;
- int glsl_version;
bool native_integers;
bool have_sqrt;
bool have_fma;
variable_storage *find_variable_storage(ir_variable *var);
int add_constant(gl_register_file file, gl_constant_value values[8],
- int size, int datatype, uint16_t *swizzle_out);
+ int size, GLenum datatype, uint16_t *swizzle_out);
st_src_reg get_temp(const glsl_type *type);
void reladdr_to_temp(ir_instruction *ir, st_src_reg *reg, int *num_reladdr);
ralloc_vasprintf_append(&prog->data->InfoLog, fmt, args);
va_end(args);
- prog->data->LinkStatus = linking_failure;
+ prog->data->LinkStatus = LINKING_FAILURE;
}
int
* sources into temps.
*/
num_reladdr += dst.reladdr != NULL || dst.reladdr2;
- num_reladdr += dst1.reladdr != NULL || dst1.reladdr2;
+ assert(!dst1.reladdr); /* should be lowered in earlier passes */
num_reladdr += src0.reladdr != NULL || src0.reladdr2 != NULL;
num_reladdr += src1.reladdr != NULL || src1.reladdr2 != NULL;
num_reladdr += src2.reladdr != NULL || src2.reladdr2 != NULL;
emit_arl(ir, address_reg2, *dst.reladdr2);
num_reladdr--;
}
- if (dst1.reladdr) {
- emit_arl(ir, address_reg, *dst1.reladdr);
- num_reladdr--;
- }
+
assert(num_reladdr == 0);
/* inst->op has only 8 bits. */
int
glsl_to_tgsi_visitor::add_constant(gl_register_file file,
- gl_constant_value values[8], int size, int datatype,
+ gl_constant_value values[8], int size,
+ GLenum datatype,
uint16_t *swizzle_out)
{
if (file == PROGRAM_CONSTANT) {
st_dst_reg result_dst;
int vector_elements = ir->operands[0]->type->vector_elements;
- if (ir->operands[1]) {
+ if (ir->operands[1] &&
+ ir->operation != ir_binop_interpolate_at_offset &&
+ ir->operation != ir_binop_interpolate_at_sample) {
+ st_src_reg *swz_op = NULL;
+ if (vector_elements > ir->operands[1]->type->vector_elements) {
+ assert(ir->operands[1]->type->vector_elements == 1);
+ swz_op = &op[1];
+ } else if (vector_elements < ir->operands[1]->type->vector_elements) {
+ assert(ir->operands[0]->type->vector_elements == 1);
+ swz_op = &op[0];
+ }
+ if (swz_op) {
+ uint16_t swizzle_x = GET_SWZ(swz_op->swizzle, 0);
+ swz_op->swizzle = MAKE_SWIZZLE4(swizzle_x, swizzle_x,
+ swizzle_x, swizzle_x);
+ }
vector_elements = MAX2(vector_elements,
ir->operands[1]->type->vector_elements);
}
+ if (ir->operands[2] &&
+ ir->operands[2]->type->vector_elements != vector_elements) {
+ /* This can happen with ir_triop_lrp, i.e. glsl mix */
+ assert(ir->operands[2]->type->vector_elements == 1);
+ uint16_t swizzle_x = GET_SWZ(op[2].swizzle, 0);
+ op[2].swizzle = MAKE_SWIZZLE4(swizzle_x, swizzle_x,
+ swizzle_x, swizzle_x);
+ }
this->result.file = PROGRAM_UNDEFINED;
case ir_binop_less:
emit_asm(ir, TGSI_OPCODE_SLT, result_dst, op[0], op[1]);
break;
- case ir_binop_greater:
- emit_asm(ir, TGSI_OPCODE_SLT, result_dst, op[1], op[0]);
- break;
- case ir_binop_lequal:
- emit_asm(ir, TGSI_OPCODE_SGE, result_dst, op[1], op[0]);
- break;
case ir_binop_gequal:
emit_asm(ir, TGSI_OPCODE_SGE, result_dst, op[0], op[1]);
break;
case ir_unop_get_buffer_size: {
ir_constant *const_offset = ir->operands[0]->as_constant();
+ int buf_base = ctx->st->has_hw_atomics ? 0 : ctx->Const.Program[shader->Stage].MaxAtomicBuffers;
st_src_reg buffer(
PROGRAM_BUFFER,
- ctx->Const.Program[shader->Stage].MaxAtomicBuffers +
- (const_offset ? const_offset->value.u[0] : 0),
+ buf_base + (const_offset ? const_offset->value.u[0] : 0),
GLSL_TYPE_UINT);
if (!const_offset) {
buffer.reladdr = ralloc(mem_ctx, st_src_reg);
/* a is - 0 + - 0 +
* (a < 0) T F F ( a < 0) T F F
* (0 < a) F F T (-a < 0) F F T
- * (a <= 0) T T F (-a < 0) F F T (swap order of other operands)
- * (0 <= a) F T T ( a < 0) T F F (swap order of other operands)
- * (a > 0) F F T (-a < 0) F F T
- * (0 > a) T F F ( a < 0) T F F
* (a >= 0) F T T ( a < 0) T F F (swap order of other operands)
* (0 >= a) T T F (-a < 0) F F T (swap order of other operands)
*
negate = zero_on_left;
break;
- case ir_binop_greater:
- switch_order = false;
- negate = !zero_on_left;
- break;
-
- case ir_binop_lequal:
- switch_order = true;
- negate = !zero_on_left;
- break;
-
case ir_binop_gequal:
switch_order = true;
negate = zero_on_left;
exec_node *param = ir->actual_parameters.get_head();
ir_dereference *deref = static_cast<ir_dereference *>(param);
ir_variable *location = deref->variable_referenced();
-
- st_src_reg buffer(
- PROGRAM_BUFFER, location->data.binding, GLSL_TYPE_ATOMIC_UINT);
-
+ bool has_hw_atomics = st_context(ctx)->has_hw_atomics;
/* Calculate the surface offset */
st_src_reg offset;
unsigned array_size = 0, base = 0;
uint16_t index = 0;
+ st_src_reg resource;
get_deref_offsets(deref, &array_size, &base, &index, &offset, false);
- if (offset.file != PROGRAM_UNDEFINED) {
- emit_asm(ir, TGSI_OPCODE_MUL, st_dst_reg(offset),
- offset, st_src_reg_for_int(ATOMIC_COUNTER_SIZE));
- emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(offset),
- offset, st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE));
+ if (has_hw_atomics) {
+ variable_storage *entry = find_variable_storage(location);
+ st_src_reg buffer(PROGRAM_HW_ATOMIC, 0, GLSL_TYPE_ATOMIC_UINT, location->data.binding);
+
+ if (!entry) {
+ entry = new(mem_ctx) variable_storage(location, PROGRAM_HW_ATOMIC,
+ num_atomics);
+ _mesa_hash_table_insert(this->variables, location, entry);
+
+ atomic_info[num_atomics].location = location->data.location;
+ atomic_info[num_atomics].binding = location->data.binding;
+ atomic_info[num_atomics].size = location->type->arrays_of_arrays_size();
+ if (atomic_info[num_atomics].size == 0)
+ atomic_info[num_atomics].size = 1;
+ atomic_info[num_atomics].array_id = 0;
+ num_atomics++;
+ }
+
+ if (offset.file != PROGRAM_UNDEFINED) {
+ if (atomic_info[entry->index].array_id == 0) {
+ num_atomic_arrays++;
+ atomic_info[entry->index].array_id = num_atomic_arrays;
+ }
+ buffer.array_id = atomic_info[entry->index].array_id;
+ }
+
+ buffer.index = index;
+ buffer.index += location->data.offset / ATOMIC_COUNTER_SIZE;
+ buffer.has_index2 = true;
+
+ if (offset.file != PROGRAM_UNDEFINED) {
+ buffer.reladdr = ralloc(mem_ctx, st_src_reg);
+ *buffer.reladdr = offset;
+ emit_arl(ir, sampler_reladdr, offset);
+ }
+ offset = st_src_reg_for_int(0);
+
+ resource = buffer;
} else {
- offset = st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE);
+ st_src_reg buffer(PROGRAM_BUFFER, location->data.binding,
+ GLSL_TYPE_ATOMIC_UINT);
+
+ if (offset.file != PROGRAM_UNDEFINED) {
+ emit_asm(ir, TGSI_OPCODE_MUL, st_dst_reg(offset),
+ offset, st_src_reg_for_int(ATOMIC_COUNTER_SIZE));
+ emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(offset),
+ offset, st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE));
+ } else {
+ offset = st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE);
+ }
+ resource = buffer;
}
ir->return_deref->accept(this);
inst = emit_asm(ir, opcode, dst, offset, data, data2);
}
- inst->resource = buffer;
+ inst->resource = resource;
}
void
ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
ir_constant *const_block = block->as_constant();
-
+ int buf_base = st_context(ctx)->has_hw_atomics ? 0 : ctx->Const.Program[shader->Stage].MaxAtomicBuffers;
st_src_reg buffer(
PROGRAM_BUFFER,
- ctx->Const.Program[shader->Stage].MaxAtomicBuffers +
- (const_block ? const_block->value.u[0] : 0),
+ buf_base + (const_block ? const_block->value.u[0] : 0),
GLSL_TYPE_UINT);
if (!const_block) {
num_outputs = 0;
num_input_arrays = 0;
num_output_arrays = 0;
+ num_atomics = 0;
+ num_atomic_arrays = 0;
num_immediates = 0;
num_address_regs = 0;
samplers_used = 0;
images_used = 0;
indirect_addr_consts = false;
wpos_transform_const = -1;
- glsl_version = 0;
native_integers = false;
mem_ctx = ralloc_context(NULL);
ctx = NULL;
{
v->samplers_used = 0;
v->images_used = 0;
+ prog->info.textures_used_by_txf = 0;
foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions) {
if (inst->info->is_tex) {
st_translate_texture_target(inst->tex_target, inst->tex_shadow);
if (inst->op == TGSI_OPCODE_TXF || inst->op == TGSI_OPCODE_TXF_LZ) {
- prog->TexelFetchSamplers |= 1u << idx;
+ prog->info.textures_used_by_txf |= 1u << idx;
}
}
}
}
static void
-rename_temp_handle_src(struct rename_reg_pair *renames,
- struct st_src_reg *src)
+rename_temp_handle_src(struct rename_reg_pair *renames, st_src_reg *src)
{
if (src && src->file == PROGRAM_TEMPORARY) {
int old_idx = src->index;
defined = 0;
inst2 = (glsl_to_tgsi_instruction *) inst->next;
- do {
+ while (!inst2->is_tail_sentinel()) {
if (inst->op == inst2->op &&
inst2->dst[defined].file == PROGRAM_UNDEFINED &&
inst->src[0].file == inst2->src[0].file &&
inst->src[0].swizzle == inst2->src[0].swizzle)
break;
inst2 = (glsl_to_tgsi_instruction *) inst2->next;
- } while (inst2);
+ }
- if (!inst2) {
+ if (inst2->is_tail_sentinel()) {
/* Undefined destinations are not allowed, substitute with an unused
* temporary register.
*/
void
glsl_to_tgsi_visitor::merge_registers(void)
{
- assert(need_uarl);
struct lifetime *lifetimes =
rzalloc_array(mem_ctx, struct lifetime, this->next_temp);
struct ureg_src buffers[PIPE_MAX_SHADER_BUFFERS];
struct ureg_src images[PIPE_MAX_SHADER_IMAGES];
struct ureg_src systemValues[SYSTEM_VALUE_MAX];
+ struct ureg_src hw_atomics[PIPE_MAX_HW_ATOMIC_BUFFERS];
struct ureg_src shared_memory;
unsigned *array_sizes;
struct inout_decl *input_decls;
static struct ureg_src
emit_immediate(struct st_translate *t,
gl_constant_value values[4],
- int type, int size)
+ GLenum type, int size)
{
struct ureg_program *ureg = t->ureg;
src = t->systemValues[src_reg->index];
break;
+ case PROGRAM_HW_ATOMIC:
+ src = ureg_src_array_register(TGSI_FILE_HW_ATOMIC, src_reg->index,
+ src_reg->array_id);
+ break;
+
default:
assert(!"unknown src register file");
return ureg_src_undef();
src[0] = t->shared_memory;
} else if (inst->resource.file == PROGRAM_BUFFER) {
src[0] = t->buffers[inst->resource.index];
+ } else if (inst->resource.file == PROGRAM_HW_ATOMIC) {
+ src[0] = translate_src(t, &inst->resource);
} else if (inst->resource.file == PROGRAM_CONSTANT) {
assert(inst->resource.has_index2);
src[0] = ureg_src_register(TGSI_FILE_CONSTBUF, inst->resource.index);
assert(numInputs <= ARRAY_SIZE(t->inputs));
assert(numOutputs <= ARRAY_SIZE(t->outputs));
+ ASSERT_BITFIELD_SIZE(st_src_reg, type, GLSL_TYPE_ERROR);
+ ASSERT_BITFIELD_SIZE(st_dst_reg, type, GLSL_TYPE_ERROR);
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, tex_type, GLSL_TYPE_ERROR);
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, image_format, PIPE_FORMAT_COUNT);
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, tex_target,
+ (gl_texture_index) (NUM_TEXTURE_TARGETS - 1));
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, image_format,
+ (enum pipe_format) (PIPE_FORMAT_COUNT - 1));
+ ASSERT_BITFIELD_SIZE(glsl_to_tgsi_instruction, op, TGSI_OPCODE_LAST - 1);
+
t = CALLOC_STRUCT(st_translate);
if (!t) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
/* texture samplers */
for (i = 0; i < frag_const->MaxTextureImageUnits; i++) {
if (program->samplers_used & (1u << i)) {
- unsigned type = st_translate_texture_type(program->sampler_types[i]);
+ enum tgsi_return_type type =
+ st_translate_texture_type(program->sampler_types[i]);
t->samplers[i] = ureg_DECL_sampler(ureg, i);
{
struct gl_program *prog = program->prog;
- for (i = 0; i < prog->info.num_abos; i++) {
- unsigned index = prog->sh.AtomicBuffers[i]->Binding;
- assert(index < frag_const->MaxAtomicBuffers);
- t->buffers[index] = ureg_DECL_buffer(ureg, index, true);
+ if (!st_context(ctx)->has_hw_atomics) {
+ for (i = 0; i < prog->info.num_abos; i++) {
+ unsigned index = prog->sh.AtomicBuffers[i]->Binding;
+ assert(index < frag_const->MaxAtomicBuffers);
+ t->buffers[index] = ureg_DECL_buffer(ureg, index, true);
+ }
+ } else {
+ for (i = 0; i < program->num_atomics; i++) {
+ struct hwatomic_decl *ainfo = &program->atomic_info[i];
+ gl_uniform_storage *uni_storage = &prog->sh.data->UniformStorage[ainfo->location];
+ int base = uni_storage->offset / ATOMIC_COUNTER_SIZE;
+ ureg_DECL_hw_atomic(ureg, base, base + ainfo->size - 1, ainfo->binding,
+ ainfo->array_id);
+ }
}
assert(prog->info.num_ssbos <= frag_const->MaxShaderStorageBlocks);
for (i = 0; i < prog->info.num_ssbos; i++) {
- unsigned index = frag_const->MaxAtomicBuffers + i;
+ unsigned index = i;
+ if (!st_context(ctx)->has_hw_atomics)
+ index += frag_const->MaxAtomicBuffers;
+
t->buffers[index] = ureg_DECL_buffer(ureg, index, false);
}
}
v->shader_program = shader_program;
v->shader = shader;
v->options = options;
- v->glsl_version = ctx->Const.GLSLVersion;
v->native_integers = ctx->Const.NativeIntegers;
v->have_sqrt = pscreen->get_shader_param(pscreen, ptarget,
_mesa_copy_linked_program_data(shader_program, shader);
shrink_array_declarations(v->inputs, v->num_inputs,
&prog->info.inputs_read,
- prog->info.double_inputs_read,
+ prog->info.vs.double_inputs_read,
&prog->info.patch_inputs_read);
shrink_array_declarations(v->outputs, v->num_outputs,
&prog->info.outputs_written, 0ULL,
struct pipe_screen *pscreen = ctx->st->pipe->screen;
assert(prog->data->LinkStatus);
+ bool use_nir = false;
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
continue;
unsigned if_threshold = pscreen->get_shader_param(pscreen, ptarget,
PIPE_SHADER_CAP_LOWER_IF_THRESHOLD);
+ enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
+ pscreen->get_shader_param(pscreen, ptarget,
+ PIPE_SHADER_CAP_PREFERRED_IR);
+ if (preferred_ir == PIPE_SHADER_IR_NIR)
+ use_nir = true;
+
/* If there are forms of indirect addressing that the driver
* cannot handle, perform the lowering pass.
*/
build_program_resource_list(ctx, prog);
+ if (use_nir)
+ return st_link_nir(ctx, prog);
+
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_linked_shader *shader = prog->_LinkedShaders[i];
if (shader == NULL)
continue;
- enum pipe_shader_type ptarget =
- pipe_shader_type_from_mesa(shader->Stage);
- enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
- pscreen->get_shader_param(pscreen, ptarget,
- PIPE_SHADER_CAP_PREFERRED_IR);
-
- struct gl_program *linked_prog = NULL;
- if (preferred_ir == PIPE_SHADER_IR_NIR) {
- /* TODO only for GLSL VS/FS/CS for now: */
- switch (shader->Stage) {
- case MESA_SHADER_VERTEX:
- case MESA_SHADER_FRAGMENT:
- case MESA_SHADER_COMPUTE:
- linked_prog = st_nir_get_mesa_program(ctx, prog, shader);
- default:
- break;
- }
- } else {
- linked_prog = get_mesa_program_tgsi(ctx, prog, shader);
- }
+ struct gl_program *linked_prog =
+ get_mesa_program_tgsi(ctx, prog, shader);
+ st_set_prog_affected_state_flags(linked_prog);
if (linked_prog) {
- st_set_prog_affected_state_flags(linked_prog);
if (!ctx->Driver.ProgramStringNotify(ctx,
_mesa_shader_stage_to_program(i),
linked_prog)) {