[virglrenderer-devel] [PATCH 2/3] renderer: Add support for TGSI_FILE_HW_ATOMIC
Tomeu Vizoso
tomeu.vizoso at collabora.com
Thu Jul 19 13:41:41 UTC 2018
Add support for TGSI's HW atomic counters, implemented here with
atomic_uint.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
---
src/virgl_hw.h | 2 ++
src/virgl_protocol.h | 8 +++++++
src/vrend_decode.c | 29 ++++++++++++++++++++++
src/vrend_renderer.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
src/vrend_renderer.h | 4 ++++
5 files changed, 100 insertions(+)
diff --git a/src/virgl_hw.h b/src/virgl_hw.h
index 1ca49c772fa1..c8deca90431a 100644
--- a/src/virgl_hw.h
+++ b/src/virgl_hw.h
@@ -320,6 +320,8 @@ struct virgl_caps_v2 {
uint32_t max_compute_shared_memory_size;
uint32_t max_ssbo;
uint32_t max_images;
+ uint32_t max_atomic_counters;
+ uint32_t max_atomic_counter_buffers;
};
union virgl_caps {
diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h
index 53a36588879e..8dc33ea734cf 100644
--- a/src/virgl_protocol.h
+++ b/src/virgl_protocol.h
@@ -87,6 +87,7 @@ enum virgl_context_cmd {
VIRGL_CCMD_SET_MIN_SAMPLES,
VIRGL_CCMD_SET_SHADER_IMAGES,
VIRGL_CCMD_SET_SHADER_BUFFERS,
+ VIRGL_CCMD_SET_ATOMIC_BUFFERS,
VIRGL_CCMD_MEMORY_BARRIER,
VIRGL_CCMD_LAUNCH_GRID,
VIRGL_CCMD_GET_QUERY_RESULT_QBO,
@@ -506,6 +507,13 @@ enum virgl_context_cmd {
#define VIRGL_SET_SHADER_IMAGE_LEVEL_SIZE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 5)
#define VIRGL_SET_SHADER_IMAGE_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 6)
+#define VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE 3
+#define VIRGL_SET_ATOMIC_BUFFER_SIZE(x) (VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE * (x)) + 1
+#define VIRGL_SET_ATOMIC_BUFFER_START_SLOT 1
+#define VIRGL_SET_ATOMIC_BUFFER_OFFSET(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 2)
+#define VIRGL_SET_ATOMIC_BUFFER_LENGTH(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 3)
+#define VIRGL_SET_ATOMIC_BUFFER_RES_HANDLE(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 4)
+
#define VIRGL_MEMORY_BARRIER_FLAGS 1
/* tess state */
diff --git a/src/vrend_decode.c b/src/vrend_decode.c
index bf2ee86550e3..e2f38a8b3620 100644
--- a/src/vrend_decode.c
+++ b/src/vrend_decode.c
@@ -1132,6 +1132,32 @@ static int vrend_decode_set_shader_buffers(struct vrend_decode_ctx *ctx, uint16_
return 0;
}
+static int vrend_decode_set_atomic_buffers(struct vrend_decode_ctx *ctx, uint16_t length)
+{
+ int num_abo;
+ uint32_t start_slot;
+
+ if (length < 2)
+ return EINVAL;
+
+ num_abo = (length - 2) / VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE;
+ start_slot = get_buf_entry(ctx, VIRGL_SET_ATOMIC_BUFFER_START_SLOT);
+ if (num_abo < 1)
+ return 0;
+
+ if (start_slot + num_abo > PIPE_MAX_HW_ATOMIC_BUFFERS)
+ return EINVAL;
+
+ for (int i = 0; i < num_abo; i++) {
+ uint32_t offset = get_buf_entry(ctx, i * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 2);
+ uint32_t buf_len = get_buf_entry(ctx, i * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 3);
+ uint32_t handle = get_buf_entry(ctx, i * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 4);
+ vrend_set_single_abo(ctx->grctx, start_slot + i, offset, buf_len, handle);
+ }
+
+ return 0;
+}
+
static int vrend_decode_set_shader_images(struct vrend_decode_ctx *ctx, uint16_t length)
{
int num_images;
@@ -1429,6 +1455,9 @@ int vrend_decode_block(uint32_t ctx_id, uint32_t *block, int ndw)
case VIRGL_CCMD_SET_SHADER_BUFFERS:
ret = vrend_decode_set_shader_buffers(gdctx, len);
break;
+ case VIRGL_CCMD_SET_ATOMIC_BUFFERS:
+ ret = vrend_decode_set_atomic_buffers(gdctx, len);
+ break;
case VIRGL_CCMD_MEMORY_BARRIER:
ret = vrend_decode_memory_barrier(gdctx, len);
break;
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index f143f1acde51..0afa60993dae 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -275,6 +275,12 @@ struct vrend_ssbo {
unsigned buffer_offset;
};
+struct vrend_abo {
+ struct vrend_resource *res;
+ unsigned buffer_size;
+ unsigned buffer_offset;
+};
+
struct vrend_vertex_element {
struct pipe_vertex_element base;
GLenum type;
@@ -421,6 +427,9 @@ struct vrend_sub_context {
struct vrend_ssbo ssbo[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
uint32_t ssbo_used_mask[PIPE_SHADER_TYPES];
+
+ struct vrend_abo abo[PIPE_MAX_HW_ATOMIC_BUFFERS];
+ uint32_t abo_used_mask;
};
struct vrend_context {
@@ -2469,6 +2478,31 @@ void vrend_set_num_ssbo(struct vrend_context *ctx,
}
+void vrend_set_single_abo(struct vrend_context *ctx,
+ int index,
+ uint32_t offset, uint32_t length,
+ uint32_t handle)
+{
+ struct vrend_abo *abo = &ctx->sub->abo[index];
+ struct vrend_resource *res;
+ if (handle) {
+ res = vrend_renderer_ctx_res_lookup(ctx, handle);
+ if (!res) {
+ report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, handle);
+ return;
+ }
+ abo->res = res;
+ abo->buffer_offset = offset;
+ abo->buffer_size = length;
+ ctx->sub->abo_used_mask |= (1 << index);
+ } else {
+ abo->res = 0;
+ abo->buffer_offset = 0;
+ abo->buffer_size = 0;
+ ctx->sub->abo_used_mask &= ~(1 << index);
+ }
+}
+
void vrend_memory_barrier(struct vrend_context *ctx,
unsigned flags)
{
@@ -3408,6 +3442,24 @@ static void vrend_draw_bind_ssbo_shader(struct vrend_context *ctx, int shader_ty
}
}
+static void vrend_draw_bind_abo_shader(struct vrend_context *ctx)
+{
+ uint32_t mask;
+ struct vrend_abo *abo;
+ struct vrend_resource *res;
+ int i;
+
+ mask = ctx->sub->abo_used_mask;
+ while (mask) {
+ i = u_bit_scan(&mask);
+
+ abo = &ctx->sub->abo[i];
+ res = (struct vrend_resource *)abo->res;
+ glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, i, res->id,
+ abo->buffer_offset, abo->buffer_size);
+ }
+}
+
static void vrend_draw_bind_images_shader(struct vrend_context *ctx, int shader_type)
{
struct vrend_image_view *iview;
@@ -3447,6 +3499,8 @@ static void vrend_draw_bind_objects(struct vrend_context *ctx, bool new_program)
vrend_draw_bind_ssbo_shader(ctx, shader_type);
}
+ vrend_draw_bind_abo_shader(ctx);
+
if (vrend_state.use_core_profile && ctx->sub->prog->fs_stipple_loc != -1) {
glActiveTexture(GL_TEXTURE0 + sampler_id);
glBindTexture(GL_TEXTURE_2D, ctx->pstipple_tex_id);
@@ -3765,6 +3819,7 @@ void vrend_launch_grid(struct vrend_context *ctx,
vrend_draw_bind_samplers_shader(ctx, PIPE_SHADER_COMPUTE, &sampler_id);
vrend_draw_bind_images_shader(ctx, PIPE_SHADER_COMPUTE);
vrend_draw_bind_ssbo_shader(ctx, PIPE_SHADER_COMPUTE);
+ vrend_draw_bind_abo_shader(ctx);
if (indirect_handle) {
indirect_res = vrend_renderer_ctx_res_lookup(ctx, indirect_handle);
@@ -8058,6 +8113,8 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.texture_buffer_offset_alignment);
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.shader_buffer_offset_alignment);
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, (GLint*)&caps->v2.max_ssbo);
+ glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, (GLint*)&caps->v2.max_atomic_counters);
+ glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, (GLint*)&caps->v2.max_atomic_counter_buffers);
glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, (GLint*)&caps->v2.max_images);
}
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index cadb9b6927d0..61d067fe8dc5 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -268,6 +268,10 @@ void vrend_set_num_ssbo(struct vrend_context *ctx,
uint32_t shader_type,
uint32_t start_slot,
uint32_t count);
+void vrend_set_single_abo(struct vrend_context *ctx,
+ int index,
+ uint32_t offset, uint32_t length,
+ uint32_t handle);
void vrend_memory_barrier(struct vrend_context *ctx,
unsigned flags);
void vrend_launch_grid(struct vrend_context *ctx,
--
2.17.1
More information about the virglrenderer-devel
mailing list