Mesa (main): freedreno: Be more strict about QUERY_AVAILABLE to simplify the code.
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Jun 15 20:59:33 UTC 2021
Module: Mesa
Branch: main
Commit: 591a3c738d7a812e220d23967d358d1e4e6034d5
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=591a3c738d7a812e220d23967d358d1e4e6034d5
Author: Emma Anholt <emma at anholt.net>
Date: Mon Jun 14 14:13:45 2021 -0700
freedreno: Be more strict about QUERY_AVAILABLE to simplify the code.
ARB_oq doesn't just say "polling in a loop will make it complete
eventually", it says "querying will make it complete in finite time."
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11368>
---
src/freedreno/.clang-format | 1 +
.../drivers/freedreno/freedreno_query_acc.c | 48 ++++++-----------
.../drivers/freedreno/freedreno_query_acc.h | 2 -
src/gallium/drivers/freedreno/freedreno_query_hw.c | 62 +++++++---------------
src/gallium/drivers/freedreno/freedreno_query_hw.h | 2 -
5 files changed, 36 insertions(+), 79 deletions(-)
diff --git a/src/freedreno/.clang-format b/src/freedreno/.clang-format
index 3036ea5fe30..461df1c8675 100644
--- a/src/freedreno/.clang-format
+++ b/src/freedreno/.clang-format
@@ -22,6 +22,7 @@ Cpp11BracedListStyle: true
ForEachMacros:
- LIST_FOR_EACH_ENTRY
- LIST_FOR_EACH_ENTRY_SAFE
+ - LIST_FOR_EACH_ENTRY_SAFE_REV
- list_for_each_entry
- list_for_each_entry_safe
- foreach_list_typed
diff --git a/src/gallium/drivers/freedreno/freedreno_query_acc.c b/src/gallium/drivers/freedreno/freedreno_query_acc.c
index c8370f7733a..d579a54759f 100644
--- a/src/gallium/drivers/freedreno/freedreno_query_acc.c
+++ b/src/gallium/drivers/freedreno/freedreno_query_acc.c
@@ -147,38 +147,14 @@ fd_acc_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
assert(list_is_empty(&aq->node));
- /* if !wait, then check the last sample (the one most likely to
- * not be ready yet) and bail if it is not ready:
+ /* ARB_occlusion_query says:
+ *
+ * "Querying the state for a given occlusion query forces that
+ * occlusion query to complete within a finite amount of time."
+ *
+ * So, regardless of whether we are supposed to wait or not, we do need to
+ * flush now.
*/
- if (!wait) {
- int ret;
-
- if (pending(rsc, false)) {
- assert(!q->base.flushed);
- tc_assert_driver_thread(ctx->tc);
-
- /* piglit spec at arb_occlusion_query@occlusion_query_conform
- * test, and silly apps perhaps, get stuck in a loop trying
- * to get query result forever with wait==false.. we don't
- * wait to flush unnecessarily but we also don't want to
- * spin forever:
- */
- if (aq->no_wait_cnt++ > 5) {
- fd_context_access_begin(ctx);
- fd_batch_flush(rsc->track->write_batch);
- fd_context_access_end(ctx);
- }
- return false;
- }
-
- ret = fd_resource_wait(
- ctx, rsc, FD_BO_PREP_READ | FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH);
- if (ret)
- return false;
-
- fd_bo_cpu_fini(rsc->bo);
- }
-
if (rsc->track->write_batch) {
tc_assert_driver_thread(ctx->tc);
fd_context_access_begin(ctx);
@@ -186,8 +162,14 @@ fd_acc_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
fd_context_access_end(ctx);
}
- /* get the result: */
- fd_resource_wait(ctx, rsc, FD_BO_PREP_READ);
+ if (!wait) {
+ int ret = fd_resource_wait(
+ ctx, rsc, FD_BO_PREP_READ | FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH);
+ if (ret)
+ return false;
+ } else {
+ fd_resource_wait(ctx, rsc, FD_BO_PREP_READ);
+ }
void *ptr = fd_bo_map(rsc->bo);
p->result(aq, ptr, result);
diff --git a/src/gallium/drivers/freedreno/freedreno_query_acc.h b/src/gallium/drivers/freedreno/freedreno_query_acc.h
index 79dd399c4fc..84f86feb7ad 100644
--- a/src/gallium/drivers/freedreno/freedreno_query_acc.h
+++ b/src/gallium/drivers/freedreno/freedreno_query_acc.h
@@ -89,8 +89,6 @@ struct fd_acc_query {
struct list_head node; /* list-node in ctx->active_acc_queries */
- int no_wait_cnt; /* see fd_acc_get_query_result() */
-
void *query_data; /* query specific data */
};
diff --git a/src/gallium/drivers/freedreno/freedreno_query_hw.c b/src/gallium/drivers/freedreno/freedreno_query_hw.c
index 2bfffdc8350..2dbf2b2a30e 100644
--- a/src/gallium/drivers/freedreno/freedreno_query_hw.c
+++ b/src/gallium/drivers/freedreno/freedreno_query_hw.c
@@ -187,7 +187,7 @@ fd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
{
struct fd_hw_query *hq = fd_hw_query(q);
const struct fd_hw_sample_provider *p = hq->provider;
- struct fd_hw_sample_period *period;
+ struct fd_hw_sample_period *period, *tmp;
DBG("%p: wait=%d", q, wait);
@@ -197,47 +197,10 @@ fd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
assert(list_is_empty(&hq->list));
assert(!hq->period);
- /* if !wait, then check the last sample (the one most likely to
- * not be ready yet) and bail if it is not ready:
+ /* sum the result across all sample periods. Start with the last period
+ * so that no-wait will bail quickly.
*/
- if (!wait) {
- int ret;
-
- period = LIST_ENTRY(struct fd_hw_sample_period, hq->periods.prev, list);
-
- struct fd_resource *rsc = fd_resource(period->end->prsc);
-
- if (pending(rsc, false)) {
- assert(!q->base.flushed);
- tc_assert_driver_thread(ctx->tc);
-
- /* piglit spec at arb_occlusion_query@occlusion_query_conform
- * test, and silly apps perhaps, get stuck in a loop trying
- * to get query result forever with wait==false.. we don't
- * wait to flush unnecessarily but we also don't want to
- * spin forever:
- */
- if (hq->no_wait_cnt++ > 5) {
- fd_context_access_begin(ctx);
- fd_batch_flush(rsc->track->write_batch);
- fd_context_access_end(ctx);
- }
- return false;
- }
-
- if (!rsc->bo)
- return false;
-
- ret = fd_resource_wait(
- ctx, rsc, FD_BO_PREP_READ | FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH);
- if (ret)
- return false;
-
- fd_bo_cpu_fini(rsc->bo);
- }
-
- /* sum the result across all sample periods: */
- LIST_FOR_EACH_ENTRY (period, &hq->periods, list) {
+ LIST_FOR_EACH_ENTRY_SAFE_REV (period, tmp, &hq->periods, list) {
struct fd_hw_sample *start = period->start;
ASSERTED struct fd_hw_sample *end = period->end;
unsigned i;
@@ -248,6 +211,14 @@ fd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
struct fd_resource *rsc = fd_resource(start->prsc);
+ /* ARB_occlusion_query says:
+ *
+ * "Querying the state for a given occlusion query forces that
+ * occlusion query to complete within a finite amount of time."
+ *
+ * So, regardless of whether we are supposed to wait or not, we do need to
+ * flush now.
+ */
if (rsc->track->write_batch) {
tc_assert_driver_thread(ctx->tc);
fd_context_access_begin(ctx);
@@ -259,7 +230,14 @@ fd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
if (!rsc->bo)
continue;
- fd_resource_wait(ctx, rsc, FD_BO_PREP_READ);
+ if (!wait) {
+ int ret = fd_resource_wait(
+ ctx, rsc, FD_BO_PREP_READ | FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH);
+ if (ret)
+ return false;
+ } else {
+ fd_resource_wait(ctx, rsc, FD_BO_PREP_READ);
+ }
void *ptr = fd_bo_map(rsc->bo);
diff --git a/src/gallium/drivers/freedreno/freedreno_query_hw.h b/src/gallium/drivers/freedreno/freedreno_query_hw.h
index 01fc9ce370f..bf8ee7820f0 100644
--- a/src/gallium/drivers/freedreno/freedreno_query_hw.h
+++ b/src/gallium/drivers/freedreno/freedreno_query_hw.h
@@ -124,8 +124,6 @@ struct fd_hw_query {
struct fd_hw_sample_period *period;
struct list_head list; /* list-node in batch->active_queries */
-
- int no_wait_cnt; /* see fd_hw_get_query_result */
};
static inline struct fd_hw_query *
More information about the mesa-commit
mailing list