From: Dave Airlie Date: Wed, 18 Jul 2018 02:54:30 +0000 (+1000) Subject: virgl: add initial images support (v2) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=452eea140d909db6d10101914dff0e1274acc1e0;p=mesa.git virgl: add initial images support (v2) v2: add max image samples support Reviwed-by: Gert Wollny --- diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index 74b232fe6cf..41ba853805b 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -182,6 +182,20 @@ static void virgl_attach_res_shader_buffers(struct virgl_context *vctx, } } +static void virgl_attach_res_shader_images(struct virgl_context *vctx, + enum pipe_shader_type shader_type) +{ + struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; + struct virgl_resource *res; + unsigned i; + for (i = 0; i < PIPE_MAX_SHADER_IMAGES; i++) { + res = virgl_resource(vctx->images[shader_type][i]); + if (res) { + vws->emit_res(vws, vctx->cbuf, res->hw_res, FALSE); + } + } +} + /* * after flushing, the hw context still has a bunch of * resources bound, so we need to rebind those here. @@ -198,6 +212,7 @@ static void virgl_reemit_res(struct virgl_context *vctx) virgl_attach_res_sampler_views(vctx, shader_type); virgl_attach_res_uniform_buffers(vctx, shader_type); virgl_attach_res_shader_buffers(vctx, shader_type); + virgl_attach_res_shader_images(vctx, shader_type); } virgl_attach_res_vertex_buffers(vctx); virgl_attach_res_so_targets(vctx); @@ -954,6 +969,34 @@ static void virgl_set_shader_buffers(struct pipe_context *ctx, virgl_encode_set_shader_buffers(vctx, shader, start_slot, count, buffers); } +static void virgl_set_shader_images(struct pipe_context *ctx, + enum pipe_shader_type shader, + unsigned start_slot, unsigned count, + const struct pipe_image_view *images) +{ + struct virgl_context *vctx = virgl_context(ctx); + struct virgl_screen *rs = virgl_screen(ctx->screen); + + for (unsigned i = 0; i < count; i++) { + unsigned idx = start_slot + i; + + if (images) { + if (images[i].resource) { + pipe_resource_reference(&vctx->images[shader][idx], images[i].resource); + continue; + } + } + pipe_resource_reference(&vctx->images[shader][idx], NULL); + } + + uint32_t max_shader_images = shader == PIPE_SHADER_FRAGMENT ? + rs->caps.caps.v2.max_shader_image_frag_compute : + rs->caps.caps.v2.max_shader_image_other_stages; + if (!max_shader_images) + return; + virgl_encode_set_shader_images(vctx, shader, start_slot, count, images); +} + static void virgl_context_destroy( struct pipe_context *ctx ) { @@ -1092,6 +1135,7 @@ struct pipe_context *virgl_context_create(struct pipe_screen *pscreen, vctx->base.blit = virgl_blit; vctx->base.set_shader_buffers = virgl_set_shader_buffers; + vctx->base.set_shader_images = virgl_set_shader_images; virgl_init_context_resource_functions(&vctx->base); virgl_init_query_functions(vctx); virgl_init_so_functions(vctx); diff --git a/src/gallium/drivers/virgl/virgl_context.h b/src/gallium/drivers/virgl/virgl_context.h index 5747654ea82..38d1f450e17 100644 --- a/src/gallium/drivers/virgl/virgl_context.h +++ b/src/gallium/drivers/virgl/virgl_context.h @@ -70,6 +70,7 @@ struct virgl_context { struct pipe_resource *ubos[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; struct pipe_resource *ssbos[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; + struct pipe_resource *images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; int num_transfers; int num_draws; struct list_head to_flush_bufs; diff --git a/src/gallium/drivers/virgl/virgl_encode.c b/src/gallium/drivers/virgl/virgl_encode.c index b09366dcee6..68ec5a1dc9d 100644 --- a/src/gallium/drivers/virgl/virgl_encode.c +++ b/src/gallium/drivers/virgl/virgl_encode.c @@ -943,3 +943,32 @@ int virgl_encode_set_shader_buffers(struct virgl_context *ctx, } return 0; } + +int virgl_encode_set_shader_images(struct virgl_context *ctx, + enum pipe_shader_type shader, + unsigned start_slot, unsigned count, + const struct pipe_image_view *images) +{ + int i; + virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_SET_SHADER_IMAGES, 0, VIRGL_SET_SHADER_IMAGE_SIZE(count))); + + virgl_encoder_write_dword(ctx->cbuf, shader); + virgl_encoder_write_dword(ctx->cbuf, start_slot); + for (i = 0; i < count; i++) { + if (images) { + struct virgl_resource *res = virgl_resource(images[i].resource); + virgl_encoder_write_dword(ctx->cbuf, images[i].format); + virgl_encoder_write_dword(ctx->cbuf, images[i].access); + virgl_encoder_write_dword(ctx->cbuf, images[i].u.buf.offset); + virgl_encoder_write_dword(ctx->cbuf, images[i].u.buf.size); + virgl_encoder_write_res(ctx, res); + } else { + virgl_encoder_write_dword(ctx->cbuf, 0); + virgl_encoder_write_dword(ctx->cbuf, 0); + virgl_encoder_write_dword(ctx->cbuf, 0); + virgl_encoder_write_dword(ctx->cbuf, 0); + virgl_encoder_write_dword(ctx->cbuf, 0); + } + } + return 0; +} diff --git a/src/gallium/drivers/virgl/virgl_encode.h b/src/gallium/drivers/virgl/virgl_encode.h index 3221fcbcd0c..a45c0ac4c6b 100644 --- a/src/gallium/drivers/virgl/virgl_encode.h +++ b/src/gallium/drivers/virgl/virgl_encode.h @@ -263,4 +263,8 @@ int virgl_encode_set_shader_buffers(struct virgl_context *ctx, enum pipe_shader_type shader, unsigned start_slot, unsigned count, const struct pipe_shader_buffer *buffers); +int virgl_encode_set_shader_images(struct virgl_context *ctx, + enum pipe_shader_type shader, + unsigned start_slot, unsigned count, + const struct pipe_image_view *images); #endif diff --git a/src/gallium/drivers/virgl/virgl_hw.h b/src/gallium/drivers/virgl/virgl_hw.h index 4469515dd12..aa6d8f8fe4b 100644 --- a/src/gallium/drivers/virgl/virgl_hw.h +++ b/src/gallium/drivers/virgl/virgl_hw.h @@ -307,6 +307,9 @@ struct virgl_caps_v2 { uint32_t max_vertex_attrib_stride; uint32_t max_shader_buffer_frag_compute; uint32_t max_shader_buffer_other_stages; + uint32_t max_shader_image_frag_compute; + uint32_t max_shader_image_other_stages; + uint32_t max_image_samples; }; union virgl_caps { diff --git a/src/gallium/drivers/virgl/virgl_protocol.h b/src/gallium/drivers/virgl/virgl_protocol.h index 51c350112ad..cdd534ff243 100644 --- a/src/gallium/drivers/virgl/virgl_protocol.h +++ b/src/gallium/drivers/virgl/virgl_protocol.h @@ -87,6 +87,7 @@ enum virgl_context_cmd { VIRGL_CCMD_SET_TESS_STATE, VIRGL_CCMD_SET_MIN_SAMPLES, VIRGL_CCMD_SET_SHADER_BUFFERS, + VIRGL_CCMD_SET_SHADER_IMAGES, }; /* @@ -501,4 +502,15 @@ enum virgl_context_cmd { #define VIRGL_SET_SHADER_BUFFER_LENGTH(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 4) #define VIRGL_SET_SHADER_BUFFER_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 5) +/* set shader images */ +#define VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE 5 +#define VIRGL_SET_SHADER_IMAGE_SIZE(x) (VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE * (x)) + 2 +#define VIRGL_SET_SHADER_IMAGE_SHADER_TYPE 1 +#define VIRGL_SET_SHADER_IMAGE_START_SLOT 2 +#define VIRGL_SET_SHADER_IMAGE_FORMAT(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 3) +#define VIRGL_SET_SHADER_IMAGE_ACCESS(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 4) +#define VIRGL_SET_SHADER_IMAGE_LAYER_OFFSET(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 5) +#define VIRGL_SET_SHADER_IMAGE_LEVEL_SIZE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 6) +#define VIRGL_SET_SHADER_IMAGE_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 7) + #endif diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c index 18b636b869f..1c94603a2dc 100644 --- a/src/gallium/drivers/virgl/virgl_screen.c +++ b/src/gallium/drivers/virgl/virgl_screen.c @@ -375,6 +375,11 @@ virgl_get_shader_param(struct pipe_screen *screen, return vscreen->caps.caps.v2.max_shader_buffer_frag_compute; else return vscreen->caps.caps.v2.max_shader_buffer_other_stages; + case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: + if (shader == PIPE_SHADER_FRAGMENT) + return vscreen->caps.caps.v2.max_shader_image_frag_compute; + else + return vscreen->caps.caps.v2.max_shader_image_other_stages; case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD: case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS: case PIPE_SHADER_CAP_INT64_ATOMICS: @@ -494,6 +499,12 @@ virgl_is_format_supported( struct pipe_screen *screen, if (sample_count > 1) { if (!vscreen->caps.caps.v1.bset.texture_multisample) return FALSE; + + if (bind & PIPE_BIND_SHADER_IMAGE) { + if (sample_count > vscreen->caps.caps.v2.max_image_samples) + return FALSE; + } + if (sample_count > vscreen->caps.caps.v1.max_samples) return FALSE; } diff --git a/src/gallium/drivers/virgl/virgl_winsys.h b/src/gallium/drivers/virgl/virgl_winsys.h index 6346c21fafc..315ca55f954 100644 --- a/src/gallium/drivers/virgl/virgl_winsys.h +++ b/src/gallium/drivers/virgl/virgl_winsys.h @@ -137,5 +137,6 @@ static inline void virgl_ws_fill_new_caps_defaults(struct virgl_drm_caps *caps) caps->caps.v2.shader_buffer_offset_alignment = 32; caps->caps.v2.capability_bits = 0; caps->caps.v2.max_vertex_attrib_stride = 0; + caps->caps.v2.max_image_samples = 0; } #endif