mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 11:28:05 +02:00
iris: fix conditional compute, don't stomp predicate for pipelined queries
This commit is contained in:
parent
40b12c103c
commit
761a5fb36a
6 changed files with 90 additions and 67 deletions
|
|
@ -257,10 +257,10 @@ iris_blit(struct pipe_context *ctx, const struct pipe_blit_info *info)
|
|||
enum blorp_batch_flags blorp_flags = 0;
|
||||
|
||||
if (info->render_condition_enable) {
|
||||
if (ice->predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
||||
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
||||
return;
|
||||
|
||||
if (ice->predicate == IRIS_PREDICATE_STATE_USE_BIT)
|
||||
if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
|
||||
blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ iris_clear(struct pipe_context *ctx,
|
|||
|
||||
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
||||
|
||||
if (ice->predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
||||
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
||||
return;
|
||||
|
||||
enum blorp_batch_flags blorp_flags = 0;
|
||||
if (ice->predicate == IRIS_PREDICATE_STATE_USE_BIT)
|
||||
if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT)
|
||||
blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
|
||||
|
||||
iris_batch_maybe_flush(batch, 1500);
|
||||
|
|
|
|||
|
|
@ -430,7 +430,6 @@ struct iris_context {
|
|||
struct iris_bo *scratch_bos[1 << 4][MESA_SHADER_STAGES];
|
||||
} shaders;
|
||||
|
||||
enum iris_predicate_state predicate;
|
||||
struct {
|
||||
uint64_t dirty;
|
||||
uint64_t dirty_for_nos[IRIS_NOS_COUNT];
|
||||
|
|
@ -483,6 +482,15 @@ struct iris_context {
|
|||
|
||||
bool statistics_counters_enabled;
|
||||
|
||||
/** Current conditional rendering mode */
|
||||
enum iris_predicate_state predicate;
|
||||
|
||||
/**
|
||||
* Query BO with a MI_PREDICATE_DATA snapshot calculated on the
|
||||
* render context that needs to be uploaded to the compute context.
|
||||
*/
|
||||
struct iris_bo *compute_predicate;
|
||||
|
||||
/** Is a PIPE_QUERY_PRIMITIVES_GENERATED query active? */
|
||||
bool prims_generated_query_active;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "util/u_upload_mgr.h"
|
||||
#include "intel/compiler/brw_compiler.h"
|
||||
#include "iris_context.h"
|
||||
#include "iris_defines.h"
|
||||
|
||||
/**
|
||||
* Record the current primitive mode and restart information, flagging
|
||||
|
|
@ -70,6 +71,9 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
|
|||
struct iris_context *ice = (struct iris_context *) ctx;
|
||||
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
||||
|
||||
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
||||
return;
|
||||
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_REEMIT))
|
||||
ice->state.dirty |= ~0ull;
|
||||
|
||||
|
|
@ -148,6 +152,9 @@ iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
|
|||
struct iris_context *ice = (struct iris_context *) ctx;
|
||||
struct iris_batch *batch = &ice->batches[IRIS_BATCH_COMPUTE];
|
||||
|
||||
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
||||
return;
|
||||
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_REEMIT))
|
||||
ice->state.dirty |= ~0ull;
|
||||
|
||||
|
|
@ -164,6 +171,13 @@ iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
|
|||
|
||||
iris_binder_reserve_compute(ice);
|
||||
ice->vtbl.update_surface_base_address(batch, &ice->state.binder);
|
||||
|
||||
if (ice->state.compute_predicate) {
|
||||
ice->vtbl.load_register_mem64(batch, MI_PREDICATE_DATA,
|
||||
ice->state.compute_predicate, 0);
|
||||
ice->state.compute_predicate = NULL;
|
||||
}
|
||||
|
||||
ice->vtbl.upload_compute_state(ice, batch, grid);
|
||||
|
||||
ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_COMPUTE;
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ struct iris_query {
|
|||
|
||||
bool ready;
|
||||
|
||||
bool stalled;
|
||||
|
||||
uint64_t result;
|
||||
|
||||
struct iris_bo *bo;
|
||||
|
|
@ -103,13 +105,21 @@ struct iris_query {
|
|||
};
|
||||
|
||||
struct iris_query_snapshots {
|
||||
/** iris_render_condition's saved MI_PREDICATE_DATA value. */
|
||||
uint64_t predicate_data;
|
||||
|
||||
/** Have the start/end snapshots landed? */
|
||||
uint64_t snapshots_landed;
|
||||
|
||||
/** Starting and ending counter snapshots */
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
struct iris_query_so_overflow {
|
||||
uint64_t predicate_data;
|
||||
uint64_t snapshots_landed;
|
||||
|
||||
struct {
|
||||
uint64_t prim_storage_needed[2];
|
||||
uint64_t num_prims[2];
|
||||
|
|
@ -179,6 +189,7 @@ write_value(struct iris_context *ice, struct iris_query *q, unsigned offset)
|
|||
iris_emit_pipe_control_flush(batch,
|
||||
PIPE_CONTROL_CS_STALL |
|
||||
PIPE_CONTROL_STALL_AT_SCOREBOARD);
|
||||
q->stalled = true;
|
||||
}
|
||||
|
||||
switch (q->type) {
|
||||
|
|
@ -694,7 +705,7 @@ iris_get_query_result_resource(struct pipe_context *ctx,
|
|||
/* Calculate the result to CS_GPR0 */
|
||||
calculate_result_on_gpu(ice, q);
|
||||
|
||||
bool predicated = !wait && iris_is_query_pipelined(q);
|
||||
bool predicated = !wait && !q->stalled;
|
||||
|
||||
if (predicated) {
|
||||
ice->vtbl.load_register_imm64(batch, MI_PREDICATE_SRC1, 0ull);
|
||||
|
|
@ -740,102 +751,90 @@ iris_set_active_query_state(struct pipe_context *ctx, boolean enable)
|
|||
}
|
||||
|
||||
static void
|
||||
set_predicate_enable(struct iris_context *ice,
|
||||
bool value)
|
||||
set_predicate_enable(struct iris_context *ice, bool value)
|
||||
{
|
||||
if (value)
|
||||
ice->predicate = IRIS_PREDICATE_STATE_RENDER;
|
||||
ice->state.predicate = IRIS_PREDICATE_STATE_RENDER;
|
||||
else
|
||||
ice->predicate = IRIS_PREDICATE_STATE_DONT_RENDER;
|
||||
}
|
||||
|
||||
static void
|
||||
set_predicate_for_overflow(struct iris_context *ice,
|
||||
struct iris_query *q)
|
||||
{
|
||||
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
||||
ice->predicate = IRIS_PREDICATE_STATE_USE_BIT;
|
||||
|
||||
/* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
|
||||
* command when loading the values into the predicate source registers for
|
||||
* conditional rendering.
|
||||
*/
|
||||
iris_emit_pipe_control_flush(batch, PIPE_CONTROL_FLUSH_ENABLE);
|
||||
|
||||
overflow_result_to_gpr0(ice, q);
|
||||
ice->vtbl.load_register_reg64(batch, CS_GPR(0), MI_PREDICATE_SRC0);
|
||||
ice->vtbl.load_register_imm64(batch, MI_PREDICATE_SRC1, 0ull);
|
||||
}
|
||||
|
||||
static void
|
||||
set_predicate_for_occlusion(struct iris_context *ice,
|
||||
struct iris_query *q)
|
||||
{
|
||||
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
||||
ice->predicate = IRIS_PREDICATE_STATE_USE_BIT;
|
||||
|
||||
/* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
|
||||
* command when loading the values into the predicate source registers for
|
||||
* conditional rendering.
|
||||
*/
|
||||
iris_emit_pipe_control_flush(batch, PIPE_CONTROL_FLUSH_ENABLE);
|
||||
|
||||
ice->vtbl.load_register_mem64(batch, MI_PREDICATE_SRC0, q->bo, offsetof(struct iris_query_snapshots, start));
|
||||
ice->vtbl.load_register_mem64(batch, MI_PREDICATE_SRC1, q->bo, offsetof(struct iris_query_snapshots, end));
|
||||
ice->state.predicate = IRIS_PREDICATE_STATE_DONT_RENDER;
|
||||
}
|
||||
|
||||
static void
|
||||
set_predicate_for_result(struct iris_context *ice,
|
||||
struct iris_query *q,
|
||||
bool condition)
|
||||
bool inverted)
|
||||
{
|
||||
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
|
||||
int load_op;
|
||||
|
||||
/* The CPU doesn't have the query result yet; use hardware predication */
|
||||
ice->state.predicate = IRIS_PREDICATE_STATE_USE_BIT;
|
||||
|
||||
/* Ensure the memory is coherent for MI_LOAD_REGISTER_* commands. */
|
||||
iris_emit_pipe_control_flush(batch, PIPE_CONTROL_FLUSH_ENABLE);
|
||||
q->stalled = true;
|
||||
|
||||
switch (q->type) {
|
||||
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
|
||||
case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
|
||||
set_predicate_for_overflow(ice, q);
|
||||
overflow_result_to_gpr0(ice, q);
|
||||
|
||||
ice->vtbl.load_register_reg64(batch, CS_GPR(0), MI_PREDICATE_SRC0);
|
||||
ice->vtbl.load_register_imm64(batch, MI_PREDICATE_SRC1, 0ull);
|
||||
break;
|
||||
default:
|
||||
set_predicate_for_occlusion(ice, q);
|
||||
/* PIPE_QUERY_OCCLUSION_* */
|
||||
ice->vtbl.load_register_mem64(batch, MI_PREDICATE_SRC0, q->bo,
|
||||
offsetof(struct iris_query_snapshots, start));
|
||||
ice->vtbl.load_register_mem64(batch, MI_PREDICATE_SRC1, q->bo,
|
||||
offsetof(struct iris_query_snapshots, end));
|
||||
break;
|
||||
}
|
||||
|
||||
if (ice->predicate == IRIS_PREDICATE_STATE_USE_BIT) {
|
||||
if (condition)
|
||||
load_op = MI_PREDICATE_LOADOP_LOAD;
|
||||
else
|
||||
load_op = MI_PREDICATE_LOADOP_LOADINV;
|
||||
|
||||
// batch emit
|
||||
uint32_t predicate = MI_PREDICATE | load_op |
|
||||
uint32_t mi_predicate = MI_PREDICATE |
|
||||
MI_PREDICATE_COMBINEOP_SET |
|
||||
MI_PREDICATE_COMPAREOP_SRCS_EQUAL;
|
||||
iris_batch_emit(batch, &predicate, sizeof(uint32_t));
|
||||
}
|
||||
MI_PREDICATE_COMPAREOP_SRCS_EQUAL |
|
||||
(inverted ? MI_PREDICATE_LOADOP_LOAD
|
||||
: MI_PREDICATE_LOADOP_LOADINV);
|
||||
iris_batch_emit(batch, &mi_predicate, sizeof(uint32_t));
|
||||
|
||||
/* We immediately set the predicate on the render batch, as all the
|
||||
* counters come from 3D operations. However, we may need to predicate
|
||||
* a compute dispatch, which executes in a different GEM context and has
|
||||
* a different MI_PREDICATE_DATA register. So, we save the result to
|
||||
* memory and reload it in iris_launch_grid.
|
||||
*/
|
||||
unsigned offset = offsetof(struct iris_query_snapshots, predicate_data);
|
||||
ice->vtbl.store_register_mem64(batch, MI_PREDICATE_DATA,
|
||||
q->bo, offset, false);
|
||||
ice->state.compute_predicate = q->bo;
|
||||
}
|
||||
|
||||
static void
|
||||
iris_render_condition(struct pipe_context *ctx,
|
||||
struct pipe_query *query,
|
||||
boolean condition,
|
||||
enum pipe_render_cond_flag mode)
|
||||
struct pipe_query *query,
|
||||
boolean condition,
|
||||
enum pipe_render_cond_flag mode)
|
||||
{
|
||||
struct iris_context *ice = (void *) ctx;
|
||||
struct iris_query *q = (void *) query;
|
||||
|
||||
if (!q) {
|
||||
ice->predicate = IRIS_PREDICATE_STATE_RENDER;
|
||||
ice->state.predicate = IRIS_PREDICATE_STATE_RENDER;
|
||||
return;
|
||||
}
|
||||
|
||||
iris_check_query_no_flush(ice, q);
|
||||
|
||||
if (q->result || q->ready)
|
||||
if (q->result || q->ready) {
|
||||
set_predicate_enable(ice, (q->result != 0) ^ condition);
|
||||
else
|
||||
} else {
|
||||
if (mode == PIPE_RENDER_COND_NO_WAIT ||
|
||||
mode == PIPE_RENDER_COND_BY_REGION_NO_WAIT) {
|
||||
perf_debug(&ice->dbg, "Conditional rendering demoted from "
|
||||
"\"no wait\" to \"wait\".");
|
||||
}
|
||||
set_predicate_for_result(ice, q, condition);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -4542,7 +4542,9 @@ iris_upload_render_state(struct iris_context *ice,
|
|||
prim.InstanceCount = draw->instance_count;
|
||||
prim.VertexCountPerInstance = draw->count;
|
||||
prim.VertexAccessType = draw->index_size > 0 ? RANDOM : SEQUENTIAL;
|
||||
prim.PredicateEnable = ice->predicate == IRIS_PREDICATE_STATE_USE_BIT ? 1 : 0;
|
||||
prim.PredicateEnable =
|
||||
ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT;
|
||||
|
||||
// XXX: this is probably bonkers.
|
||||
prim.StartVertexLocation = draw->start;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue