mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-11-01 11:18:03 +03:00
init
This commit is contained in:
12511 files changed
+6156641
No files matched your search
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Intel Corporation
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "compiler/nir/nir_builder.h"
|
||||
#include "brw_nir.h"
|
||||
|
||||
static nir_def *
|
||||
load_input_vertex(struct nir_builder *b, nir_intrinsic_instr *intrin,
|
||||
int vtx_index, uint8_t num_components)
|
||||
{
|
||||
return nir_load_input_vertex(b,
|
||||
num_components,
|
||||
intrin->def.bit_size,
|
||||
nir_imm_int(b, vtx_index),
|
||||
intrin->src[0].ssa,
|
||||
.base = nir_intrinsic_base(intrin),
|
||||
.component = nir_intrinsic_component(intrin),
|
||||
/* No dest_type means it's fs_interp_deltas,
|
||||
* and then we just want floats.
|
||||
*/
|
||||
.dest_type = nir_intrinsic_has_dest_type(intrin) ?
|
||||
nir_intrinsic_dest_type(intrin) :
|
||||
nir_type_float | intrin->def.bit_size,
|
||||
.io_semantics = nir_intrinsic_io_semantics(intrin));
|
||||
}
|
||||
|
||||
/* If an input is marked for constant interpolation, the HW will copy the
|
||||
* value of the provoking vertex to all components in the FS payload.
|
||||
* However, due to the way we have to program the provoking vertex state
|
||||
* to respect the order in which Vulkan says the per-vertex values should
|
||||
* come, we cannot count on that value being correct.
|
||||
* To work around that, we convert any load_input into a load_input_vertex
|
||||
* for the corresponding vertex index depending on the provoking vertex value.
|
||||
*/
|
||||
static bool
|
||||
lower_flat_inputs(nir_builder *b, nir_intrinsic_instr *intrin, void *data)
|
||||
{
|
||||
if (intrin->intrinsic != nir_intrinsic_load_input)
|
||||
return false;
|
||||
|
||||
b->cursor = nir_after_instr(&intrin->instr);
|
||||
|
||||
nir_def *first_vtx = load_input_vertex(b, intrin, 0, intrin->def.num_components);
|
||||
nir_def *last_vtx = load_input_vertex(b, intrin, 2, intrin->def.num_components);
|
||||
|
||||
nir_def *last = nir_test_fs_config_intel(
|
||||
b, 1, INTEL_FS_CONFIG_PROVOKING_VERTEX_LAST);
|
||||
nir_def *input_vertex = nir_bcsel(b, last, last_vtx, first_vtx);
|
||||
|
||||
nir_def_replace(&intrin->def, input_vertex);
|
||||
return true;
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
get_bary_deltas(nir_builder *b, nir_intrinsic_instr *bary, nir_intrinsic_op op, unsigned interp_mode)
|
||||
{
|
||||
nir_def *deltas;
|
||||
|
||||
switch (op) {
|
||||
case nir_intrinsic_load_barycentric_pixel:
|
||||
case nir_intrinsic_load_barycentric_centroid:
|
||||
case nir_intrinsic_load_barycentric_sample:
|
||||
deltas = nir_load_barycentric(b, op, interp_mode);
|
||||
break;
|
||||
case nir_intrinsic_load_barycentric_at_sample:
|
||||
deltas = nir_load_barycentric_at_sample(b, bary->def.bit_size,
|
||||
bary->src[0].ssa,
|
||||
.interp_mode = interp_mode);
|
||||
break;
|
||||
case nir_intrinsic_load_barycentric_at_offset:
|
||||
deltas = nir_load_barycentric_at_offset(b, bary->def.bit_size,
|
||||
bary->src[0].ssa,
|
||||
.interp_mode = interp_mode);
|
||||
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("invalid barycentric op");
|
||||
}
|
||||
|
||||
return deltas;
|
||||
}
|
||||
|
||||
/* Lower the coord version of bary intrinsics to the non-coord version,
|
||||
* then calculate the three components from the assumption they all add
|
||||
* up to 1.0.
|
||||
*/
|
||||
static bool
|
||||
lower_coord_barycentrics(nir_builder *b, nir_intrinsic_instr *intrin, void *data)
|
||||
{
|
||||
nir_intrinsic_op op;
|
||||
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_load_barycentric_coord_pixel:
|
||||
op = nir_intrinsic_load_barycentric_pixel;
|
||||
break;
|
||||
case nir_intrinsic_load_barycentric_coord_centroid:
|
||||
op = nir_intrinsic_load_barycentric_centroid;
|
||||
break;
|
||||
case nir_intrinsic_load_barycentric_coord_sample:
|
||||
op = nir_intrinsic_load_barycentric_sample;
|
||||
break;
|
||||
case nir_intrinsic_load_barycentric_coord_at_sample:
|
||||
op = nir_intrinsic_load_barycentric_at_sample;
|
||||
break;
|
||||
case nir_intrinsic_load_barycentric_coord_at_offset:
|
||||
op = nir_intrinsic_load_barycentric_at_offset;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
b->cursor = nir_after_instr(&intrin->instr);
|
||||
|
||||
nir_def *delta_xy = get_bary_deltas(b, intrin, op,
|
||||
nir_intrinsic_interp_mode(intrin));
|
||||
|
||||
nir_def *barys[3], *res;
|
||||
barys[0] = nir_fsub_imm(b, 1.0f,
|
||||
nir_fadd(b,
|
||||
nir_channel(b, delta_xy, 0),
|
||||
nir_channel(b, delta_xy, 1)));
|
||||
barys[1] = nir_channel(b, delta_xy, 0);
|
||||
barys[2] = nir_channel(b, delta_xy, 1);
|
||||
|
||||
res = nir_vec(b, barys, 3);
|
||||
nir_def_replace(&intrin->def, res);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The HW can give us the interpolation deltas for inputs, or the per-vertex
|
||||
* values, but it does not mix them. If we have any per-vertex inputs, we need
|
||||
* to calculate the deltas for any old fashioned interpolated values
|
||||
* ourselves.
|
||||
*/
|
||||
static bool
|
||||
lower_fs_interp_deltas(nir_builder *b, nir_intrinsic_instr *intrin, void *data)
|
||||
{
|
||||
if (intrin->intrinsic != nir_intrinsic_load_fs_input_interp_deltas)
|
||||
return false;
|
||||
|
||||
b->cursor = nir_after_instr(&intrin->instr);
|
||||
|
||||
nir_def *vertices[3] = {
|
||||
load_input_vertex(b, intrin, 0, 1),
|
||||
load_input_vertex(b, intrin, 2, 1),
|
||||
load_input_vertex(b, intrin, 1, 1),
|
||||
};
|
||||
nir_def *deltas[3] = {
|
||||
vertices[0],
|
||||
nir_fsub(b, vertices[1], vertices[0]),
|
||||
nir_fsub(b, vertices[2], vertices[0]),
|
||||
};
|
||||
nir_def *vec = nir_vec(b, deltas, 3);
|
||||
nir_def_replace(&intrin->def, vec);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
brw_nir_lower_fs_barycentrics(nir_shader *shader)
|
||||
{
|
||||
NIR_PASS(_, shader, nir_shader_intrinsics_pass,
|
||||
lower_flat_inputs,
|
||||
nir_metadata_control_flow,
|
||||
NULL);
|
||||
|
||||
NIR_PASS(_, shader, nir_shader_intrinsics_pass,
|
||||
lower_coord_barycentrics,
|
||||
nir_metadata_control_flow,
|
||||
NULL);
|
||||
|
||||
NIR_PASS(_, shader, nir_shader_intrinsics_pass,
|
||||
lower_fs_interp_deltas,
|
||||
nir_metadata_control_flow,
|
||||
NULL);
|
||||
|
||||
/* If there were any flat inputs, we lowered to per-vertex,
|
||||
* so change the interpolation mode here to avoid setting
|
||||
* them up for constant interpolation in the SBE setup.
|
||||
*/
|
||||
nir_foreach_shader_in_variable(var, shader) {
|
||||
if (var->data.interpolation == INTERP_MODE_FLAT) {
|
||||
var->data.interpolation = INTERP_MODE_SMOOTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user