2014-12-02 06:01:05 +00:00
|
|
|
/*
|
|
|
|
* Copyright © 2014 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.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Connor Abbott (cwabbott0@gmail.com)
|
|
|
|
* Jason Ekstrand (jason@jlekstrand.net)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This lowering pass converts references to input/output variables with
|
|
|
|
* loads/stores to actual input/output intrinsics.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nir.h"
|
2015-08-12 19:26:34 +01:00
|
|
|
#include "nir_builder.h"
|
2014-12-02 06:01:05 +00:00
|
|
|
|
|
|
|
struct lower_io_state {
|
2015-08-12 19:26:34 +01:00
|
|
|
nir_builder builder;
|
2014-12-02 06:01:05 +00:00
|
|
|
void *mem_ctx;
|
2015-08-12 22:29:25 +01:00
|
|
|
int (*type_size)(const struct glsl_type *type);
|
2015-08-12 23:14:35 +01:00
|
|
|
nir_variable_mode mode;
|
2014-12-02 06:01:05 +00:00
|
|
|
};
|
|
|
|
|
2015-03-18 22:04:15 +00:00
|
|
|
void
|
2015-08-12 22:29:25 +01:00
|
|
|
nir_assign_var_locations(struct exec_list *var_list, unsigned *size,
|
|
|
|
int (*type_size)(const struct glsl_type *))
|
2014-12-02 06:01:05 +00:00
|
|
|
{
|
|
|
|
unsigned location = 0;
|
|
|
|
|
2015-10-03 02:15:06 +01:00
|
|
|
nir_foreach_variable(var, var_list) {
|
2014-12-02 06:01:05 +00:00
|
|
|
/*
|
|
|
|
* UBO's have their own address spaces, so don't count them towards the
|
|
|
|
* number of global uniforms
|
|
|
|
*/
|
2015-05-18 14:47:18 +01:00
|
|
|
if ((var->data.mode == nir_var_uniform || var->data.mode == nir_var_shader_storage) &&
|
|
|
|
var->interface_type != NULL)
|
2014-12-02 06:01:05 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
var->data.driver_location = location;
|
2015-08-12 22:29:25 +01:00
|
|
|
location += type_size(var->type);
|
2014-12-02 06:01:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*size = location;
|
|
|
|
}
|
|
|
|
|
2015-10-01 08:46:19 +01:00
|
|
|
/**
|
|
|
|
* Returns true if we're processing a stage whose inputs are arrays indexed
|
|
|
|
* by a vertex number (such as geometry shader inputs).
|
|
|
|
*/
|
|
|
|
static bool
|
2015-10-01 01:17:35 +01:00
|
|
|
is_per_vertex_input(struct lower_io_state *state, nir_variable *var)
|
2015-10-01 08:46:19 +01:00
|
|
|
{
|
|
|
|
gl_shader_stage stage = state->builder.shader->stage;
|
2015-10-01 01:17:35 +01:00
|
|
|
|
|
|
|
return var->data.mode == nir_var_shader_in && !var->data.patch &&
|
|
|
|
(stage == MESA_SHADER_TESS_CTRL ||
|
|
|
|
stage == MESA_SHADER_TESS_EVAL ||
|
|
|
|
stage == MESA_SHADER_GEOMETRY);
|
2015-10-01 08:46:19 +01:00
|
|
|
}
|
|
|
|
|
2015-10-02 08:11:01 +01:00
|
|
|
static bool
|
|
|
|
is_per_vertex_output(struct lower_io_state *state, nir_variable *var)
|
|
|
|
{
|
|
|
|
gl_shader_stage stage = state->builder.shader->stage;
|
|
|
|
return var->data.mode == nir_var_shader_out && !var->data.patch &&
|
|
|
|
stage == MESA_SHADER_TESS_CTRL;
|
|
|
|
}
|
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
static nir_ssa_def *
|
2015-11-25 20:33:38 +00:00
|
|
|
get_io_offset(nir_builder *b, nir_deref_var *deref,
|
2015-10-01 08:46:19 +01:00
|
|
|
nir_ssa_def **vertex_index,
|
2015-11-25 20:33:38 +00:00
|
|
|
int (*type_size)(const struct glsl_type *))
|
2014-12-02 06:01:05 +00:00
|
|
|
{
|
|
|
|
nir_deref *tail = &deref->deref;
|
2015-10-01 08:46:19 +01:00
|
|
|
|
|
|
|
/* For per-vertex input arrays (i.e. geometry shader inputs), keep the
|
|
|
|
* outermost array index separate. Process the rest normally.
|
|
|
|
*/
|
|
|
|
if (vertex_index != NULL) {
|
|
|
|
tail = tail->child;
|
|
|
|
assert(tail->deref_type == nir_deref_type_array);
|
|
|
|
nir_deref_array *deref_array = nir_deref_as_array(tail);
|
|
|
|
|
|
|
|
nir_ssa_def *vtx = nir_imm_int(b, deref_array->base_offset);
|
|
|
|
if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
|
|
|
|
vtx = nir_iadd(b, vtx, nir_ssa_for_src(b, deref_array->indirect, 1));
|
|
|
|
}
|
|
|
|
*vertex_index = vtx;
|
|
|
|
}
|
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
/* Just emit code and let constant-folding go to town */
|
|
|
|
nir_ssa_def *offset = nir_imm_int(b, 0);
|
2015-11-25 20:33:38 +00:00
|
|
|
|
2014-12-02 06:01:05 +00:00
|
|
|
while (tail->child != NULL) {
|
|
|
|
const struct glsl_type *parent_type = tail->type;
|
|
|
|
tail = tail->child;
|
|
|
|
|
|
|
|
if (tail->deref_type == nir_deref_type_array) {
|
|
|
|
nir_deref_array *deref_array = nir_deref_as_array(tail);
|
2015-11-25 20:33:38 +00:00
|
|
|
unsigned size = type_size(tail->type);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
offset = nir_iadd(b, offset,
|
|
|
|
nir_imm_int(b, size * deref_array->base_offset));
|
2014-12-02 06:01:05 +00:00
|
|
|
|
|
|
|
if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
|
2015-08-12 19:26:34 +01:00
|
|
|
nir_ssa_def *mul =
|
|
|
|
nir_imul(b, nir_imm_int(b, size),
|
|
|
|
nir_ssa_for_src(b, deref_array->indirect, 1));
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
offset = nir_iadd(b, offset, mul);
|
2014-12-02 06:01:05 +00:00
|
|
|
}
|
|
|
|
} else if (tail->deref_type == nir_deref_type_struct) {
|
|
|
|
nir_deref_struct *deref_struct = nir_deref_as_struct(tail);
|
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
unsigned field_offset = 0;
|
2015-08-12 22:29:25 +01:00
|
|
|
for (unsigned i = 0; i < deref_struct->index; i++) {
|
2015-11-25 22:14:05 +00:00
|
|
|
field_offset += type_size(glsl_get_struct_field(parent_type, i));
|
2015-08-12 22:29:25 +01:00
|
|
|
}
|
2015-11-25 22:14:05 +00:00
|
|
|
offset = nir_iadd(b, offset, nir_imm_int(b, field_offset));
|
2014-12-02 06:01:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
return offset;
|
2014-12-02 06:01:05 +00:00
|
|
|
}
|
|
|
|
|
2015-08-12 18:57:31 +01:00
|
|
|
static nir_intrinsic_op
|
2015-10-01 08:46:19 +01:00
|
|
|
load_op(struct lower_io_state *state,
|
2015-11-25 22:14:05 +00:00
|
|
|
nir_variable_mode mode, bool per_vertex)
|
2015-08-12 18:57:31 +01:00
|
|
|
{
|
|
|
|
nir_intrinsic_op op;
|
|
|
|
switch (mode) {
|
|
|
|
case nir_var_shader_in:
|
2015-11-25 22:14:05 +00:00
|
|
|
op = per_vertex ? nir_intrinsic_load_per_vertex_input :
|
|
|
|
nir_intrinsic_load_input;
|
2015-08-12 18:57:31 +01:00
|
|
|
break;
|
2015-10-19 19:44:28 +01:00
|
|
|
case nir_var_shader_out:
|
2015-11-25 22:14:05 +00:00
|
|
|
op = per_vertex ? nir_intrinsic_load_per_vertex_output :
|
|
|
|
nir_intrinsic_load_output;
|
2015-10-19 19:44:28 +01:00
|
|
|
break;
|
2015-08-12 18:57:31 +01:00
|
|
|
case nir_var_uniform:
|
2015-11-25 22:14:05 +00:00
|
|
|
op = nir_intrinsic_load_uniform;
|
2015-08-12 18:57:31 +01:00
|
|
|
break;
|
2016-01-18 17:44:31 +00:00
|
|
|
case nir_var_shared:
|
|
|
|
op = nir_intrinsic_load_shared;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
unreachable("Unknown variable mode");
|
|
|
|
}
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
|
|
|
static nir_intrinsic_op
|
|
|
|
store_op(struct lower_io_state *state,
|
|
|
|
nir_variable_mode mode, bool per_vertex)
|
|
|
|
{
|
|
|
|
nir_intrinsic_op op;
|
|
|
|
switch (mode) {
|
|
|
|
case nir_var_shader_in:
|
|
|
|
case nir_var_shader_out:
|
|
|
|
op = per_vertex ? nir_intrinsic_store_per_vertex_output :
|
|
|
|
nir_intrinsic_store_output;
|
|
|
|
break;
|
|
|
|
case nir_var_shared:
|
|
|
|
op = nir_intrinsic_store_shared;
|
|
|
|
break;
|
2015-08-12 18:57:31 +01:00
|
|
|
default:
|
|
|
|
unreachable("Unknown variable mode");
|
|
|
|
}
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
2016-01-18 17:59:19 +00:00
|
|
|
static nir_intrinsic_op
|
|
|
|
atomic_op(nir_intrinsic_op opcode)
|
|
|
|
{
|
|
|
|
switch (opcode) {
|
|
|
|
#define OP(O) case nir_intrinsic_var_##O: return nir_intrinsic_shared_##O;
|
|
|
|
OP(atomic_exchange)
|
|
|
|
OP(atomic_comp_swap)
|
|
|
|
OP(atomic_add)
|
|
|
|
OP(atomic_imin)
|
|
|
|
OP(atomic_umin)
|
|
|
|
OP(atomic_imax)
|
|
|
|
OP(atomic_umax)
|
|
|
|
OP(atomic_and)
|
|
|
|
OP(atomic_or)
|
|
|
|
OP(atomic_xor)
|
|
|
|
#undef OP
|
|
|
|
default:
|
|
|
|
unreachable("Invalid atomic");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-02 06:01:05 +00:00
|
|
|
static bool
|
|
|
|
nir_lower_io_block(nir_block *block, void *void_state)
|
|
|
|
{
|
|
|
|
struct lower_io_state *state = void_state;
|
|
|
|
|
2015-11-25 20:33:38 +00:00
|
|
|
nir_builder *b = &state->builder;
|
|
|
|
|
2014-12-02 06:01:05 +00:00
|
|
|
nir_foreach_instr_safe(block, instr) {
|
|
|
|
if (instr->type != nir_instr_type_intrinsic)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
|
|
|
|
2016-01-18 17:59:19 +00:00
|
|
|
switch (intrin->intrinsic) {
|
|
|
|
case nir_intrinsic_load_var:
|
|
|
|
case nir_intrinsic_store_var:
|
|
|
|
case nir_intrinsic_var_atomic_add:
|
|
|
|
case nir_intrinsic_var_atomic_imin:
|
|
|
|
case nir_intrinsic_var_atomic_umin:
|
|
|
|
case nir_intrinsic_var_atomic_imax:
|
|
|
|
case nir_intrinsic_var_atomic_umax:
|
|
|
|
case nir_intrinsic_var_atomic_and:
|
|
|
|
case nir_intrinsic_var_atomic_or:
|
|
|
|
case nir_intrinsic_var_atomic_xor:
|
|
|
|
case nir_intrinsic_var_atomic_exchange:
|
|
|
|
case nir_intrinsic_var_atomic_comp_swap:
|
|
|
|
/* We can lower the io for this nir instrinsic */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* We can't lower the io for this nir instrinsic, so skip it */
|
2015-08-12 23:14:35 +01:00
|
|
|
continue;
|
2016-01-18 17:59:19 +00:00
|
|
|
}
|
2015-08-12 23:14:35 +01:00
|
|
|
|
|
|
|
nir_variable_mode mode = intrin->variables[0]->var->data.mode;
|
|
|
|
|
2015-10-19 16:57:51 +01:00
|
|
|
if (state->mode != nir_var_all && state->mode != mode)
|
2015-08-12 23:14:35 +01:00
|
|
|
continue;
|
|
|
|
|
2015-10-19 19:44:28 +01:00
|
|
|
if (mode != nir_var_shader_in &&
|
|
|
|
mode != nir_var_shader_out &&
|
2016-01-18 17:44:31 +00:00
|
|
|
mode != nir_var_shared &&
|
2015-10-19 19:44:28 +01:00
|
|
|
mode != nir_var_uniform)
|
|
|
|
continue;
|
|
|
|
|
2015-11-25 20:33:38 +00:00
|
|
|
b->cursor = nir_before_instr(instr);
|
|
|
|
|
2014-12-02 06:01:05 +00:00
|
|
|
switch (intrin->intrinsic) {
|
2014-12-04 01:03:19 +00:00
|
|
|
case nir_intrinsic_load_var: {
|
2015-10-01 01:17:35 +01:00
|
|
|
bool per_vertex =
|
2015-10-19 19:44:28 +01:00
|
|
|
is_per_vertex_input(state, intrin->variables[0]->var) ||
|
|
|
|
is_per_vertex_output(state, intrin->variables[0]->var);
|
2015-10-01 08:46:19 +01:00
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
nir_ssa_def *offset;
|
2015-10-01 08:46:19 +01:00
|
|
|
nir_ssa_def *vertex_index;
|
2015-10-01 08:36:25 +01:00
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
offset = get_io_offset(b, intrin->variables[0],
|
|
|
|
per_vertex ? &vertex_index : NULL,
|
|
|
|
state->type_size);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2015-08-12 18:57:31 +01:00
|
|
|
nir_intrinsic_instr *load =
|
|
|
|
nir_intrinsic_instr_create(state->mem_ctx,
|
2015-11-25 22:14:05 +00:00
|
|
|
load_op(state, mode, per_vertex));
|
2014-12-04 01:03:19 +00:00
|
|
|
load->num_components = intrin->num_components;
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2016-01-21 19:12:58 +00:00
|
|
|
nir_intrinsic_set_base(load,
|
|
|
|
intrin->variables[0]->var->data.driver_location);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2015-10-01 08:46:19 +01:00
|
|
|
if (per_vertex)
|
|
|
|
load->src[0] = nir_src_for_ssa(vertex_index);
|
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
load->src[per_vertex ? 1 : 0] = nir_src_for_ssa(offset);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
|
|
|
if (intrin->dest.is_ssa) {
|
2015-01-21 00:23:51 +00:00
|
|
|
nir_ssa_dest_init(&load->instr, &load->dest,
|
2015-11-17 12:57:54 +00:00
|
|
|
intrin->num_components,
|
|
|
|
intrin->dest.ssa.bit_size, NULL);
|
2015-01-21 19:11:03 +00:00
|
|
|
nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
|
2015-09-09 21:24:35 +01:00
|
|
|
nir_src_for_ssa(&load->dest.ssa));
|
2014-12-02 06:01:05 +00:00
|
|
|
} else {
|
2015-01-24 00:57:40 +00:00
|
|
|
nir_dest_copy(&load->dest, &intrin->dest, state->mem_ctx);
|
2014-12-02 06:01:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nir_instr_insert_before(&intrin->instr, &load->instr);
|
|
|
|
nir_instr_remove(&intrin->instr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-12-04 01:03:19 +00:00
|
|
|
case nir_intrinsic_store_var: {
|
2016-01-18 17:44:31 +00:00
|
|
|
assert(mode == nir_var_shader_out || mode == nir_var_shared);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
nir_ssa_def *offset;
|
2015-10-02 08:11:01 +01:00
|
|
|
nir_ssa_def *vertex_index;
|
|
|
|
|
|
|
|
bool per_vertex =
|
|
|
|
is_per_vertex_output(state, intrin->variables[0]->var);
|
2015-10-01 08:36:25 +01:00
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
offset = get_io_offset(b, intrin->variables[0],
|
|
|
|
per_vertex ? &vertex_index : NULL,
|
|
|
|
state->type_size);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2016-01-18 17:44:31 +00:00
|
|
|
nir_intrinsic_instr *store =
|
|
|
|
nir_intrinsic_instr_create(state->mem_ctx,
|
|
|
|
store_op(state, mode, per_vertex));
|
2014-12-04 01:03:19 +00:00
|
|
|
store->num_components = intrin->num_components;
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2015-09-09 21:18:29 +01:00
|
|
|
nir_src_copy(&store->src[0], &intrin->src[0], store);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
2016-01-21 19:12:58 +00:00
|
|
|
nir_intrinsic_set_base(store,
|
|
|
|
intrin->variables[0]->var->data.driver_location);
|
|
|
|
nir_intrinsic_set_write_mask(store, nir_intrinsic_write_mask(intrin));
|
nir: Add a writemask to store intrinsics.
Tessellation control shaders need to be careful when writing outputs.
Because multiple threads can concurrently write the same output
variables, we need to only write the exact components we were told.
Traditionally, for sub-vector writes, we've read the whole vector,
updated the temporary, and written the whole vector back. This breaks
down with concurrent access.
This patch prepares the way for a solution by adding a writemask field
to store_var intrinsics, as well as the other store intrinsics. It then
updates all produces to emit a writemask of "all channels enabled". It
updates nir_lower_io to copy the writemask to output store intrinsics.
Finally, it updates nir_lower_vars_to_ssa to handle partial writemasks
by doing a read-modify-write cycle (which is safe, because local
variables are specific to a single thread).
This should have no functional change, since no one actually emits
partial writemasks yet.
v2: Make nir_validate momentarily assert that writemasks cover the
complete value - we shouldn't have partial writemasks yet
(requested by Jason Ekstrand).
v3: Fix accidental SSBO change that arose from merge conflicts.
v4: Don't try to handle writemasks in ir3_compiler_nir - my code
for indirects was likely wrong, and TTN doesn't generate partial
writemasks today anyway. Change them to asserts as requested by
Rob Clark.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Jason Ekstrand <jason.ekstrand@intel.com> [v3]
2015-11-17 08:26:37 +00:00
|
|
|
|
2015-10-02 08:11:01 +01:00
|
|
|
if (per_vertex)
|
|
|
|
store->src[1] = nir_src_for_ssa(vertex_index);
|
|
|
|
|
2015-11-25 22:14:05 +00:00
|
|
|
store->src[per_vertex ? 2 : 1] = nir_src_for_ssa(offset);
|
2014-12-02 06:01:05 +00:00
|
|
|
|
|
|
|
nir_instr_insert_before(&intrin->instr, &store->instr);
|
|
|
|
nir_instr_remove(&intrin->instr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-01-18 17:59:19 +00:00
|
|
|
case nir_intrinsic_var_atomic_add:
|
|
|
|
case nir_intrinsic_var_atomic_imin:
|
|
|
|
case nir_intrinsic_var_atomic_umin:
|
|
|
|
case nir_intrinsic_var_atomic_imax:
|
|
|
|
case nir_intrinsic_var_atomic_umax:
|
|
|
|
case nir_intrinsic_var_atomic_and:
|
|
|
|
case nir_intrinsic_var_atomic_or:
|
|
|
|
case nir_intrinsic_var_atomic_xor:
|
|
|
|
case nir_intrinsic_var_atomic_exchange:
|
|
|
|
case nir_intrinsic_var_atomic_comp_swap: {
|
|
|
|
assert(mode == nir_var_shared);
|
|
|
|
|
|
|
|
nir_ssa_def *offset;
|
|
|
|
|
|
|
|
offset = get_io_offset(b, intrin->variables[0],
|
|
|
|
NULL, state->type_size);
|
|
|
|
|
|
|
|
nir_intrinsic_instr *atomic =
|
|
|
|
nir_intrinsic_instr_create(state->mem_ctx,
|
|
|
|
atomic_op(intrin->intrinsic));
|
|
|
|
|
|
|
|
atomic->src[0] = nir_src_for_ssa(offset);
|
|
|
|
|
|
|
|
atomic->const_index[0] =
|
|
|
|
intrin->variables[0]->var->data.driver_location;
|
|
|
|
|
|
|
|
for (unsigned i = 0;
|
|
|
|
i < nir_op_infos[intrin->intrinsic].num_inputs;
|
|
|
|
i++) {
|
|
|
|
nir_src_copy(&atomic->src[i+1], &intrin->src[i], atomic);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (intrin->dest.is_ssa) {
|
|
|
|
nir_ssa_dest_init(&atomic->instr, &atomic->dest,
|
2015-11-17 12:57:54 +00:00
|
|
|
intrin->dest.ssa.num_components,
|
|
|
|
intrin->dest.ssa.bit_size, NULL);
|
2016-01-18 17:59:19 +00:00
|
|
|
nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
|
|
|
|
nir_src_for_ssa(&atomic->dest.ssa));
|
|
|
|
} else {
|
|
|
|
nir_dest_copy(&atomic->dest, &intrin->dest, state->mem_ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
nir_instr_insert_before(&intrin->instr, &atomic->instr);
|
|
|
|
nir_instr_remove(&intrin->instr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-12-02 06:01:05 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-08-12 23:14:35 +01:00
|
|
|
nir_lower_io_impl(nir_function_impl *impl,
|
|
|
|
nir_variable_mode mode,
|
|
|
|
int (*type_size)(const struct glsl_type *))
|
2014-12-02 06:01:05 +00:00
|
|
|
{
|
|
|
|
struct lower_io_state state;
|
|
|
|
|
2015-08-12 19:26:34 +01:00
|
|
|
nir_builder_init(&state.builder, impl);
|
2014-12-02 06:01:05 +00:00
|
|
|
state.mem_ctx = ralloc_parent(impl);
|
2015-08-12 23:14:35 +01:00
|
|
|
state.mode = mode;
|
2015-08-12 22:29:25 +01:00
|
|
|
state.type_size = type_size;
|
2014-12-02 06:01:05 +00:00
|
|
|
|
|
|
|
nir_foreach_block(impl, nir_lower_io_block, &state);
|
2014-12-13 00:25:38 +00:00
|
|
|
|
|
|
|
nir_metadata_preserve(impl, nir_metadata_block_index |
|
|
|
|
nir_metadata_dominance);
|
2014-12-02 06:01:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-08-12 23:14:35 +01:00
|
|
|
nir_lower_io(nir_shader *shader, nir_variable_mode mode,
|
|
|
|
int (*type_size)(const struct glsl_type *))
|
2014-12-02 06:01:05 +00:00
|
|
|
{
|
2015-12-26 18:00:47 +00:00
|
|
|
nir_foreach_function(shader, function) {
|
|
|
|
if (function->impl)
|
|
|
|
nir_lower_io_impl(function->impl, mode, type_size);
|
2014-12-02 06:01:05 +00:00
|
|
|
}
|
|
|
|
}
|
2015-11-08 06:35:33 +00:00
|
|
|
|
|
|
|
/**
|
2015-11-25 22:14:05 +00:00
|
|
|
* Return the offset soruce for a load/store intrinsic.
|
2015-11-08 06:35:33 +00:00
|
|
|
*/
|
|
|
|
nir_src *
|
2015-11-25 22:14:05 +00:00
|
|
|
nir_get_io_offset_src(nir_intrinsic_instr *instr)
|
2015-11-08 06:35:33 +00:00
|
|
|
{
|
|
|
|
switch (instr->intrinsic) {
|
2015-11-25 22:14:05 +00:00
|
|
|
case nir_intrinsic_load_input:
|
|
|
|
case nir_intrinsic_load_output:
|
|
|
|
case nir_intrinsic_load_uniform:
|
2015-11-08 06:35:33 +00:00
|
|
|
return &instr->src[0];
|
2015-11-25 22:14:05 +00:00
|
|
|
case nir_intrinsic_load_per_vertex_input:
|
|
|
|
case nir_intrinsic_load_per_vertex_output:
|
|
|
|
case nir_intrinsic_store_output:
|
2015-11-08 06:35:33 +00:00
|
|
|
return &instr->src[1];
|
2015-11-25 22:14:05 +00:00
|
|
|
case nir_intrinsic_store_per_vertex_output:
|
2015-11-08 06:35:33 +00:00
|
|
|
return &instr->src[2];
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the vertex index source for a load/store per_vertex intrinsic.
|
|
|
|
*/
|
|
|
|
nir_src *
|
|
|
|
nir_get_io_vertex_index_src(nir_intrinsic_instr *instr)
|
|
|
|
{
|
|
|
|
switch (instr->intrinsic) {
|
|
|
|
case nir_intrinsic_load_per_vertex_input:
|
|
|
|
case nir_intrinsic_load_per_vertex_output:
|
|
|
|
return &instr->src[0];
|
|
|
|
case nir_intrinsic_store_per_vertex_output:
|
|
|
|
return &instr->src[1];
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|