diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index e8619bd4462..ab949110566 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -572,6 +572,17 @@ use_hw_binning(struct tu_cmd_buffer *cmd) return true; } + /* VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT emulates GL_PRIMITIVES_GENERATED, + * which wasn't designed to care about tilers and expects the result not to + * be multiplied by tile count. + * See https://gitlab.khronos.org/vulkan/vulkan/-/issues/3131 + */ + if (cmd->state.has_prim_generated_query_in_rp || + cmd->state.prim_generated_query_running_before_rp) { + assert(fb->binning_possible); + return true; + } + return fb->binning; } @@ -604,6 +615,14 @@ use_sysmem_rendering(struct tu_cmd_buffer *cmd, if (cmd->state.xfb_used && !cmd->state.framebuffer->binning_possible) return true; + /* QUERY_TYPE_PRIMITIVES_GENERATED is incompatible with non-hw binning + * GMEM rendering, see use_hw_binning. + */ + if ((cmd->state.has_prim_generated_query_in_rp || + cmd->state.prim_generated_query_running_before_rp) && + !cmd->state.framebuffer->binning_possible) + return true; + if (unlikely(cmd->device->physical_device->instance->debug_flags & TU_DEBUG_GMEM)) return false; @@ -4963,6 +4982,7 @@ tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer, cmd_buffer->state.disable_gmem = false; cmd_buffer->state.drawcall_count = 0; cmd_buffer->state.drawcall_bandwidth_per_sample_sum = 0; + cmd_buffer->state.has_prim_generated_query_in_rp = false; /* LRZ is not valid next time we use it */ cmd_buffer->state.lrz.valid = false; diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index 554405d2a4d..a78ea48aa95 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -1250,6 +1250,9 @@ struct tu_cmd_state */ uint32_t drawcall_bandwidth_per_sample_sum; + bool prim_generated_query_running_before_rp; + bool has_prim_generated_query_in_rp; + struct tu_lrz_state lrz; struct tu_draw_state lrz_and_depth_plane_state; diff --git a/src/freedreno/vulkan/tu_query.c b/src/freedreno/vulkan/tu_query.c index 95d9b51b4aa..18b8fec966e 100644 --- a/src/freedreno/vulkan/tu_query.c +++ b/src/freedreno/vulkan/tu_query.c @@ -965,6 +965,12 @@ emit_begin_prim_generated_query(struct tu_cmd_buffer *cmdbuf, struct tu_cs *cs = cmdbuf->state.pass ? &cmdbuf->draw_cs : &cmdbuf->cs; uint64_t begin_iova = primitives_generated_query_iova(pool, query, begin); + if (cmdbuf->state.pass) { + cmdbuf->state.has_prim_generated_query_in_rp = true; + } else { + cmdbuf->state.prim_generated_query_running_before_rp = true; + } + 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); @@ -1297,6 +1303,10 @@ emit_end_prim_generated_query(struct tu_cmd_buffer *cmdbuf, { struct tu_cs *cs = cmdbuf->state.pass ? &cmdbuf->draw_cs : &cmdbuf->cs; + if (!cmdbuf->state.pass) { + cmdbuf->state.prim_generated_query_running_before_rp = false; + } + 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);