diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index a1255258ece..07e1b6f8bfc 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -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); diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 895d8c43e70..eccb43989ec 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -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); diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index b2a9b08ca4c..636e7cc1f44 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -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 diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index ad3cbcf07db..62433a4477b 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -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) { diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp b/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp index 863d562c7dc..ff7e671139c 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp @@ -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 { diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp b/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp index cd0abd98014..bee78694fdf 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp @@ -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 {