pvr, pco: rewrite compiler/driver interface for vs & fs I/O
Basic vertex/fragment shader I/O and sysval allocation rewritten to use the new compiler/driver interface, with allocation moved entirely into the driver. RHW coeffs now only emitted when required. Boilerplate support for converting formats for vs inputs/fs outputs. Signed-off-by: Simon Perretta <simon.perretta@imgtec.com> Acked-by: Frank Binns <frank.binns@imgtec.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258>
This commit is contained in:
committed by
Marge Bot
parent
99852fbe4d
commit
527b38d1fd
@@ -165,4 +165,6 @@
|
||||
#define ROGUE_USRM_LINE_SIZE_PER_INSTANCE \
|
||||
(ROGUE_PDS_US_TEMP_ALLOCATION_GRANULARITY * ROGUE_USRM_LINE_SIZE)
|
||||
|
||||
#define ROGUE_USC_COEFFICIENT_SET_SIZE 4U
|
||||
|
||||
#endif /* ROGUE_HW_DEFS_H */
|
||||
|
||||
@@ -288,11 +288,11 @@ void pco_instr_delete(pco_instr *instr)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the number of temps allocated to the entrypoint function.
|
||||
* \brief Returns the shader data.
|
||||
*
|
||||
* \param[in] shader PCO shader.
|
||||
*/
|
||||
unsigned pco_shader_temps(pco_shader *shader)
|
||||
pco_data *pco_shader_data(pco_shader *shader)
|
||||
{
|
||||
return pco_entrypoint(shader)->temps;
|
||||
return &shader->data;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ struct pvr_device_info;
|
||||
/* Compiler-specific forward-declarations. */
|
||||
typedef struct _pco_shader pco_shader;
|
||||
typedef struct _pco_ctx pco_ctx;
|
||||
typedef struct _pco_data pco_data;
|
||||
|
||||
pco_ctx *pco_ctx_create(const struct pvr_device_info *dev_info, void *mem_ctx);
|
||||
const struct spirv_to_nir_options *pco_spirv_options(pco_ctx *ctx);
|
||||
@@ -31,16 +32,18 @@ const nir_shader_compiler_options *pco_nir_options(pco_ctx *ctx);
|
||||
|
||||
void pco_preprocess_nir(pco_ctx *ctx, nir_shader *nir);
|
||||
void pco_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer);
|
||||
void pco_lower_nir(pco_ctx *ctx, nir_shader *nir);
|
||||
void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir);
|
||||
void pco_rev_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer);
|
||||
void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data);
|
||||
void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data);
|
||||
|
||||
pco_shader *pco_trans_nir(pco_ctx *ctx, nir_shader *nir, void *mem_ctx);
|
||||
pco_shader *
|
||||
pco_trans_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data, void *mem_ctx);
|
||||
void pco_process_ir(pco_ctx *ctx, pco_shader *shader);
|
||||
|
||||
void pco_encode_ir(pco_ctx *ctx, pco_shader *shader);
|
||||
void pco_shader_finalize(pco_ctx *ctx, pco_shader *shader);
|
||||
|
||||
unsigned pco_shader_temps(pco_shader *shader);
|
||||
pco_data *pco_shader_data(pco_shader *shader);
|
||||
|
||||
unsigned pco_shader_binary_size(pco_shader *shader);
|
||||
const void *pco_shader_binary_data(pco_shader *shader);
|
||||
|
||||
@@ -142,6 +142,9 @@ void pco_shader_finalize(pco_ctx *ctx, pco_shader *shader)
|
||||
{
|
||||
puts("finishme: pco_shader_finalize");
|
||||
|
||||
pco_func *entry = pco_entrypoint(shader);
|
||||
shader->data.common.entry_offset = entry->enc_offset;
|
||||
|
||||
if (pco_should_print_binary(shader))
|
||||
pco_print_binary(shader, stdout, "after finalizing");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright © 2024 Imagination Technologies Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef PCO_DATA_H
|
||||
#define PCO_DATA_H
|
||||
|
||||
/**
|
||||
* \file pco_data.h
|
||||
*
|
||||
* \brief PCO shader-specific data/compiler-driver interface.
|
||||
*/
|
||||
|
||||
#include "compiler/shader_enums.h"
|
||||
#include "util/format/u_format.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/** Generic range struct. */
|
||||
typedef struct _pco_range {
|
||||
unsigned start;
|
||||
unsigned count;
|
||||
} pco_range;
|
||||
|
||||
/** PCO vertex shader-specific data. */
|
||||
typedef struct _pco_vs_data {
|
||||
/** Attributes/input mappings. */
|
||||
pco_range attribs[VERT_ATTRIB_MAX];
|
||||
|
||||
enum pipe_format attrib_formats[VERT_ATTRIB_MAX];
|
||||
|
||||
/** Varyings/output mappings. */
|
||||
pco_range varyings[VARYING_SLOT_MAX];
|
||||
|
||||
unsigned f32_smooth; /** Number of F32 linear varyings. */
|
||||
unsigned f32_flat; /** Number of F32 flat varyings. */
|
||||
unsigned f32_npc; /** Number of F32 NPC varyings. */
|
||||
|
||||
unsigned f16_smooth; /** Number of F16 linear varyings. */
|
||||
unsigned f16_flat; /** Number of F16 flat varyings. */
|
||||
unsigned f16_npc; /** Number of F16 NPC varyings. */
|
||||
|
||||
unsigned vtxouts; /** How many vertex outputs are written to. */
|
||||
} pco_vs_data;
|
||||
|
||||
/** PCO fragment shader-specific data. */
|
||||
typedef struct _pco_fs_data {
|
||||
/** Varyings/input mappings. */
|
||||
pco_range varyings[VARYING_SLOT_MAX];
|
||||
|
||||
/** Results/output mappings. */
|
||||
pco_range outputs[FRAG_RESULT_MAX];
|
||||
|
||||
/** If outputs are to be placed in pixout regs. */
|
||||
bool output_reg[FRAG_RESULT_MAX];
|
||||
|
||||
/** Fragment output formats. */
|
||||
enum pipe_format output_formats[FRAG_RESULT_MAX];
|
||||
|
||||
struct {
|
||||
bool w; /** Whether the shader uses pos.w. */
|
||||
bool z; /** Whether the shader uses pos.z */
|
||||
bool pntc; /** Whether the shader uses point coord. */
|
||||
bool phase_change; /** Whether the shader does a phase change. */
|
||||
} uses;
|
||||
} pco_fs_data;
|
||||
|
||||
/** PCO compute shader-specific data. */
|
||||
typedef struct _pco_cs_data {
|
||||
/**/
|
||||
} pco_cs_data;
|
||||
|
||||
/** PCO common data. */
|
||||
typedef struct _pco_common_data {
|
||||
/** System value mappings. */
|
||||
pco_range sys_vals[SYSTEM_VALUE_MAX];
|
||||
|
||||
unsigned temps; /** Number of allocated temp registers. */
|
||||
unsigned vtxins; /** Number of allocated vertex input registers. */
|
||||
unsigned interns; /** Number of allocated internal registers. */
|
||||
|
||||
unsigned coeffs; /** Number of allocated coefficient registers. */
|
||||
unsigned shareds; /** Number of allocated shared registers. */
|
||||
|
||||
unsigned entry_offset; /** Offset of the shader entrypoint. */
|
||||
|
||||
struct {
|
||||
bool atomics; /** Whether the shader uses atomics. */
|
||||
bool barriers; /** Whether the shader uses barriers. */
|
||||
bool side_effects; /** Whether the shader has side effects. */
|
||||
bool empty; /** Whether the shader is empty. */
|
||||
} uses;
|
||||
} pco_common_data;
|
||||
|
||||
/** PCO shader data. */
|
||||
typedef struct _pco_data {
|
||||
union {
|
||||
pco_vs_data vs;
|
||||
pco_fs_data fs;
|
||||
pco_cs_data cs;
|
||||
};
|
||||
|
||||
pco_common_data common;
|
||||
} pco_data;
|
||||
|
||||
#endif /* PCO_DATA_H */
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "hwdef/rogue_hw_utils.h"
|
||||
#include "pco.h"
|
||||
#include "pco_common.h"
|
||||
#include "pco_data.h"
|
||||
#include "pco_ops.h"
|
||||
#include "spirv/nir_spirv.h"
|
||||
#include "util/compiler.h"
|
||||
@@ -340,6 +341,8 @@ typedef struct _pco_shader {
|
||||
struct list_head funcs; /** List of functions. */
|
||||
unsigned next_func; /** Next function index. */
|
||||
|
||||
pco_data data; /** Shader data. */
|
||||
|
||||
struct {
|
||||
struct util_dynarray buf; /** Shader binary. */
|
||||
|
||||
@@ -1116,8 +1119,8 @@ bool pco_dce(pco_shader *shader);
|
||||
bool pco_end(pco_shader *shader);
|
||||
bool pco_group_instrs(pco_shader *shader);
|
||||
bool pco_index(pco_shader *shader, bool skip_ssa);
|
||||
bool pco_nir_pfo(nir_shader *nir);
|
||||
bool pco_nir_pvi(nir_shader *nir);
|
||||
bool pco_nir_pfo(nir_shader *nir, pco_fs_data *fs);
|
||||
bool pco_nir_pvi(nir_shader *nir, pco_vs_data *vs);
|
||||
bool pco_opt(pco_shader *shader);
|
||||
bool pco_ra(pco_shader *shader);
|
||||
bool pco_schedule(pco_shader *shader);
|
||||
|
||||
+181
-10
@@ -10,6 +10,7 @@
|
||||
* \brief NIR-specific functions.
|
||||
*/
|
||||
|
||||
#include "nir/nir_builder.h"
|
||||
#include "pco.h"
|
||||
#include "pco_internal.h"
|
||||
|
||||
@@ -140,13 +141,32 @@ static uint8_t vectorize_filter(const nir_instr *instr, UNUSED const void *data)
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Filters for a varying position load_input in frag shaders.
|
||||
*
|
||||
* \param[in] instr Instruction.
|
||||
* \param[in] data User data.
|
||||
* \return True if the instruction was found.
|
||||
*/
|
||||
static bool frag_pos_filter(const nir_instr *instr, UNUSED const void *data)
|
||||
{
|
||||
assert(instr->type == nir_instr_type_intrinsic);
|
||||
|
||||
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||
if (intr->intrinsic != nir_intrinsic_load_input)
|
||||
return false;
|
||||
|
||||
return nir_intrinsic_io_semantics(intr).location == VARYING_SLOT_POS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Lowers a NIR shader.
|
||||
*
|
||||
* \param[in] ctx PCO compiler context.
|
||||
* \param[in,out] nir NIR shader.
|
||||
* \param[in,out] data Shader data.
|
||||
*/
|
||||
void pco_lower_nir(pco_ctx *ctx, nir_shader *nir)
|
||||
void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data)
|
||||
{
|
||||
NIR_PASS(_,
|
||||
nir,
|
||||
@@ -163,9 +183,9 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir)
|
||||
nir_var_shader_in | nir_var_shader_out);
|
||||
|
||||
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
|
||||
NIR_PASS(_, nir, pco_nir_pfo);
|
||||
NIR_PASS(_, nir, pco_nir_pfo, &data->fs);
|
||||
} else if (nir->info.stage == MESA_SHADER_VERTEX) {
|
||||
NIR_PASS(_, nir, pco_nir_pvi);
|
||||
NIR_PASS(_, nir, pco_nir_pvi, &data->vs);
|
||||
}
|
||||
|
||||
/* TODO: this should happen in the linking stage to cull unused I/O. */
|
||||
@@ -196,10 +216,26 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir)
|
||||
NIR_PASS(_, nir, nir_opt_cse);
|
||||
} while (progress);
|
||||
|
||||
NIR_PASS(_,
|
||||
nir,
|
||||
nir_opt_vectorize_io,
|
||||
nir_var_shader_in | nir_var_shader_out);
|
||||
nir_variable_mode vec_modes = nir_var_shader_in;
|
||||
/* Fragment shader needs scalar writes after pfo. */
|
||||
if (nir->info.stage != MESA_SHADER_FRAGMENT)
|
||||
vec_modes |= nir_var_shader_out;
|
||||
|
||||
NIR_PASS(_, nir, nir_opt_vectorize_io, vec_modes);
|
||||
|
||||
/* Special case for frag coords:
|
||||
* - x,y come from (non-consecutive) special regs - always scalar.
|
||||
* - z,w are iterated and driver will make sure they're consecutive.
|
||||
* - TODO: keep scalar for now, but add pass to vectorize.
|
||||
*/
|
||||
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
|
||||
NIR_PASS(_,
|
||||
nir,
|
||||
nir_lower_io_to_scalar,
|
||||
nir_var_shader_in,
|
||||
frag_pos_filter,
|
||||
NULL);
|
||||
}
|
||||
|
||||
NIR_PASS(_, nir, nir_lower_alu_to_scalar, NULL, NULL);
|
||||
|
||||
@@ -219,13 +255,88 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gather fragment shader data pass.
|
||||
*
|
||||
* \param[in] b NIR builder.
|
||||
* \param[in] intr NIR intrinsic instruction.
|
||||
* \param[in,out] cb_data Callback data.
|
||||
* \return True if the shader was modified (always return false).
|
||||
*/
|
||||
static bool gather_fs_data_pass(UNUSED struct nir_builder *b,
|
||||
nir_intrinsic_instr *intr,
|
||||
void *cb_data)
|
||||
{
|
||||
/* Check whether the shader accesses z/w. */
|
||||
if (intr->intrinsic != nir_intrinsic_load_input)
|
||||
return false;
|
||||
|
||||
struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
|
||||
if (io_semantics.location != VARYING_SLOT_POS)
|
||||
return false;
|
||||
|
||||
unsigned component = nir_intrinsic_component(intr);
|
||||
unsigned chans = intr->def.num_components;
|
||||
|
||||
pco_data *data = cb_data;
|
||||
|
||||
data->fs.uses.z |= (component + chans > 2);
|
||||
data->fs.uses.w |= (component + chans > 3);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gathers fragment shader data.
|
||||
*
|
||||
* \param[in] nir NIR shader.
|
||||
* \param[in,out] data Shader data.
|
||||
*/
|
||||
static void gather_fs_data(nir_shader *nir, pco_data *data)
|
||||
{
|
||||
nir_shader_intrinsics_pass(nir, gather_fs_data_pass, nir_metadata_all, data);
|
||||
|
||||
/* If any inputs use smooth shading, then w is needed. */
|
||||
if (!data->fs.uses.w) {
|
||||
nir_foreach_shader_in_variable (var, nir) {
|
||||
if (var->data.interpolation > INTERP_MODE_SMOOTH)
|
||||
continue;
|
||||
|
||||
data->fs.uses.w = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gathers shader data.
|
||||
*
|
||||
* \param[in] nir NIR shader.
|
||||
* \param[in,out] data Shader data.
|
||||
*/
|
||||
static void gather_data(nir_shader *nir, pco_data *data)
|
||||
{
|
||||
switch (nir->info.stage) {
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
return gather_fs_data(nir, data);
|
||||
|
||||
case MESA_SHADER_VERTEX:
|
||||
/* TODO */
|
||||
break;
|
||||
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Runs post-processing passes on a NIR shader.
|
||||
*
|
||||
* \param[in] ctx PCO compiler context.
|
||||
* \param[in,out] nir NIR shader.
|
||||
* \param[in,out] data Shader data.
|
||||
*/
|
||||
void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir)
|
||||
void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data)
|
||||
{
|
||||
NIR_PASS(_, nir, nir_move_vec_src_uses_to_dest, false);
|
||||
|
||||
@@ -238,6 +349,8 @@ void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir)
|
||||
|
||||
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
|
||||
|
||||
gather_data(nir, data);
|
||||
|
||||
if (pco_should_print_nir(nir)) {
|
||||
puts("after pco_postprocess_nir:");
|
||||
nir_print_shader(nir, stdout);
|
||||
@@ -253,6 +366,9 @@ void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir)
|
||||
*/
|
||||
void pco_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer)
|
||||
{
|
||||
/* TODO */
|
||||
puts("finishme: pco_link_nir");
|
||||
|
||||
if (pco_should_print_nir(producer)) {
|
||||
puts("producer after pco_link_nir:");
|
||||
nir_print_shader(producer, stdout);
|
||||
@@ -262,6 +378,61 @@ void pco_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer)
|
||||
puts("consumer after pco_link_nir:");
|
||||
nir_print_shader(consumer, stdout);
|
||||
}
|
||||
|
||||
puts("finishme: pco_link_nir");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks whether two varying variables are the same.
|
||||
*
|
||||
* \param[in] out_var The first varying being compared.
|
||||
* \param[in] in_var The second varying being compared.
|
||||
* \return True if the varyings match.
|
||||
*/
|
||||
static bool varyings_match(nir_variable *out_var, nir_variable *in_var)
|
||||
{
|
||||
return in_var->data.location == out_var->data.location &&
|
||||
in_var->data.location_frac == out_var->data.location_frac &&
|
||||
in_var->type == out_var->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Performs reverse linking optimizations on consecutive NIR shader
|
||||
* stages.
|
||||
*
|
||||
* \param[in] ctx PCO compiler context.
|
||||
* \param[in,out] producer NIR producer shader.
|
||||
* \param[in,out] consumer NIR consumer shader.
|
||||
*/
|
||||
PUBLIC
|
||||
void pco_rev_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer)
|
||||
{
|
||||
/* TODO */
|
||||
puts("finishme: pco_rev_link_nir");
|
||||
|
||||
/* Propagate back/adjust the interpolation qualifiers. */
|
||||
nir_foreach_shader_in_variable (in_var, consumer) {
|
||||
if (in_var->data.location == VARYING_SLOT_POS ||
|
||||
in_var->data.location == VARYING_SLOT_PNTC) {
|
||||
in_var->data.interpolation = INTERP_MODE_NOPERSPECTIVE;
|
||||
} else if (in_var->data.interpolation == INTERP_MODE_NONE) {
|
||||
in_var->data.interpolation = INTERP_MODE_SMOOTH;
|
||||
}
|
||||
|
||||
nir_foreach_shader_out_variable (out_var, producer) {
|
||||
if (!varyings_match(out_var, in_var))
|
||||
continue;
|
||||
|
||||
out_var->data.interpolation = in_var->data.interpolation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pco_should_print_nir(producer)) {
|
||||
puts("producer after pco_rev_link_nir:");
|
||||
nir_print_shader(producer, stdout);
|
||||
}
|
||||
|
||||
if (pco_should_print_nir(consumer)) {
|
||||
puts("consumer after pco_rev_link_nir:");
|
||||
nir_print_shader(consumer, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
* \brief PCO NIR per-vertex/fragment input/output passes.
|
||||
*/
|
||||
|
||||
#include "compiler/glsl_types.h"
|
||||
#include "compiler/shader_enums.h"
|
||||
#include "nir.h"
|
||||
#include "nir_builder.h"
|
||||
#include "pco.h"
|
||||
@@ -25,6 +27,7 @@
|
||||
/** Per-fragment output pass state. */
|
||||
struct pfo_state {
|
||||
struct util_dynarray stores; /** List of fragment stores. */
|
||||
pco_fs_data *fs; /** Fragment-specific data. */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -51,6 +54,36 @@ static inline nir_intrinsic_instr *is_intr(nir_instr *instr,
|
||||
return intr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the GLSL base type equivalent of a pipe format.
|
||||
*
|
||||
* \param[in] format Pipe format.
|
||||
* \return The GLSL base type, or GLSL_TYPE_ERROR if unsupported/invalid.
|
||||
*/
|
||||
static inline enum glsl_base_type base_type_from_fmt(enum pipe_format format)
|
||||
{
|
||||
const struct util_format_description *desc = util_format_description(format);
|
||||
int chan = util_format_get_first_non_void_channel(format);
|
||||
if (chan < 0)
|
||||
return GLSL_TYPE_ERROR;
|
||||
|
||||
switch (desc->channel[chan].type) {
|
||||
case UTIL_FORMAT_TYPE_UNSIGNED:
|
||||
return GLSL_TYPE_UINT;
|
||||
|
||||
case UTIL_FORMAT_TYPE_SIGNED:
|
||||
return GLSL_TYPE_INT;
|
||||
|
||||
case UTIL_FORMAT_TYPE_FLOAT:
|
||||
return GLSL_TYPE_FLOAT;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GLSL_TYPE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Lowers a PFO-related instruction.
|
||||
*
|
||||
@@ -89,31 +122,48 @@ static bool lower_pfo(nir_builder *b, nir_instr *instr, void *cb_data)
|
||||
assert(nir_src_num_components(*value) == 4);
|
||||
assert(nir_src_bit_size(*value) == 32);
|
||||
|
||||
/* Update the type of the stored variable. */
|
||||
nir_variable *var = nir_find_variable_with_location(
|
||||
b->shader,
|
||||
nir_var_shader_out,
|
||||
nir_intrinsic_io_semantics(intr).location);
|
||||
struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
|
||||
gl_frag_result location = io_semantics.location;
|
||||
|
||||
var->type = glsl_uint_type();
|
||||
enum pipe_format format = state->fs->output_formats[location];
|
||||
|
||||
unsigned format_bits = util_format_get_blocksizebits(format);
|
||||
assert(!(format_bits % 32));
|
||||
|
||||
/* Update the type of the stored variable. */
|
||||
nir_variable *var = nir_find_variable_with_location(b->shader,
|
||||
nir_var_shader_out,
|
||||
location);
|
||||
assert(var);
|
||||
|
||||
var->type = glsl_simple_explicit_type(base_type_from_fmt(format),
|
||||
format_bits / 32,
|
||||
1,
|
||||
0,
|
||||
false,
|
||||
0);
|
||||
|
||||
b->cursor = nir_after_block(
|
||||
nir_impl_last_block(nir_shader_get_entrypoint(b->shader)));
|
||||
|
||||
/* Emit and track the new store. */
|
||||
/* TODO NEXT: base is calculated to be the register offset. */
|
||||
nir_intrinsic_instr *store =
|
||||
nir_store_output(b,
|
||||
nir_pack_unorm_4x8(b, value->ssa),
|
||||
offset->ssa,
|
||||
.base = nir_intrinsic_base(intr),
|
||||
.write_mask = 1,
|
||||
.component = 0,
|
||||
.src_type = nir_type_uint32,
|
||||
.io_semantics = nir_intrinsic_io_semantics(intr),
|
||||
.io_xfb = nir_intrinsic_io_xfb(intr),
|
||||
.io_xfb2 = nir_intrinsic_io_xfb2(intr));
|
||||
util_dynarray_append(&state->stores, nir_intrinsic_instr *, store);
|
||||
/* TODO: support other formats. */
|
||||
if (format == PIPE_FORMAT_R8G8B8A8_UNORM) {
|
||||
nir_intrinsic_instr *store =
|
||||
nir_store_output(b,
|
||||
nir_pack_unorm_4x8(b, value->ssa),
|
||||
offset->ssa,
|
||||
.base = nir_intrinsic_base(intr),
|
||||
.write_mask = 1,
|
||||
.component = 0,
|
||||
.src_type = nir_type_uint32,
|
||||
.io_semantics = io_semantics,
|
||||
.io_xfb = nir_intrinsic_io_xfb(intr),
|
||||
.io_xfb2 = nir_intrinsic_io_xfb2(intr));
|
||||
util_dynarray_append(&state->stores, nir_intrinsic_instr *, store);
|
||||
} else {
|
||||
unreachable();
|
||||
}
|
||||
|
||||
/* Remove the old store. */
|
||||
b->cursor = nir_instr_remove(instr);
|
||||
@@ -128,13 +178,14 @@ static bool lower_pfo(nir_builder *b, nir_instr *instr, void *cb_data)
|
||||
* \brief Per-fragment output pass.
|
||||
*
|
||||
* \param[in,out] nir NIR shader.
|
||||
* \param[in,out] fs Fragment shader-specific data.
|
||||
* \return True if the pass made progress.
|
||||
*/
|
||||
bool pco_nir_pfo(nir_shader *nir)
|
||||
bool pco_nir_pfo(nir_shader *nir, pco_fs_data *fs)
|
||||
{
|
||||
assert(nir->info.stage == MESA_SHADER_FRAGMENT);
|
||||
|
||||
struct pfo_state state = {};
|
||||
struct pfo_state state = { .fs = fs };
|
||||
util_dynarray_init(&state.stores, NULL);
|
||||
|
||||
bool progress =
|
||||
@@ -149,9 +200,10 @@ bool pco_nir_pfo(nir_shader *nir)
|
||||
* \brief Per-vertex input pass.
|
||||
*
|
||||
* \param[in,out] nir NIR shader.
|
||||
* \param[in,out] vs Vertex shader-specific data.
|
||||
* \return True if the pass made progress.
|
||||
*/
|
||||
bool pco_nir_pvi(nir_shader *nir)
|
||||
bool pco_nir_pvi(nir_shader *nir, pco_vs_data *vs)
|
||||
{
|
||||
assert(nir->info.stage == MESA_SHADER_VERTEX);
|
||||
|
||||
|
||||
@@ -377,6 +377,8 @@ bool pco_ra(pco_shader *shader)
|
||||
allocable_temps,
|
||||
allocable_vtxins,
|
||||
allocable_interns);
|
||||
|
||||
shader->data.common.temps = MAX2(shader->data.common.temps, func->temps);
|
||||
}
|
||||
|
||||
return progress;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "compiler/glsl/list.h"
|
||||
#include "compiler/shader_enums.h"
|
||||
#include "hwdef/rogue_hw_defs.h"
|
||||
#include "pco.h"
|
||||
#include "pco_builder.h"
|
||||
#include "pco_internal.h"
|
||||
@@ -182,21 +183,25 @@ pco_ref_nir_alu_src_t(const nir_alu_instr *alu, unsigned src, trans_ctx *tctx)
|
||||
static pco_instr *
|
||||
trans_load_input_vs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref dest)
|
||||
{
|
||||
puts("finishme: trans_load_input_vs");
|
||||
ASSERTED unsigned base = nir_intrinsic_base(intr);
|
||||
assert(!base);
|
||||
|
||||
/* unsigned base = nir_intrinsic_base(intr); */
|
||||
unsigned base =
|
||||
nir_intrinsic_io_semantics(intr).location - VERT_ATTRIB_GENERIC0;
|
||||
ASSERTED nir_alu_type type = nir_intrinsic_dest_type(intr);
|
||||
assert(type == nir_type_float32);
|
||||
/* TODO: f16 support. */
|
||||
|
||||
ASSERTED const nir_src offset = intr->src[0];
|
||||
assert(nir_src_as_uint(offset) == 0);
|
||||
|
||||
gl_vert_attrib location = nir_intrinsic_io_semantics(intr).location;
|
||||
unsigned component = nir_intrinsic_component(intr);
|
||||
unsigned chans = pco_ref_get_chans(dest);
|
||||
|
||||
const nir_src offset = intr->src[0];
|
||||
assert(nir_src_as_uint(offset) == 0);
|
||||
|
||||
/* TODO NEXT: Wrong! Do properly! */
|
||||
unsigned vtxin_offset = (4 * base) + component;
|
||||
pco_ref src = pco_ref_hwreg_vec(vtxin_offset, PCO_REG_CLASS_VTXIN, chans);
|
||||
const pco_range *range = &tctx->shader->data.vs.attribs[location];
|
||||
assert(component + chans <= range->count);
|
||||
|
||||
pco_ref src =
|
||||
pco_ref_hwreg_vec(range->start + component, PCO_REG_CLASS_VTXIN, chans);
|
||||
return pco_mov(&tctx->b, dest, src, .rpt = chans);
|
||||
}
|
||||
|
||||
@@ -211,34 +216,28 @@ trans_load_input_vs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref dest)
|
||||
static pco_instr *
|
||||
trans_store_output_vs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref src)
|
||||
{
|
||||
puts("finishme: trans_store_output_vs");
|
||||
ASSERTED unsigned base = nir_intrinsic_base(intr);
|
||||
assert(!base);
|
||||
|
||||
/* unsigned base = nir_intrinsic_base(intr); */
|
||||
ASSERTED nir_alu_type type = nir_intrinsic_src_type(intr);
|
||||
assert(type == nir_type_float32);
|
||||
/* TODO: f16 support. */
|
||||
|
||||
unsigned location = nir_intrinsic_io_semantics(intr).location;
|
||||
unsigned base;
|
||||
switch (location) {
|
||||
case VARYING_SLOT_POS:
|
||||
base = 0;
|
||||
break;
|
||||
|
||||
case VARYING_SLOT_VAR0 ... VARYING_SLOT_VAR31:
|
||||
base = location - VARYING_SLOT_VAR0 + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
ASSERTED const nir_src offset = intr->src[1];
|
||||
assert(nir_src_as_uint(offset) == 0);
|
||||
|
||||
gl_varying_slot location = nir_intrinsic_io_semantics(intr).location;
|
||||
unsigned component = nir_intrinsic_component(intr);
|
||||
unsigned chans = pco_ref_get_chans(src);
|
||||
|
||||
const nir_src offset = intr->src[1];
|
||||
assert(nir_src_as_uint(offset) == 0);
|
||||
/* Only contiguous write masks supported. */
|
||||
ASSERTED unsigned write_mask = nir_intrinsic_write_mask(intr);
|
||||
assert(write_mask == BITFIELD_MASK(chans));
|
||||
|
||||
/* TODO NEXT: Wrong! Do properly! */
|
||||
pco_ref vtxout_addr = pco_ref_val8((4 * base) + component);
|
||||
const pco_range *range = &tctx->shader->data.vs.varyings[location];
|
||||
assert(component + chans <= range->count);
|
||||
|
||||
pco_ref vtxout_addr = pco_ref_val8(range->start + component);
|
||||
return pco_uvsw_write(&tctx->b, src, vtxout_addr, .rpt = chans);
|
||||
}
|
||||
|
||||
@@ -253,8 +252,7 @@ trans_store_output_vs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref src)
|
||||
static pco_instr *
|
||||
trans_load_input_fs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref dest)
|
||||
{
|
||||
puts("finishme: trans_load_input_fs");
|
||||
|
||||
pco_fs_data *fs_data = &tctx->shader->data.fs;
|
||||
ASSERTED unsigned base = nir_intrinsic_base(intr);
|
||||
assert(!base);
|
||||
|
||||
@@ -264,34 +262,116 @@ trans_load_input_fs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref dest)
|
||||
const nir_src offset = intr->src[0];
|
||||
assert(nir_src_as_uint(offset) == 0);
|
||||
|
||||
/* TODO NEXT: Wrong! Do properly! */
|
||||
unsigned loc_offset =
|
||||
nir_intrinsic_io_semantics(intr).location - VARYING_SLOT_VAR0;
|
||||
/* TEMP: +1 to skip over wcoeffs */
|
||||
unsigned coeffs_index = 4 * (loc_offset + component + 1);
|
||||
unsigned wcoeffs_index = 0;
|
||||
struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
|
||||
gl_varying_slot location = io_semantics.location;
|
||||
|
||||
pco_ref coeffs =
|
||||
pco_ref_hwreg_vec(coeffs_index, PCO_REG_CLASS_COEFF, 4 * chans);
|
||||
pco_ref wcoeffs = pco_ref_hwreg_vec(wcoeffs_index, PCO_REG_CLASS_COEFF, 4);
|
||||
nir_variable *var = nir_find_variable_with_location(tctx->shader->nir,
|
||||
nir_var_shader_in,
|
||||
location);
|
||||
|
||||
enum pco_itr_mode itr_mode = PCO_ITR_MODE_PIXEL;
|
||||
assert(!(var->data.sample && var->data.centroid));
|
||||
if (var->data.sample)
|
||||
itr_mode = PCO_ITR_MODE_SAMPLE;
|
||||
else if (var->data.centroid)
|
||||
itr_mode = PCO_ITR_MODE_CENTROID;
|
||||
|
||||
if (location == VARYING_SLOT_POS) {
|
||||
/* Only scalar supported for now. */
|
||||
/* TODO: support vector for zw. */
|
||||
assert(chans == 1);
|
||||
|
||||
/* TODO: support packing/partial vars. */
|
||||
assert(!var->data.location_frac);
|
||||
|
||||
assert(var->data.interpolation == INTERP_MODE_NOPERSPECTIVE);
|
||||
|
||||
/* Special case: x and y are loaded from special registers. */
|
||||
/* TODO: select appropriate regs if sample rate shading. */
|
||||
switch (component) {
|
||||
case 0: /* x */
|
||||
return pco_mov(&tctx->b,
|
||||
dest,
|
||||
pco_ref_hwreg(PCO_SR_X_P, PCO_REG_CLASS_SPEC));
|
||||
|
||||
case 1: /* y */
|
||||
return pco_mov(&tctx->b,
|
||||
dest,
|
||||
pco_ref_hwreg(PCO_SR_Y_P, PCO_REG_CLASS_SPEC));
|
||||
|
||||
case 2:
|
||||
assert(fs_data->uses.z);
|
||||
component = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assert(fs_data->uses.w);
|
||||
component = fs_data->uses.z ? 1 : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
const pco_range *range = &fs_data->varyings[location];
|
||||
assert(component + (ROGUE_USC_COEFFICIENT_SET_SIZE * chans) <= range->count);
|
||||
|
||||
unsigned coeffs_index =
|
||||
range->start + (ROGUE_USC_COEFFICIENT_SET_SIZE * component);
|
||||
|
||||
pco_ref coeffs = pco_ref_hwreg_vec(coeffs_index,
|
||||
PCO_REG_CLASS_COEFF,
|
||||
ROGUE_USC_COEFFICIENT_SET_SIZE * chans);
|
||||
pco_ref itr_count = pco_ref_val16(chans);
|
||||
|
||||
if (PVR_HAS_FEATURE(tctx->pco_ctx->dev_info, usc_itrsmp_enhanced)) {
|
||||
return pco_ditrp(&tctx->b,
|
||||
dest,
|
||||
pco_ref_drc(PCO_DRC_0),
|
||||
coeffs,
|
||||
wcoeffs,
|
||||
itr_count,
|
||||
.itr_mode = PCO_ITR_MODE_PIXEL);
|
||||
} else {
|
||||
return pco_fitrp(&tctx->b,
|
||||
dest,
|
||||
pco_ref_drc(PCO_DRC_0),
|
||||
coeffs,
|
||||
wcoeffs,
|
||||
itr_count,
|
||||
.itr_mode = PCO_ITR_MODE_PIXEL);
|
||||
bool usc_itrsmp_enhanced =
|
||||
PVR_HAS_FEATURE(tctx->pco_ctx->dev_info, usc_itrsmp_enhanced);
|
||||
|
||||
switch (var->data.interpolation) {
|
||||
case INTERP_MODE_SMOOTH: {
|
||||
assert(fs_data->uses.w);
|
||||
|
||||
unsigned wcoeffs_index = fs_data->uses.z ? ROGUE_USC_COEFFICIENT_SET_SIZE
|
||||
: 0;
|
||||
|
||||
pco_ref wcoeffs = pco_ref_hwreg_vec(wcoeffs_index,
|
||||
PCO_REG_CLASS_COEFF,
|
||||
ROGUE_USC_COEFFICIENT_SET_SIZE);
|
||||
|
||||
return usc_itrsmp_enhanced ? pco_ditrp(&tctx->b,
|
||||
dest,
|
||||
pco_ref_drc(PCO_DRC_0),
|
||||
coeffs,
|
||||
wcoeffs,
|
||||
itr_count,
|
||||
.itr_mode = itr_mode)
|
||||
: pco_fitrp(&tctx->b,
|
||||
dest,
|
||||
pco_ref_drc(PCO_DRC_0),
|
||||
coeffs,
|
||||
wcoeffs,
|
||||
itr_count,
|
||||
.itr_mode = itr_mode);
|
||||
}
|
||||
|
||||
case INTERP_MODE_NOPERSPECTIVE:
|
||||
return usc_itrsmp_enhanced ? pco_ditr(&tctx->b,
|
||||
dest,
|
||||
pco_ref_drc(PCO_DRC_0),
|
||||
coeffs,
|
||||
itr_count,
|
||||
.itr_mode = itr_mode)
|
||||
: pco_fitr(&tctx->b,
|
||||
dest,
|
||||
pco_ref_drc(PCO_DRC_0),
|
||||
coeffs,
|
||||
itr_count,
|
||||
.itr_mode = itr_mode);
|
||||
|
||||
default:
|
||||
/* Should have been previously lowered. */
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,21 +386,26 @@ trans_load_input_fs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref dest)
|
||||
static pco_instr *
|
||||
trans_store_output_fs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref src)
|
||||
{
|
||||
ASSERTED unsigned base = nir_intrinsic_base(intr);
|
||||
assert(!base);
|
||||
|
||||
assert(pco_ref_is_scalar(src));
|
||||
puts("finishme: trans_store_output_fs");
|
||||
unsigned component = nir_intrinsic_component(intr);
|
||||
|
||||
bool is_reg_store = nir_src_is_const(intr->src[1]);
|
||||
unsigned base = nir_intrinsic_base(intr);
|
||||
ASSERTED const nir_src offset = intr->src[1];
|
||||
assert(nir_src_as_uint(offset) == 0);
|
||||
|
||||
if (is_reg_store) {
|
||||
/* TODO NEXT: Wrong! Do properly! */
|
||||
pco_ref dest = pco_ref_hwreg(base, PCO_REG_CLASS_PIXOUT);
|
||||
/* TODO NEXT: optimize this to be propagated (backwards?) */
|
||||
/* return pco_mbyp0(&tctx->b, dest, src, .olchk = true); */
|
||||
return pco_mov(&tctx->b, dest, src, .olchk = true);
|
||||
}
|
||||
gl_varying_slot location = nir_intrinsic_io_semantics(intr).location;
|
||||
|
||||
unreachable();
|
||||
const pco_range *range = &tctx->shader->data.fs.outputs[location];
|
||||
assert(component < range->count);
|
||||
|
||||
ASSERTED bool output_reg = tctx->shader->data.fs.output_reg[location];
|
||||
assert(output_reg);
|
||||
/* TODO: tile buffer support. */
|
||||
|
||||
pco_ref dest = pco_ref_hwreg(range->start + component, PCO_REG_CLASS_PIXOUT);
|
||||
return pco_mov(&tctx->b, dest, src, .olchk = true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -804,12 +889,18 @@ static pco_block *trans_cf_nodes(trans_ctx *tctx,
|
||||
*
|
||||
* \param[in] ctx PCO compiler context.
|
||||
* \param[in] nir NIR shader.
|
||||
* \param[in] data Shader-specific data.
|
||||
* \param[in] mem_ctx Ralloc memory allocation context.
|
||||
* \return The PCO shader.
|
||||
*/
|
||||
pco_shader *pco_trans_nir(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
|
||||
pco_shader *
|
||||
pco_trans_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data, void *mem_ctx)
|
||||
{
|
||||
pco_shader *shader = pco_shader_create(ctx, nir, mem_ctx);
|
||||
|
||||
if (data)
|
||||
memcpy(&shader->data, data, sizeof(*data));
|
||||
|
||||
trans_ctx tctx = {
|
||||
.pco_ctx = ctx,
|
||||
.shader = shader,
|
||||
|
||||
@@ -3366,9 +3366,11 @@ pvr_setup_vertex_buffers(struct pvr_cmd_buffer *cmd_buffer,
|
||||
case PVR_PDS_CONST_MAP_ENTRY_TYPE_DOUTU_ADDRESS: {
|
||||
const struct pvr_const_map_entry_doutu_address *const doutu_addr =
|
||||
(struct pvr_const_map_entry_doutu_address *)entries;
|
||||
|
||||
const pco_data *const vs_data = &state->gfx_pipeline->vs_data;
|
||||
const pvr_dev_addr_t exec_addr =
|
||||
PVR_DEV_ADDR_OFFSET(vertex_state->bo->dev_addr,
|
||||
vertex_state->entry_offset);
|
||||
vs_data->common.entry_offset);
|
||||
uint64_t addr = 0ULL;
|
||||
|
||||
pvr_set_usc_execution_address64(&addr, exec_addr.addr);
|
||||
@@ -4769,19 +4771,10 @@ pvr_update_draw_state(struct pvr_cmd_buffer_state *const state,
|
||||
static uint32_t pvr_calc_shared_regs_count(
|
||||
const struct pvr_graphics_pipeline *const gfx_pipeline)
|
||||
{
|
||||
const struct pvr_pipeline_stage_state *const vertex_state =
|
||||
&gfx_pipeline->shader_state.vertex.stage_state;
|
||||
|
||||
uint32_t shared_regs = vertex_state->const_shared_reg_count +
|
||||
vertex_state->const_shared_reg_offset;
|
||||
uint32_t shared_regs = gfx_pipeline->vs_data.common.shareds;
|
||||
|
||||
if (gfx_pipeline->shader_state.fragment.bo) {
|
||||
const struct pvr_pipeline_stage_state *const fragment_state =
|
||||
&gfx_pipeline->shader_state.fragment.stage_state;
|
||||
|
||||
uint32_t fragment_regs = fragment_state->const_shared_reg_count +
|
||||
fragment_state->const_shared_reg_offset;
|
||||
|
||||
uint32_t fragment_regs = gfx_pipeline->fs_data.common.shareds;
|
||||
shared_regs = MAX2(shared_regs, fragment_regs);
|
||||
}
|
||||
|
||||
@@ -4797,8 +4790,7 @@ pvr_emit_dirty_pds_state(const struct pvr_cmd_buffer *const cmd_buffer,
|
||||
const struct pvr_stage_allocation_descriptor_state
|
||||
*const vertex_descriptor_state =
|
||||
&state->gfx_pipeline->shader_state.vertex.descriptor_state;
|
||||
const struct pvr_pipeline_stage_state *const vertex_stage_state =
|
||||
&state->gfx_pipeline->shader_state.vertex.stage_state;
|
||||
const pco_data *const vs_data = &state->gfx_pipeline->vs_data;
|
||||
struct pvr_csb *const csb = &sub_cmd->control_stream;
|
||||
|
||||
if (!vertex_descriptor_state->pds_info.code_size_in_dwords)
|
||||
@@ -4810,7 +4802,7 @@ pvr_emit_dirty_pds_state(const struct pvr_cmd_buffer *const cmd_buffer,
|
||||
state0.usc_target = ROGUE_VDMCTRL_USC_TARGET_ALL;
|
||||
|
||||
state0.usc_common_size =
|
||||
DIV_ROUND_UP(vertex_stage_state->const_shared_reg_count << 2,
|
||||
DIV_ROUND_UP(vs_data->common.shareds,
|
||||
ROGUE_VDMCTRL_PDS_STATE0_USC_COMMON_SIZE_UNIT_SIZE);
|
||||
|
||||
state0.pds_data_size = DIV_ROUND_UP(
|
||||
@@ -4835,21 +4827,33 @@ static void pvr_setup_output_select(struct pvr_cmd_buffer *const cmd_buffer)
|
||||
{
|
||||
const struct pvr_graphics_pipeline *const gfx_pipeline =
|
||||
cmd_buffer->state.gfx_pipeline;
|
||||
const struct pvr_vertex_shader_state *const vertex_state =
|
||||
&gfx_pipeline->shader_state.vertex;
|
||||
struct vk_dynamic_graphics_state *const dynamic_state =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
struct ROGUE_TA_STATE_HEADER *const header = &cmd_buffer->state.emit_header;
|
||||
struct pvr_ppp_state *const ppp_state = &cmd_buffer->state.ppp_state;
|
||||
const pco_data *const vs_data = &gfx_pipeline->vs_data;
|
||||
const pco_data *const fs_data = &gfx_pipeline->fs_data;
|
||||
uint32_t output_selects;
|
||||
uint32_t varying[2];
|
||||
|
||||
/* TODO: Handle vertex and fragment shader state flags. */
|
||||
const pco_range *varyings = vs_data->vs.varyings;
|
||||
|
||||
const bool has_point_size = dynamic_state->ia.primitive_topology ==
|
||||
VK_PRIMITIVE_TOPOLOGY_POINT_LIST &&
|
||||
varyings[VARYING_SLOT_PSIZ].count > 0;
|
||||
|
||||
const bool has_viewport = varyings[VARYING_SLOT_VIEWPORT].count > 0;
|
||||
|
||||
const bool has_layer = varyings[VARYING_SLOT_LAYER].count > 0;
|
||||
|
||||
pvr_csb_pack (&output_selects, TA_OUTPUT_SEL, state) {
|
||||
state.rhw_pres = true;
|
||||
state.vtxsize = DIV_ROUND_UP(vertex_state->vertex_output_size, 4U);
|
||||
state.psprite_size_pres = (dynamic_state->ia.primitive_topology ==
|
||||
VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
|
||||
state.rhw_pres = fs_data->fs.uses.w;
|
||||
state.tsp_unclamped_z_pres = fs_data->fs.uses.z;
|
||||
|
||||
state.vtxsize = vs_data->vs.vtxouts;
|
||||
state.psprite_size_pres = has_point_size;
|
||||
state.vpt_tgt_pres = has_viewport;
|
||||
state.render_tgt_pres = has_layer;
|
||||
}
|
||||
|
||||
if (ppp_state->output_selects != output_selects) {
|
||||
@@ -4857,13 +4861,25 @@ static void pvr_setup_output_select(struct pvr_cmd_buffer *const cmd_buffer)
|
||||
header->pres_outselects = true;
|
||||
}
|
||||
|
||||
if (ppp_state->varying_word[0] != vertex_state->varying[0]) {
|
||||
ppp_state->varying_word[0] = vertex_state->varying[0];
|
||||
pvr_csb_pack (&varying[0], TA_STATE_VARYING0, varying0) {
|
||||
varying0.f32_linear = vs_data->vs.f32_smooth;
|
||||
varying0.f32_flat = vs_data->vs.f32_flat;
|
||||
varying0.f32_npc = vs_data->vs.f32_npc;
|
||||
}
|
||||
|
||||
if (ppp_state->varying_word[0] != varying[0]) {
|
||||
ppp_state->varying_word[0] = varying[0];
|
||||
header->pres_varying_word0 = true;
|
||||
}
|
||||
|
||||
if (ppp_state->varying_word[1] != vertex_state->varying[1]) {
|
||||
ppp_state->varying_word[1] = vertex_state->varying[1];
|
||||
pvr_csb_pack (&varying[1], TA_STATE_VARYING1, varying1) {
|
||||
varying1.f16_linear = vs_data->vs.f16_smooth;
|
||||
varying1.f16_flat = vs_data->vs.f16_flat;
|
||||
varying1.f16_npc = vs_data->vs.f16_npc;
|
||||
}
|
||||
|
||||
if (ppp_state->varying_word[1] != varying[1]) {
|
||||
ppp_state->varying_word[1] = varying[1];
|
||||
header->pres_varying_word1 = true;
|
||||
}
|
||||
}
|
||||
@@ -5402,15 +5418,16 @@ pvr_setup_fragment_state_pointers(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
struct pvr_sub_cmd_gfx *const sub_cmd)
|
||||
{
|
||||
struct pvr_cmd_buffer_state *const state = &cmd_buffer->state;
|
||||
const pco_data *const fs_data = &state->gfx_pipeline->fs_data;
|
||||
|
||||
const struct pvr_fragment_shader_state *const fragment =
|
||||
const struct pvr_fragment_shader_state *const fragment_shader_state =
|
||||
&state->gfx_pipeline->shader_state.fragment;
|
||||
const struct pvr_stage_allocation_descriptor_state *descriptor_shader_state =
|
||||
&fragment->descriptor_state;
|
||||
&fragment_shader_state->descriptor_state;
|
||||
const struct pvr_pipeline_stage_state *fragment_state =
|
||||
&fragment->stage_state;
|
||||
&fragment_shader_state->stage_state;
|
||||
const struct pvr_pds_upload *pds_coeff_program =
|
||||
&fragment->pds_coeff_program;
|
||||
&fragment_shader_state->pds_coeff_program;
|
||||
|
||||
const struct pvr_physical_device *pdevice = cmd_buffer->device->pdevice;
|
||||
struct ROGUE_TA_STATE_HEADER *const header = &state->emit_header;
|
||||
@@ -5425,7 +5442,7 @@ pvr_setup_fragment_state_pointers(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
ROGUE_TA_STATE_PDS_SIZEINFO1_PDS_VARYINGSIZE_UNIT_SIZE);
|
||||
|
||||
const uint32_t usc_varying_size =
|
||||
DIV_ROUND_UP(fragment_state->coefficient_size,
|
||||
DIV_ROUND_UP(fs_data->common.coeffs,
|
||||
ROGUE_TA_STATE_PDS_SIZEINFO1_USC_VARYINGSIZE_UNIT_SIZE);
|
||||
|
||||
const uint32_t pds_temp_size =
|
||||
@@ -5433,7 +5450,7 @@ pvr_setup_fragment_state_pointers(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
ROGUE_TA_STATE_PDS_SIZEINFO1_PDS_TEMPSIZE_UNIT_SIZE);
|
||||
|
||||
const uint32_t usc_shared_size =
|
||||
DIV_ROUND_UP(fragment_state->const_shared_reg_count,
|
||||
DIV_ROUND_UP(fs_data->common.shareds,
|
||||
ROGUE_TA_STATE_PDS_SIZEINFO2_USC_SHAREDSIZE_UNIT_SIZE);
|
||||
|
||||
const uint32_t max_tiles_in_flight =
|
||||
@@ -5453,7 +5470,7 @@ pvr_setup_fragment_state_pointers(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
TA_STATE_PDS_SHADERBASE,
|
||||
shader_base) {
|
||||
const struct pvr_pds_upload *const pds_upload =
|
||||
&fragment->pds_fragment_program;
|
||||
&fragment_shader_state->pds_fragment_program;
|
||||
|
||||
shader_base.addr = PVR_DEV_ADDR(pds_upload->data_offset);
|
||||
}
|
||||
@@ -6010,7 +6027,7 @@ pvr_emit_dirty_ppp_state(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
if (!dynamic_state->rs.rasterizer_discard_enable &&
|
||||
state->dirty.fragment_descriptors &&
|
||||
state->gfx_pipeline->shader_state.fragment.bo &&
|
||||
!state->gfx_pipeline->shader_state.fragment.stage_state.empty_program) {
|
||||
!state->gfx_pipeline->fs_data.common.uses.empty) {
|
||||
pvr_setup_fragment_state_pointers(cmd_buffer, sub_cmd);
|
||||
}
|
||||
|
||||
@@ -6127,22 +6144,16 @@ static void pvr_emit_dirty_vdm_state(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
struct vk_dynamic_graphics_state *const dynamic_state =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
const struct pvr_cmd_buffer_state *const state = &cmd_buffer->state;
|
||||
const struct pvr_vertex_shader_state *const vertex_shader_state =
|
||||
&state->gfx_pipeline->shader_state.vertex;
|
||||
const pco_data *const vs_data = &state->gfx_pipeline->vs_data;
|
||||
struct pvr_csb *const csb = &sub_cmd->control_stream;
|
||||
uint32_t vs_output_size;
|
||||
uint32_t max_instances;
|
||||
uint32_t cam_size;
|
||||
|
||||
/* CAM Calculations and HW state take vertex size aligned to DWORDS. */
|
||||
vs_output_size =
|
||||
DIV_ROUND_UP(vertex_shader_state->vertex_output_size,
|
||||
ROGUE_VDMCTRL_VDM_STATE4_VS_OUTPUT_SIZE_UNIT_SIZE);
|
||||
|
||||
assert(vs_output_size <= max_user_vertex_output_components);
|
||||
assert(vs_data->vs.vtxouts <= max_user_vertex_output_components);
|
||||
|
||||
pvr_calculate_vertex_cam_size(dev_info,
|
||||
vs_output_size,
|
||||
vs_data->vs.vtxouts,
|
||||
true,
|
||||
&cam_size,
|
||||
&max_instances);
|
||||
@@ -6210,8 +6221,8 @@ static void pvr_emit_dirty_vdm_state(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
}
|
||||
|
||||
if (header.vs_other_present) {
|
||||
const uint32_t usc_unified_store_size_in_bytes =
|
||||
vertex_shader_state->vertex_input_size << 2;
|
||||
const uint32_t usc_unified_store_size_in_bytes = vs_data->common.vtxins
|
||||
<< 2;
|
||||
|
||||
pvr_csb_emit (csb, VDMCTRL_VDM_STATE3, state3) {
|
||||
state3.vs_pds_code_base_addr =
|
||||
@@ -6219,7 +6230,7 @@ static void pvr_emit_dirty_vdm_state(struct pvr_cmd_buffer *const cmd_buffer,
|
||||
}
|
||||
|
||||
pvr_csb_emit (csb, VDMCTRL_VDM_STATE4, state4) {
|
||||
state4.vs_output_size = vs_output_size;
|
||||
state4.vs_output_size = vs_data->vs.vtxouts;
|
||||
}
|
||||
|
||||
pvr_csb_emit (csb, VDMCTRL_VDM_STATE5, state5) {
|
||||
@@ -6246,10 +6257,7 @@ static VkResult pvr_validate_draw_state(struct pvr_cmd_buffer *cmd_buffer)
|
||||
struct vk_dynamic_graphics_state *const dynamic_state =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
const struct pvr_graphics_pipeline *const gfx_pipeline = state->gfx_pipeline;
|
||||
const struct pvr_pipeline_stage_state *const fragment_state =
|
||||
&gfx_pipeline->shader_state.fragment.stage_state;
|
||||
const struct pvr_pipeline_stage_state *const vertex_state =
|
||||
&gfx_pipeline->shader_state.vertex.stage_state;
|
||||
const pco_data *const fs_data = &gfx_pipeline->fs_data;
|
||||
struct pvr_sub_cmd_gfx *sub_cmd;
|
||||
bool fstencil_writemask_zero;
|
||||
bool bstencil_writemask_zero;
|
||||
@@ -6282,7 +6290,7 @@ static VkResult pvr_validate_draw_state(struct pvr_cmd_buffer *cmd_buffer)
|
||||
if (PVR_HAS_FEATURE(&cmd_buffer->device->pdevice->dev_info,
|
||||
compute_overlap)) {
|
||||
uint32_t coefficient_size =
|
||||
DIV_ROUND_UP(fragment_state->coefficient_size,
|
||||
DIV_ROUND_UP(fs_data->common.coeffs,
|
||||
ROGUE_TA_STATE_PDS_SIZEINFO1_USC_VARYINGSIZE_UNIT_SIZE);
|
||||
|
||||
if (coefficient_size >
|
||||
@@ -6290,10 +6298,10 @@ static VkResult pvr_validate_draw_state(struct pvr_cmd_buffer *cmd_buffer)
|
||||
sub_cmd->disable_compute_overlap = true;
|
||||
}
|
||||
|
||||
sub_cmd->frag_uses_atomic_ops |= fragment_state->uses_atomic_ops;
|
||||
sub_cmd->frag_has_side_effects |= fragment_state->has_side_effects;
|
||||
sub_cmd->frag_uses_texture_rw |= fragment_state->uses_texture_rw;
|
||||
sub_cmd->vertex_uses_texture_rw |= vertex_state->uses_texture_rw;
|
||||
sub_cmd->frag_uses_atomic_ops |= fs_data->common.uses.atomics;
|
||||
sub_cmd->frag_has_side_effects |= fs_data->common.uses.side_effects;
|
||||
sub_cmd->frag_uses_texture_rw |= false;
|
||||
sub_cmd->vertex_uses_texture_rw |= false;
|
||||
|
||||
sub_cmd->job.get_vis_results = state->vis_test_enabled;
|
||||
|
||||
@@ -6656,8 +6664,8 @@ static void pvr_emit_vdm_index_list(struct pvr_cmd_buffer *cmd_buffer,
|
||||
uint32_t stride)
|
||||
{
|
||||
struct pvr_cmd_buffer_state *state = &cmd_buffer->state;
|
||||
const bool vertex_shader_has_side_effects =
|
||||
state->gfx_pipeline->shader_state.vertex.stage_state.has_side_effects;
|
||||
|
||||
const pco_data *const vs_data = &state->gfx_pipeline->vs_data;
|
||||
struct ROGUE_VDMCTRL_INDEX_LIST0 list_hdr = { pvr_cmd_header(
|
||||
VDMCTRL_INDEX_LIST0) };
|
||||
pvr_dev_addr_t index_buffer_addr = PVR_DEV_ADDR_INVALID;
|
||||
@@ -6695,7 +6703,7 @@ static void pvr_emit_vdm_index_list(struct pvr_cmd_buffer *cmd_buffer,
|
||||
list_hdr.degen_cull_enable =
|
||||
PVR_HAS_FEATURE(&cmd_buffer->device->pdevice->dev_info,
|
||||
vdm_degenerate_culling) &&
|
||||
!vertex_shader_has_side_effects;
|
||||
!vs_data->common.uses.side_effects;
|
||||
|
||||
if (state->draw_state.draw_indirect) {
|
||||
assert(buffer);
|
||||
|
||||
@@ -108,27 +108,6 @@ pvr_zls_format_type_is_int(enum ROGUE_CR_ZLS_FORMAT_TYPE type)
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
PDS
|
||||
******************************************************************************/
|
||||
|
||||
/* clang-format off */
|
||||
static inline enum ROGUE_PDSINST_DOUTU_SAMPLE_RATE
|
||||
pvr_pdsinst_doutu_sample_rate(enum pvr_msaa_mode msaa_mode)
|
||||
/* clang-format on */
|
||||
{
|
||||
switch (msaa_mode) {
|
||||
case PVR_MSAA_MODE_PIXEL:
|
||||
return ROGUE_PDSINST_DOUTU_SAMPLE_RATE_INSTANCE;
|
||||
case PVR_MSAA_MODE_SELECTIVE:
|
||||
return ROGUE_PDSINST_DOUTU_SAMPLE_RATE_SELECTIVE;
|
||||
case PVR_MSAA_MODE_FULL:
|
||||
return ROGUE_PDSINST_DOUTU_SAMPLE_RATE_FULL;
|
||||
default:
|
||||
unreachable("Undefined MSAA mode.");
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
PBESTATE
|
||||
******************************************************************************/
|
||||
|
||||
@@ -294,10 +294,6 @@ void pvr_hard_code_graphics_get_build_info(
|
||||
data->graphics.vert_shader_states[pipeline_n]
|
||||
->stage_state.pds_temps_count);
|
||||
|
||||
assert(data->graphics.build_infos[pipeline_n]->vert_common_data.coeffs ==
|
||||
data->graphics.vert_shader_states[pipeline_n]
|
||||
->stage_state.coefficient_size);
|
||||
|
||||
build_data->vs = data->graphics.build_infos[pipeline_n]->stage_data.vs;
|
||||
*common_build_data =
|
||||
data->graphics.build_infos[pipeline_n]->vert_common_data;
|
||||
@@ -311,10 +307,6 @@ void pvr_hard_code_graphics_get_build_info(
|
||||
data->graphics.frag_shader_states[pipeline_n]
|
||||
->stage_state.pds_temps_count);
|
||||
|
||||
assert(data->graphics.build_infos[pipeline_n]->frag_common_data.coeffs ==
|
||||
data->graphics.frag_shader_states[pipeline_n]
|
||||
->stage_state.coefficient_size);
|
||||
|
||||
build_data->fs = data->graphics.build_infos[pipeline_n]->stage_data.fs;
|
||||
*common_build_data =
|
||||
data->graphics.build_infos[pipeline_n]->frag_common_data;
|
||||
|
||||
@@ -40,26 +40,6 @@
|
||||
#include "vk_log.h"
|
||||
#include "vk_render_pass.h"
|
||||
|
||||
/*****************************************************************************
|
||||
PDS pre-baked program generation parameters and variables.
|
||||
*****************************************************************************/
|
||||
/* These would normally be produced by the compiler or other code. We're using
|
||||
* them for now just to speed up things. All of these should eventually be
|
||||
* removed.
|
||||
*/
|
||||
|
||||
static const struct {
|
||||
/* Indicates the amount of temporaries for the shader. */
|
||||
uint32_t temp_count;
|
||||
enum pvr_msaa_mode msaa_mode;
|
||||
/* Indicates the presence of PHAS instruction. */
|
||||
bool has_phase_rate_change;
|
||||
} pvr_pds_fragment_program_params = {
|
||||
.temp_count = 0,
|
||||
.msaa_mode = PVR_MSAA_MODE_PIXEL,
|
||||
.has_phase_rate_change = false,
|
||||
};
|
||||
|
||||
static inline bool pvr_subpass_has_msaa_input_attachment(
|
||||
struct pvr_render_subpass *subpass,
|
||||
const VkRenderPassCreateInfo2 *pCreateInfo)
|
||||
@@ -330,14 +310,20 @@ pvr_generate_load_op_shader(struct pvr_device *device,
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = pvr_pds_fragment_program_create_and_upload(
|
||||
device,
|
||||
allocator,
|
||||
load_op->usc_frag_prog_bo,
|
||||
pvr_pds_fragment_program_params.temp_count,
|
||||
pvr_pds_fragment_program_params.msaa_mode,
|
||||
pvr_pds_fragment_program_params.has_phase_rate_change,
|
||||
&load_op->pds_frag_prog);
|
||||
/* TODO: amend this once the hardcoded shaders have been removed. */
|
||||
struct pvr_fragment_shader_state fragment_state = {
|
||||
.bo = load_op->usc_frag_prog_bo,
|
||||
.sample_rate = ROGUE_PDSINST_DOUTU_SAMPLE_RATE_INSTANCE,
|
||||
.pds_fragment_program = load_op->pds_frag_prog,
|
||||
};
|
||||
|
||||
result = pvr_pds_fragment_program_create_and_upload(device,
|
||||
allocator,
|
||||
NULL,
|
||||
&fragment_state);
|
||||
load_op->usc_frag_prog_bo = fragment_state.bo;
|
||||
load_op->pds_frag_prog = fragment_state.pds_fragment_program;
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
goto err_free_usc_frag_prog_bo;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,7 @@
|
||||
#include "compiler/shader_enums.h"
|
||||
#include "hwdef/rogue_hw_defs.h"
|
||||
#include "pco/pco.h"
|
||||
#include "pco/pco_data.h"
|
||||
#include "pvr_border.h"
|
||||
#include "pvr_clear.h"
|
||||
#include "pvr_common.h"
|
||||
@@ -851,26 +852,7 @@ struct pvr_pds_attrib_program {
|
||||
};
|
||||
|
||||
struct pvr_pipeline_stage_state {
|
||||
uint32_t const_shared_reg_count;
|
||||
uint32_t const_shared_reg_offset;
|
||||
uint32_t pds_temps_count;
|
||||
|
||||
uint32_t coefficient_size;
|
||||
|
||||
/* True if this shader uses any atomic operations. */
|
||||
bool uses_atomic_ops;
|
||||
|
||||
/* True if this shader uses both texture reads and texture writes. */
|
||||
bool uses_texture_rw;
|
||||
|
||||
/* Only used for compute stage. */
|
||||
bool uses_barrier;
|
||||
|
||||
/* True if this shader has side effects */
|
||||
bool has_side_effects;
|
||||
|
||||
/* True if this shader is simply a nop.end. */
|
||||
bool empty_program;
|
||||
};
|
||||
|
||||
struct pvr_compute_shader_state {
|
||||
@@ -891,10 +873,6 @@ struct pvr_compute_shader_state {
|
||||
struct pvr_vertex_shader_state {
|
||||
/* Pointer to a buffer object that contains the shader binary. */
|
||||
struct pvr_suballoc_bo *bo;
|
||||
uint32_t entry_offset;
|
||||
|
||||
/* 2 since we only need STATE_VARYING{0,1} state words. */
|
||||
uint32_t varying[2];
|
||||
|
||||
struct pvr_pds_attrib_program
|
||||
pds_attrib_programs[PVR_PDS_VERTEX_ATTRIB_PROGRAM_COUNT];
|
||||
@@ -902,20 +880,17 @@ struct pvr_vertex_shader_state {
|
||||
struct pvr_pipeline_stage_state stage_state;
|
||||
/* FIXME: Move this into stage_state? */
|
||||
struct pvr_stage_allocation_descriptor_state descriptor_state;
|
||||
uint32_t vertex_input_size;
|
||||
uint32_t vertex_output_size;
|
||||
uint32_t user_clip_planes_mask;
|
||||
};
|
||||
|
||||
struct pvr_fragment_shader_state {
|
||||
/* Pointer to a buffer object that contains the shader binary. */
|
||||
struct pvr_suballoc_bo *bo;
|
||||
uint32_t entry_offset;
|
||||
|
||||
struct pvr_pipeline_stage_state stage_state;
|
||||
/* FIXME: Move this into stage_state? */
|
||||
struct pvr_stage_allocation_descriptor_state descriptor_state;
|
||||
enum ROGUE_TA_PASSTYPE pass_type;
|
||||
enum ROGUE_PDSINST_DOUTU_SAMPLE_RATE sample_rate;
|
||||
|
||||
struct pvr_pds_upload pds_coeff_program;
|
||||
struct pvr_pds_upload pds_fragment_program;
|
||||
@@ -967,6 +942,9 @@ struct pvr_graphics_pipeline {
|
||||
/* Derived and other state */
|
||||
size_t stage_indices[MESA_SHADER_STAGES];
|
||||
|
||||
pco_data vs_data;
|
||||
pco_data fs_data;
|
||||
|
||||
struct {
|
||||
struct pvr_vertex_shader_state vertex;
|
||||
struct pvr_fragment_shader_state fragment;
|
||||
@@ -1390,11 +1368,8 @@ enum pvr_msaa_mode {
|
||||
VkResult pvr_pds_fragment_program_create_and_upload(
|
||||
struct pvr_device *device,
|
||||
const VkAllocationCallbacks *allocator,
|
||||
const struct pvr_suballoc_bo *fragment_shader_bo,
|
||||
uint32_t fragment_temp_count,
|
||||
enum pvr_msaa_mode msaa_mode,
|
||||
bool has_phase_rate_change,
|
||||
struct pvr_pds_upload *const pds_upload_out);
|
||||
pco_shader *fs,
|
||||
struct pvr_fragment_shader_state *fragment_state);
|
||||
|
||||
VkResult pvr_pds_unitex_state_program_create_and_upload(
|
||||
struct pvr_device *device,
|
||||
|
||||
Reference in New Issue
Block a user