[Mesa-dev] [PATCH 12/24] cso: don't track the number of sampler states bound
Marek Olšák
maraeo at gmail.com
Wed Jun 14 18:03:03 UTC 2017
On Wed, Jun 14, 2017 at 9:23 AM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> On 12.06.2017 20:18, Marek Olšák wrote:
>>
>> From: Marek Olšák <marek.olsak at amd.com>
>>
>> This removes 2 loops from hot codepaths and adds 1 loop to a rare codepath
>> (restore_sampler_states), and makes sanitize_hash() slightly worse.
>>
>> Sampler states, when bound, are not unbound for draw calls that don't need
>> them. That's OK, because bound sampler states don't add any overhead.
>
>
> Is this really always true? They might show up in texture decompression
> checks.
Sampler states are not sampler views. They don't have any resources
attached to them.
Marek
>
> Cheers,
> Nicolai
>
>
>
>>
>> This results in lower CPU overhead in most cases.
>> ---
>> src/gallium/auxiliary/cso_cache/cso_context.c | 59
>> +++++++++++----------------
>> 1 file changed, 23 insertions(+), 36 deletions(-)
>>
>> diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c
>> b/src/gallium/auxiliary/cso_cache/cso_context.c
>> index 5558385..4947b8e 100644
>> --- a/src/gallium/auxiliary/cso_cache/cso_context.c
>> +++ b/src/gallium/auxiliary/cso_cache/cso_context.c
>> @@ -50,21 +50,20 @@
>> #include "cso_context.h"
>> /**
>> * Per-shader sampler information.
>> */
>> struct sampler_info
>> {
>> struct cso_sampler *cso_samplers[PIPE_MAX_SAMPLERS];
>> void *samplers[PIPE_MAX_SAMPLERS];
>> - unsigned nr_samplers;
>> };
>> struct cso_context {
>> struct pipe_context *pipe;
>> struct cso_cache *cache;
>> struct u_vbuf *vbuf;
>> boolean has_geometry_shader;
>> @@ -76,20 +75,25 @@ struct cso_context {
>> struct pipe_sampler_view
>> *fragment_views[PIPE_MAX_SHADER_SAMPLER_VIEWS];
>> unsigned nr_fragment_views;
>> struct pipe_sampler_view
>> *fragment_views_saved[PIPE_MAX_SHADER_SAMPLER_VIEWS];
>> unsigned nr_fragment_views_saved;
>> struct sampler_info fragment_samplers_saved;
>> struct sampler_info samplers[PIPE_SHADER_TYPES];
>> + /* Temporary number until cso_single_sampler_done is called.
>> + * It tracks the highest sampler seen in cso_single_sampler.
>> + */
>> + int max_sampler_seen;
>> +
>> struct pipe_vertex_buffer aux_vertex_buffer_current;
>> struct pipe_vertex_buffer aux_vertex_buffer_saved;
>> unsigned aux_vertex_buffer_index;
>> struct pipe_constant_buffer
>> aux_constbuf_current[PIPE_SHADER_TYPES];
>> struct pipe_constant_buffer aux_constbuf_saved[PIPE_SHADER_TYPES];
>> struct pipe_image_view fragment_image0_current;
>> struct pipe_image_view fragment_image0_saved;
>> @@ -233,21 +237,21 @@ sanitize_hash(struct cso_hash *hash, enum
>> cso_cache_type type,
>> if (type == CSO_SAMPLER) {
>> int i, j;
>> samplers_to_restore = MALLOC(PIPE_SHADER_TYPES *
>> PIPE_MAX_SAMPLERS *
>> sizeof(*samplers_to_restore));
>> /* Temporarily remove currently bound sampler states from the
>> hash
>> * table, to prevent them from being deleted
>> */
>> for (i = 0; i < PIPE_SHADER_TYPES; i++) {
>> - for (j = 0; j < ctx->samplers[i].nr_samplers; j++) {
>> + for (j = 0; j < PIPE_MAX_SAMPLERS; j++) {
>> struct cso_sampler *sampler =
>> ctx->samplers[i].cso_samplers[j];
>> if (sampler && cso_hash_take(hash, sampler->hash_key))
>> samplers_to_restore[to_restore++] = sampler;
>> }
>> }
>> }
>> iter = cso_hash_first_node(hash);
>> while (to_remove) {
>> @@ -327,20 +331,21 @@ cso_create_context(struct pipe_context *pipe,
>> unsigned u_vbuf_flags)
>> PIPE_SHADER_CAP_SUPPORTED_IRS);
>> if (supported_irs & (1 << PIPE_SHADER_IR_TGSI)) {
>> ctx->has_compute_shader = TRUE;
>> }
>> }
>> if (pipe->screen->get_param(pipe->screen,
>> PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0)
>> {
>> ctx->has_streamout = TRUE;
>> }
>> + ctx->max_sampler_seen = -1;
>> return ctx;
>> out:
>> cso_destroy_context( ctx );
>> return NULL;
>> }
>> /**
>> * Free the CSO context.
>> */
>> @@ -1223,116 +1228,98 @@ cso_single_sampler(struct cso_context *ctx, enum
>> pipe_shader_type shader_stage,
>> FREE(cso);
>> return PIPE_ERROR_OUT_OF_MEMORY;
>> }
>> }
>> else {
>> cso = cso_hash_iter_data(iter);
>> }
>> ctx->samplers[shader_stage].cso_samplers[idx] = cso;
>> ctx->samplers[shader_stage].samplers[idx] = cso->data;
>> - } else {
>> - ctx->samplers[shader_stage].cso_samplers[idx] = NULL;
>> - ctx->samplers[shader_stage].samplers[idx] = NULL;
>> + ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, (int)idx);
>> }
>> return PIPE_OK;
>> }
>> /**
>> * Send staged sampler state to the driver.
>> */
>> void
>> cso_single_sampler_done(struct cso_context *ctx,
>> enum pipe_shader_type shader_stage)
>> {
>> struct sampler_info *info = &ctx->samplers[shader_stage];
>> - const unsigned old_nr_samplers = info->nr_samplers;
>> - unsigned i;
>> - /* find highest non-null sampler */
>> - for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
>> - if (info->samplers[i - 1] != NULL)
>> - break;
>> - }
>> + if (ctx->max_sampler_seen == -1)
>> + return;
>> - info->nr_samplers = i;
>> ctx->pipe->bind_sampler_states(ctx->pipe, shader_stage, 0,
>> - MAX2(old_nr_samplers,
>> info->nr_samplers),
>> + ctx->max_sampler_seen + 1,
>> info->samplers);
>> + ctx->max_sampler_seen = -1;
>> }
>> /*
>> * If the function encouters any errors it will return the
>> * last one. Done to always try to set as many samplers
>> * as possible.
>> */
>> enum pipe_error
>> cso_set_samplers(struct cso_context *ctx,
>> enum pipe_shader_type shader_stage,
>> unsigned nr,
>> const struct pipe_sampler_state **templates)
>> {
>> - struct sampler_info *info = &ctx->samplers[shader_stage];
>> unsigned i;
>> enum pipe_error temp, error = PIPE_OK;
>> for (i = 0; i < nr; i++) {
>> temp = cso_single_sampler(ctx, shader_stage, i, templates[i]);
>> if (temp != PIPE_OK)
>> error = temp;
>> }
>> - for ( ; i < info->nr_samplers; i++) {
>> - temp = cso_single_sampler(ctx, shader_stage, i, NULL);
>> - if (temp != PIPE_OK)
>> - error = temp;
>> - }
>> -
>> cso_single_sampler_done(ctx, shader_stage);
>> return error;
>> }
>> static void
>> cso_save_fragment_samplers(struct cso_context *ctx)
>> {
>> struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT];
>> struct sampler_info *saved = &ctx->fragment_samplers_saved;
>> - saved->nr_samplers = info->nr_samplers;
>> - memcpy(saved->cso_samplers, info->cso_samplers, info->nr_samplers *
>> - sizeof(*info->cso_samplers));
>> - memcpy(saved->samplers, info->samplers, info->nr_samplers *
>> - sizeof(*info->samplers));
>> + memcpy(saved->cso_samplers, info->cso_samplers,
>> + sizeof(info->cso_samplers));
>> + memcpy(saved->samplers, info->samplers, sizeof(info->samplers));
>> }
>> static void
>> cso_restore_fragment_samplers(struct cso_context *ctx)
>> {
>> struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT];
>> struct sampler_info *saved = &ctx->fragment_samplers_saved;
>> - int delta = (int)info->nr_samplers - saved->nr_samplers;
>> memcpy(info->cso_samplers, saved->cso_samplers,
>> - saved->nr_samplers * sizeof(*info->cso_samplers));
>> - memcpy(info->samplers, saved->samplers,
>> - saved->nr_samplers * sizeof(*info->samplers));
>> -
>> - if (delta > 0) {
>> - memset(&info->cso_samplers[saved->nr_samplers], 0,
>> - delta * sizeof(*info->cso_samplers));
>> - memset(&info->samplers[saved->nr_samplers], 0,
>> - delta * sizeof(*info->samplers));
>> + sizeof(info->cso_samplers));
>> + memcpy(info->samplers, saved->samplers, sizeof(info->samplers));
>> +
>> + for (int i = PIPE_MAX_SAMPLERS - 1; i >= 0; i--) {
>> + if (info->samplers[i]) {
>> + ctx->max_sampler_seen = i;
>> + break;
>> + }
>> }
>> cso_single_sampler_done(ctx, PIPE_SHADER_FRAGMENT);
>> }
>> void
>> cso_set_sampler_views(struct cso_context *ctx,
>> enum pipe_shader_type shader_stage,
>> unsigned count,
>>
>
>
> --
> Lerne, wie die Welt wirklich ist,
> Aber vergiss niemals, wie sie sein sollte.
More information about the mesa-dev
mailing list