diff --git a/src/broadcom/compiler/v3d_nir_lower_image_load_store.c b/src/broadcom/compiler/v3d_nir_lower_image_load_store.c index 2706432d5ef..6b459e1afa9 100644 --- a/src/broadcom/compiler/v3d_nir_lower_image_load_store.c +++ b/src/broadcom/compiler/v3d_nir_lower_image_load_store.c @@ -88,6 +88,7 @@ static void v3d_nir_lower_image_store(nir_builder *b, nir_intrinsic_instr *instr) { enum pipe_format format = nir_intrinsic_format(instr); + assert(format != PIPE_FORMAT_NONE); const struct util_format_description *desc = util_format_description(format); const struct util_format_channel_description *r_chan = &desc->channel[0]; diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 4f2a02054b4..9a2be69d709 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -326,6 +326,13 @@ struct st_context void *vs; void *gs; void *upload_fs[5][2]; + /** + * For drivers supporting formatless storing + * (PIPE_CAP_IMAGE_STORE_FORMATTED) it is a pointer to the download FS; + * for those not supporting it, it is a pointer to an array of + * PIPE_FORMAT_COUNT elements, where each element is a pointer to the + * download FS using that PIPE_FORMAT as the storing format. + */ void *download_fs[5][PIPE_MAX_TEXTURE_TYPES][2]; struct hash_table *shaders; bool upload_enabled; diff --git a/src/mesa/state_tracker/st_pbo.c b/src/mesa/state_tracker/st_pbo.c index a3fb0e65208..51a29e8bcfa 100644 --- a/src/mesa/state_tracker/st_pbo.c +++ b/src/mesa/state_tracker/st_pbo.c @@ -33,6 +33,7 @@ #include "state_tracker/st_pbo.h" #include "state_tracker/st_cb_bufferobjects.h" +#include "main/context.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -407,6 +408,7 @@ static void * create_fs(struct st_context *st, bool download, enum pipe_texture_target target, enum st_pbo_conversion conversion, + enum pipe_format format, bool need_layer) { struct pipe_screen *screen = st->screen; @@ -552,6 +554,7 @@ create_fs(struct st_context *st, bool download, img_var->data.access = ACCESS_NON_READABLE; img_var->data.explicit_binding = true; img_var->data.binding = 0; + img_var->data.image.format = format; nir_deref_instr *img_deref = nir_build_deref_var(&b, img_var); nir_image_deref_store(&b, &img_deref->dest.ssa, @@ -601,7 +604,7 @@ st_pbo_get_upload_fs(struct st_context *st, enum st_pbo_conversion conversion = get_pbo_conversion(src_format, dst_format); if (!st->pbo.upload_fs[conversion][need_layer]) - st->pbo.upload_fs[conversion][need_layer] = create_fs(st, false, 0, conversion, need_layer); + st->pbo.upload_fs[conversion][need_layer] = create_fs(st, false, 0, conversion, PIPE_FORMAT_NONE, need_layer); return st->pbo.upload_fs[conversion][need_layer]; } @@ -615,12 +618,26 @@ st_pbo_get_download_fs(struct st_context *st, enum pipe_texture_target target, STATIC_ASSERT(ARRAY_SIZE(st->pbo.download_fs) == ST_NUM_PBO_CONVERSIONS); assert(target < PIPE_MAX_TEXTURE_TYPES); + struct pipe_screen *screen = st->screen; enum st_pbo_conversion conversion = get_pbo_conversion(src_format, dst_format); + bool formatless_store = screen->get_param(screen, PIPE_CAP_IMAGE_STORE_FORMATTED); - if (!st->pbo.download_fs[conversion][target][need_layer]) - st->pbo.download_fs[conversion][target][need_layer] = create_fs(st, true, target, conversion, need_layer); + /* For drivers not supporting formatless storing, download FS is stored in an + * indirect dynamically allocated array of storing formats. + */ + if (!formatless_store && !st->pbo.download_fs[conversion][target][need_layer]) + st->pbo.download_fs[conversion][target][need_layer] = calloc(sizeof(void *), PIPE_FORMAT_COUNT); - return st->pbo.download_fs[conversion][target][need_layer]; + if (formatless_store) { + if (!st->pbo.download_fs[conversion][target][need_layer]) + st->pbo.download_fs[conversion][target][need_layer] = create_fs(st, true, target, conversion, PIPE_FORMAT_NONE, need_layer); + return st->pbo.download_fs[conversion][target][need_layer]; + } else { + void **fs_array = (void **)st->pbo.download_fs[conversion][target][need_layer]; + if (!fs_array[dst_format]) + fs_array[dst_format] = create_fs(st, true, target, conversion, dst_format, need_layer); + return fs_array[dst_format]; + } } void @@ -675,6 +692,8 @@ st_init_pbo_helpers(struct st_context *st) void st_destroy_pbo_helpers(struct st_context *st) { + struct pipe_screen *screen = st->screen; + bool formatless_store = screen->get_param(screen, PIPE_CAP_IMAGE_STORE_FORMATTED); unsigned i; for (i = 0; i < ARRAY_SIZE(st->pbo.upload_fs); ++i) { @@ -690,7 +709,15 @@ st_destroy_pbo_helpers(struct st_context *st) for (unsigned j = 0; j < ARRAY_SIZE(st->pbo.download_fs[0]); ++j) { for (unsigned k = 0; k < ARRAY_SIZE(st->pbo.download_fs[0][0]); k++) { if (st->pbo.download_fs[i][j][k]) { - st->pipe->delete_fs_state(st->pipe, st->pbo.download_fs[i][j][k]); + if (formatless_store) { + st->pipe->delete_fs_state(st->pipe, st->pbo.download_fs[i][j][k]); + } else { + void **fs_array = (void **)st->pbo.download_fs[i][j][k]; + for (unsigned l = 0; l < PIPE_FORMAT_COUNT; l++) + if (fs_array[l]) + st->pipe->delete_fs_state(st->pipe, fs_array[l]); + free(st->pbo.download_fs[i][j][k]); + } st->pbo.download_fs[i][j][k] = NULL; } }