r600: cypress resinfo buffer size workaround

Reading the buffer size (GET_BUFFER_RESINFO) does not work
on cypress. This issue is the main difference on a test
basis between cypress and other gpus like palm and cayman.
This change adds a dedicated function which extends the
previous workaround algorithm for cubearray to this end.

This change assumes that all the gpus between cedar and
hemlock have the same issue.

Signed-off-by: Patrick Lerda <patrick9876@free.fr>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39650>
This commit is contained in:
Patrick Lerda 2026-02-02 13:34:55 +01:00 committed by Marge Bot
parent 34336c7f16
commit c54f134f60
6 changed files with 130 additions and 8 deletions

View file

@ -4551,6 +4551,7 @@ static void evergreen_set_shader_buffers(struct pipe_context *ctx,
}
istate->atom.num_dw = util_bitcount(istate->enabled_mask) * 46;
istate->dirty_buffer_constants = true;
if (old_mask != istate->enabled_mask)
r600_mark_atom_dirty(rctx, &rctx->cb_state.atom);

View file

@ -202,7 +202,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen,
rctx->append_fence = pipe_buffer_create(rctx->b.b.screen, PIPE_BIND_CUSTOM,
PIPE_USAGE_DEFAULT, 32);
rctx->setup_buffer_constants = r600_palm_to_aruba_setup_buffer_constants;
rctx->setup_buffer_constants = rctx->b.family >= CHIP_PALM ?
r600_palm_to_aruba_setup_buffer_constants :
r600_cedar_to_hemlock_setup_buffer_constants;
break;
default:
R600_ERR("Unsupported gfx level %d.\n", rctx->b.gfx_level);

View file

@ -1124,6 +1124,7 @@ void evergreen_emit_atomic_buffer_save(struct r600_context *rctx,
void r600_update_compressed_resource_state(struct r600_context *rctx, bool compute_only);
void r600_palm_to_aruba_setup_buffer_constants(struct r600_context *rctx, int shader_type);
void r600_cedar_to_hemlock_setup_buffer_constants(struct r600_context *rctx, int shader_type);
void r600_setup_buffer_constants(struct r600_context *rctx, int shader_type);
void r600_update_driver_const_buffers(struct r600_context *rctx, bool compute_only);
#endif

View file

@ -1477,7 +1477,7 @@ void r600_setup_buffer_constants(struct r600_context *rctx, int shader_type)
}
/* On evergreen we store one value
/* On palm to aruba we store one value
* 1. number of cube layers in a cube map array.
*/
void r600_palm_to_aruba_setup_buffer_constants(struct r600_context *rctx, int shader_type)
@ -1532,6 +1532,84 @@ void r600_palm_to_aruba_setup_buffer_constants(struct r600_context *rctx, int sh
}
}
/* On cedar to hemlock we store two values using the same location
* 1. number of cube layers in a cube map array.
* 2. buffer size
*/
void r600_cedar_to_hemlock_setup_buffer_constants(struct r600_context *rctx, int shader_type)
{
struct r600_textures_info *const samplers = &rctx->samplers[shader_type];
struct r600_image_state *images = NULL;
struct r600_image_state *buffers = NULL;
if (shader_type == MESA_SHADER_FRAGMENT) {
images = &rctx->fragment_images;
buffers = &rctx->fragment_buffers;
} else if (shader_type == MESA_SHADER_COMPUTE) {
images = &rctx->compute_images;
buffers = &rctx->compute_buffers;
}
if (!samplers->views.dirty_buffer_constants &&
!(images && images->dirty_buffer_constants) &&
!(buffers && buffers->dirty_buffer_constants))
return;
if (images)
images->dirty_buffer_constants = false;
if (buffers)
buffers->dirty_buffer_constants = false;
samplers->views.dirty_buffer_constants = false;
const unsigned sview_bits = util_last_bit(samplers->views.enabled_mask);
unsigned bits = sview_bits;
if (images)
bits += util_last_bit(images->enabled_mask);
const unsigned img_bits = bits;
if (buffers)
bits += util_last_bit(buffers->enabled_mask);
const uint32_t array_size = bits * sizeof(uint32_t);
uint32_t base_offset;
uint32_t *const constants = r600_alloc_buf_consts(rctx, shader_type, array_size,
&base_offset);
for (unsigned i = 0; i < sview_bits; i++) {
if (samplers->views.enabled_mask & (1 << i)) {
uint32_t offset = (base_offset / 4) + i;
if (samplers->views.views[i]->tex_resource->b.b.target == PIPE_BUFFER) {
constants[offset] = samplers->views.views[i]->tex_resource_words[4];
} else {
constants[offset] = samplers->views.views[i]->base.texture->array_size / 6;
}
}
}
if (images) {
for (unsigned i = sview_bits; i < img_bits; i++) {
int idx = i - sview_bits;
if (images->enabled_mask & (1 << idx)) {
uint32_t offset = (base_offset / 4) + i;
if (images->views[idx].base.resource->target == PIPE_BUFFER) {
constants[offset] = images->views[idx].resource_words[4];
} else {
constants[offset] = (G_038014_LAST_ARRAY(images->views[idx].resource_words[5]) -
G_038014_BASE_ARRAY(images->views[idx].resource_words[5]) + 1) / 6;
}
}
}
}
if (buffers) {
for (unsigned i = img_bits; i < bits; i++) {
int idx = i - img_bits;
if (buffers->enabled_mask & (1 << idx)) {
uint32_t offset = (base_offset / 4) + i;
constants[offset] = buffers->views[idx].resource_words[4];
}
}
}
}
/* set sample xy locations as array of fragment shader constants */
void r600_set_sample_locations_constant_buffer(struct r600_context *rctx)
{

View file

@ -797,7 +797,19 @@ RatInstr::emit_ssbo_size(nir_intrinsic_instr *intr, Shader& shader)
else
assert(0 && "dynamic buffer offset not supported in buffer_size");
shader.emit_instruction(new QueryBufferSizeInstr(dest, {0, 1, 2, 3}, res_id));
if (shader.chip_family() >= CHIP_PALM) {
shader.emit_instruction(new QueryBufferSizeInstr(dest, {0, 1, 2, 3}, res_id));
} else {
const unsigned index = res_id - R600_IMAGE_REAL_RESOURCE_OFFSET;
shader.set_flag(Shader::sh_resinfo_via_uniform);
shader.emit_instruction(new AluInstr(op1_mov,
dest[0],
vf.uniform(index / 4 +
R600_SHADER_BUFFER_INFO_SEL,
index % 4,
R600_BUFFER_INFO_CONST_BUFFER),
AluInstr::write));
}
return true;
}
@ -957,7 +969,24 @@ RatInstr::emit_image_size(nir_intrinsic_instr *intrin, Shader& shader)
if (nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_BUF) {
auto dest = vf.dest_vec4(intrin->def, pin_group);
shader.emit_instruction(new QueryBufferSizeInstr(dest, {0, 1, 2, 3}, res_id));
if (shader.chip_family() >= CHIP_PALM) {
shader.emit_instruction(new QueryBufferSizeInstr(dest, {0, 1, 2, 3}, res_id));
} else {
if (const_offset) {
shader.set_flag(Shader::sh_resinfo_via_uniform);
unsigned lookup_resid = (res_id - R600_IMAGE_REAL_RESOURCE_OFFSET) +
shader.image_size_const_offset();
shader.emit_instruction(
new AluInstr(op1_mov,
dest[0],
vf.uniform(lookup_resid / 4 + R600_SHADER_BUFFER_INFO_SEL,
lookup_resid % 4,
R600_BUFFER_INFO_CONST_BUFFER),
AluInstr::write));
} else {
assert(0);
}
}
return true;
} else {

View file

@ -654,14 +654,25 @@ TexInstr::emit_tex_txs(nir_tex_instr *tex,
auto dest = vf.dest_vec4(tex->def, pin_group);
if (tex->sampler_dim == GLSL_SAMPLER_DIM_BUF) {
if (shader.chip_class() >= ISA_CC_EVERGREEN) {
shader.emit_instruction(new QueryBufferSizeInstr(
dest, {0, 7, 7, 7}, tex->texture_index + R600_MAX_CONST_BUFFERS));
} else {
if (shader.chip_family() >= CHIP_PALM) {
shader.emit_instruction(new QueryBufferSizeInstr(dest,
{0, 7, 7, 7},
tex->texture_index +
R600_MAX_CONST_BUFFERS));
} else if (shader.chip_family() < CHIP_CEDAR) {
int id = 2 * tex->texture_index + R600_SHADER_BUFFER_INFO_SEL + 1;
auto src = vf.uniform(id, 1, R600_BUFFER_INFO_CONST_BUFFER);
shader.emit_instruction(new AluInstr(op1_mov, dest[0], src, AluInstr::write));
shader.set_flag(Shader::sh_uses_tex_buffer);
} else {
shader.set_flag(Shader::sh_resinfo_via_uniform);
shader.emit_instruction(new AluInstr(op1_mov,
dest[0],
vf.uniform(tex->texture_index / 4 +
R600_SHADER_BUFFER_INFO_SEL,
tex->texture_index % 4,
R600_BUFFER_INFO_CONST_BUFFER),
AluInstr::write));
}
} else {