From 690cc3bb803a933c86a2f6f975e9f49b6edfd7a9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 24 Sep 2021 13:01:16 +1000 Subject: [PATCH] llvmpipe: overhaul fs/cs variant keys to be simpler. These currently always had one sampler state embedded, but got messy when images was 1 and samplers was 0. This should fix some undefined reads seen Fixes: e639e311a1a7 ("llvmpipe/cs: overhaul cs variant key state.") Reviewed-by: Roland Scheidegger Part-of: --- src/gallium/drivers/llvmpipe/lp_linear.c | 5 +-- .../drivers/llvmpipe/lp_linear_fastpath.c | 10 ++++-- src/gallium/drivers/llvmpipe/lp_setup_rect.c | 6 ++-- src/gallium/drivers/llvmpipe/lp_state_cs.c | 14 +++++--- src/gallium/drivers/llvmpipe/lp_state_cs.h | 15 +++++---- src/gallium/drivers/llvmpipe/lp_state_fs.c | 33 +++++++++++-------- src/gallium/drivers/llvmpipe/lp_state_fs.h | 23 +++++++++---- .../drivers/llvmpipe/lp_state_fs_linear.c | 10 ++++-- 8 files changed, 75 insertions(+), 41 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_linear.c b/src/gallium/drivers/llvmpipe/lp_linear.c index 62939a39750..c069f04486e 100644 --- a/src/gallium/drivers/llvmpipe/lp_linear.c +++ b/src/gallium/drivers/llvmpipe/lp_linear.c @@ -175,7 +175,7 @@ lp_fs_linear_run(const struct lp_rast_state *state, if (!lp_linear_init_sampler(&samp[i], tex_info, - &variant->key.samplers[unit], + lp_fs_variant_key_sampler_idx(&variant->key, unit), &state->jit_context.textures[unit], x, y, width, height, a0, dadx, dady)) { @@ -315,7 +315,8 @@ lp_linear_check_variant(struct lp_fragment_shader_variant *variant) goto fail; } - if (!lp_linear_check_sampler(&key->samplers[unit], tex_info)) { + struct lp_sampler_static_state *samp = lp_fs_variant_key_sampler_idx(key, unit); + if (!lp_linear_check_sampler(samp, tex_info)) { if (LP_DEBUG & DEBUG_LINEAR) debug_printf(" -- samp[%d]: check_sampler failed\n", i); goto fail; diff --git a/src/gallium/drivers/llvmpipe/lp_linear_fastpath.c b/src/gallium/drivers/llvmpipe/lp_linear_fastpath.c index b97ea1b88e1..84863dc9e15 100644 --- a/src/gallium/drivers/llvmpipe/lp_linear_fastpath.c +++ b/src/gallium/drivers/llvmpipe/lp_linear_fastpath.c @@ -199,11 +199,15 @@ lp_linear_purple(const struct lp_rast_state *state, boolean lp_linear_check_fastpath(struct lp_fragment_shader_variant *variant) { - enum pipe_format tex_format = variant->key.samplers[0].texture_state.format; + struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(&variant->key, 0); + if (!samp0) + return false; + + enum pipe_format tex_format = samp0->texture_state.format; if (variant->shader->kind == LP_FS_KIND_BLIT_RGBA && tex_format == PIPE_FORMAT_B8G8R8A8_UNORM && - is_nearest_clamp_sampler(&variant->key.samplers[0]) && + is_nearest_clamp_sampler(samp0) && variant->opaque) { variant->jit_linear_blit = lp_linear_blit_rgba_blit; } @@ -212,7 +216,7 @@ lp_linear_check_fastpath(struct lp_fragment_shader_variant *variant) variant->opaque && (tex_format == PIPE_FORMAT_B8G8R8A8_UNORM || tex_format == PIPE_FORMAT_B8G8R8X8_UNORM) && - is_nearest_clamp_sampler(&variant->key.samplers[0])) { + is_nearest_clamp_sampler(samp0)) { variant->jit_linear_blit = lp_linear_blit_rgb1_blit; } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_rect.c b/src/gallium/drivers/llvmpipe/lp_setup_rect.c index 7c1234eafe7..4b1e0cc1a99 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_rect.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_rect.c @@ -173,8 +173,10 @@ lp_setup_is_blit(const struct lp_setup_context *setup, * texture filtering. */ - assert(variant->key.samplers[0].sampler_state.min_img_filter == PIPE_TEX_FILTER_NEAREST); - assert(variant->key.samplers[0].sampler_state.mag_img_filter == PIPE_TEX_FILTER_NEAREST); + ASSERTED struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(&variant->key, 0); + assert(samp0); + assert(samp0->sampler_state.min_img_filter == PIPE_TEX_FILTER_NEAREST); + assert(samp0->sampler_state.mag_img_filter == PIPE_TEX_FILTER_NEAREST); /* * Check for 1:1 match of texels to dest pixels diff --git a/src/gallium/drivers/llvmpipe/lp_state_cs.c b/src/gallium/drivers/llvmpipe/lp_state_cs.c index 4100688223a..c655a5477a9 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_cs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_cs.c @@ -179,7 +179,7 @@ generate_compute(struct llvmpipe_context *lp, builder = gallivm->builder; assert(builder); LLVMPositionBuilderAtEnd(builder, block); - sampler = lp_llvm_sampler_soa_create(key->samplers, key->nr_samplers); + sampler = lp_llvm_sampler_soa_create(lp_cs_variant_key_samplers(key), key->nr_samplers); image = lp_llvm_image_soa_create(lp_cs_variant_key_images(key), key->nr_images); struct lp_build_loop_state loop_state[4]; @@ -578,7 +578,7 @@ make_variant_key(struct llvmpipe_context *lp, int i; struct lp_compute_shader_variant_key *key; key = (struct lp_compute_shader_variant_key *)store; - memset(key, 0, offsetof(struct lp_compute_shader_variant_key, samplers[1])); + memset(key, 0, sizeof(*key)); /* This value will be the same for all the variants of a given shader: */ @@ -586,7 +586,9 @@ make_variant_key(struct llvmpipe_context *lp, struct lp_sampler_static_state *cs_sampler; - cs_sampler = key->samplers; + cs_sampler = lp_cs_variant_key_samplers(key); + + memset(cs_sampler, 0, MAX2(key->nr_samplers, key->nr_sampler_views) * sizeof *cs_sampler); for(i = 0; i < key->nr_samplers; ++i) { if(shader->info.base.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) { lp_sampler_static_sampler_state(&cs_sampler[i].sampler_state, @@ -642,7 +644,8 @@ dump_cs_variant_key(const struct lp_compute_shader_variant_key *key) debug_printf("cs variant %p:\n", (void *) key); for (i = 0; i < key->nr_samplers; ++i) { - const struct lp_static_sampler_state *sampler = &key->samplers[i].sampler_state; + const struct lp_sampler_static_state *samplers = lp_cs_variant_key_samplers(key); + const struct lp_static_sampler_state *sampler = &samplers[i].sampler_state; debug_printf("sampler[%u] = \n", i); debug_printf(" .wrap = %s %s %s\n", util_str_tex_wrap(sampler->wrap_s, TRUE), @@ -664,7 +667,8 @@ dump_cs_variant_key(const struct lp_compute_shader_variant_key *key) debug_printf(" .aniso = %u\n", sampler->aniso); } for (i = 0; i < key->nr_sampler_views; ++i) { - const struct lp_static_texture_state *texture = &key->samplers[i].texture_state; + const struct lp_sampler_static_state *samplers = lp_cs_variant_key_samplers(key); + const struct lp_static_texture_state *texture = &samplers[i].texture_state; debug_printf("texture[%u] = \n", i); debug_printf(" .format = %s\n", util_format_name(texture->format)); diff --git a/src/gallium/drivers/llvmpipe/lp_state_cs.h b/src/gallium/drivers/llvmpipe/lp_state_cs.h index 61267aadf09..8b578424b44 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_cs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_cs.h @@ -42,29 +42,32 @@ struct lp_compute_shader_variant_key unsigned nr_samplers:8; unsigned nr_sampler_views:8; unsigned nr_images:8; - /* followed by variable number of images */ - struct lp_sampler_static_state samplers[1]; }; #define LP_CS_MAX_VARIANT_KEY_SIZE \ (sizeof(struct lp_compute_shader_variant_key) + \ - PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct lp_sampler_static_state) +\ + PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct lp_sampler_static_state) + \ PIPE_MAX_SHADER_IMAGES * sizeof(struct lp_image_static_state)) static inline size_t lp_cs_variant_key_size(unsigned nr_samplers, unsigned nr_images) { - unsigned samplers = nr_samplers > 1 ? (nr_samplers - 1) : 0; return (sizeof(struct lp_compute_shader_variant_key) + - samplers * sizeof(struct lp_sampler_static_state) + + nr_samplers * sizeof(struct lp_sampler_static_state) + nr_images * sizeof(struct lp_image_static_state)); } +static inline struct lp_sampler_static_state * +lp_cs_variant_key_samplers(const struct lp_compute_shader_variant_key *key) +{ + return (struct lp_sampler_static_state *)&(key[1]); +} + static inline struct lp_image_static_state * lp_cs_variant_key_images(const struct lp_compute_shader_variant_key *key) { return (struct lp_image_static_state *) - &key->samplers[key->nr_samplers]; + &(lp_cs_variant_key_samplers(key)[key->nr_samplers]); } struct lp_cs_variant_list_item diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 23416b958e3..197c60f7e04 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -3158,7 +3158,7 @@ generate_fragment(struct llvmpipe_context *lp, } /* code generated texture sampling */ - sampler = lp_llvm_sampler_soa_create(key->samplers, key->nr_samplers); + sampler = lp_llvm_sampler_soa_create(lp_fs_variant_key_samplers(key), key->nr_samplers); image = lp_llvm_image_soa_create(lp_fs_variant_key_images(key), key->nr_images); num_fs = 16 / fs_type.length; /* number of loops per 4x4 stamp */ @@ -3432,7 +3432,8 @@ dump_fs_variant_key(struct lp_fragment_shader_variant_key *key) debug_printf("blend.alpha_to_coverage is enabled\n"); } for (i = 0; i < key->nr_samplers; ++i) { - const struct lp_static_sampler_state *sampler = &key->samplers[i].sampler_state; + const struct lp_sampler_static_state *samplers = lp_fs_variant_key_samplers(key); + const struct lp_static_sampler_state *sampler = &samplers[i].sampler_state; debug_printf("sampler[%u] = \n", i); debug_printf(" .wrap = %s %s %s\n", util_str_tex_wrap(sampler->wrap_s, TRUE), @@ -3455,7 +3456,8 @@ dump_fs_variant_key(struct lp_fragment_shader_variant_key *key) debug_printf(" .aniso = %u\n", sampler->aniso); } for (i = 0; i < key->nr_sampler_views; ++i) { - const struct lp_static_texture_state *texture = &key->samplers[i].texture_state; + const struct lp_sampler_static_state *samplers = lp_fs_variant_key_samplers(key); + const struct lp_static_texture_state *texture = &samplers[i].texture_state; debug_printf("texture[%u] = \n", i); debug_printf(" .format = %s\n", util_format_name(texture->format)); @@ -3645,15 +3647,16 @@ generate_variant(struct llvmpipe_context *lp, shader->kind == LP_FS_KIND_BLIT_RGB1)) { unsigned target, min_img_filter, mag_img_filter, min_mip_filter; enum pipe_format texture_format; - - texture_format = key->samplers[0].texture_state.format; - target = key->samplers[0].texture_state.target; - min_img_filter = key->samplers[0].sampler_state.min_img_filter; - mag_img_filter = key->samplers[0].sampler_state.mag_img_filter; - if (key->samplers[0].texture_state.level_zero_only) { + struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(key, 0); + assert(samp0); + texture_format = samp0->texture_state.format; + target = samp0->texture_state.target; + min_img_filter = samp0->sampler_state.min_img_filter; + mag_img_filter = samp0->sampler_state.mag_img_filter; + if (samp0->texture_state.level_zero_only) { min_mip_filter = PIPE_TEX_MIPFILTER_NONE; } else { - min_mip_filter = key->samplers[0].sampler_state.min_mip_filter; + min_mip_filter = samp0->sampler_state.min_mip_filter; } if (target == PIPE_TEXTURE_2D && @@ -4138,7 +4141,7 @@ make_variant_key(struct llvmpipe_context *lp, key = (struct lp_fragment_shader_variant_key *)store; - memset(key, 0, offsetof(struct lp_fragment_shader_variant_key, samplers[1])); + memset(key, 0, sizeof(*key)); if (lp->framebuffer.zsbuf) { enum pipe_format zsbuf_format = lp->framebuffer.zsbuf->format; @@ -4283,7 +4286,7 @@ make_variant_key(struct llvmpipe_context *lp, struct lp_sampler_static_state *fs_sampler; - fs_sampler = key->samplers; + fs_sampler = lp_fs_variant_key_samplers(key); memset(fs_sampler, 0, MAX2(key->nr_samplers, key->nr_sampler_views) * sizeof *fs_sampler); @@ -4334,8 +4337,10 @@ make_variant_key(struct llvmpipe_context *lp, } if (shader->kind == LP_FS_KIND_AERO_MINIFICATION) { - key->samplers[0].sampler_state.min_img_filter = PIPE_TEX_FILTER_NEAREST; - key->samplers[0].sampler_state.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(key, 0); + assert(samp0); + samp0->sampler_state.min_img_filter = PIPE_TEX_FILTER_NEAREST; + samp0->sampler_state.mag_img_filter = PIPE_TEX_FILTER_NEAREST; } return key; diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h index 9f43665d839..f88ef70dbd2 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h @@ -111,9 +111,7 @@ struct lp_fragment_shader_variant_key uint8_t zsbuf_nr_samples; uint8_t coverage_samples; uint8_t min_samples; - - struct lp_sampler_static_state samplers[1]; - /* followed by variable number of images */ + /* followed by variable number of samplers + images */ }; #define LP_FS_MAX_VARIANT_KEY_SIZE \ @@ -124,17 +122,30 @@ struct lp_fragment_shader_variant_key static inline size_t lp_fs_variant_key_size(unsigned nr_samplers, unsigned nr_images) { - unsigned samplers = nr_samplers > 1 ? (nr_samplers - 1) : 0; return (sizeof(struct lp_fragment_shader_variant_key) + - samplers * sizeof(struct lp_sampler_static_state) + + nr_samplers * sizeof(struct lp_sampler_static_state) + nr_images * sizeof(struct lp_image_static_state)); } +static inline struct lp_sampler_static_state * +lp_fs_variant_key_samplers(const struct lp_fragment_shader_variant_key *key) +{ + return (struct lp_sampler_static_state *)&(key[1]); +} + +static inline struct lp_sampler_static_state * +lp_fs_variant_key_sampler_idx(const struct lp_fragment_shader_variant_key *key, int idx) +{ + if (idx >= key->nr_samplers) + return NULL; + return &lp_fs_variant_key_samplers(key)[idx]; +} + static inline struct lp_image_static_state * lp_fs_variant_key_images(struct lp_fragment_shader_variant_key *key) { return (struct lp_image_static_state *) - &key->samplers[key->nr_samplers]; + &(lp_fs_variant_key_samplers(key)[key->nr_samplers]); } /** doubly-linked list item */ diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs_linear.c b/src/gallium/drivers/llvmpipe/lp_state_fs_linear.c index a8d10ae300d..fb710701b16 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs_linear.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs_linear.c @@ -667,16 +667,20 @@ is_one_inv_src_alpha_blend(const struct lp_fragment_shader_variant *variant) void llvmpipe_fs_variant_linear_fastpath(struct lp_fragment_shader_variant *variant) { - enum pipe_format tex_format = variant->key.samplers[0].texture_state.format; + struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(&variant->key, 0); if (LP_PERF & PERF_NO_SHADE) { variant->jit_linear = linear_red; return; } + if (!samp0) + return; + + enum pipe_format tex_format = samp0->texture_state.format; if (variant->shader->kind == LP_FS_KIND_BLIT_RGBA && tex_format == PIPE_FORMAT_B8G8R8A8_UNORM && - is_nearest_clamp_sampler(&variant->key.samplers[0])) { + is_nearest_clamp_sampler(samp0)) { if (variant->opaque) { variant->jit_linear_blit = blit_rgba_blit; variant->jit_linear = blit_rgba; @@ -692,7 +696,7 @@ llvmpipe_fs_variant_linear_fastpath(struct lp_fragment_shader_variant *variant) variant->opaque && (tex_format == PIPE_FORMAT_B8G8R8A8_UNORM || tex_format == PIPE_FORMAT_B8G8R8X8_UNORM) && - is_nearest_clamp_sampler(&variant->key.samplers[0])) { + is_nearest_clamp_sampler(samp0)) { variant->jit_linear_blit = blit_rgb1_blit; variant->jit_linear = blit_rgb1; return;