Mesa (main): turnip: Implement VK_EXT_primitives_generated_query

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 7 08:23:11 UTC 2022


Module: Mesa
Branch: main
Commit: dde1623ed2a57156013b10056461f15e8e78957f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=dde1623ed2a57156013b10056461f15e8e78957f

Author: Danylo Piliaiev <dpiliaiev at igalia.com>
Date:   Tue Apr  5 12:41:10 2022 +0300

turnip: Implement VK_EXT_primitives_generated_query

Similar to pipeline statistics but done for a single counter.

We use REG_A6XX_RBBM_PRIMCTR_7 to get generated primitives
and not PRIMCTR_8 because PRIMCTR_7 counts pre-clipped prims
while PRIMCTR_8 counts them after clipping.

OpenGL spec for GL_PRIMITIVES_GENERATED says:
 "Subsequent rendering will increment the counter once for every
  vertex that is emitted from the geometry shader, or from the
  vertex shader if no geometry shader is present."

Passes tests:
 dEQP-VK.transform_feedback.primitives_generated_query.*

Signed-off-by: Danylo Piliaiev <dpiliaiev at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15746>

---

 docs/features.txt                |  2 +-
 src/freedreno/vulkan/tu_device.c |  9 ++++
 src/freedreno/vulkan/tu_query.c  | 93 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/docs/features.txt b/docs/features.txt
index e688333fe54..c37784369ef 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -560,7 +560,7 @@ Khronos extensions that are not part of any Vulkan version:
   VK_EXT_physical_device_drm                            DONE (anv, radv, tu, v3dv)
   VK_EXT_post_depth_coverage                            DONE (anv/gfx10+, lvp, radv/gfx10+)
   VK_EXT_primitive_topology_list_restart                DONE (anv, lvp, radv, tu)
-  VK_EXT_primitives_generated_query                     DONE (lvp)
+  VK_EXT_primitives_generated_query                     DONE (lvp, tu)
   VK_EXT_provoking_vertex                               DONE (anv, lvp, radv, tu, v3dv)
   VK_EXT_queue_family_foreign                           DONE (anv, radv, vn)
   VK_EXT_robustness2                                    DONE (anv, radv, tu)
diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c
index f0cc72de141..b12f49e2465 100644
--- a/src/freedreno/vulkan/tu_device.c
+++ b/src/freedreno/vulkan/tu_device.c
@@ -203,6 +203,7 @@ get_device_extensions(const struct tu_physical_device *device,
       .EXT_line_rasterization = true,
       .EXT_subgroup_size_control = true,
       .EXT_image_robustness = true,
+      .EXT_primitives_generated_query = true,
 #ifndef TU_USE_KGSL
       .EXT_physical_device_drm = true,
 #endif
@@ -838,6 +839,14 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
          features->texelBufferAlignment = true;
          break;
       }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT: {
+         VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT *features =
+            (VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT *)ext;
+         features->primitivesGeneratedQuery = true;
+         features->primitivesGeneratedQueryWithRasterizerDiscard = false;
+         features->primitivesGeneratedQueryWithNonZeroStreams = false;
+         break;
+      }
 
       default:
          break;
diff --git a/src/freedreno/vulkan/tu_query.c b/src/freedreno/vulkan/tu_query.c
index 81a67a05239..7bf710f5e30 100644
--- a/src/freedreno/vulkan/tu_query.c
+++ b/src/freedreno/vulkan/tu_query.c
@@ -108,6 +108,13 @@ struct PACKED perf_query_slot {
    struct perfcntr_query_slot perfcntr;
 };
 
+struct PACKED primitives_generated_query_slot {
+   struct query_slot common;
+   uint64_t result;
+   uint64_t begin;
+   uint64_t end;
+};
+
 /* Returns the IOVA of a given uint64_t field in a given slot of a query
  * pool. */
 #define query_iova(type, pool, query, field)                         \
@@ -130,6 +137,9 @@ struct PACKED perf_query_slot {
    sizeof(struct perfcntr_query_slot) * (i) +                          \
    offsetof(struct perfcntr_query_slot, field)
 
+#define primitives_generated_query_iova(pool, query, field)               \
+   query_iova(struct primitives_generated_query_slot, pool, query, field)
+
 #define query_available_iova(pool, query)                            \
    query_iova(struct query_slot, pool, query, available)
 
@@ -239,6 +249,9 @@ tu_CreateQueryPool(VkDevice _device,
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
       slot_size = sizeof(struct primitive_query_slot);
       break;
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
+      slot_size = sizeof(struct primitives_generated_query_slot);
+      break;
    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: {
       perf_query_info =
             vk_find_struct_const(pCreateInfo->pNext,
@@ -364,6 +377,7 @@ get_result_count(struct tu_query_pool *pool)
    /* Occulusion and timestamp queries write one integer value */
    case VK_QUERY_TYPE_OCCLUSION:
    case VK_QUERY_TYPE_TIMESTAMP:
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
       return 1;
    /* Transform feedback queries write two integer values */
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
@@ -548,6 +562,7 @@ tu_GetQueryPoolResults(VkDevice _device,
    case VK_QUERY_TYPE_OCCLUSION:
    case VK_QUERY_TYPE_TIMESTAMP:
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
    case VK_QUERY_TYPE_PIPELINE_STATISTICS:
    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
       return get_query_pool_results(device, pool, firstQuery, queryCount,
@@ -689,6 +704,7 @@ tu_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
    case VK_QUERY_TYPE_OCCLUSION:
    case VK_QUERY_TYPE_TIMESTAMP:
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
    case VK_QUERY_TYPE_PIPELINE_STATISTICS:
       return emit_copy_query_pool_results(cmdbuf, cs, pool, firstQuery,
                queryCount, buffer, dstOffset, stride, flags);
@@ -749,6 +765,7 @@ tu_CmdResetQueryPool(VkCommandBuffer commandBuffer,
    case VK_QUERY_TYPE_TIMESTAMP:
    case VK_QUERY_TYPE_OCCLUSION:
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
    case VK_QUERY_TYPE_PIPELINE_STATISTICS:
    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
       emit_reset_query_pool(cmdbuf, pool, firstQuery, queryCount);
@@ -936,6 +953,27 @@ emit_begin_xfb_query(struct tu_cmd_buffer *cmdbuf,
    tu6_emit_event_write(cmdbuf, cs, WRITE_PRIMITIVE_COUNTS);
 }
 
+static void
+emit_begin_prim_generated_query(struct tu_cmd_buffer *cmdbuf,
+                                struct tu_query_pool *pool,
+                                uint32_t query)
+{
+   struct tu_cs *cs = cmdbuf->state.pass ? &cmdbuf->draw_cs : &cmdbuf->cs;
+   uint64_t begin_iova = primitives_generated_query_iova(pool, query, begin);
+
+   tu6_emit_event_write(cmdbuf, cs, START_PRIMITIVE_CTRS);
+   tu6_emit_event_write(cmdbuf, cs, RST_PIX_CNT);
+   tu6_emit_event_write(cmdbuf, cs, TILE_FLUSH);
+
+   tu_cs_emit_wfi(cs);
+
+   tu_cs_emit_pkt7(cs, CP_REG_TO_MEM, 3);
+   tu_cs_emit(cs, CP_REG_TO_MEM_0_REG(REG_A6XX_RBBM_PRIMCTR_7_LO) |
+                  CP_REG_TO_MEM_0_CNT(2) |
+                  CP_REG_TO_MEM_0_64B);
+   tu_cs_emit_qw(cs, begin_iova);
+}
+
 VKAPI_ATTR void VKAPI_CALL
 tu_CmdBeginQuery(VkCommandBuffer commandBuffer,
                  VkQueryPool queryPool,
@@ -957,6 +995,9 @@ tu_CmdBeginQuery(VkCommandBuffer commandBuffer,
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
       emit_begin_xfb_query(cmdbuf, pool, query, 0);
       break;
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
+      emit_begin_prim_generated_query(cmdbuf, pool, query);
+      break;
    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
       emit_begin_perf_query(cmdbuf, pool, query);
       break;
@@ -985,6 +1026,9 @@ tu_CmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer,
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
       emit_begin_xfb_query(cmdbuf, pool, query, index);
       break;
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
+      emit_begin_prim_generated_query(cmdbuf, pool, query);
+      break;
    default:
       assert(!"Invalid query type");
    }
@@ -1242,6 +1286,49 @@ emit_end_xfb_query(struct tu_cmd_buffer *cmdbuf,
    tu_cs_emit_qw(cs, 0x1);
 }
 
+static void
+emit_end_prim_generated_query(struct tu_cmd_buffer *cmdbuf,
+                              struct tu_query_pool *pool,
+                              uint32_t query)
+{
+   struct tu_cs *cs = cmdbuf->state.pass ? &cmdbuf->draw_cs : &cmdbuf->cs;
+
+   uint64_t begin_iova = primitives_generated_query_iova(pool, query, begin);
+   uint64_t end_iova = primitives_generated_query_iova(pool, query, end);
+   uint64_t result_iova = primitives_generated_query_iova(pool, query, result);
+   uint64_t available_iova = query_available_iova(pool, query);
+
+   tu6_emit_event_write(cmdbuf, cs, STOP_PRIMITIVE_CTRS);
+   tu6_emit_event_write(cmdbuf, cs, RST_VTX_CNT);
+   tu6_emit_event_write(cmdbuf, cs, STAT_EVENT);
+
+   tu_cs_emit_wfi(cs);
+
+   tu_cs_emit_pkt7(cs, CP_REG_TO_MEM, 3);
+   tu_cs_emit(cs, CP_REG_TO_MEM_0_REG(REG_A6XX_RBBM_PRIMCTR_7_LO) |
+                  CP_REG_TO_MEM_0_CNT(2) |
+                  CP_REG_TO_MEM_0_64B);
+   tu_cs_emit_qw(cs, end_iova);
+
+   tu_cs_emit_pkt7(cs, CP_MEM_TO_MEM, 9);
+   tu_cs_emit(cs, CP_MEM_TO_MEM_0_DOUBLE | CP_MEM_TO_MEM_0_NEG_C |
+                  CP_MEM_TO_MEM_0_WAIT_FOR_MEM_WRITES);
+   tu_cs_emit_qw(cs, result_iova);
+   tu_cs_emit_qw(cs, result_iova);
+   tu_cs_emit_qw(cs, end_iova);
+   tu_cs_emit_qw(cs, begin_iova);
+
+   tu_cs_emit_pkt7(cs, CP_WAIT_MEM_WRITES, 0);
+
+   if (cmdbuf->state.pass)
+      cs = &cmdbuf->draw_epilogue_cs;
+
+   /* Set the availability to 1 */
+   tu_cs_emit_pkt7(cs, CP_MEM_WRITE, 4);
+   tu_cs_emit_qw(cs, available_iova);
+   tu_cs_emit_qw(cs, 0x1);
+}
+
 /* Implement this bit of spec text from section 17.2 "Query Operation":
  *
  *     If queries are used while executing a render pass instance that has
@@ -1296,6 +1383,9 @@ tu_CmdEndQuery(VkCommandBuffer commandBuffer,
    case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
       emit_end_xfb_query(cmdbuf, pool, query, 0);
       break;
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
+      emit_end_prim_generated_query(cmdbuf, pool, query);
+      break;
    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
       emit_end_perf_query(cmdbuf, pool, query);
       break;
@@ -1326,6 +1416,9 @@ tu_CmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer,
       assert(index <= 4);
       emit_end_xfb_query(cmdbuf, pool, query, index);
       break;
+   case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
+      emit_end_prim_generated_query(cmdbuf, pool, query);
+      break;
    default:
       assert(!"Invalid query type");
    }



More information about the mesa-commit mailing list