2015-12-22 02:34:11 +00:00
|
|
|
/*
|
|
|
|
* Copyright © 2015 Red Hat
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "st_nir.h"
|
|
|
|
|
|
|
|
#include "pipe/p_defines.h"
|
|
|
|
#include "pipe/p_screen.h"
|
|
|
|
#include "pipe/p_context.h"
|
|
|
|
|
|
|
|
#include "program/program.h"
|
|
|
|
#include "program/prog_statevars.h"
|
|
|
|
#include "program/prog_parameter.h"
|
2019-12-13 10:58:28 +00:00
|
|
|
#include "main/context.h"
|
2015-12-22 02:34:11 +00:00
|
|
|
#include "main/mtypes.h"
|
|
|
|
#include "main/errors.h"
|
2019-08-22 14:43:28 +01:00
|
|
|
#include "main/glspirv.h"
|
2015-12-22 02:34:11 +00:00
|
|
|
#include "main/shaderapi.h"
|
|
|
|
#include "main/uniforms.h"
|
|
|
|
|
2019-01-10 06:24:57 +00:00
|
|
|
#include "main/shaderobj.h"
|
2015-12-22 02:34:11 +00:00
|
|
|
#include "st_context.h"
|
|
|
|
#include "st_program.h"
|
2019-09-27 22:43:42 +01:00
|
|
|
#include "st_shader_cache.h"
|
2015-12-22 02:34:11 +00:00
|
|
|
|
|
|
|
#include "compiler/nir/nir.h"
|
2022-03-02 15:54:14 +00:00
|
|
|
#include "compiler/nir/nir_builder.h"
|
2015-12-22 02:34:11 +00:00
|
|
|
#include "compiler/glsl_types.h"
|
2016-05-26 00:00:38 +01:00
|
|
|
#include "compiler/glsl/glsl_to_nir.h"
|
2018-04-30 11:39:43 +01:00
|
|
|
#include "compiler/glsl/gl_nir.h"
|
2019-08-22 14:43:28 +01:00
|
|
|
#include "compiler/glsl/gl_nir_linker.h"
|
2015-12-22 02:34:11 +00:00
|
|
|
#include "compiler/glsl/ir.h"
|
2018-02-20 16:56:47 +00:00
|
|
|
#include "compiler/glsl/ir_optimization.h"
|
2021-08-03 18:20:18 +01:00
|
|
|
#include "compiler/glsl/linker_util.h"
|
2017-08-26 02:37:11 +01:00
|
|
|
#include "compiler/glsl/string_to_uint_map.h"
|
2015-12-22 02:34:11 +00:00
|
|
|
|
2017-07-04 09:22:02 +01:00
|
|
|
static int
|
|
|
|
type_size(const struct glsl_type *type)
|
|
|
|
{
|
|
|
|
return type->count_attribute_slots(false);
|
|
|
|
}
|
|
|
|
|
2015-12-22 02:34:11 +00:00
|
|
|
/* Depending on PIPE_CAP_TGSI_TEXCOORD (st->needs_texcoord_semantic) we
|
|
|
|
* may need to fix up varying slots so the glsl->nir path is aligned
|
|
|
|
* with the anything->tgsi->nir path.
|
|
|
|
*/
|
|
|
|
static void
|
2020-07-20 21:57:45 +01:00
|
|
|
st_nir_fixup_varying_slots(struct st_context *st, nir_shader *shader,
|
|
|
|
nir_variable_mode mode)
|
2015-12-22 02:34:11 +00:00
|
|
|
{
|
|
|
|
if (st->needs_texcoord_semantic)
|
|
|
|
return;
|
|
|
|
|
2021-09-01 00:31:26 +01:00
|
|
|
/* This is called from finalize, but we don't want to do this adjustment twice. */
|
|
|
|
assert(!st->allow_st_finalize_nir_twice);
|
|
|
|
|
2020-07-20 21:57:45 +01:00
|
|
|
nir_foreach_variable_with_modes(var, shader, mode) {
|
2021-09-09 00:24:02 +01:00
|
|
|
if (var->data.location >= VARYING_SLOT_VAR0 && var->data.location < VARYING_SLOT_PATCH0) {
|
2015-12-22 02:34:11 +00:00
|
|
|
var->data.location += 9;
|
2020-04-23 15:08:21 +01:00
|
|
|
} else if (var->data.location == VARYING_SLOT_PNTC) {
|
|
|
|
var->data.location = VARYING_SLOT_VAR8;
|
2015-12-22 02:34:11 +00:00
|
|
|
} else if ((var->data.location >= VARYING_SLOT_TEX0) &&
|
|
|
|
(var->data.location <= VARYING_SLOT_TEX7)) {
|
|
|
|
var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-16 00:35:09 +01:00
|
|
|
static void
|
|
|
|
st_shader_gather_info(nir_shader *nir, struct gl_program *prog)
|
|
|
|
{
|
|
|
|
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
|
|
|
|
|
|
|
|
/* Copy the info we just generated back into the gl_program */
|
|
|
|
const char *prog_name = prog->info.name;
|
|
|
|
const char *prog_label = prog->info.label;
|
|
|
|
prog->info = nir->info;
|
|
|
|
prog->info.name = prog_name;
|
|
|
|
prog->info.label = prog_label;
|
|
|
|
}
|
|
|
|
|
2015-12-22 02:34:11 +00:00
|
|
|
/* input location assignment for VS inputs must be handled specially, so
|
|
|
|
* that it is aligned w/ st's vbo state.
|
|
|
|
* (This isn't the case with, for ex, FS inputs, which only need to agree
|
|
|
|
* on varying-slot w/ the VS outputs)
|
|
|
|
*/
|
2019-10-18 18:02:15 +01:00
|
|
|
void
|
|
|
|
st_nir_assign_vs_in_locations(struct nir_shader *nir)
|
2015-12-22 02:34:11 +00:00
|
|
|
{
|
2020-08-26 00:27:26 +01:00
|
|
|
if (nir->info.stage != MESA_SHADER_VERTEX || nir->info.io_lowered)
|
2019-10-18 18:02:15 +01:00
|
|
|
return;
|
|
|
|
|
2020-08-14 06:32:00 +01:00
|
|
|
nir->num_inputs = util_bitcount64(nir->info.inputs_read);
|
|
|
|
|
2019-10-22 20:32:17 +01:00
|
|
|
bool removed_inputs = false;
|
|
|
|
|
2020-07-19 00:24:25 +01:00
|
|
|
nir_foreach_shader_in_variable_safe(var, nir) {
|
2018-08-31 13:55:07 +01:00
|
|
|
/* NIR already assigns dual-slot inputs to two locations so all we have
|
|
|
|
* to do is compact everything down.
|
|
|
|
*/
|
2019-10-18 18:02:15 +01:00
|
|
|
if (nir->info.inputs_read & BITFIELD64_BIT(var->data.location)) {
|
2018-08-31 13:55:07 +01:00
|
|
|
var->data.driver_location =
|
2018-08-21 17:46:46 +01:00
|
|
|
util_bitcount64(nir->info.inputs_read &
|
2018-08-31 13:55:07 +01:00
|
|
|
BITFIELD64_MASK(var->data.location));
|
2016-08-20 01:12:12 +01:00
|
|
|
} else {
|
2020-07-20 22:30:37 +01:00
|
|
|
/* Convert unused input variables to shader_temp (with no
|
2016-08-20 01:12:12 +01:00
|
|
|
* initialization), to avoid confusing drivers looking through the
|
|
|
|
* inputs array and expecting to find inputs with a driver_location
|
|
|
|
* set.
|
|
|
|
*/
|
2019-01-15 22:56:29 +00:00
|
|
|
var->data.mode = nir_var_shader_temp;
|
2019-10-22 20:32:17 +01:00
|
|
|
removed_inputs = true;
|
2016-08-20 01:12:12 +01:00
|
|
|
}
|
2015-12-22 02:34:11 +00:00
|
|
|
}
|
2019-10-22 20:32:17 +01:00
|
|
|
|
|
|
|
/* Re-lower global vars, to deal with any dead VS inputs. */
|
|
|
|
if (removed_inputs)
|
|
|
|
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
|
2015-12-22 02:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2019-08-22 05:04:27 +01:00
|
|
|
st_nir_lookup_parameter_index(struct gl_program *prog, nir_variable *var)
|
2015-12-22 02:34:11 +00:00
|
|
|
{
|
2019-09-12 00:55:57 +01:00
|
|
|
struct gl_program_parameter_list *params = prog->Parameters;
|
|
|
|
|
2019-08-22 05:04:27 +01:00
|
|
|
/* Lookup the first parameter that the uniform storage that match the
|
|
|
|
* variable location.
|
2015-12-22 02:34:11 +00:00
|
|
|
*/
|
2019-09-12 00:55:57 +01:00
|
|
|
for (unsigned i = 0; i < params->NumParameters; i++) {
|
|
|
|
int index = params->Parameters[i].MainUniformStorageIndex;
|
2019-08-22 05:04:27 +01:00
|
|
|
if (index == var->data.location)
|
|
|
|
return i;
|
2015-12-22 02:34:11 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 00:55:57 +01:00
|
|
|
/* TODO: Handle this fallback for SPIR-V. We need this for GLSL e.g. in
|
|
|
|
* dEQP-GLES2.functional.uniform_api.random.3
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* is there a better way to do this? If we have something like:
|
|
|
|
*
|
|
|
|
* struct S {
|
|
|
|
* float f;
|
|
|
|
* vec4 v;
|
|
|
|
* };
|
|
|
|
* uniform S color;
|
|
|
|
*
|
|
|
|
* Then what we get in prog->Parameters looks like:
|
|
|
|
*
|
|
|
|
* 0: Name=color.f, Type=6, DataType=1406, Size=1
|
|
|
|
* 1: Name=color.v, Type=6, DataType=8b52, Size=4
|
|
|
|
*
|
|
|
|
* So the name doesn't match up and _mesa_lookup_parameter_index()
|
|
|
|
* fails. In this case just find the first matching "color.*"..
|
|
|
|
*
|
|
|
|
* Note for arrays you could end up w/ color[n].f, for example.
|
|
|
|
*/
|
|
|
|
if (!prog->sh.data->spirv) {
|
|
|
|
int namelen = strlen(var->name);
|
|
|
|
for (unsigned i = 0; i < params->NumParameters; i++) {
|
|
|
|
struct gl_program_parameter *p = ¶ms->Parameters[i];
|
|
|
|
if ((strncmp(p->Name, var->name, namelen) == 0) &&
|
|
|
|
((p->Name[namelen] == '.') || (p->Name[namelen] == '['))) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-22 05:04:27 +01:00
|
|
|
return -1;
|
2015-12-22 02:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-03-13 09:50:27 +00:00
|
|
|
st_nir_assign_uniform_locations(struct gl_context *ctx,
|
|
|
|
struct gl_program *prog,
|
2020-07-19 00:45:18 +01:00
|
|
|
nir_shader *nir)
|
2015-12-22 02:34:11 +00:00
|
|
|
{
|
|
|
|
int shaderidx = 0;
|
2017-11-03 16:47:51 +00:00
|
|
|
int imageidx = 0;
|
2015-12-22 02:34:11 +00:00
|
|
|
|
2021-09-15 22:53:44 +01:00
|
|
|
nir_foreach_variable_with_modes(uniform, nir, nir_var_uniform |
|
2021-10-15 18:58:22 +01:00
|
|
|
nir_var_image) {
|
2015-12-22 02:34:11 +00:00
|
|
|
int loc;
|
|
|
|
|
2018-06-11 19:49:12 +01:00
|
|
|
const struct glsl_type *type = glsl_without_array(uniform->type);
|
|
|
|
if (!uniform->data.bindless && (type->is_sampler() || type->is_image())) {
|
|
|
|
if (type->is_sampler()) {
|
|
|
|
loc = shaderidx;
|
|
|
|
shaderidx += type_size(uniform->type);
|
|
|
|
} else {
|
|
|
|
loc = imageidx;
|
|
|
|
imageidx += type_size(uniform->type);
|
|
|
|
}
|
2019-08-21 17:38:10 +01:00
|
|
|
} else if (uniform->state_slots) {
|
2017-11-16 03:29:35 +00:00
|
|
|
const gl_state_index16 *const stateTokens = uniform->state_slots[0].tokens;
|
2018-03-13 09:50:27 +00:00
|
|
|
|
|
|
|
unsigned comps;
|
2019-03-05 05:07:12 +00:00
|
|
|
if (glsl_type_is_struct_or_ifc(type)) {
|
2018-03-13 09:50:27 +00:00
|
|
|
comps = 4;
|
|
|
|
} else {
|
|
|
|
comps = glsl_get_vector_elements(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->Const.PackedDriverUniformStorage) {
|
|
|
|
loc = _mesa_add_sized_state_reference(prog->Parameters,
|
|
|
|
stateTokens, comps, false);
|
2020-11-22 08:39:56 +00:00
|
|
|
loc = prog->Parameters->Parameters[loc].ValueOffset;
|
2018-03-13 09:50:27 +00:00
|
|
|
} else {
|
|
|
|
loc = _mesa_add_state_reference(prog->Parameters, stateTokens);
|
|
|
|
}
|
2015-12-22 02:34:11 +00:00
|
|
|
} else {
|
2019-08-22 05:04:27 +01:00
|
|
|
loc = st_nir_lookup_parameter_index(prog, uniform);
|
2018-03-22 00:52:19 +00:00
|
|
|
|
2019-03-01 10:35:41 +00:00
|
|
|
/* We need to check that loc is not -1 here before accessing the
|
|
|
|
* array. It can be negative for example when we have a struct that
|
|
|
|
* only contains opaque types.
|
|
|
|
*/
|
|
|
|
if (loc >= 0 && ctx->Const.PackedDriverUniformStorage) {
|
2020-11-22 08:39:56 +00:00
|
|
|
loc = prog->Parameters->Parameters[loc].ValueOffset;
|
2018-03-22 00:52:19 +00:00
|
|
|
}
|
2015-12-22 02:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uniform->data.driver_location = loc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-02 15:54:14 +00:00
|
|
|
/* - create a gl_PointSizeMESA variable
|
|
|
|
* - find every gl_Position write
|
|
|
|
* - store 1.0 to gl_PointSizeMESA after every gl_Position write
|
|
|
|
*/
|
2022-04-04 16:35:21 +01:00
|
|
|
void
|
2022-03-02 15:54:14 +00:00
|
|
|
st_nir_add_point_size(nir_shader *nir)
|
|
|
|
{
|
|
|
|
nir_variable *psiz = nir_variable_create(nir, nir_var_shader_out, glsl_float_type(), "gl_PointSizeMESA");
|
|
|
|
psiz->data.location = VARYING_SLOT_PSIZ;
|
2022-03-30 17:46:21 +01:00
|
|
|
psiz->data.how_declared = nir_var_hidden;
|
2022-03-02 15:54:14 +00:00
|
|
|
|
|
|
|
nir_builder b;
|
|
|
|
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
|
|
|
|
nir_builder_init(&b, impl);
|
2022-04-08 17:45:22 +01:00
|
|
|
bool found = false;
|
2022-03-02 15:54:14 +00:00
|
|
|
nir_foreach_block_safe(block, impl) {
|
|
|
|
nir_foreach_instr_safe(instr, block) {
|
|
|
|
if (instr->type == nir_instr_type_intrinsic) {
|
|
|
|
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
2022-04-08 16:36:14 +01:00
|
|
|
if (intr->intrinsic == nir_intrinsic_store_deref ||
|
|
|
|
intr->intrinsic == nir_intrinsic_copy_deref) {
|
2022-03-02 15:54:14 +00:00
|
|
|
nir_variable *var = nir_intrinsic_get_var(intr, 0);
|
|
|
|
if (var->data.location == VARYING_SLOT_POS) {
|
|
|
|
b.cursor = nir_after_instr(instr);
|
|
|
|
nir_deref_instr *deref = nir_build_deref_var(&b, psiz);
|
|
|
|
nir_store_deref(&b, deref, nir_imm_float(&b, 1.0), BITFIELD_BIT(0));
|
2022-04-08 17:45:22 +01:00
|
|
|
found = true;
|
2022-03-02 15:54:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-08 17:45:22 +01:00
|
|
|
if (!found) {
|
|
|
|
b.cursor = nir_before_cf_list(&impl->body);
|
|
|
|
nir_deref_instr *deref = nir_build_deref_var(&b, psiz);
|
|
|
|
nir_store_deref(&b, deref, nir_imm_float(&b, 1.0), BITFIELD_BIT(0));
|
|
|
|
}
|
2022-03-02 15:54:14 +00:00
|
|
|
}
|
|
|
|
|
2019-08-22 14:43:28 +01:00
|
|
|
static void
|
|
|
|
shared_type_info(const struct glsl_type *type, unsigned *size, unsigned *align)
|
|
|
|
{
|
|
|
|
assert(glsl_type_is_vector_or_scalar(type));
|
|
|
|
|
|
|
|
uint32_t comp_size = glsl_type_is_boolean(type)
|
|
|
|
? 4 : glsl_get_bit_size(type) / 8;
|
|
|
|
unsigned length = glsl_get_vector_elements(type);
|
|
|
|
*size = comp_size * length,
|
|
|
|
*align = comp_size * (length == 3 ? 4 : length);
|
|
|
|
}
|
|
|
|
|
2021-11-23 01:44:07 +00:00
|
|
|
static bool
|
|
|
|
st_can_remove_varying_before_linking(nir_variable *var, void *data)
|
|
|
|
{
|
|
|
|
bool *is_sso = (bool *) data;
|
|
|
|
if (*is_sso) {
|
|
|
|
/* Allow the removal of unused builtins in SSO */
|
|
|
|
return var->data.location > -1 && var->data.location < VARYING_SLOT_VAR0;
|
|
|
|
} else
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-13 22:15:54 +00:00
|
|
|
/* First third of converting glsl_to_nir.. this leaves things in a pre-
|
2015-12-22 02:34:11 +00:00
|
|
|
* nir_lower_io state, so that shader variants can more easily insert/
|
|
|
|
* replace variables, etc.
|
|
|
|
*/
|
2019-08-22 15:10:32 +01:00
|
|
|
static void
|
|
|
|
st_nir_preprocess(struct st_context *st, struct gl_program *prog,
|
|
|
|
struct gl_shader_program *shader_program,
|
|
|
|
gl_shader_stage stage)
|
2015-12-22 02:34:11 +00:00
|
|
|
{
|
2020-11-29 08:27:37 +00:00
|
|
|
struct pipe_screen *screen = st->screen;
|
2018-01-30 00:51:31 +00:00
|
|
|
const nir_shader_compiler_options *options =
|
|
|
|
st->ctx->Const.ShaderCompilerOptions[prog->info.stage].NirOptions;
|
2015-12-22 02:34:11 +00:00
|
|
|
assert(options);
|
2019-08-22 15:10:32 +01:00
|
|
|
nir_shader *nir = prog->nir;
|
2017-11-14 01:56:20 +00:00
|
|
|
|
2018-02-26 09:40:38 +00:00
|
|
|
/* Set the next shader stage hint for VS and TES. */
|
|
|
|
if (!nir->info.separate_shader &&
|
|
|
|
(nir->info.stage == MESA_SHADER_VERTEX ||
|
|
|
|
nir->info.stage == MESA_SHADER_TESS_EVAL)) {
|
|
|
|
|
|
|
|
unsigned prev_stages = (1 << (prog->info.stage + 1)) - 1;
|
|
|
|
unsigned stages_mask =
|
|
|
|
~prev_stages & shader_program->data->linked_stages;
|
|
|
|
|
|
|
|
nir->info.next_stage = stages_mask ?
|
2018-10-20 05:02:59 +01:00
|
|
|
(gl_shader_stage) u_bit_scan(&stages_mask) : MESA_SHADER_FRAGMENT;
|
2018-02-26 09:40:38 +00:00
|
|
|
} else {
|
|
|
|
nir->info.next_stage = MESA_SHADER_FRAGMENT;
|
|
|
|
}
|
|
|
|
|
2019-01-10 06:24:57 +00:00
|
|
|
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
|
2020-10-29 10:52:25 +00:00
|
|
|
if (!st->ctx->SoftFP64 && ((nir->info.bit_sizes_int | nir->info.bit_sizes_float) & 64) &&
|
2019-01-10 06:24:57 +00:00
|
|
|
(options->lower_doubles_options & nir_lower_fp64_full_software) != 0) {
|
2022-01-07 05:28:08 +00:00
|
|
|
|
|
|
|
/* It's not possible to use float64 on GLSL ES, so don't bother trying to
|
|
|
|
* build the support code. The support code depends on higher versions of
|
|
|
|
* desktop GLSL, so it will fail to compile (below) anyway.
|
|
|
|
*/
|
|
|
|
if (_mesa_is_desktop_gl(st->ctx) && st->ctx->Const.GLSLVersion >= 400)
|
|
|
|
st->ctx->SoftFP64 = glsl_float64_funcs_to_nir(st->ctx, options);
|
2019-01-10 06:24:57 +00:00
|
|
|
}
|
|
|
|
|
2022-03-02 19:03:42 +00:00
|
|
|
prog->skip_pointsize_xfb = !(nir->info.outputs_written & VARYING_BIT_PSIZ);
|
2022-03-30 14:24:03 +01:00
|
|
|
if (st->lower_point_size && prog->skip_pointsize_xfb &&
|
|
|
|
stage < MESA_SHADER_FRAGMENT && stage != MESA_SHADER_TESS_CTRL &&
|
2022-03-02 16:48:43 +00:00
|
|
|
st_can_add_pointsize_to_program(st, prog)) {
|
2022-03-30 14:24:03 +01:00
|
|
|
NIR_PASS_V(nir, st_nir_add_point_size);
|
2022-03-02 15:54:14 +00:00
|
|
|
}
|
2022-03-02 19:03:42 +00:00
|
|
|
|
2021-11-23 01:44:07 +00:00
|
|
|
struct nir_remove_dead_variables_options opts;
|
|
|
|
bool is_sso = nir->info.separate_shader;
|
|
|
|
opts.can_remove_var_data = &is_sso;
|
|
|
|
opts.can_remove_var = &st_can_remove_varying_before_linking;
|
|
|
|
nir_variable_mode mask = nir_var_shader_in | nir_var_shader_out;
|
|
|
|
nir_remove_dead_variables(nir, mask, &opts);
|
2018-01-29 06:33:57 +00:00
|
|
|
|
2018-01-31 01:58:48 +00:00
|
|
|
if (options->lower_all_io_to_temps ||
|
|
|
|
nir->info.stage == MESA_SHADER_VERTEX ||
|
|
|
|
nir->info.stage == MESA_SHADER_GEOMETRY) {
|
|
|
|
NIR_PASS_V(nir, nir_lower_io_to_temporaries,
|
|
|
|
nir_shader_get_entrypoint(nir),
|
|
|
|
true, true);
|
2019-10-30 00:24:37 +00:00
|
|
|
} else if (nir->info.stage == MESA_SHADER_FRAGMENT ||
|
2022-03-14 09:13:40 +00:00
|
|
|
!screen->get_param(screen, PIPE_CAP_SHADER_CAN_READ_OUTPUTS)) {
|
2018-01-31 01:58:48 +00:00
|
|
|
NIR_PASS_V(nir, nir_lower_io_to_temporaries,
|
|
|
|
nir_shader_get_entrypoint(nir),
|
|
|
|
true, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
|
|
|
|
NIR_PASS_V(nir, nir_split_var_copies);
|
|
|
|
NIR_PASS_V(nir, nir_lower_var_copies);
|
|
|
|
|
2019-10-08 03:47:23 +01:00
|
|
|
if (options->lower_to_scalar) {
|
2021-03-31 09:55:18 +01:00
|
|
|
NIR_PASS_V(nir, nir_lower_alu_to_scalar,
|
|
|
|
options->lower_to_scalar_filter, NULL);
|
2019-01-10 06:24:57 +00:00
|
|
|
}
|
|
|
|
|
2019-03-31 10:30:12 +01:00
|
|
|
/* before buffers and vars_to_ssa */
|
2020-01-23 18:49:02 +00:00
|
|
|
NIR_PASS_V(nir, gl_nir_lower_images, true);
|
2019-03-04 23:02:39 +00:00
|
|
|
|
2019-08-22 14:43:28 +01:00
|
|
|
/* TODO: Change GLSL to not lower shared memory. */
|
|
|
|
if (prog->nir->info.stage == MESA_SHADER_COMPUTE &&
|
|
|
|
shader_program->data->spirv) {
|
|
|
|
NIR_PASS_V(prog->nir, nir_lower_vars_to_explicit_types,
|
|
|
|
nir_var_mem_shared, shared_type_info);
|
|
|
|
NIR_PASS_V(prog->nir, nir_lower_explicit_io,
|
|
|
|
nir_var_mem_shared, nir_address_format_32bit_offset);
|
|
|
|
}
|
|
|
|
|
2019-03-10 13:57:51 +00:00
|
|
|
/* Do a round of constant folding to clean up address calculations */
|
|
|
|
NIR_PASS_V(nir, nir_opt_constant_folding);
|
2017-11-13 22:15:54 +00:00
|
|
|
}
|
|
|
|
|
2020-10-25 18:28:22 +00:00
|
|
|
static bool
|
|
|
|
dest_is_64bit(nir_dest *dest, void *state)
|
|
|
|
{
|
|
|
|
bool *lower = (bool *)state;
|
|
|
|
if (dest && (nir_dest_bit_size(*dest) == 64)) {
|
|
|
|
*lower = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
src_is_64bit(nir_src *src, void *state)
|
|
|
|
{
|
|
|
|
bool *lower = (bool *)state;
|
|
|
|
if (src && (nir_src_bit_size(*src) == 64)) {
|
|
|
|
*lower = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
filter_64_bit_instr(const nir_instr *const_instr, UNUSED const void *data)
|
|
|
|
{
|
|
|
|
bool lower = false;
|
|
|
|
/* lower_alu_to_scalar required nir_instr to be const, but nir_foreach_*
|
|
|
|
* doesn't have const variants, so do the ugly const_cast here. */
|
|
|
|
nir_instr *instr = const_cast<nir_instr *>(const_instr);
|
|
|
|
|
|
|
|
nir_foreach_dest(instr, dest_is_64bit, &lower);
|
|
|
|
if (lower)
|
|
|
|
return true;
|
|
|
|
nir_foreach_src(instr, src_is_64bit, &lower);
|
|
|
|
return lower;
|
|
|
|
}
|
|
|
|
|
2017-11-13 22:15:54 +00:00
|
|
|
/* Second third of converting glsl_to_nir. This creates uniforms, gathers
|
|
|
|
* info on varyings, etc after NIR link time opts have been applied.
|
|
|
|
*/
|
2021-08-03 18:20:18 +01:00
|
|
|
static char *
|
2017-11-13 22:15:54 +00:00
|
|
|
st_glsl_to_nir_post_opts(struct st_context *st, struct gl_program *prog,
|
|
|
|
struct gl_shader_program *shader_program)
|
|
|
|
{
|
|
|
|
nir_shader *nir = prog->nir;
|
2020-11-29 08:27:37 +00:00
|
|
|
struct pipe_screen *screen = st->screen;
|
2015-12-22 02:34:11 +00:00
|
|
|
|
2017-11-01 03:15:22 +00:00
|
|
|
/* Make a pass over the IR to add state references for any built-in
|
|
|
|
* uniforms that are used. This has to be done now (during linking).
|
|
|
|
* Code generation doesn't happen until the first time this shader is
|
|
|
|
* used for rendering. Waiting until then to generate the parameters is
|
|
|
|
* too late. At that point, the values for the built-in uniforms won't
|
|
|
|
* get sent to the shader.
|
|
|
|
*/
|
2020-07-19 00:45:18 +01:00
|
|
|
nir_foreach_uniform_variable(var, nir) {
|
2019-08-21 17:38:10 +01:00
|
|
|
const nir_state_slot *const slots = var->state_slots;
|
|
|
|
if (slots != NULL) {
|
2018-03-13 09:50:27 +00:00
|
|
|
const struct glsl_type *type = glsl_without_array(var->type);
|
2017-11-01 03:15:22 +00:00
|
|
|
for (unsigned int i = 0; i < var->num_state_slots; i++) {
|
2018-03-13 09:50:27 +00:00
|
|
|
unsigned comps;
|
2019-03-05 05:07:12 +00:00
|
|
|
if (glsl_type_is_struct_or_ifc(type)) {
|
2020-06-26 06:28:51 +01:00
|
|
|
comps = _mesa_program_state_value_size(slots[i].tokens);
|
2018-03-13 09:50:27 +00:00
|
|
|
} else {
|
|
|
|
comps = glsl_get_vector_elements(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (st->ctx->Const.PackedDriverUniformStorage) {
|
|
|
|
_mesa_add_sized_state_reference(prog->Parameters,
|
|
|
|
slots[i].tokens,
|
|
|
|
comps, false);
|
|
|
|
} else {
|
|
|
|
_mesa_add_state_reference(prog->Parameters,
|
|
|
|
slots[i].tokens);
|
|
|
|
}
|
2017-11-01 03:15:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Avoid reallocation of the program parameter list, because the uniform
|
|
|
|
* storage is only associated with the original parameter list.
|
|
|
|
* This should be enough for Bitmap and DrawPixels constants.
|
|
|
|
*/
|
2022-06-03 14:52:29 +01:00
|
|
|
_mesa_ensure_and_associate_uniform_storage(st->ctx, shader_program, prog, 28);
|
2017-11-01 03:15:22 +00:00
|
|
|
|
2019-08-22 14:43:28 +01:00
|
|
|
/* None of the builtins being lowered here can be produced by SPIR-V. See
|
2020-06-26 06:28:51 +01:00
|
|
|
* _mesa_builtin_uniform_desc. Also drivers that support packed uniform
|
|
|
|
* storage don't need to lower builtins.
|
2019-08-22 14:43:28 +01:00
|
|
|
*/
|
2020-06-26 06:28:51 +01:00
|
|
|
if (!shader_program->data->spirv &&
|
2022-05-12 20:10:32 +01:00
|
|
|
!st->ctx->Const.PackedDriverUniformStorage)
|
2019-08-22 14:43:28 +01:00
|
|
|
NIR_PASS_V(nir, st_nir_lower_builtin);
|
|
|
|
|
2020-06-27 21:40:56 +01:00
|
|
|
if (!screen->get_param(screen, PIPE_CAP_NIR_ATOMICS_AS_DEREF))
|
|
|
|
NIR_PASS_V(nir, gl_nir_lower_atomics, shader_program, true);
|
|
|
|
|
2019-04-10 02:40:33 +01:00
|
|
|
NIR_PASS_V(nir, nir_opt_intrinsics);
|
2021-05-07 15:36:47 +01:00
|
|
|
NIR_PASS_V(nir, nir_opt_fragdepth);
|
2017-11-01 09:32:12 +00:00
|
|
|
|
2019-10-15 21:49:06 +01:00
|
|
|
/* Lower 64-bit ops. */
|
|
|
|
if (nir->options->lower_int64_options ||
|
|
|
|
nir->options->lower_doubles_options) {
|
|
|
|
bool lowered_64bit_ops = false;
|
2021-05-18 04:31:14 +01:00
|
|
|
bool revectorize = false;
|
2020-10-25 18:28:22 +00:00
|
|
|
|
2019-10-15 21:49:06 +01:00
|
|
|
if (nir->options->lower_doubles_options) {
|
2022-05-10 20:13:17 +01:00
|
|
|
/* nir_lower_doubles is not prepared for vector ops, so if the backend doesn't
|
|
|
|
* request lower_alu_to_scalar until now, lower all 64 bit ops, and try to
|
|
|
|
* vectorize them afterwards again */
|
|
|
|
if (!nir->options->lower_to_scalar) {
|
|
|
|
NIR_PASS(revectorize, nir, nir_lower_alu_to_scalar, filter_64_bit_instr, nullptr);
|
|
|
|
NIR_PASS(revectorize, nir, nir_lower_phis_to_scalar, false);
|
|
|
|
}
|
2019-10-15 21:49:06 +01:00
|
|
|
NIR_PASS(lowered_64bit_ops, nir, nir_lower_doubles,
|
|
|
|
st->ctx->SoftFP64, nir->options->lower_doubles_options);
|
|
|
|
}
|
2020-07-13 19:28:16 +01:00
|
|
|
if (nir->options->lower_int64_options)
|
|
|
|
NIR_PASS(lowered_64bit_ops, nir, nir_lower_int64);
|
2019-10-15 21:49:06 +01:00
|
|
|
|
2020-12-18 18:05:47 +00:00
|
|
|
if (revectorize && !nir->options->vectorize_vec2_16bit)
|
2021-05-18 04:31:14 +01:00
|
|
|
NIR_PASS_V(nir, nir_opt_vectorize, nullptr, nullptr);
|
|
|
|
|
|
|
|
if (revectorize || lowered_64bit_ops)
|
2022-01-04 01:51:56 +00:00
|
|
|
gl_nir_opts(nir);
|
2019-10-15 21:49:06 +01:00
|
|
|
}
|
|
|
|
|
2020-08-31 17:08:49 +01:00
|
|
|
nir_variable_mode mask =
|
|
|
|
nir_var_shader_in | nir_var_shader_out | nir_var_function_temp;
|
2020-05-28 01:59:28 +01:00
|
|
|
nir_remove_dead_variables(nir, mask, NULL);
|
2019-01-31 04:59:18 +00:00
|
|
|
|
2022-05-27 18:34:09 +01:00
|
|
|
if (!st->has_hw_atomics && !screen->get_param(screen, PIPE_CAP_NIR_ATOMICS_AS_DEREF)) {
|
|
|
|
unsigned align_offset_state = 0;
|
|
|
|
if (st->ctx->Const.ShaderStorageBufferOffsetAlignment > 4) {
|
|
|
|
struct gl_program_parameter_list *params = prog->Parameters;
|
|
|
|
for (unsigned i = 0; i < shader_program->data->NumAtomicBuffers; i++) {
|
|
|
|
gl_state_index16 state[STATE_LENGTH] = { STATE_ATOMIC_COUNTER_OFFSET, (short)shader_program->data->AtomicBuffers[i].Binding };
|
|
|
|
_mesa_add_state_reference(params, state);
|
|
|
|
}
|
|
|
|
align_offset_state = STATE_ATOMIC_COUNTER_OFFSET;
|
|
|
|
}
|
|
|
|
NIR_PASS_V(nir, nir_lower_atomics_to_ssbo, align_offset_state);
|
|
|
|
}
|
2019-10-18 02:03:34 +01:00
|
|
|
|
2022-06-02 22:44:34 +01:00
|
|
|
st_set_prog_affected_state_flags(prog);
|
|
|
|
|
2019-10-18 02:03:34 +01:00
|
|
|
st_finalize_nir_before_variants(nir);
|
|
|
|
|
2021-08-03 18:20:18 +01:00
|
|
|
char *msg = NULL;
|
2019-09-27 23:09:11 +01:00
|
|
|
if (st->allow_st_finalize_nir_twice)
|
2021-08-03 18:20:18 +01:00
|
|
|
msg = st_finalize_nir(st, prog, shader_program, nir, true, true);
|
2019-09-27 23:09:11 +01:00
|
|
|
|
2015-12-22 02:34:11 +00:00
|
|
|
if (st->ctx->_Shader->Flags & GLSL_DUMP) {
|
|
|
|
_mesa_log("\n");
|
|
|
|
_mesa_log("NIR IR for linked %s program %d:\n",
|
2017-11-13 22:15:54 +00:00
|
|
|
_mesa_shader_stage_to_string(prog->info.stage),
|
2015-12-22 02:34:11 +00:00
|
|
|
shader_program->Name);
|
|
|
|
nir_print_shader(nir, _mesa_get_log_file());
|
|
|
|
_mesa_log("\n\n");
|
|
|
|
}
|
2021-08-03 18:20:18 +01:00
|
|
|
|
|
|
|
return msg;
|
2015-12-22 02:34:11 +00:00
|
|
|
}
|
|
|
|
|
st/nir: Re-vectorize shader IO
We scalarize IO to enable further optimizations, such as propagating
constant components across shaders, eliminating dead components, and
so on. This patch attempts to re-vectorize those operations after
the varying optimizations are done.
Intel GPUs are a scalar architecture, but IO operations work on whole
vec4's at a time, so we'd prefer to have a single IO load per vector
rather than 4 scalar IO loads. This re-vectorization can help a lot.
Broadcom GPUs, however, really do want scalar IO. radeonsi may want
this, or may want to leave it to LLVM. So, we make a new flag in the
NIR compiler options struct, and key it off of that, allowing drivers
to pick. (It's a bit awkward because we have per-stage settings, but
this is about IO between two stages...but I expect drivers to globally
prefer one way or the other. We can adjust later if needed.)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
2019-04-11 20:28:48 +01:00
|
|
|
static void
|
|
|
|
st_nir_vectorize_io(nir_shader *producer, nir_shader *consumer)
|
|
|
|
{
|
2022-04-14 04:35:57 +01:00
|
|
|
if (consumer)
|
|
|
|
NIR_PASS_V(consumer, nir_lower_io_to_vector, nir_var_shader_in);
|
|
|
|
|
|
|
|
if (!producer)
|
|
|
|
return;
|
|
|
|
|
st/nir: Re-vectorize shader IO
We scalarize IO to enable further optimizations, such as propagating
constant components across shaders, eliminating dead components, and
so on. This patch attempts to re-vectorize those operations after
the varying optimizations are done.
Intel GPUs are a scalar architecture, but IO operations work on whole
vec4's at a time, so we'd prefer to have a single IO load per vector
rather than 4 scalar IO loads. This re-vectorization can help a lot.
Broadcom GPUs, however, really do want scalar IO. radeonsi may want
this, or may want to leave it to LLVM. So, we make a new flag in the
NIR compiler options struct, and key it off of that, allowing drivers
to pick. (It's a bit awkward because we have per-stage settings, but
this is about IO between two stages...but I expect drivers to globally
prefer one way or the other. We can adjust later if needed.)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
2019-04-11 20:28:48 +01:00
|
|
|
NIR_PASS_V(producer, nir_lower_io_to_vector, nir_var_shader_out);
|
|
|
|
NIR_PASS_V(producer, nir_opt_combine_stores, nir_var_shader_out);
|
|
|
|
|
|
|
|
if ((producer)->info.stage != MESA_SHADER_TESS_CTRL) {
|
|
|
|
/* Calling lower_io_to_vector creates output variable writes with
|
|
|
|
* write-masks. We only support these for TCS outputs, so for other
|
|
|
|
* stages, we need to call nir_lower_io_to_temporaries to get rid of
|
|
|
|
* them. This, in turn, creates temporary variables and extra
|
|
|
|
* copy_deref intrinsics that we need to clean up.
|
|
|
|
*/
|
|
|
|
NIR_PASS_V(producer, nir_lower_io_to_temporaries,
|
|
|
|
nir_shader_get_entrypoint(producer), true, false);
|
|
|
|
NIR_PASS_V(producer, nir_lower_global_vars_to_local);
|
|
|
|
NIR_PASS_V(producer, nir_split_var_copies);
|
|
|
|
NIR_PASS_V(producer, nir_lower_var_copies);
|
|
|
|
}
|
2021-02-08 11:06:24 +00:00
|
|
|
|
|
|
|
/* Undef scalar store_deref intrinsics are not ignored by nir_lower_io,
|
|
|
|
* so they must be removed before that. These passes remove them.
|
|
|
|
*/
|
|
|
|
NIR_PASS_V(producer, nir_lower_vars_to_ssa);
|
|
|
|
NIR_PASS_V(producer, nir_opt_undef);
|
|
|
|
NIR_PASS_V(producer, nir_opt_dce);
|
st/nir: Re-vectorize shader IO
We scalarize IO to enable further optimizations, such as propagating
constant components across shaders, eliminating dead components, and
so on. This patch attempts to re-vectorize those operations after
the varying optimizations are done.
Intel GPUs are a scalar architecture, but IO operations work on whole
vec4's at a time, so we'd prefer to have a single IO load per vector
rather than 4 scalar IO loads. This re-vectorization can help a lot.
Broadcom GPUs, however, really do want scalar IO. radeonsi may want
this, or may want to leave it to LLVM. So, we make a new flag in the
NIR compiler options struct, and key it off of that, allowing drivers
to pick. (It's a bit awkward because we have per-stage settings, but
this is about IO between two stages...but I expect drivers to globally
prefer one way or the other. We can adjust later if needed.)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
2019-04-11 20:28:48 +01:00
|
|
|
}
|
|
|
|
|
2018-07-19 02:46:09 +01:00
|
|
|
static void
|
|
|
|
st_lower_patch_vertices_in(struct gl_shader_program *shader_prog)
|
|
|
|
{
|
|
|
|
struct gl_linked_shader *linked_tcs =
|
|
|
|
shader_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL];
|
|
|
|
struct gl_linked_shader *linked_tes =
|
|
|
|
shader_prog->_LinkedShaders[MESA_SHADER_TESS_EVAL];
|
|
|
|
|
|
|
|
/* If we have a TCS and TES linked together, lower TES patch vertices. */
|
|
|
|
if (linked_tcs && linked_tes) {
|
|
|
|
nir_shader *tcs_nir = linked_tcs->Program->nir;
|
|
|
|
nir_shader *tes_nir = linked_tes->Program->nir;
|
|
|
|
|
|
|
|
/* The TES input vertex count is the TCS output vertex count,
|
|
|
|
* lower TES gl_PatchVerticesIn to a constant.
|
|
|
|
*/
|
|
|
|
uint32_t tes_patch_verts = tcs_nir->info.tess.tcs_vertices_out;
|
|
|
|
NIR_PASS_V(tes_nir, nir_lower_patch_vertices, tes_patch_verts, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:06:47 +00:00
|
|
|
extern "C" {
|
|
|
|
|
2018-10-25 10:22:33 +01:00
|
|
|
void
|
|
|
|
st_nir_lower_wpos_ytransform(struct nir_shader *nir,
|
|
|
|
struct gl_program *prog,
|
|
|
|
struct pipe_screen *pscreen)
|
|
|
|
{
|
|
|
|
if (nir->info.stage != MESA_SHADER_FRAGMENT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
static const gl_state_index16 wposTransformState[STATE_LENGTH] = {
|
2020-12-05 00:19:22 +00:00
|
|
|
STATE_FB_WPOS_Y_TRANSFORM
|
2018-10-25 10:22:33 +01:00
|
|
|
};
|
|
|
|
nir_lower_wpos_ytransform_options wpos_options = { { 0 } };
|
|
|
|
|
|
|
|
memcpy(wpos_options.state_tokens, wposTransformState,
|
|
|
|
sizeof(wpos_options.state_tokens));
|
|
|
|
wpos_options.fs_coord_origin_upper_left =
|
|
|
|
pscreen->get_param(pscreen,
|
2022-03-14 08:02:05 +00:00
|
|
|
PIPE_CAP_FS_COORD_ORIGIN_UPPER_LEFT);
|
2018-10-25 10:22:33 +01:00
|
|
|
wpos_options.fs_coord_origin_lower_left =
|
|
|
|
pscreen->get_param(pscreen,
|
2022-03-14 08:02:05 +00:00
|
|
|
PIPE_CAP_FS_COORD_ORIGIN_LOWER_LEFT);
|
2018-10-25 10:22:33 +01:00
|
|
|
wpos_options.fs_coord_pixel_center_integer =
|
|
|
|
pscreen->get_param(pscreen,
|
2022-03-14 08:02:05 +00:00
|
|
|
PIPE_CAP_FS_COORD_PIXEL_CENTER_INTEGER);
|
2018-10-25 10:22:33 +01:00
|
|
|
wpos_options.fs_coord_pixel_center_half_integer =
|
|
|
|
pscreen->get_param(pscreen,
|
2022-03-14 08:02:05 +00:00
|
|
|
PIPE_CAP_FS_COORD_PIXEL_CENTER_HALF_INTEGER);
|
2018-10-25 10:22:33 +01:00
|
|
|
|
|
|
|
if (nir_lower_wpos_ytransform(nir, &wpos_options)) {
|
|
|
|
nir_validate_shader(nir, "after nir_lower_wpos_ytransform");
|
|
|
|
_mesa_add_state_reference(prog->Parameters, wposTransformState);
|
|
|
|
}
|
2020-12-22 12:37:45 +00:00
|
|
|
|
|
|
|
static const gl_state_index16 pntcTransformState[STATE_LENGTH] = {
|
2020-12-05 00:19:22 +00:00
|
|
|
STATE_FB_PNTC_Y_TRANSFORM
|
2020-12-22 12:37:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (nir_lower_pntc_ytransform(nir, &pntcTransformState)) {
|
|
|
|
_mesa_add_state_reference(prog->Parameters, pntcTransformState);
|
|
|
|
}
|
2018-10-25 10:22:33 +01:00
|
|
|
}
|
|
|
|
|
2017-11-09 06:32:08 +00:00
|
|
|
bool
|
|
|
|
st_link_nir(struct gl_context *ctx,
|
|
|
|
struct gl_shader_program *shader_program)
|
|
|
|
{
|
2017-11-13 22:15:54 +00:00
|
|
|
struct st_context *st = st_context(ctx);
|
2019-11-19 22:30:03 +00:00
|
|
|
struct gl_linked_shader *linked_shader[MESA_SHADER_STAGES];
|
|
|
|
unsigned num_shaders = 0;
|
2018-06-15 11:29:59 +01:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
2019-11-19 22:30:03 +00:00
|
|
|
if (shader_program->_LinkedShaders[i])
|
|
|
|
linked_shader[num_shaders++] = shader_program->_LinkedShaders[i];
|
|
|
|
}
|
2019-10-08 03:15:01 +01:00
|
|
|
|
2019-11-19 22:30:03 +00:00
|
|
|
for (unsigned i = 0; i < num_shaders; i++) {
|
|
|
|
struct gl_linked_shader *shader = linked_shader[i];
|
2019-10-08 03:47:23 +01:00
|
|
|
const nir_shader_compiler_options *options =
|
|
|
|
st->ctx->Const.ShaderCompilerOptions[shader->Stage].NirOptions;
|
2019-08-22 14:43:28 +01:00
|
|
|
struct gl_program *prog = shader->Program;
|
2019-11-21 00:18:21 +00:00
|
|
|
|
2019-08-22 14:43:28 +01:00
|
|
|
_mesa_copy_linked_program_data(shader_program, shader);
|
|
|
|
|
2019-08-22 19:23:51 +01:00
|
|
|
assert(!prog->nir);
|
2021-12-20 05:54:08 +00:00
|
|
|
prog->shader_program = shader_program;
|
|
|
|
prog->state.type = PIPE_SHADER_IR_NIR;
|
2019-08-22 19:23:51 +01:00
|
|
|
|
2020-01-07 03:38:14 +00:00
|
|
|
/* Parameters will be filled during NIR linking. */
|
|
|
|
prog->Parameters = _mesa_new_parameter_list();
|
2019-08-22 14:43:28 +01:00
|
|
|
|
2020-01-07 03:38:14 +00:00
|
|
|
if (shader_program->data->spirv) {
|
2019-08-22 14:43:28 +01:00
|
|
|
prog->nir = _mesa_spirv_to_nir(ctx, shader_program, shader->Stage, options);
|
|
|
|
} else {
|
|
|
|
validate_ir_tree(shader->ir);
|
|
|
|
|
|
|
|
if (ctx->_Shader->Flags & GLSL_DUMP) {
|
|
|
|
_mesa_log("\n");
|
|
|
|
_mesa_log("GLSL IR for linked %s program %d:\n",
|
|
|
|
_mesa_shader_stage_to_string(shader->Stage),
|
|
|
|
shader_program->Name);
|
|
|
|
_mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
|
|
|
|
_mesa_log("\n\n");
|
|
|
|
}
|
|
|
|
|
2022-01-07 02:47:08 +00:00
|
|
|
prog->nir = glsl_to_nir(&st->ctx->Const, shader_program, shader->Stage, options);
|
2019-08-22 14:43:28 +01:00
|
|
|
}
|
|
|
|
|
2021-11-18 14:28:17 +00:00
|
|
|
memcpy(prog->nir->info.source_sha1, shader->linked_source_sha1,
|
|
|
|
SHA1_DIGEST_LENGTH);
|
2021-09-08 07:44:11 +01:00
|
|
|
st_nir_preprocess(st, prog, shader_program, shader->Stage);
|
|
|
|
|
2019-10-08 03:47:23 +01:00
|
|
|
if (options->lower_to_scalar) {
|
2019-01-02 23:03:05 +00:00
|
|
|
NIR_PASS_V(shader->Program->nir, nir_lower_load_const_to_scalar);
|
2018-12-11 04:06:37 +00:00
|
|
|
}
|
2017-11-20 06:20:35 +00:00
|
|
|
}
|
|
|
|
|
2019-11-13 04:48:02 +00:00
|
|
|
st_lower_patch_vertices_in(shader_program);
|
|
|
|
|
2019-11-13 22:49:53 +00:00
|
|
|
/* Linking shaders also optimizes them. Separate shaders, compute shaders
|
|
|
|
* and shaders with a fixed-func VS or FS that don't need linking are
|
|
|
|
* optimized here.
|
|
|
|
*/
|
|
|
|
if (num_shaders == 1)
|
2022-01-04 01:51:56 +00:00
|
|
|
gl_nir_opts(linked_shader[0]->Program->nir);
|
2017-11-09 06:32:08 +00:00
|
|
|
|
2021-09-08 07:44:11 +01:00
|
|
|
if (shader_program->data->spirv) {
|
|
|
|
static const gl_nir_linker_options opts = {
|
|
|
|
true /*fill_parameters */
|
|
|
|
};
|
2022-01-07 01:20:14 +00:00
|
|
|
if (!gl_nir_link_spirv(&ctx->Const, shader_program, &opts))
|
2021-09-08 07:44:11 +01:00
|
|
|
return GL_FALSE;
|
|
|
|
} else {
|
2021-11-23 01:44:07 +00:00
|
|
|
if (!gl_nir_link_glsl(&ctx->Const, &ctx->Extensions, ctx->API,
|
2022-01-07 01:20:14 +00:00
|
|
|
shader_program))
|
2019-12-23 00:37:57 +00:00
|
|
|
return GL_FALSE;
|
2021-09-08 07:44:11 +01:00
|
|
|
}
|
2019-12-23 00:37:57 +00:00
|
|
|
|
2021-09-08 07:44:11 +01:00
|
|
|
for (unsigned i = 0; i < num_shaders; i++) {
|
|
|
|
struct gl_program *prog = linked_shader[i]->Program;
|
|
|
|
prog->ExternalSamplersUsed = gl_external_samplers(prog);
|
|
|
|
_mesa_update_shader_textures_used(shader_program, prog);
|
2019-12-23 00:37:57 +00:00
|
|
|
}
|
2019-12-06 10:57:16 +00:00
|
|
|
|
2022-01-07 01:20:14 +00:00
|
|
|
nir_build_program_resource_list(&ctx->Const, shader_program,
|
2021-09-08 07:44:11 +01:00
|
|
|
shader_program->data->spirv);
|
|
|
|
|
2019-11-19 22:30:03 +00:00
|
|
|
for (unsigned i = 0; i < num_shaders; i++) {
|
|
|
|
struct gl_linked_shader *shader = linked_shader[i];
|
2017-11-17 06:45:32 +00:00
|
|
|
nir_shader *nir = shader->Program->nir;
|
2022-04-12 02:23:31 +01:00
|
|
|
gl_shader_stage stage = shader->Stage;
|
|
|
|
const struct gl_shader_compiler_options *options =
|
|
|
|
&ctx->Const.ShaderCompilerOptions[stage];
|
|
|
|
|
|
|
|
/* If there are forms of indirect addressing that the driver
|
|
|
|
* cannot handle, perform the lowering pass.
|
|
|
|
*/
|
|
|
|
if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput ||
|
|
|
|
options->EmitNoIndirectTemp || options->EmitNoIndirectUniform) {
|
|
|
|
nir_variable_mode mode = options->EmitNoIndirectInput ?
|
|
|
|
nir_var_shader_in : (nir_variable_mode)0;
|
|
|
|
mode |= options->EmitNoIndirectOutput ?
|
|
|
|
nir_var_shader_out : (nir_variable_mode)0;
|
|
|
|
mode |= options->EmitNoIndirectTemp ?
|
|
|
|
nir_var_function_temp : (nir_variable_mode)0;
|
|
|
|
mode |= options->EmitNoIndirectUniform ?
|
|
|
|
nir_var_uniform | nir_var_mem_ubo | nir_var_mem_ssbo :
|
|
|
|
(nir_variable_mode)0;
|
|
|
|
|
|
|
|
nir_lower_indirect_derefs(nir, mode, UINT32_MAX);
|
|
|
|
}
|
2017-11-17 06:45:32 +00:00
|
|
|
|
2020-08-25 17:36:14 +01:00
|
|
|
/* don't infer ACCESS_NON_READABLE so that Program->sh.ImageAccess is
|
|
|
|
* correct: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3278
|
|
|
|
*/
|
|
|
|
nir_opt_access_options opt_access_options;
|
|
|
|
opt_access_options.is_vulkan = false;
|
|
|
|
opt_access_options.infer_non_readable = false;
|
|
|
|
NIR_PASS_V(nir, nir_opt_access, &opt_access_options);
|
2020-09-18 17:12:29 +01:00
|
|
|
|
2019-11-13 22:49:53 +00:00
|
|
|
/* This needs to run after the initial pass of nir_lower_vars_to_ssa, so
|
|
|
|
* that the buffer indices are constants in nir where they where
|
|
|
|
* constants in GLSL. */
|
2019-12-06 10:53:17 +00:00
|
|
|
NIR_PASS_V(nir, gl_nir_lower_buffers, shader_program);
|
|
|
|
|
2019-12-06 02:53:24 +00:00
|
|
|
/* Remap the locations to slots so those requiring two slots will occupy
|
|
|
|
* two locations. For instance, if we have in the IR code a dvec3 attr0 in
|
|
|
|
* location 0 and vec4 attr1 in location 1, in NIR attr0 will use
|
|
|
|
* locations/slots 0 and 1, and attr1 will use location/slot 2
|
|
|
|
*/
|
|
|
|
if (nir->info.stage == MESA_SHADER_VERTEX && !shader_program->data->spirv)
|
|
|
|
nir_remap_dual_slot_attributes(nir, &shader->Program->DualSlotInputs);
|
|
|
|
|
2018-10-25 10:22:33 +01:00
|
|
|
NIR_PASS_V(nir, st_nir_lower_wpos_ytransform, shader->Program,
|
2020-11-29 08:27:37 +00:00
|
|
|
st->screen);
|
2017-11-17 06:45:32 +00:00
|
|
|
|
|
|
|
NIR_PASS_V(nir, nir_lower_system_values);
|
2020-08-21 18:40:45 +01:00
|
|
|
NIR_PASS_V(nir, nir_lower_compute_system_values, NULL);
|
2020-08-21 18:18:14 +01:00
|
|
|
|
2022-02-04 16:15:08 +00:00
|
|
|
if (!st->screen->get_param(st->screen, PIPE_CAP_CULL_DISTANCE_NOCOMBINE))
|
|
|
|
NIR_PASS_V(nir, nir_lower_clip_cull_distance_arrays);
|
2017-11-17 06:45:32 +00:00
|
|
|
|
2020-06-16 00:35:09 +01:00
|
|
|
st_shader_gather_info(nir, shader->Program);
|
2019-11-19 22:30:03 +00:00
|
|
|
if (shader->Stage == MESA_SHADER_VERTEX) {
|
2018-08-31 13:55:07 +01:00
|
|
|
/* NIR expands dual-slot inputs out to two locations. We need to
|
|
|
|
* compact things back down GL-style single-slot inputs to avoid
|
|
|
|
* confusing the state tracker.
|
|
|
|
*/
|
|
|
|
shader->Program->info.inputs_read =
|
|
|
|
nir_get_single_slot_attribs_mask(nir->info.inputs_read,
|
|
|
|
shader->Program->DualSlotInputs);
|
|
|
|
}
|
2017-11-17 06:45:32 +00:00
|
|
|
|
2019-11-19 22:30:03 +00:00
|
|
|
if (i >= 1) {
|
|
|
|
struct gl_program *prev_shader = linked_shader[i - 1]->Program;
|
2018-06-20 21:26:52 +01:00
|
|
|
|
|
|
|
/* We can't use nir_compact_varyings with transform feedback, since
|
|
|
|
* the pipe_stream_output->output_register field is based on the
|
|
|
|
* pre-compacted driver_locations.
|
|
|
|
*/
|
2018-12-08 18:21:52 +00:00
|
|
|
if (!(prev_shader->sh.LinkedTransformFeedback &&
|
|
|
|
prev_shader->sh.LinkedTransformFeedback->NumVarying > 0))
|
2019-11-19 22:30:03 +00:00
|
|
|
nir_compact_varyings(prev_shader->nir,
|
|
|
|
nir, ctx->API != API_OPENGL_COMPAT);
|
st/nir: Re-vectorize shader IO
We scalarize IO to enable further optimizations, such as propagating
constant components across shaders, eliminating dead components, and
so on. This patch attempts to re-vectorize those operations after
the varying optimizations are done.
Intel GPUs are a scalar architecture, but IO operations work on whole
vec4's at a time, so we'd prefer to have a single IO load per vector
rather than 4 scalar IO loads. This re-vectorization can help a lot.
Broadcom GPUs, however, really do want scalar IO. radeonsi may want
this, or may want to leave it to LLVM. So, we make a new flag in the
NIR compiler options struct, and key it off of that, allowing drivers
to pick. (It's a bit awkward because we have per-stage settings, but
this is about IO between two stages...but I expect drivers to globally
prefer one way or the other. We can adjust later if needed.)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
2019-04-11 20:28:48 +01:00
|
|
|
|
2019-11-19 22:30:03 +00:00
|
|
|
if (ctx->Const.ShaderCompilerOptions[shader->Stage].NirOptions->vectorize_io)
|
st/nir: Re-vectorize shader IO
We scalarize IO to enable further optimizations, such as propagating
constant components across shaders, eliminating dead components, and
so on. This patch attempts to re-vectorize those operations after
the varying optimizations are done.
Intel GPUs are a scalar architecture, but IO operations work on whole
vec4's at a time, so we'd prefer to have a single IO load per vector
rather than 4 scalar IO loads. This re-vectorization can help a lot.
Broadcom GPUs, however, really do want scalar IO. radeonsi may want
this, or may want to leave it to LLVM. So, we make a new flag in the
NIR compiler options struct, and key it off of that, allowing drivers
to pick. (It's a bit awkward because we have per-stage settings, but
this is about IO between two stages...but I expect drivers to globally
prefer one way or the other. We can adjust later if needed.)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
2019-04-11 20:28:48 +01:00
|
|
|
st_nir_vectorize_io(prev_shader->nir, nir);
|
2017-11-20 06:20:35 +00:00
|
|
|
}
|
2017-12-14 03:48:49 +00:00
|
|
|
}
|
|
|
|
|
2022-04-14 04:35:57 +01:00
|
|
|
/* If the program is a separate shader program check if we need to vectorise
|
|
|
|
* the first and last program interfaces too.
|
|
|
|
*/
|
|
|
|
if (shader_program->SeparateShader && num_shaders > 0) {
|
|
|
|
struct gl_linked_shader *first_shader = linked_shader[0];
|
|
|
|
struct gl_linked_shader *last_shader = linked_shader[num_shaders - 1];
|
|
|
|
if (first_shader->Stage != MESA_SHADER_COMPUTE) {
|
|
|
|
if (ctx->Const.ShaderCompilerOptions[first_shader->Stage].NirOptions->vectorize_io &&
|
|
|
|
first_shader->Stage > MESA_SHADER_VERTEX)
|
|
|
|
st_nir_vectorize_io(NULL, first_shader->Program->nir);
|
|
|
|
|
|
|
|
if (ctx->Const.ShaderCompilerOptions[last_shader->Stage].NirOptions->vectorize_io &&
|
|
|
|
last_shader->Stage < MESA_SHADER_FRAGMENT)
|
|
|
|
st_nir_vectorize_io(last_shader->Program->nir, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-12 10:45:55 +00:00
|
|
|
struct shader_info *prev_info = NULL;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_shaders; i++) {
|
|
|
|
struct gl_linked_shader *shader = linked_shader[i];
|
|
|
|
struct shader_info *info = &shader->Program->nir->info;
|
|
|
|
|
2021-08-03 18:20:18 +01:00
|
|
|
char *msg = st_glsl_to_nir_post_opts(st, shader->Program, shader_program);
|
|
|
|
if (msg) {
|
|
|
|
linker_error(shader_program, msg);
|
2022-06-06 20:43:50 +01:00
|
|
|
return false;
|
2021-08-03 18:20:18 +01:00
|
|
|
}
|
2020-09-08 11:22:12 +01:00
|
|
|
|
2020-02-12 10:45:55 +00:00
|
|
|
if (prev_info &&
|
|
|
|
ctx->Const.ShaderCompilerOptions[shader->Stage].NirOptions->unify_interfaces) {
|
|
|
|
prev_info->outputs_written |= info->inputs_read &
|
|
|
|
~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER);
|
|
|
|
info->inputs_read |= prev_info->outputs_written &
|
|
|
|
~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER);
|
|
|
|
|
|
|
|
prev_info->patch_outputs_written |= info->patch_inputs_read;
|
|
|
|
info->patch_inputs_read |= prev_info->patch_outputs_written;
|
|
|
|
}
|
|
|
|
prev_info = info;
|
|
|
|
}
|
|
|
|
|
2019-11-19 22:30:03 +00:00
|
|
|
for (unsigned i = 0; i < num_shaders; i++) {
|
|
|
|
struct gl_linked_shader *shader = linked_shader[i];
|
2019-09-27 22:28:48 +01:00
|
|
|
struct gl_program *prog = shader->Program;
|
2017-11-13 22:15:54 +00:00
|
|
|
|
2020-09-28 23:18:43 +01:00
|
|
|
/* Make sure that prog->info is in sync with nir->info, but st/mesa
|
|
|
|
* expects some of the values to be from before lowering.
|
|
|
|
*/
|
|
|
|
shader_info old_info = prog->info;
|
|
|
|
prog->info = prog->nir->info;
|
2020-11-09 21:20:13 +00:00
|
|
|
prog->info.name = old_info.name;
|
|
|
|
prog->info.label = old_info.label;
|
2020-09-28 23:18:43 +01:00
|
|
|
prog->info.num_ssbos = old_info.num_ssbos;
|
|
|
|
prog->info.num_ubos = old_info.num_ubos;
|
|
|
|
prog->info.num_abos = old_info.num_abos;
|
|
|
|
if (prog->info.stage == MESA_SHADER_VERTEX)
|
|
|
|
prog->info.inputs_read = old_info.inputs_read;
|
|
|
|
|
2019-09-27 22:43:42 +01:00
|
|
|
/* Initialize st_vertex_program members. */
|
2019-11-19 22:30:03 +00:00
|
|
|
if (shader->Stage == MESA_SHADER_VERTEX)
|
2022-04-08 19:07:13 +01:00
|
|
|
st_prepare_vertex_program(prog);
|
2019-09-27 22:43:42 +01:00
|
|
|
|
|
|
|
/* Get pipe_stream_output_info. */
|
2019-11-19 22:30:03 +00:00
|
|
|
if (shader->Stage == MESA_SHADER_VERTEX ||
|
|
|
|
shader->Stage == MESA_SHADER_TESS_EVAL ||
|
|
|
|
shader->Stage == MESA_SHADER_GEOMETRY)
|
2019-09-27 22:43:42 +01:00
|
|
|
st_translate_stream_output_info(prog);
|
|
|
|
|
2021-09-08 00:46:55 +01:00
|
|
|
st_store_nir_in_disk_cache(st, prog);
|
2019-09-27 22:43:42 +01:00
|
|
|
|
2021-12-20 05:54:08 +00:00
|
|
|
st_release_variants(st, prog);
|
2019-11-13 04:46:37 +00:00
|
|
|
st_finalize_program(st, prog);
|
2017-11-09 06:32:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-13 23:06:47 +00:00
|
|
|
void
|
2018-10-30 05:41:18 +00:00
|
|
|
st_nir_assign_varying_locations(struct st_context *st, nir_shader *nir)
|
2017-11-13 23:06:47 +00:00
|
|
|
{
|
|
|
|
if (nir->info.stage == MESA_SHADER_VERTEX) {
|
2020-07-20 20:42:53 +01:00
|
|
|
nir_assign_io_var_locations(nir, nir_var_shader_out,
|
2017-11-10 10:33:37 +00:00
|
|
|
&nir->num_outputs,
|
|
|
|
nir->info.stage);
|
2020-07-20 21:57:45 +01:00
|
|
|
st_nir_fixup_varying_slots(st, nir, nir_var_shader_out);
|
2017-12-06 02:32:17 +00:00
|
|
|
} else if (nir->info.stage == MESA_SHADER_GEOMETRY ||
|
|
|
|
nir->info.stage == MESA_SHADER_TESS_CTRL ||
|
|
|
|
nir->info.stage == MESA_SHADER_TESS_EVAL) {
|
2020-07-20 20:42:53 +01:00
|
|
|
nir_assign_io_var_locations(nir, nir_var_shader_in,
|
2017-11-10 10:33:37 +00:00
|
|
|
&nir->num_inputs,
|
|
|
|
nir->info.stage);
|
2020-07-20 21:57:45 +01:00
|
|
|
st_nir_fixup_varying_slots(st, nir, nir_var_shader_in);
|
2017-11-10 10:33:37 +00:00
|
|
|
|
2020-07-20 20:42:53 +01:00
|
|
|
nir_assign_io_var_locations(nir, nir_var_shader_out,
|
2017-11-22 06:37:32 +00:00
|
|
|
&nir->num_outputs,
|
|
|
|
nir->info.stage);
|
2020-07-20 21:57:45 +01:00
|
|
|
st_nir_fixup_varying_slots(st, nir, nir_var_shader_out);
|
2017-11-13 23:06:47 +00:00
|
|
|
} else if (nir->info.stage == MESA_SHADER_FRAGMENT) {
|
2020-07-20 20:42:53 +01:00
|
|
|
nir_assign_io_var_locations(nir, nir_var_shader_in,
|
2017-11-22 06:37:32 +00:00
|
|
|
&nir->num_inputs,
|
|
|
|
nir->info.stage);
|
2020-07-20 21:57:45 +01:00
|
|
|
st_nir_fixup_varying_slots(st, nir, nir_var_shader_in);
|
2020-07-20 20:42:53 +01:00
|
|
|
nir_assign_io_var_locations(nir, nir_var_shader_out,
|
2017-11-22 06:37:32 +00:00
|
|
|
&nir->num_outputs,
|
|
|
|
nir->info.stage);
|
2017-11-13 23:06:47 +00:00
|
|
|
} else if (nir->info.stage == MESA_SHADER_COMPUTE) {
|
|
|
|
/* TODO? */
|
|
|
|
} else {
|
2018-10-30 05:41:18 +00:00
|
|
|
unreachable("invalid shader type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-06 08:03:49 +00:00
|
|
|
void
|
|
|
|
st_nir_lower_samplers(struct pipe_screen *screen, nir_shader *nir,
|
nir: Gather texture bitmasks in gl_nir_lower_samplers_as_deref.
Eric and I would like a bitmask of which samplers are used, similar to
prog->SamplersUsed, but available in NIR. The linker uses SamplersUsed
for resource limit checking, but later optimizations may eliminate more
samplers. So instead of propagating it through, we gather a new one.
While there, we also gather the existing textures_used_by_txf bitmask.
Gathering these bitfields in nir_shader_gather_info is awkward at best.
The main reason is that it introduces an ordering dependency between the
two passes. If gathering runs before lower_samplers_as_deref, it can't
look at var->data.binding. If the driver doesn't use the full lowering
to texture_index/texture_array_size (like radeonsi), then the gathering
can't use those fields. Gathering might be run early /and/ late, first
to get varying info, and later to update it after variant lowering. At
this point, should gathering work on pre-lowered or post-lowered code?
Pre-lowered is also harder due to the presence of structure types.
Just doing the gathering when we do the lowering alleviates these
ordering problems. This fixes ordering issues in i965 and makes the
txf info gathering work for radeonsi (though they don't use it).
Reviewed-by: Eric Anholt <eric@anholt.net>
2019-01-13 18:39:41 +00:00
|
|
|
struct gl_shader_program *shader_program,
|
|
|
|
struct gl_program *prog)
|
2019-02-06 08:03:49 +00:00
|
|
|
{
|
|
|
|
if (screen->get_param(screen, PIPE_CAP_NIR_SAMPLERS_AS_DEREF))
|
|
|
|
NIR_PASS_V(nir, gl_nir_lower_samplers_as_deref, shader_program);
|
|
|
|
else
|
|
|
|
NIR_PASS_V(nir, gl_nir_lower_samplers, shader_program);
|
nir: Gather texture bitmasks in gl_nir_lower_samplers_as_deref.
Eric and I would like a bitmask of which samplers are used, similar to
prog->SamplersUsed, but available in NIR. The linker uses SamplersUsed
for resource limit checking, but later optimizations may eliminate more
samplers. So instead of propagating it through, we gather a new one.
While there, we also gather the existing textures_used_by_txf bitmask.
Gathering these bitfields in nir_shader_gather_info is awkward at best.
The main reason is that it introduces an ordering dependency between the
two passes. If gathering runs before lower_samplers_as_deref, it can't
look at var->data.binding. If the driver doesn't use the full lowering
to texture_index/texture_array_size (like radeonsi), then the gathering
can't use those fields. Gathering might be run early /and/ late, first
to get varying info, and later to update it after variant lowering. At
this point, should gathering work on pre-lowered or post-lowered code?
Pre-lowered is also harder due to the presence of structure types.
Just doing the gathering when we do the lowering alleviates these
ordering problems. This fixes ordering issues in i965 and makes the
txf info gathering work for radeonsi (though they don't use it).
Reviewed-by: Eric Anholt <eric@anholt.net>
2019-01-13 18:39:41 +00:00
|
|
|
|
|
|
|
if (prog) {
|
2021-03-08 05:23:31 +00:00
|
|
|
BITSET_COPY(prog->info.textures_used, nir->info.textures_used);
|
|
|
|
BITSET_COPY(prog->info.textures_used_by_txf, nir->info.textures_used_by_txf);
|
2022-04-15 22:16:03 +01:00
|
|
|
BITSET_COPY(prog->info.samplers_used, nir->info.samplers_used);
|
2022-04-15 21:32:29 +01:00
|
|
|
BITSET_COPY(prog->info.images_used, nir->info.images_used);
|
|
|
|
BITSET_COPY(prog->info.image_buffers, nir->info.image_buffers);
|
|
|
|
BITSET_COPY(prog->info.msaa_images, nir->info.msaa_images);
|
nir: Gather texture bitmasks in gl_nir_lower_samplers_as_deref.
Eric and I would like a bitmask of which samplers are used, similar to
prog->SamplersUsed, but available in NIR. The linker uses SamplersUsed
for resource limit checking, but later optimizations may eliminate more
samplers. So instead of propagating it through, we gather a new one.
While there, we also gather the existing textures_used_by_txf bitmask.
Gathering these bitfields in nir_shader_gather_info is awkward at best.
The main reason is that it introduces an ordering dependency between the
two passes. If gathering runs before lower_samplers_as_deref, it can't
look at var->data.binding. If the driver doesn't use the full lowering
to texture_index/texture_array_size (like radeonsi), then the gathering
can't use those fields. Gathering might be run early /and/ late, first
to get varying info, and later to update it after variant lowering. At
this point, should gathering work on pre-lowered or post-lowered code?
Pre-lowered is also harder due to the presence of structure types.
Just doing the gathering when we do the lowering alleviates these
ordering problems. This fixes ordering issues in i965 and makes the
txf info gathering work for radeonsi (though they don't use it).
Reviewed-by: Eric Anholt <eric@anholt.net>
2019-01-13 18:39:41 +00:00
|
|
|
}
|
2019-02-06 08:03:49 +00:00
|
|
|
}
|
|
|
|
|
2020-01-06 20:00:57 +00:00
|
|
|
static int
|
|
|
|
st_packed_uniforms_type_size(const struct glsl_type *type, bool bindless)
|
|
|
|
{
|
|
|
|
return glsl_count_dword_slots(type, bindless);
|
|
|
|
}
|
|
|
|
|
2020-01-06 19:37:38 +00:00
|
|
|
static int
|
|
|
|
st_unpacked_uniforms_type_size(const struct glsl_type *type, bool bindless)
|
|
|
|
{
|
|
|
|
return glsl_count_vec4_slots(type, false, bindless);
|
|
|
|
}
|
|
|
|
|
2020-01-06 19:47:03 +00:00
|
|
|
void
|
|
|
|
st_nir_lower_uniforms(struct st_context *st, nir_shader *nir)
|
|
|
|
{
|
|
|
|
if (st->ctx->Const.PackedDriverUniformStorage) {
|
2020-01-06 20:00:57 +00:00
|
|
|
NIR_PASS_V(nir, nir_lower_io, nir_var_uniform,
|
|
|
|
st_packed_uniforms_type_size,
|
2020-01-06 19:47:03 +00:00
|
|
|
(nir_lower_io_options)0);
|
|
|
|
} else {
|
2020-01-06 19:37:38 +00:00
|
|
|
NIR_PASS_V(nir, nir_lower_io, nir_var_uniform,
|
|
|
|
st_unpacked_uniforms_type_size,
|
2020-01-06 19:47:03 +00:00
|
|
|
(nir_lower_io_options)0);
|
|
|
|
}
|
2020-09-13 20:31:27 +01:00
|
|
|
|
|
|
|
if (nir->options->lower_uniforms_to_ubo)
|
2021-04-10 00:10:30 +01:00
|
|
|
NIR_PASS_V(nir, nir_lower_uniforms_to_ubo,
|
|
|
|
st->ctx->Const.PackedDriverUniformStorage,
|
|
|
|
!st->ctx->Const.NativeIntegers);
|
2020-01-06 19:47:03 +00:00
|
|
|
}
|
|
|
|
|
2018-10-30 05:41:18 +00:00
|
|
|
/* Last third of preparing nir from glsl, which happens after shader
|
|
|
|
* variant lowering.
|
|
|
|
*/
|
2021-08-03 18:20:18 +01:00
|
|
|
char *
|
2018-10-30 05:41:18 +00:00
|
|
|
st_finalize_nir(struct st_context *st, struct gl_program *prog,
|
2019-09-27 23:09:11 +01:00
|
|
|
struct gl_shader_program *shader_program,
|
2020-11-23 04:30:57 +00:00
|
|
|
nir_shader *nir, bool finalize_by_driver,
|
|
|
|
bool is_before_variants)
|
2018-10-30 05:41:18 +00:00
|
|
|
{
|
2020-11-29 08:27:37 +00:00
|
|
|
struct pipe_screen *screen = st->screen;
|
2018-10-30 05:41:18 +00:00
|
|
|
|
|
|
|
NIR_PASS_V(nir, nir_split_var_copies);
|
|
|
|
NIR_PASS_V(nir, nir_lower_var_copies);
|
2017-11-13 23:06:47 +00:00
|
|
|
|
2021-02-01 10:48:02 +00:00
|
|
|
if (st->lower_rect_tex) {
|
|
|
|
struct nir_lower_tex_options opts = { 0 };
|
|
|
|
|
|
|
|
opts.lower_rect = true;
|
|
|
|
|
|
|
|
NIR_PASS_V(nir, nir_lower_tex, &opts);
|
|
|
|
}
|
|
|
|
|
2018-10-30 05:41:18 +00:00
|
|
|
st_nir_assign_varying_locations(st, nir);
|
2020-07-19 00:45:18 +01:00
|
|
|
st_nir_assign_uniform_locations(st->ctx, prog, nir);
|
2019-03-26 16:53:38 +00:00
|
|
|
|
2022-01-01 10:50:05 +00:00
|
|
|
/* Lower load_deref/store_deref of inputs and outputs.
|
|
|
|
* This depends on st_nir_assign_varying_locations.
|
|
|
|
*/
|
2022-05-27 19:36:50 +01:00
|
|
|
if (nir->options->lower_io_variables)
|
|
|
|
nir_lower_io_passes(nir);
|
2022-01-01 10:50:05 +00:00
|
|
|
|
2019-03-26 16:53:38 +00:00
|
|
|
/* Set num_uniforms in number of attribute slots (vec4s) */
|
|
|
|
nir->num_uniforms = DIV_ROUND_UP(prog->Parameters->NumParameterValues, 4);
|
2017-11-13 23:06:47 +00:00
|
|
|
|
2020-01-06 19:47:03 +00:00
|
|
|
st_nir_lower_uniforms(st, nir);
|
2020-11-23 04:30:57 +00:00
|
|
|
|
|
|
|
if (is_before_variants && nir->options->lower_uniforms_to_ubo) {
|
|
|
|
/* This must be done after uniforms are lowered to UBO and all
|
|
|
|
* nir_var_uniform variables are removed from NIR to prevent conflicts
|
|
|
|
* between state parameter merging and shader variant generation.
|
|
|
|
*/
|
|
|
|
_mesa_optimize_state_parameters(&st->ctx->Const, prog->Parameters);
|
|
|
|
}
|
|
|
|
|
nir: Gather texture bitmasks in gl_nir_lower_samplers_as_deref.
Eric and I would like a bitmask of which samplers are used, similar to
prog->SamplersUsed, but available in NIR. The linker uses SamplersUsed
for resource limit checking, but later optimizations may eliminate more
samplers. So instead of propagating it through, we gather a new one.
While there, we also gather the existing textures_used_by_txf bitmask.
Gathering these bitfields in nir_shader_gather_info is awkward at best.
The main reason is that it introduces an ordering dependency between the
two passes. If gathering runs before lower_samplers_as_deref, it can't
look at var->data.binding. If the driver doesn't use the full lowering
to texture_index/texture_array_size (like radeonsi), then the gathering
can't use those fields. Gathering might be run early /and/ late, first
to get varying info, and later to update it after variant lowering. At
this point, should gathering work on pre-lowered or post-lowered code?
Pre-lowered is also harder due to the presence of structure types.
Just doing the gathering when we do the lowering alleviates these
ordering problems. This fixes ordering issues in i965 and makes the
txf info gathering work for radeonsi (though they don't use it).
Reviewed-by: Eric Anholt <eric@anholt.net>
2019-01-13 18:39:41 +00:00
|
|
|
st_nir_lower_samplers(screen, nir, shader_program, prog);
|
2020-01-23 18:52:39 +00:00
|
|
|
if (!screen->get_param(screen, PIPE_CAP_NIR_IMAGES_AS_DEREF))
|
|
|
|
NIR_PASS_V(nir, gl_nir_lower_images, false);
|
2019-09-27 23:09:11 +01:00
|
|
|
|
2021-08-03 18:20:18 +01:00
|
|
|
char *msg = NULL;
|
2019-09-27 23:09:11 +01:00
|
|
|
if (finalize_by_driver && screen->finalize_nir)
|
2021-08-03 18:20:18 +01:00
|
|
|
msg = screen->finalize_nir(screen, nir);
|
|
|
|
|
|
|
|
return msg;
|
2017-11-13 23:06:47 +00:00
|
|
|
}
|
|
|
|
|
2015-12-22 02:34:11 +00:00
|
|
|
} /* extern "C" */
|