diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index fcd0838..b413227 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -369,6 +369,7 @@ enum pipe_flush_flags { #define PIPE_BIND_SHADER_RESOURCE (1 << 19) /* set_shader_resources */ #define PIPE_BIND_COMPUTE_RESOURCE (1 << 20) /* set_compute_resources */ #define PIPE_BIND_COMMAND_ARGS_BUFFER (1 << 21) /* pipe_draw_info.indirect */ +#define PIPE_BIND_QUERY_BUFFER (1 << 22) /* get_query_result_resource */ /* The first two flags above were previously part of the amorphous * TEXTURE_USAGE, most of which are now descriptions of the ways a @@ -772,6 +773,14 @@ union pipe_query_result struct pipe_query_data_pipeline_statistics pipeline_statistics; }; +enum pipe_query_value_type +{ + PIPE_QUERY_TYPE_I32, + PIPE_QUERY_TYPE_U32, + PIPE_QUERY_TYPE_I64, + PIPE_QUERY_TYPE_U64, +}; + union pipe_color_union { float f[4]; diff --git a/src/virgl_hw.h b/src/virgl_hw.h index 6357927..3da6848 100644 --- a/src/virgl_hw.h +++ b/src/virgl_hw.h @@ -237,6 +237,7 @@ enum virgl_formats { #define VIRGL_CAP_TGSI_COMPONENTS (1 << 13) #define VIRGL_CAP_GUEST_MAY_INIT_LOG (1 << 14) #define VIRGL_CAP_SRGB_WRITE_CONTROL (1 << 15) +#define VIRGL_CAP_QBO (1 << 16) /* virgl bind flags - these are compatible with mesa 10.5 gallium. * but are fixed, no other should be passed to virgl either. @@ -250,6 +251,7 @@ enum virgl_formats { #define VIRGL_BIND_DISPLAY_TARGET (1 << 7) #define VIRGL_BIND_STREAM_OUTPUT (1 << 11) #define VIRGL_BIND_SHADER_BUFFER (1 << 14) +#define VIRGL_BIND_QUERY_BUFFER (1 << 15) #define VIRGL_BIND_CURSOR (1 << 16) #define VIRGL_BIND_CUSTOM (1 << 17) #define VIRGL_BIND_SCANOUT (1 << 18) diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h index e19976a..d9f58ce 100644 --- a/src/virgl_protocol.h +++ b/src/virgl_protocol.h @@ -97,6 +97,7 @@ enum virgl_context_cmd { VIRGL_CCMD_TEXTURE_BARRIER, VIRGL_CCMD_SET_ATOMIC_BUFFERS, VIRGL_CCMD_SET_DEBUG_FLAGS, + VIRGL_CCMD_GET_QUERY_RESULT_QBO, VIRGL_MAX_COMMANDS }; @@ -563,4 +564,13 @@ enum virgl_context_cmd { #define VIRGL_SET_DEBUG_FLAGS_MIN_SIZE 2 #define VIRGL_SET_DEBUG_FLAGSTRING_OFFSET 1 +/* query buffer object */ +#define VIRGL_QUERY_RESULT_QBO_SIZE 6 +#define VIRGL_QUERY_RESULT_QBO_HANDLE 1 +#define VIRGL_QUERY_RESULT_QBO_QBO_HANDLE 2 +#define VIRGL_QUERY_RESULT_QBO_WAIT 3 +#define VIRGL_QUERY_RESULT_QBO_RESULT_TYPE 4 +#define VIRGL_QUERY_RESULT_QBO_OFFSET 5 +#define VIRGL_QUERY_RESULT_QBO_INDEX 6 + #endif diff --git a/src/vrend_debug.c b/src/vrend_debug.c index efdef32..ecc6d4f 100644 --- a/src/vrend_debug.c +++ b/src/vrend_debug.c @@ -70,7 +70,8 @@ static const char *command_names[VIRGL_MAX_COMMANDS] = { "SET_FRAMEBUFFER_STATE_NO_ATTACH", "TEXTURE_BARRIER", "SET_ATOMIC_BUFFERS", - "SET_DEBUG_FLAGS" + "SET_DEBUG_FLAGS", + "GET_QBO_RESULT" }; static const char *object_type_names[VIRGL_MAX_OBJECTS] = { diff --git a/src/vrend_decode.c b/src/vrend_decode.c index 909c754..54d4015 100644 --- a/src/vrend_decode.c +++ b/src/vrend_decode.c @@ -1041,6 +1041,22 @@ static int vrend_decode_get_query_result(struct vrend_decode_ctx *ctx, int lengt return 0; } +static int vrend_decode_get_query_result_qbo(struct vrend_decode_ctx *ctx, int length) +{ + if (length != VIRGL_QUERY_RESULT_QBO_SIZE) + return EINVAL; + + uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_RESULT_QBO_HANDLE); + uint32_t qbo_handle = get_buf_entry(ctx, VIRGL_QUERY_RESULT_QBO_QBO_HANDLE); + uint32_t wait = get_buf_entry(ctx, VIRGL_QUERY_RESULT_QBO_WAIT); + uint32_t result_type = get_buf_entry(ctx, VIRGL_QUERY_RESULT_QBO_RESULT_TYPE); + uint32_t offset = get_buf_entry(ctx, VIRGL_QUERY_RESULT_QBO_OFFSET); + int32_t index = get_buf_entry(ctx, VIRGL_QUERY_RESULT_QBO_INDEX); + + vrend_get_query_result_qbo(ctx->grctx, handle, qbo_handle, wait, result_type, offset, index); + return 0; +} + static int vrend_decode_set_render_condition(struct vrend_decode_ctx *ctx, int length) { if (length != VIRGL_RENDER_CONDITION_SIZE) @@ -1522,6 +1538,9 @@ int vrend_decode_block(uint32_t ctx_id, uint32_t *block, int ndw) case VIRGL_CCMD_SET_DEBUG_FLAGS: ret = vrend_decode_set_debug_mask(gdctx, len); break; + case VIRGL_CCMD_GET_QUERY_RESULT_QBO: + ret = vrend_decode_get_query_result_qbo(gdctx, len); + break; default: ret = EINVAL; } diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index b6fb2eb..631e34f 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -120,6 +120,7 @@ enum features_id feat_nv_conditional_render, feat_nv_prim_restart, feat_polygon_offset_clamp, + feat_qbo, feat_robust_buffer_access, feat_sample_mask, feat_sample_shading, @@ -194,6 +195,7 @@ static const struct { FEAT(nv_conditional_render, UNAVAIL, UNAVAIL, "GL_NV_conditional_render" ), FEAT(nv_prim_restart, UNAVAIL, UNAVAIL, "GL_NV_primitive_restart" ), FEAT(polygon_offset_clamp, 46, UNAVAIL, "GL_ARB_polygon_offset_clamp" ), + FEAT(qbo, 44, UNAVAIL, "GL_ARB_query_buffer_object" ), FEAT(robust_buffer_access, 43, UNAVAIL, "GL_ARB_robust_buffer_access_behavior", "GL_KHR_robust_buffer_access_behavior" ), FEAT(sample_mask, 32, 31, "GL_ARB_texture_multisample" ), FEAT(sample_shading, 40, 32, "GL_ARB_sample_shading", "GL_OES_sample_shading" ), @@ -2761,6 +2763,8 @@ void vrend_memory_barrier(UNUSED struct vrend_context *ctx, if (has_feature(feat_ssbo_barrier)) gl_barrier |= GL_SHADER_STORAGE_BARRIER_BIT; } + if (has_feature(feat_qbo) && (flags & PIPE_BARRIER_QUERY_BUFFER)) + gl_barrier |= GL_QUERY_BUFFER_BARRIER_BIT; } glMemoryBarrier(gl_barrier); } @@ -5619,11 +5623,14 @@ static int check_resource_valid(struct vrend_renderer_resource_create_args *args args->bind == VIRGL_BIND_STREAM_OUTPUT || args->bind == VIRGL_BIND_VERTEX_BUFFER || args->bind == VIRGL_BIND_CONSTANT_BUFFER || + args->bind == VIRGL_BIND_QUERY_BUFFER || args->bind == VIRGL_BIND_SHADER_BUFFER) { if (args->target != PIPE_BUFFER) return -1; if (args->height != 1 || args->depth != 1) return -1; + if (args->bind == VIRGL_BIND_QUERY_BUFFER && !has_feature(feat_qbo)) + return -1; } else { if (!((args->bind & VIRGL_BIND_SAMPLER_VIEW) || (args->bind & VIRGL_BIND_DEPTH_STENCIL) || @@ -5863,6 +5870,9 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a } else if (args->bind == VIRGL_BIND_CONSTANT_BUFFER) { gr->target = GL_UNIFORM_BUFFER; vrend_create_buffer(gr, args->width); + } else if (args->bind == VIRGL_BIND_QUERY_BUFFER) { + gr->target = GL_QUERY_BUFFER; + vrend_create_buffer(gr, args->width); } else if (args->target == PIPE_BUFFER && (args->bind == 0 || args->bind == VIRGL_BIND_SHADER_BUFFER)) { gr->target = GL_ARRAY_BUFFER_ARB; vrend_create_buffer(gr, args->width); @@ -6165,6 +6175,7 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx, res->target == GL_ELEMENT_ARRAY_BUFFER_ARB || res->target == GL_ARRAY_BUFFER_ARB || res->target == GL_TEXTURE_BUFFER || + res->target == GL_QUERY_BUFFER || res->target == GL_UNIFORM_BUFFER || res->target == GL_PIXEL_PACK_BUFFER || res->target == GL_PIXEL_UNPACK_BUFFER) { @@ -6675,6 +6686,7 @@ static int vrend_renderer_transfer_send_iov(struct vrend_context *ctx, res->target == GL_TRANSFORM_FEEDBACK_BUFFER || res->target == GL_TEXTURE_BUFFER || res->target == GL_UNIFORM_BUFFER || + res->target == GL_QUERY_BUFFER || res->target == GL_PIXEL_PACK_BUFFER || res->target == GL_PIXEL_UNPACK_BUFFER) { uint32_t send_size = info->box->width * util_format_get_blocksize(res->base.format); @@ -7896,6 +7908,54 @@ void vrend_get_query_result(struct vrend_context *ctx, uint32_t handle, list_addtail(&q->waiting_queries, &vrend_state.waiting_query_list); } +#define BUFFER_OFFSET(i) ((void *)((char *)NULL + i)) +void vrend_get_query_result_qbo(struct vrend_context *ctx, uint32_t handle, + uint32_t qbo_handle, + uint32_t wait, uint32_t result_type, uint32_t offset, + int32_t index) +{ + struct vrend_query *q; + struct vrend_resource *res; + + if (!has_feature(feat_qbo)) + return; + + q = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_QUERY); + if (!q) + return; + + res = vrend_renderer_ctx_res_lookup(ctx, qbo_handle); + if (!res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, qbo_handle); + return; + } + + glBindBuffer(GL_QUERY_BUFFER, res->id); + GLenum qtype; + + if (index == -1) + qtype = GL_QUERY_RESULT_AVAILABLE; + else + qtype = wait ? GL_QUERY_RESULT : GL_QUERY_RESULT_NO_WAIT; + + switch ((enum pipe_query_value_type)result_type) { + case PIPE_QUERY_TYPE_I32: + glGetQueryObjectiv(q->id, qtype, BUFFER_OFFSET(offset)); + break; + case PIPE_QUERY_TYPE_U32: + glGetQueryObjectuiv(q->id, qtype, BUFFER_OFFSET(offset)); + break; + case PIPE_QUERY_TYPE_I64: + glGetQueryObjecti64v(q->id, qtype, BUFFER_OFFSET(offset)); + break; + case PIPE_QUERY_TYPE_U64: + glGetQueryObjectui64v(q->id, qtype, BUFFER_OFFSET(offset)); + break; + } + + glBindBuffer(GL_QUERY_BUFFER, 0); +} + static void vrend_pause_render_condition(struct vrend_context *ctx, bool pause) { if (pause) { @@ -8461,6 +8521,7 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c if (has_feature(feat_texture_barrier)) caps->v2.capability_bits |= VIRGL_CAP_TEXTURE_BARRIER; + /* always enable this since it doesn't require an ext to pass tests */ caps->v2.capability_bits |= VIRGL_CAP_TGSI_COMPONENTS; @@ -8475,6 +8536,8 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c /* always enable, only indicates that the CMD is supported */ caps->v2.capability_bits |= VIRGL_CAP_GUEST_MAY_INIT_LOG; + if (has_feature(feat_qbo)) + caps->v2.capability_bits |= VIRGL_CAP_QBO; } void vrend_renderer_fill_caps(uint32_t set, UNUSED uint32_t version, diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index 8579006..b9c912d 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -324,6 +324,10 @@ int vrend_begin_query(struct vrend_context *ctx, uint32_t handle); int vrend_end_query(struct vrend_context *ctx, uint32_t handle); void vrend_get_query_result(struct vrend_context *ctx, uint32_t handle, uint32_t wait); +void vrend_get_query_result_qbo(struct vrend_context *ctx, uint32_t handle, + uint32_t qbo_handle, + uint32_t wait, uint32_t result_type, uint32_t offset, + int32_t index); void vrend_render_condition(struct vrend_context *ctx, uint32_t handle, bool condtion,