diff --git a/docs/features.txt b/docs/features.txt index cbb7838e3ed..4701af8a22f 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -205,7 +205,7 @@ GL 4.4, GLSL 4.40 -- all DONE: i965/gen8+, nvc0, r600, radeonsi, llvmpipe, zink - specified transform/feedback layout DONE - input/output block locations DONE GL_ARB_multi_bind DONE (all drivers) - GL_ARB_query_buffer_object DONE (i965/hsw+, virgl) + GL_ARB_query_buffer_object DONE (freedreno/a6xx, i965/hsw+, virgl) GL_ARB_texture_mirror_clamp_to_edge DONE (freedreno, i965, nv50, softpipe, virgl, v3d, panfrost) GL_ARB_texture_stencil8 DONE (freedreno, i965/hsw+, nv50, softpipe, virgl, v3d, panfrost, d3d12) GL_ARB_vertex_type_10f_11f_11f_rev DONE (freedreno, i965, nv50, softpipe, virgl, panfrost, d3d12) diff --git a/src/freedreno/ci/freedreno-a630-fails.txt b/src/freedreno/ci/freedreno-a630-fails.txt index 69f5ddfd753..228ba9465eb 100644 --- a/src/freedreno/ci/freedreno-a630-fails.txt +++ b/src/freedreno/ci/freedreno-a630-fails.txt @@ -1,9 +1,6 @@ # Shader compilation error log: 0:6(1): error: invalid stream specified 1 is larger than MAX_VERTEX_STREAMS - 1 KHR-GL43.transform_feedback.draw_xfb_stream_instanced_test,Fail -# glGetError() returned GL_INVALID_ENUM at gl4cMapBufferAlignmentTests.cpp:279 -KHR-GL43.map_buffer_alignment.functional,Fail - KHR-GL43.gpu_shader_fp64.fp64.max_uniform_components,Fail KHR-GL43.gpu_shader_fp64.builtin.mod_dvec2,Fail KHR-GL43.gpu_shader_fp64.builtin.mod_dvec3,Fail @@ -368,6 +365,23 @@ spec@!opengl 1.0@depth-clear-precision-check@depth24,Fail spec@!opengl 1.0@depth-clear-precision-check@depth24_stencil8,Fail spec@!opengl 1.0@depth-clear-precision-check@depth32,Fail +# timestamp/time-elapsed qbo tests fail due to lack of way to convert +# from ticks to ns on the CP (ie. we'd need to spin up a compute shader +# or something equally drastic) +spec@arb_query_buffer_object@qbo,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIMESTAMP-ASYNC_CPU_READ_AFTER-GL_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIMESTAMP-ASYNC_CPU_READ_AFTER-GL_UNSIGNED_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIMESTAMP-ASYNC_CPU_READ_AFTER-GL_UNSIGNED_INT64_ARB,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIMESTAMP-SYNC_CPU_READ_AFTER_CACHE_TEST-GL_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIMESTAMP-SYNC_CPU_READ_AFTER_CACHE_TEST-GL_UNSIGNED_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIMESTAMP-SYNC_CPU_READ_AFTER_CACHE_TEST-GL_UNSIGNED_INT64_ARB,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIME_ELAPSED-ASYNC_CPU_READ_AFTER-GL_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIME_ELAPSED-ASYNC_CPU_READ_AFTER-GL_UNSIGNED_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIME_ELAPSED-ASYNC_CPU_READ_AFTER-GL_UNSIGNED_INT64_ARB,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIME_ELAPSED-SYNC_CPU_READ_AFTER_CACHE_TEST-GL_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIME_ELAPSED-SYNC_CPU_READ_AFTER_CACHE_TEST-GL_UNSIGNED_INT,Fail +spec@arb_query_buffer_object@qbo@query-GL_TIME_ELAPSED-SYNC_CPU_READ_AFTER_CACHE_TEST-GL_UNSIGNED_INT64_ARB,Fail + # https://gitlab.khronos.org/Tracker/vk-gl-cts/-/issues/3759 # deqp-vk: ../src/freedreno/vulkan/tu_pipeline.c:3894: tu_pipeline_builder_init_graphics: Assertion `subpass->color_count == 0 || !create_info->pColorBlendState || subpass->color_count == create_info->pColorBlendState->attachmentCount' failed dEQP-VK.pipeline.monolithic.color_write_enable_maxa.cwe_after_bind.attachments4_more0,Crash diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_query.c b/src/gallium/drivers/freedreno/a6xx/fd6_query.c index 89a55cb5184..cc7efa587df 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_query.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_query.c @@ -134,6 +134,16 @@ occlusion_counter_result(struct fd_acc_query *aq, result->u64 = sp->result; } +static void +occlusion_counter_result_resource(struct fd_acc_query *aq, struct fd_ringbuffer *ring, + enum pipe_query_value_type result_type, + int index, struct fd_resource *dst, + unsigned offset) +{ + copy_result(ring, result_type, dst, offset, fd_resource(aq->prsc), + offsetof(struct fd6_query_sample, result)); +} + static void occlusion_predicate_result(struct fd_acc_query *aq, struct fd_acc_query_sample *s, @@ -143,12 +153,39 @@ occlusion_predicate_result(struct fd_acc_query *aq, result->b = !!sp->result; } +static void +occlusion_predicate_result_resource(struct fd_acc_query *aq, struct fd_ringbuffer *ring, + enum pipe_query_value_type result_type, + int index, struct fd_resource *dst, + unsigned offset) +{ + /* This is a bit annoying but we need to turn the result into a one or + * zero.. to do this use a CP_COND_WRITE to overwrite the result with + * a one if it is non-zero. This doesn't change the results if the + * query is also read on the CPU (ie. occlusion_predicate_result()). + */ + OUT_PKT7(ring, CP_COND_WRITE5, 9); + OUT_RING(ring, CP_COND_WRITE5_0_FUNCTION(WRITE_NE) | + CP_COND_WRITE5_0_POLL_MEMORY | + CP_COND_WRITE5_0_WRITE_MEMORY); + OUT_RELOC(ring, query_sample(aq, result)); /* POLL_ADDR_LO/HI */ + OUT_RING(ring, CP_COND_WRITE5_3_REF(0)); + OUT_RING(ring, CP_COND_WRITE5_4_MASK(~0)); + OUT_RELOC(ring, query_sample(aq, result)); /* WRITE_ADDR_LO/HI */ + OUT_RING(ring, 1); + OUT_RING(ring, 0); + + copy_result(ring, result_type, dst, offset, fd_resource(aq->prsc), + offsetof(struct fd6_query_sample, result)); +} + static const struct fd_acc_sample_provider occlusion_counter = { .query_type = PIPE_QUERY_OCCLUSION_COUNTER, .size = sizeof(struct fd6_query_sample), .resume = occlusion_resume, .pause = occlusion_pause, .result = occlusion_counter_result, + .result_resource = occlusion_counter_result_resource, }; static const struct fd_acc_sample_provider occlusion_predicate = { @@ -157,6 +194,7 @@ static const struct fd_acc_sample_provider occlusion_predicate = { .resume = occlusion_resume, .pause = occlusion_pause, .result = occlusion_predicate_result, + .result_resource = occlusion_predicate_result_resource, }; static const struct fd_acc_sample_provider occlusion_predicate_conservative = { @@ -165,6 +203,7 @@ static const struct fd_acc_sample_provider occlusion_predicate_conservative = { .resume = occlusion_resume, .pause = occlusion_pause, .result = occlusion_predicate_result, + .result_resource = occlusion_predicate_result_resource, }; /* @@ -244,6 +283,17 @@ time_elapsed_accumulate_result(struct fd_acc_query *aq, result->u64 = ticks_to_ns(sp->result); } +static void +time_elapsed_result_resource(struct fd_acc_query *aq, struct fd_ringbuffer *ring, + enum pipe_query_value_type result_type, + int index, struct fd_resource *dst, + unsigned offset) +{ + // TODO ticks_to_ns conversion would require spinning up a compute shader? + copy_result(ring, result_type, dst, offset, fd_resource(aq->prsc), + offsetof(struct fd6_query_sample, result)); +} + static void timestamp_accumulate_result(struct fd_acc_query *aq, struct fd_acc_query_sample *s, @@ -253,6 +303,17 @@ timestamp_accumulate_result(struct fd_acc_query *aq, result->u64 = ticks_to_ns(sp->start); } +static void +timestamp_result_resource(struct fd_acc_query *aq, struct fd_ringbuffer *ring, + enum pipe_query_value_type result_type, + int index, struct fd_resource *dst, + unsigned offset) +{ + // TODO ticks_to_ns conversion would require spinning up a compute shader? + copy_result(ring, result_type, dst, offset, fd_resource(aq->prsc), + offsetof(struct fd6_query_sample, start)); +} + static const struct fd_acc_sample_provider time_elapsed = { .query_type = PIPE_QUERY_TIME_ELAPSED, .always = true, @@ -260,6 +321,7 @@ static const struct fd_acc_sample_provider time_elapsed = { .resume = timestamp_resume, .pause = time_elapsed_pause, .result = time_elapsed_accumulate_result, + .result_resource = time_elapsed_result_resource, }; /* NOTE: timestamp query isn't going to give terribly sensible results @@ -276,6 +338,7 @@ static const struct fd_acc_sample_provider timestamp = { .resume = timestamp_resume, .pause = timestamp_pause, .result = timestamp_accumulate_result, + .result_resource = timestamp_result_resource, }; struct PACKED fd6_primitives_sample { @@ -406,12 +469,24 @@ primitives_generated_result(struct fd_acc_query *aq, result->u64 = ps->result.generated; } +static void +primitives_generated_result_resource(struct fd_acc_query *aq, + struct fd_ringbuffer *ring, + enum pipe_query_value_type result_type, + int index, struct fd_resource *dst, + unsigned offset) +{ + copy_result(ring, result_type, dst, offset, fd_resource(aq->prsc), + offsetof(struct fd6_primitives_sample, result.generated)); +} + static const struct fd_acc_sample_provider primitives_generated = { .query_type = PIPE_QUERY_PRIMITIVES_GENERATED, .size = sizeof(struct fd6_primitives_sample), .resume = primitives_generated_resume, .pause = primitives_generated_pause, .result = primitives_generated_result, + .result_resource = primitives_generated_result_resource, }; static void @@ -468,12 +543,24 @@ primitives_emitted_result(struct fd_acc_query *aq, result->u64 = ps->result.emitted; } +static void +primitives_emitted_result_resource(struct fd_acc_query *aq, + struct fd_ringbuffer *ring, + enum pipe_query_value_type result_type, + int index, struct fd_resource *dst, + unsigned offset) +{ + copy_result(ring, result_type, dst, offset, fd_resource(aq->prsc), + offsetof(struct fd6_primitives_sample, result.emitted)); +} + static const struct fd_acc_sample_provider primitives_emitted = { .query_type = PIPE_QUERY_PRIMITIVES_EMITTED, .size = sizeof(struct fd6_primitives_sample), .resume = primitives_emitted_resume, .pause = primitives_emitted_pause, .result = primitives_emitted_result, + .result_resource = primitives_emitted_result_resource, }; /* diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 91f00ecf432..451f06476a1 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -526,6 +526,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) /* only a4xx, requires new enough kernel so we know max_freq: */ return (screen->max_freq > 0) && (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)); + case PIPE_CAP_QUERY_BUFFER_OBJECT: + return is_a6xx(screen); case PIPE_CAP_VENDOR_ID: return 0x5143;