pvr, pco: add input attachment sampler and initial support

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36412>
This commit is contained in:
Simon Perretta
2025-02-02 17:23:21 +00:00
committed by Marge Bot
parent 486ca8bbc1
commit 8afde5ec19
12 changed files with 243 additions and 45 deletions
+9
View File
@@ -21,6 +21,7 @@
#include <stdbool.h>
#define PCO_POINT_SAMPLER 0xffff
#define PCO_IA_SAMPLER 0xfffe
/* Compiler-specific forward-declarations. */
typedef struct _pco_shader pco_shader;
@@ -67,6 +68,12 @@ typedef struct _pco_fs_data {
/** Fragment output formats. */
enum pipe_format output_formats[FRAG_RESULT_MAX];
/** On-chip input attachment mappings. */
pco_range ias_onchip[4];
/** On-chip input attachment formats. */
enum pipe_format ia_formats[4];
/* Blend options. */
nir_lower_blend_options blend_opts;
pco_range blend_consts;
@@ -149,6 +156,7 @@ typedef struct _pco_common_data {
pco_push_const_data push_consts;
pco_range point_sampler;
pco_range ia_sampler;
unsigned temps; /** Number of allocated temp registers. */
unsigned vtxins; /** Number of allocated vertex input registers. */
@@ -165,6 +173,7 @@ typedef struct _pco_common_data {
bool side_effects; /** Whether the shader has side effects. */
bool empty; /** Whether the shader is empty. */
bool point_sampler; /** Whether the shader uses a point sampler. */
bool ia_sampler; /** Does the shader use an input attachment sampler? */
} uses;
} pco_common_data;
+2 -2
View File
@@ -1649,10 +1649,10 @@ bool pco_nir_lower_algebraic(nir_shader *shader);
bool pco_nir_lower_algebraic_late(nir_shader *shader);
bool pco_nir_lower_atomics(nir_shader *shader, bool *uses_usclib);
bool pco_nir_lower_barriers(nir_shader *shader, bool *uses_usclib);
bool pco_nir_lower_images(nir_shader *shader);
bool pco_nir_lower_images(nir_shader *shader, pco_data *data);
bool pco_nir_lower_io(nir_shader *shader);
bool pco_nir_lower_tex(nir_shader *shader);
bool pco_nir_lower_vk(nir_shader *shader, pco_common_data *common);
bool pco_nir_lower_vk(nir_shader *shader, pco_data *data);
bool pco_nir_pfo(nir_shader *shader, pco_fs_data *fs);
bool pco_nir_point_size(nir_shader *shader);
bool pco_nir_pvi(nir_shader *shader, pco_vs_data *vs);
+5 -2
View File
@@ -512,6 +512,9 @@ void pco_preprocess_nir(pco_ctx *ctx, nir_shader *nir)
NIR_PASS(_, nir, nir_lower_flrp, 32, true);
NIR_PASS(_, nir, nir_remove_dead_derefs);
NIR_PASS(_, nir, nir_opt_undef);
NIR_PASS(_, nir, nir_lower_undef_to_zero);
NIR_PASS(_, nir, nir_opt_cse);
NIR_PASS(_, nir, nir_opt_dce);
NIR_PASS(_,
nir,
@@ -685,7 +688,7 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data)
nir_address_format_32bit_offset);
NIR_PASS(_, nir, nir_lower_io_to_scalar, nir_var_mem_shared, NULL, NULL);
NIR_PASS(_, nir, pco_nir_lower_vk, &data->common);
NIR_PASS(_, nir, pco_nir_lower_vk, data);
NIR_PASS(_, nir, pco_nir_lower_io);
NIR_PASS(_, nir, pco_nir_lower_atomics, &uses_usclib);
@@ -711,7 +714,7 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data)
nir_io_add_const_offset_to_base,
nir_var_shader_in | nir_var_shader_out);
NIR_PASS(_, nir, pco_nir_lower_images);
NIR_PASS(_, nir, pco_nir_lower_images, data);
NIR_PASS(_, nir, nir_lower_tex, &(nir_lower_tex_options){});
NIR_PASS(_, nir, pco_nir_lower_tex);
+10 -1
View File
@@ -819,7 +819,16 @@ static nir_def *lower_pfo_load(nir_builder *b,
struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
gl_frag_result location = io_semantics.location;
enum pipe_format format = state->fs->output_formats[location];
enum pipe_format format;
/* Special case for input attachments. */
if (location == FRAG_RESULT_COLOR) {
format = state->fs->ia_formats[base];
} else {
assert(location >= FRAG_RESULT_DATA0);
assert(!base);
format = state->fs->output_formats[location];
}
if (format == PIPE_FORMAT_NONE)
return nir_undef(b, intr->def.num_components, intr->def.bit_size);
+33 -10
View File
@@ -763,13 +763,15 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data)
? nir_intrinsic_dest_type(intr)
: nir_intrinsic_src_type(intr);
bool msaa = image_dim == GLSL_SAMPLER_DIM_MS ||
image_dim == GLSL_SAMPLER_DIM_SUBPASS_MS;
unsigned desc_set = nir_src_comp_as_uint(intr->src[0], 0);
unsigned binding = nir_src_comp_as_uint(intr->src[0], 1);
nir_def *elem = nir_channel(b, intr->src[0].ssa, 2);
nir_def *coords = !nir_src_is_undef(intr->src[1]) ? intr->src[1].ssa : NULL;
nir_def *sample_index = !nir_src_is_undef(intr->src[2]) ? intr->src[2].ssa
: NULL;
nir_def *coords = intr->src[1].ssa;
nir_def *sample_index = msaa ? intr->src[2].ssa : NULL;
nir_def *write_data = intr->intrinsic == nir_intrinsic_image_deref_store
? intr->src[3].ssa
@@ -780,9 +782,30 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data)
assert(write_data->num_components == 4);
}
ASSERTED bool msaa = image_dim == GLSL_SAMPLER_DIM_MS ||
image_dim == GLSL_SAMPLER_DIM_SUBPASS_MS;
assert(!!sample_index == msaa);
bool ia = image_dim == GLSL_SAMPLER_DIM_SUBPASS ||
image_dim == GLSL_SAMPLER_DIM_SUBPASS_MS;
if (ia) {
nir_load_const_instr *load =
nir_instr_as_load_const(intr->src[0].ssa->parent_instr);
bool onchip = load->def.num_components == 4;
if (onchip) {
unsigned ia_idx = nir_src_comp_as_uint(intr->src[0], 3);
return nir_load_output(b,
intr->def.num_components,
intr->def.bit_size,
nir_imm_int(b, 0),
.base = ia_idx,
.component = 0,
.dest_type = nir_intrinsic_dest_type(intr),
.io_semantics.location = FRAG_RESULT_COLOR,
.io_semantics.num_slots = 1/*,
.io_semantics.fb_fetch_output = true*/);
}
}
unsigned smp_desc = ia ? PCO_IA_SAMPLER : PCO_POINT_SAMPLER;
nir_def *tex_state = nir_load_tex_state_pco(b,
ROGUE_NUM_TEXSTATE_DWORDS,
@@ -793,8 +816,8 @@ static nir_def *lower_image(nir_builder *b, nir_instr *instr, void *cb_data)
nir_def *smp_state = nir_load_smp_state_pco(b,
ROGUE_NUM_TEXSTATE_DWORDS,
nir_imm_int(b, 0),
.desc_set = PCO_POINT_SAMPLER,
.binding = PCO_POINT_SAMPLER);
.desc_set = smp_desc,
.binding = smp_desc);
unsigned num_coord_comps = nir_image_intrinsic_coord_components(intr);
if (coords)
@@ -859,7 +882,7 @@ static bool is_image(const nir_instr *instr, UNUSED const void *cb_data)
return false;
}
bool pco_nir_lower_images(nir_shader *shader)
bool pco_nir_lower_images(nir_shader *shader, pco_data *data)
{
return nir_shader_lower_instructions(shader, is_image, lower_image, NULL);
return nir_shader_lower_instructions(shader, is_image, lower_image, data);
}
+38 -12
View File
@@ -122,9 +122,8 @@ lower_tex_derefs(nir_builder *b, nir_tex_instr *tex, pco_common_data *common)
lower_tex_deref_to_binding(b, tex, deref_index, common);
}
static nir_def *lower_image_derefs(nir_builder *b,
nir_intrinsic_instr *intr,
pco_common_data *common)
static nir_def *
lower_image_derefs(nir_builder *b, nir_intrinsic_instr *intr, pco_data *data)
{
nir_src *deref_src = &intr->src[0];
nir_deref_instr *deref = nir_src_as_deref(*deref_src);
@@ -132,16 +131,42 @@ static nir_def *lower_image_derefs(nir_builder *b,
nir_variable *var = nir_deref_instr_get_variable(deref);
assert(var);
unsigned desc_set = var->data.descriptor_set;
unsigned binding = var->data.binding;
nir_def *elem = array_elem_from_deref(b, deref);
set_resource_used(common, desc_set, binding);
common->uses.point_sampler = true;
set_resource_used(&data->common, desc_set, binding);
if (nir_intrinsic_format(intr) == PIPE_FORMAT_NONE)
nir_intrinsic_set_format(intr, var->data.image.format);
enum glsl_sampler_dim image_dim = nir_intrinsic_image_dim(intr);
bool ia = image_dim == GLSL_SAMPLER_DIM_SUBPASS ||
image_dim == GLSL_SAMPLER_DIM_SUBPASS_MS;
if (ia) {
unsigned ia_idx = var->data.index;
bool onchip = data->fs.ias_onchip[ia_idx].count > 0;
if (onchip) {
nir_def *elem = array_elem_from_deref(b, deref);
nir_def *index = nir_vec4(b,
nir_imm_int(b, desc_set),
nir_imm_int(b, binding),
elem,
nir_imm_int(b, ia_idx));
nir_src_rewrite(deref_src, index);
return NIR_LOWER_INSTR_PROGRESS;
}
/* Sampler not needed for on-chip input attachments. */
data->common.uses.ia_sampler = true;
} else {
data->common.uses.point_sampler = true;
}
nir_def *elem = array_elem_from_deref(b, deref);
nir_def *index =
nir_vec3(b, nir_imm_int(b, desc_set), nir_imm_int(b, binding), elem);
@@ -160,7 +185,8 @@ static nir_def *lower_image_derefs(nir_builder *b,
*/
static nir_def *lower_vk(nir_builder *b, nir_instr *instr, void *cb_data)
{
pco_common_data *common = cb_data;
pco_data *data = cb_data;
pco_common_data *common = &data->common;
switch (instr->type) {
case nir_instr_type_intrinsic: {
@@ -171,7 +197,7 @@ static nir_def *lower_vk(nir_builder *b, nir_instr *instr, void *cb_data)
case nir_intrinsic_image_deref_load:
case nir_intrinsic_image_deref_store:
return lower_image_derefs(b, intr, common);
return lower_image_derefs(b, intr, data);
default:
break;
@@ -239,14 +265,14 @@ static bool is_vk(const nir_instr *instr, UNUSED const void *cb_data)
* \brief Vulkan lowering pass.
*
* \param[in,out] shader NIR shader.
* \param[in,out] common Common shader data.
* \param[in,out] data Shader data.
* \return True if the pass made progress.
*/
bool pco_nir_lower_vk(nir_shader *shader, pco_common_data *common)
bool pco_nir_lower_vk(nir_shader *shader, pco_data *data)
{
bool progress = false;
progress |= nir_shader_lower_instructions(shader, is_vk, lower_vk, common);
progress |= nir_shader_lower_instructions(shader, is_vk, lower_vk, data);
return progress;
}
+26 -10
View File
@@ -406,7 +406,7 @@ trans_store_output_fs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref src)
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;
gl_frag_result location = nir_intrinsic_io_semantics(intr).location;
const pco_range *range = &tctx->shader->data.fs.outputs[location];
assert(component < range->count);
@@ -430,6 +430,12 @@ static unsigned fetch_resource_base_reg(const pco_common_data *common,
assert(common->uses.point_sampler);
range = &common->point_sampler;
if (is_img_smp)
*is_img_smp = false;
} else if (desc_set == PCO_IA_SAMPLER && binding == PCO_IA_SAMPLER) {
assert(common->uses.ia_sampler);
range = &common->ia_sampler;
if (is_img_smp)
*is_img_smp = false;
} else {
@@ -477,23 +483,33 @@ static unsigned fetch_resource_base_reg_packed(const pco_common_data *common,
static pco_instr *
trans_load_output_fs(trans_ctx *tctx, nir_intrinsic_instr *intr, pco_ref dest)
{
ASSERTED unsigned base = nir_intrinsic_base(intr);
assert(!base);
unsigned base = nir_intrinsic_base(intr);
unsigned component = nir_intrinsic_component(intr);
ASSERTED const nir_src offset = intr->src[0];
assert(nir_src_as_uint(offset) == 0);
gl_varying_slot location = nir_intrinsic_io_semantics(intr).location;
gl_frag_result location = nir_intrinsic_io_semantics(intr).location;
const pco_range *range;
if (location >= FRAG_RESULT_DATA0) {
assert(!base);
range = &tctx->shader->data.fs.outputs[location];
ASSERTED bool output_reg = tctx->shader->data.fs.output_reg[location];
assert(output_reg);
/* TODO: tile buffer support. */
} else if (location == FRAG_RESULT_COLOR) {
/* Special case for on-chip input attachments. */
assert(base < ARRAY_SIZE(tctx->shader->data.fs.ias_onchip));
range = &tctx->shader->data.fs.ias_onchip[base];
} else {
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 src = pco_ref_hwreg(range->start + component, PCO_REG_CLASS_PIXOUT);
return pco_mov(&tctx->b, dest, src, .olchk = true);
}
+1
View File
@@ -893,6 +893,7 @@ struct pvr_pds_descriptor_set {
#define PVR_BUFFER_TYPE_DYNAMIC (5)
#define PVR_BUFFER_TYPE_UBO_ZEROING (6)
#define PVR_BUFFER_TYPE_POINT_SAMPLER (7)
#define PVR_BUFFER_TYPE_IA_SAMPLER (8)
#define PVR_BUFFER_TYPE_INVALID (~0)
struct pvr_pds_buffer {
@@ -1576,7 +1576,8 @@ void pvr_pds_generate_descriptor_upload_program(
switch (buffer->type) {
case PVR_BUFFER_TYPE_PUSH_CONSTS:
case PVR_BUFFER_TYPE_BLEND_CONSTS:
case PVR_BUFFER_TYPE_POINT_SAMPLER: {
case PVR_BUFFER_TYPE_POINT_SAMPLER:
case PVR_BUFFER_TYPE_IA_SAMPLER: {
struct pvr_const_map_entry_special_buffer *special_buffer_entry;
special_buffer_entry =
+36
View File
@@ -3686,6 +3686,42 @@ static VkResult pvr_setup_descriptor_mappings(
break;
}
case PVR_BUFFER_TYPE_IA_SAMPLER: {
uint64_t ia_sampler_words[ROGUE_NUM_TEXSTATE_SAMPLER_WORDS];
pvr_csb_pack (&ia_sampler_words[0],
TEXSTATE_SAMPLER_WORD0,
sampler) {
sampler.addrmode_u = ROGUE_TEXSTATE_ADDRMODE_CLAMP_TO_EDGE;
sampler.addrmode_v = ROGUE_TEXSTATE_ADDRMODE_CLAMP_TO_EDGE;
sampler.addrmode_w = ROGUE_TEXSTATE_ADDRMODE_CLAMP_TO_EDGE;
sampler.dadjust = ROGUE_TEXSTATE_DADJUST_ZERO_UINT;
sampler.magfilter = ROGUE_TEXSTATE_FILTER_POINT;
sampler.minfilter = ROGUE_TEXSTATE_FILTER_POINT;
sampler.anisoctl = ROGUE_TEXSTATE_ANISOCTL_DISABLED;
sampler.non_normalized_coords = true;
}
pvr_csb_pack (&ia_sampler_words[1],
TEXSTATE_SAMPLER_WORD1,
sampler) {
}
struct pvr_suballoc_bo *ia_sampler_bo;
result = pvr_cmd_buffer_upload_general(cmd_buffer,
ia_sampler_words,
sizeof(ia_sampler_words),
&ia_sampler_bo);
if (result != VK_SUCCESS)
return result;
PVR_WRITE(qword_buffer,
ia_sampler_bo->dev_addr.addr,
special_buff_entry->const_offset,
pds_info->data_size_in_dwords);
break;
}
default:
UNREACHABLE("Unsupported special buffer type.");
}
@@ -85,6 +85,7 @@ static unsigned pvr_descriptor_size(VkDescriptorType type)
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return sizeof(struct pvr_image_descriptor);
default:
@@ -514,6 +515,23 @@ write_image_sampler(const struct pvr_descriptor_set *set,
memcpy(desc_mapping, &image_sampler_desc, sizeof(image_sampler_desc));
}
static void
write_input_attachment(const struct pvr_descriptor_set *set,
const VkDescriptorImageInfo *image_info,
const struct pvr_descriptor_set_layout_binding *binding,
uint32_t elem)
{
PVR_FROM_HANDLE(pvr_image_view, image_view, image_info->imageView);
const unsigned desc_offset = binding->offset + (elem * binding->stride);
void *desc_mapping = (uint8_t *)set->mapping + desc_offset;
struct pvr_image_descriptor image_desc =
image_view->image_state[PVR_TEXTURE_STATE_ATTACHMENT];
memcpy(desc_mapping, &image_desc, sizeof(image_desc));
}
static void
write_storage_image(const struct pvr_descriptor_set *set,
const VkDescriptorImageInfo *image_info,
@@ -643,6 +661,15 @@ void pvr_UpdateDescriptorSets(VkDevice _device,
}
break;
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
write_input_attachment(set,
&write->pImageInfo[j],
binding,
write->dstArrayElement + j);
}
break;
default:
UNREACHABLE("");
}
+54 -7
View File
@@ -606,6 +606,14 @@ static VkResult pvr_pds_descriptor_program_create_and_upload(
};
}
if (data->common.ia_sampler.count > 0) {
program.buffers[program.buffer_count++] = (struct pvr_pds_buffer){
.type = PVR_BUFFER_TYPE_IA_SAMPLER,
.size_in_dwords = data->common.ia_sampler.count,
.destination = data->common.ia_sampler.start,
};
}
pds_info->entries_size_in_bytes = const_entries_size_in_bytes;
pvr_pds_generate_descriptor_upload_program(&program, NULL, pds_info);
@@ -1799,11 +1807,7 @@ pvr_setup_fs_outputs(pco_data *data,
const struct pvr_render_subpass *const subpass,
const struct pvr_renderpass_hwsetup_subpass *hw_subpass)
{
ASSERTED unsigned num_outputs = hw_subpass->setup.num_render_targets;
assert(num_outputs == subpass->color_count);
uint64_t outputs_written = nir->info.outputs_written;
assert(util_bitcount64(outputs_written) == num_outputs);
for (unsigned u = 0; u < subpass->color_count; ++u) {
gl_frag_result location = FRAG_RESULT_DATA0 + u;
@@ -1846,10 +1850,44 @@ pvr_setup_fs_outputs(pco_data *data,
static void pvr_init_fs_input_attachments(
pco_data *data,
const struct pvr_render_pass *pass,
const struct pvr_render_subpass *const subpass,
const struct pvr_renderpass_hwsetup_subpass *hw_subpass)
{
pvr_finishme("pvr_init_fs_input_attachments");
for (unsigned u = 0; u < subpass->input_count; ++u) {
unsigned idx = subpass->input_attachments[u];
if (idx == VK_ATTACHMENT_UNUSED)
continue;
bool onchip = hw_subpass->input_access[u].type !=
PVR_RENDERPASS_HWSETUP_INPUT_ACCESS_OFFCHIP;
if (!onchip)
continue;
/* TODO: z-replicate. */
assert(hw_subpass->input_access[u].type !=
PVR_RENDERPASS_HWSETUP_INPUT_ACCESS_ONCHIP_ZREPLICATE);
VkFormat vk_format = pass->attachments[idx].vk_format;
data->fs.ia_formats[u] = vk_format_to_pipe_format(vk_format);
unsigned mrt_idx = hw_subpass->input_access[u].on_chip_rt;
const struct usc_mrt_resource *mrt_resource =
&hw_subpass->setup.mrt_resources[mrt_idx];
ASSERTED bool output_reg = mrt_resource->type ==
USC_MRT_RESOURCE_TYPE_OUTPUT_REG;
assert(output_reg);
/* TODO: tile buffer support. */
unsigned format_bits =
util_format_get_blocksizebits(data->fs.ia_formats[u]);
data->fs.ias_onchip[u] = (pco_range){
.start = mrt_resource->reg.output_reg,
.count = DIV_ROUND_UP(format_bits, 32),
};
}
}
static void pvr_init_fs_blend(pco_data *data,
@@ -1903,7 +1941,7 @@ static void pvr_setup_fs_input_attachments(
const struct pvr_render_subpass *const subpass,
const struct pvr_renderpass_hwsetup_subpass *hw_subpass)
{
pvr_finishme("pvr_setup_fs_input_attachments");
/* pvr_finishme("pvr_setup_fs_input_attachments"); */
}
static void pvr_setup_fs_blend(pco_data *data)
@@ -2088,6 +2126,15 @@ static void pvr_setup_descriptors(pco_data *data,
data->common.shareds += ROGUE_NUM_TEXSTATE_DWORDS;
}
if (data->common.uses.ia_sampler) {
data->common.ia_sampler = (pco_range){
.start = data->common.shareds,
.count = ROGUE_NUM_TEXSTATE_DWORDS,
};
data->common.shareds += ROGUE_NUM_TEXSTATE_DWORDS;
}
assert(data->common.shareds < 256);
}
@@ -2120,7 +2167,7 @@ pvr_preprocess_shader_data(pco_data *data,
.subpasses[subpass_map->subpass];
pvr_init_fs_outputs(data, pass, subpass, hw_subpass);
pvr_init_fs_input_attachments(data, subpass, hw_subpass);
pvr_init_fs_input_attachments(data, pass, subpass, hw_subpass);
pvr_init_fs_blend(data, state->cb);
/* TODO: push consts, dynamic state, etc. */