From 0b51e73de22456c2d2b9dd7c643c14678594059c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 27 Aug 2019 15:28:13 +1000 Subject: [PATCH] llvmpipe: add compute shader images support Reviewed-by: Roland Scheidegger --- src/gallium/drivers/llvmpipe/lp_state.h | 1 + src/gallium/drivers/llvmpipe/lp_state_cs.c | 101 +++++++++++++++++++++ src/gallium/drivers/llvmpipe/lp_state_cs.h | 6 ++ src/gallium/drivers/llvmpipe/lp_state_fs.c | 4 +- 4 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index be7eeec811e..a14ed06f711 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -64,6 +64,7 @@ #define LP_CSNEW_SAMPLER 0x4 #define LP_CSNEW_SAMPLER_VIEW 0x8 #define LP_CSNEW_SSBOS 0x10 +#define LP_CSNEW_IMAGES 0x20 struct vertex_info; struct pipe_context; diff --git a/src/gallium/drivers/llvmpipe/lp_state_cs.c b/src/gallium/drivers/llvmpipe/lp_state_cs.c index 43760852826..a04313891f3 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_cs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_cs.c @@ -70,6 +70,7 @@ generate_compute(struct llvmpipe_context *lp, LLVMBasicBlockRef block; LLVMBuilderRef builder; struct lp_build_sampler_soa *sampler; + struct lp_build_image_soa *image; LLVMValueRef function, coro; struct lp_type cs_type; unsigned i; @@ -156,6 +157,7 @@ generate_compute(struct llvmpipe_context *lp, assert(builder); LLVMPositionBuilderAtEnd(builder, block); sampler = lp_llvm_sampler_soa_create(key->state); + image = lp_llvm_image_soa_create(key->image_state); struct lp_build_loop_state loop_state[4]; LLVMValueRef num_x_loop; @@ -353,6 +355,7 @@ generate_compute(struct llvmpipe_context *lp, params.info = &shader->info.base; params.ssbo_ptr = ssbo_ptr; params.ssbo_sizes_ptr = num_ssbo_ptr; + params.image = image; params.shared_ptr = shared_ptr; params.coro = &coro_info; @@ -373,6 +376,7 @@ generate_compute(struct llvmpipe_context *lp, } sampler->destroy(sampler); + image->destroy(image); gallivm_verify_function(gallivm, coro); gallivm_verify_function(gallivm, function); @@ -513,6 +517,13 @@ make_variant_key(struct llvmpipe_context *lp, } } + key->nr_images = shader->info.base.file_max[TGSI_FILE_IMAGE] + 1; + for (i = 0; i < key->nr_images; ++i) { + if (shader->info.base.file_mask[TGSI_FILE_IMAGE] & (1 << i)) { + lp_sampler_static_texture_state_image(&key->image_state[i].image_state, + &lp->images[PIPE_SHADER_COMPUTE][i]); + } + } } static void @@ -556,6 +567,20 @@ dump_cs_variant_key(const struct lp_compute_shader_variant_key *key) texture->pot_height, texture->pot_depth); } + for (i = 0; i < key->nr_images; ++i) { + const struct lp_static_texture_state *image = &key->image_state[i].image_state; + debug_printf("image[%u] = \n", i); + debug_printf(" .format = %s\n", + util_format_name(image->format)); + debug_printf(" .target = %s\n", + util_str_tex_target(image->target, TRUE)); + debug_printf(" .level_zero_only = %u\n", + image->level_zero_only); + debug_printf(" .pot = %u %u %u\n", + image->pot_width, + image->pot_height, + image->pot_depth); + } } static void @@ -923,6 +948,76 @@ lp_csctx_set_cs_ssbos(struct lp_cs_context *csctx, } } +static void +lp_csctx_set_cs_images(struct lp_cs_context *csctx, + unsigned num, + struct pipe_image_view *images) +{ + unsigned i; + + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) images); + + assert(num <= ARRAY_SIZE(csctx->images)); + + for (i = 0; i < num; ++i) { + struct pipe_image_view *image = &images[i]; + util_copy_image_view(&csctx->images[i].current, &images[i]); + + struct pipe_resource *res = image->resource; + struct llvmpipe_resource *lp_res = llvmpipe_resource(res); + struct lp_jit_image *jit_image; + + jit_image = &csctx->cs.current.jit_context.images[i]; + if (!lp_res) + continue; + if (!lp_res->dt) { + /* regular texture - csctx array of mipmap level offsets */ + if (llvmpipe_resource_is_texture(res)) { + jit_image->base = lp_res->tex_data; + } else + jit_image->base = lp_res->data; + + jit_image->width = res->width0; + jit_image->height = res->height0; + jit_image->depth = res->depth0; + + if (llvmpipe_resource_is_texture(res)) { + uint32_t mip_offset = lp_res->mip_offsets[image->u.tex.level]; + + jit_image->width = u_minify(jit_image->width, image->u.tex.level); + jit_image->height = u_minify(jit_image->height, image->u.tex.level); + + if (res->target == PIPE_TEXTURE_1D_ARRAY || + res->target == PIPE_TEXTURE_2D_ARRAY || + res->target == PIPE_TEXTURE_3D || + res->target == PIPE_TEXTURE_CUBE || + res->target == PIPE_TEXTURE_CUBE_ARRAY) { + /* + * For array textures, we don't have first_layer, instead + * adjust last_layer (stored as depth) plus the mip level offsets + * (as we have mip-first layout can't just adjust base ptr). + * XXX For mip levels, could do something similar. + */ + jit_image->depth = image->u.tex.last_layer - image->u.tex.first_layer + 1; + mip_offset += image->u.tex.first_layer * lp_res->img_stride[image->u.tex.level]; + } else + jit_image->depth = u_minify(jit_image->depth, image->u.tex.level); + + jit_image->row_stride = lp_res->row_stride[image->u.tex.level]; + jit_image->img_stride = lp_res->img_stride[image->u.tex.level]; + jit_image->base = (uint8_t *)jit_image->base + mip_offset; + } else { + unsigned view_blocksize = util_format_get_blocksize(image->format); + jit_image->width = image->u.buf.size / view_blocksize; + jit_image->base = (uint8_t *)jit_image->base + image->u.buf.offset; + } + } + } + for (; i < ARRAY_SIZE(csctx->images); i++) { + util_copy_image_view(&csctx->images[i].current, NULL); + } +} + static void update_csctx_consts(struct llvmpipe_context *llvmpipe) { @@ -1008,6 +1103,12 @@ llvmpipe_cs_update_derived(struct llvmpipe_context *llvmpipe) lp_csctx_set_sampler_state(llvmpipe->csctx, llvmpipe->num_samplers[PIPE_SHADER_COMPUTE], llvmpipe->samplers[PIPE_SHADER_COMPUTE]); + + if (llvmpipe->cs_dirty & LP_CSNEW_IMAGES) + lp_csctx_set_cs_images(llvmpipe->csctx, + ARRAY_SIZE(llvmpipe->images[PIPE_SHADER_COMPUTE]), + llvmpipe->images[PIPE_SHADER_COMPUTE]); + llvmpipe->cs_dirty = 0; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_cs.h b/src/gallium/drivers/llvmpipe/lp_state_cs.h index fd72950a927..481a129ab6e 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_cs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_cs.h @@ -41,6 +41,8 @@ struct lp_compute_shader_variant_key { unsigned nr_samplers:8; unsigned nr_sampler_views:8; + unsigned nr_images:8; + struct lp_image_static_state image_state[PIPE_MAX_SHADER_IMAGES]; struct lp_sampler_static_state state[PIPE_MAX_SHADER_SAMPLER_VIEWS]; }; @@ -111,6 +113,10 @@ struct lp_cs_context { struct { struct pipe_shader_buffer current; } ssbos[LP_MAX_TGSI_SHADER_BUFFERS]; + + struct { + struct pipe_image_view current; + } images[LP_MAX_TGSI_SHADER_IMAGES]; }; struct lp_cs_context *lp_csctx_create(struct pipe_context *pipe); diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 91dee27deba..20d46f8af90 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -3233,7 +3233,9 @@ llvmpipe_set_shader_images(struct pipe_context *pipe, shader, llvmpipe->images[shader], start_slot + count); - } else + } else if (shader == PIPE_SHADER_COMPUTE) + llvmpipe->cs_dirty |= LP_CSNEW_IMAGES; + else llvmpipe->dirty |= LP_NEW_FS_IMAGES; } -- 2.30.2