mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-10-31 19:08:03 +03:00
wip: crocus/rusticl/elk/hasvk local changes before h264 cherry-pick
This commit is contained in:
35 files changed
+1177
-191
No files matched your search
@@ -301,7 +301,7 @@ ensure_exec_obj_space(struct crocus_batch *batch, uint32_t count)
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_i915_gem_exec_object2 *
|
||||
struct drm_i915_gem_exec_object2 *
|
||||
crocus_use_bo(struct crocus_batch *batch, struct crocus_bo *bo, bool writable)
|
||||
{
|
||||
assert(bo->bufmgr == batch->command.bo->bufmgr);
|
||||
@@ -458,7 +458,10 @@ recreate_growing_buffer(struct crocus_batch *batch,
|
||||
struct crocus_screen *screen = batch->screen;
|
||||
struct crocus_bufmgr *bufmgr = screen->bufmgr;
|
||||
grow->bo = crocus_bo_alloc(bufmgr, name, size);
|
||||
grow->bo->kflags |= EXEC_OBJECT_CAPTURE;
|
||||
static uint64_t next_grow_pin = 0x20000000ULL; /* 512MB */
|
||||
grow->bo->gtt_offset = next_grow_pin;
|
||||
next_grow_pin += align64(size, 4096);
|
||||
grow->bo->kflags |= EXEC_OBJECT_CAPTURE | EXEC_OBJECT_PINNED;
|
||||
grow->partial_bo = NULL;
|
||||
grow->partial_bo_map = NULL;
|
||||
grow->partial_bytes = 0;
|
||||
@@ -903,8 +906,9 @@ submit_batch(struct crocus_batch *batch)
|
||||
DBG("BO %d migrated: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
|
||||
bo->gem_handle, bo->gtt_offset,
|
||||
(uint64_t)batch->validation_list[i].offset);
|
||||
assert(!(bo->kflags & EXEC_OBJECT_PINNED));
|
||||
bo->gtt_offset = batch->validation_list[i].offset;
|
||||
if (!(bo->kflags & EXEC_OBJECT_PINNED)) {
|
||||
bo->gtt_offset = batch->validation_list[i].offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -200,6 +200,7 @@ bool crocus_batch_prepare_noop(struct crocus_batch *batch, bool noop_enable);
|
||||
/* Inverted meaning, but using the same bit...emit_reloc will flip it. */
|
||||
#define RELOC_32BIT EXEC_OBJECT_SUPPORTS_48B_ADDRESS
|
||||
|
||||
struct drm_i915_gem_exec_object2 *crocus_use_bo(struct crocus_batch *batch, struct crocus_bo *bo, bool writable);
|
||||
void crocus_use_pinned_bo(struct crocus_batch *batch, struct crocus_bo *bo,
|
||||
bool writable);
|
||||
uint64_t crocus_command_reloc(struct crocus_batch *batch, uint32_t batch_offset,
|
||||
|
||||
@@ -339,6 +339,7 @@ enum crocus_surface_group {
|
||||
CROCUS_SURFACE_GROUP_IMAGE,
|
||||
CROCUS_SURFACE_GROUP_UBO,
|
||||
CROCUS_SURFACE_GROUP_SSBO,
|
||||
CROCUS_SURFACE_GROUP_GLOBAL,
|
||||
|
||||
CROCUS_SURFACE_GROUP_COUNT,
|
||||
};
|
||||
@@ -608,6 +609,7 @@ struct crocus_context {
|
||||
struct crocus_state_ref grid_size;
|
||||
/** Global bindings for compute */
|
||||
struct pipe_resource *global_bindings[CROCUS_MAX_GLOBAL_BINDINGS];
|
||||
uint32_t *global_binding_handles[CROCUS_MAX_GLOBAL_BINDINGS];
|
||||
|
||||
/**
|
||||
* Array of aux usages for drawing, altered to account for any
|
||||
|
||||
@@ -517,9 +517,16 @@ crocus_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
|
||||
|
||||
crocus_handle_always_flush_cache(batch);
|
||||
|
||||
for (unsigned i = 0; i < CROCUS_MAX_GLOBAL_BINDINGS; i++) {
|
||||
if (ice->state.global_bindings[i]) {
|
||||
struct crocus_resource *res = (struct crocus_resource *)ice->state.global_bindings[i];
|
||||
crocus_use_bo(batch, res->bo, true);
|
||||
}
|
||||
}
|
||||
|
||||
screen->vtbl.upload_compute_state(ice, batch, grid);
|
||||
|
||||
crocus_handle_always_flush_cache(batch);
|
||||
crocus_flush_all_caches(batch);
|
||||
|
||||
ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_COMPUTE;
|
||||
ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE;
|
||||
|
||||
@@ -509,10 +509,18 @@ crocus_is_format_supported(struct pipe_screen *pscreen,
|
||||
/* Dataport doesn't support compression, and we can't resolve an MCS
|
||||
* compressed surface. (Buffer images may have sample count of 0.)
|
||||
*/
|
||||
supported &= sample_count == 0;
|
||||
bool sc_ok = sample_count == 0;
|
||||
bool tw_ok = isl_format_supports_typed_writes(devinfo, format);
|
||||
bool ts_ok = isl_has_matching_typed_storage_image_format(devinfo, format);
|
||||
supported &= sc_ok && tw_ok && ts_ok;
|
||||
|
||||
supported &= isl_format_supports_typed_writes(devinfo, format);
|
||||
supported &= isl_has_matching_typed_storage_image_format(devinfo, format);
|
||||
FILE *dbgf = fopen("/tmp/crocus_debug.log", "a");
|
||||
if (dbgf) {
|
||||
fprintf(dbgf, "CROCUS_DBG: shader_image check pformat=%d target=%d sample_count=%u "
|
||||
"isl_format=%d sc_ok=%d tw_ok=%d ts_ok=%d supported=%d\n",
|
||||
pformat, target, sample_count, format, sc_ok, tw_ok, ts_ok, supported);
|
||||
fclose(dbgf);
|
||||
}
|
||||
}
|
||||
|
||||
if (usage & PIPE_BIND_SAMPLER_VIEW) {
|
||||
|
||||
@@ -714,6 +714,7 @@ static const char *surface_group_names[] = {
|
||||
[CROCUS_SURFACE_GROUP_UBO] = "ubo",
|
||||
[CROCUS_SURFACE_GROUP_SSBO] = "ssbo",
|
||||
[CROCUS_SURFACE_GROUP_IMAGE] = "image",
|
||||
[CROCUS_SURFACE_GROUP_GLOBAL] = "global (IVB)",
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -842,7 +843,8 @@ crocus_setup_binding_table(const struct intel_device_info *devinfo,
|
||||
bt->used_mask[CROCUS_SURFACE_GROUP_RENDER_TARGET_READ] =
|
||||
BITFIELD64_MASK(num_render_targets);
|
||||
}
|
||||
} else if (info->stage == MESA_SHADER_COMPUTE) {
|
||||
} else if (info->stage == MESA_SHADER_COMPUTE ||
|
||||
info->stage == MESA_SHADER_KERNEL) {
|
||||
bt->sizes[CROCUS_SURFACE_GROUP_CS_WORK_GROUPS] = 1;
|
||||
} else if (info->stage == MESA_SHADER_GEOMETRY) {
|
||||
/* In gfx6 we reserve the first ELK_MAX_SOL_BINDINGS entries for transform
|
||||
@@ -2504,6 +2506,335 @@ crocus_update_compiled_shaders(struct crocus_context *ice)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* IVB Gen7 doesn't support stateless global memory access (BTI 255 is only
|
||||
* valid on Haswell+ / Gen7.5+). Instead of a dedicated global-memory BTI
|
||||
* (limited to 64 slots, and unable to distinguish multiple __global buffer
|
||||
* arguments since their kernel_input handles all resolve to address 0),
|
||||
* redirect every load_global/store_global to load_ssbo/store_ssbo.
|
||||
*
|
||||
* The address of a global access is always kernel_input UBO offset N
|
||||
* (optionally + a relative offset expression). N corresponds 1:1, in
|
||||
* increasing order, to rusticl's start_slot ordering in
|
||||
* crocus_set_global_binding() -- both are "the Nth __global buffer
|
||||
* argument that's actually used", skipping dead/scalar arguments. So we
|
||||
* assign SSBO index = rank of N among all distinct offsets seen.
|
||||
*/
|
||||
/* Pass 1 helper: find N in load_ubo(0,N), without building any new
|
||||
* instructions (safe to call speculatively during discovery). Handles
|
||||
* arbitrarily nested iadd chains, e.g. iadd(iadd(load_ubo(0,N), i*8), 4)
|
||||
* which occurs for struct field access (out[i].b). */
|
||||
/* Recursively determines whether following iadd chains from `def`
|
||||
* eventually reaches a load_ubo intrinsic. Unlike a shallow type check,
|
||||
* this actually walks the chain so mul/bcsel/etc. on the *other* branch
|
||||
* don't cause a false positive. */
|
||||
static bool
|
||||
crocus_def_leads_to_ubo(nir_def *def)
|
||||
{
|
||||
nir_instr *instr = nir_def_instr(def);
|
||||
|
||||
if (instr->type == nir_instr_type_intrinsic &&
|
||||
nir_instr_as_intrinsic(instr)->intrinsic == nir_intrinsic_load_ubo)
|
||||
return true;
|
||||
|
||||
if (instr->type == nir_instr_type_phi) {
|
||||
nir_phi_instr *phi = nir_instr_as_phi(instr);
|
||||
nir_foreach_phi_src(phi_src, phi) {
|
||||
if (!crocus_def_leads_to_ubo(phi_src->src.ssa))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (instr->type != nir_instr_type_alu)
|
||||
return false;
|
||||
|
||||
nir_alu_instr *alu = nir_instr_as_alu(instr);
|
||||
if (alu->op != nir_op_iadd)
|
||||
return false;
|
||||
|
||||
nir_def *lhs = alu->src[0].src.ssa;
|
||||
nir_def *rhs = alu->src[1].src.ssa;
|
||||
|
||||
return crocus_def_leads_to_ubo(lhs) || crocus_def_leads_to_ubo(rhs);
|
||||
}
|
||||
|
||||
static bool
|
||||
crocus_global_addr_find_ubo_offset(nir_src *addr_src, uint32_t *out_offset)
|
||||
{
|
||||
nir_def *cur = addr_src->ssa;
|
||||
|
||||
for (;;) {
|
||||
if (nir_def_instr(cur)->type == nir_instr_type_intrinsic &&
|
||||
nir_instr_as_intrinsic(nir_def_instr(cur))->intrinsic ==
|
||||
nir_intrinsic_load_ubo) {
|
||||
nir_intrinsic_instr *ld_ubo = nir_instr_as_intrinsic(nir_def_instr(cur));
|
||||
if (!nir_src_is_const(ld_ubo->src[1]))
|
||||
return false;
|
||||
*out_offset = nir_src_as_uint(ld_ubo->src[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Control-flow merge: all phi sources must resolve to the
|
||||
* same underlying UBO offset (i.e. the same buffer), only
|
||||
* the runtime-computed relative offset may differ per branch. */
|
||||
if (nir_def_instr(cur)->type == nir_instr_type_phi) {
|
||||
nir_phi_instr *phi = nir_instr_as_phi(nir_def_instr(cur));
|
||||
uint32_t phi_off;
|
||||
bool first = true;
|
||||
nir_foreach_phi_src(phi_src, phi) {
|
||||
uint32_t src_off;
|
||||
if (!crocus_global_addr_find_ubo_offset(&phi_src->src, &src_off))
|
||||
return false;
|
||||
if (first) {
|
||||
phi_off = src_off;
|
||||
first = false;
|
||||
} else if (src_off != phi_off) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*out_offset = phi_off;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nir_def_instr(cur)->type != nir_instr_type_alu)
|
||||
return false;
|
||||
|
||||
nir_alu_instr *alu = nir_instr_as_alu(nir_def_instr(cur));
|
||||
if (alu->op != nir_op_iadd)
|
||||
return false;
|
||||
|
||||
nir_def *lhs = alu->src[0].src.ssa;
|
||||
nir_def *rhs = alu->src[1].src.ssa;
|
||||
|
||||
if (crocus_def_leads_to_ubo(lhs))
|
||||
cur = lhs;
|
||||
else if (crocus_def_leads_to_ubo(rhs))
|
||||
cur = rhs;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 2 helper: rebuild the full relative offset expression (sum of
|
||||
* everything peeled off while descending to the load_ubo leaf). Must
|
||||
* only be called with b.cursor already positioned before the real
|
||||
* instruction being rewritten. */
|
||||
static nir_def *
|
||||
crocus_global_addr_build_rel_offset(nir_builder *b, nir_src *addr_src)
|
||||
{
|
||||
nir_def *cur = addr_src->ssa;
|
||||
nir_def *sum = NULL;
|
||||
|
||||
for (;;) {
|
||||
if (nir_def_instr(cur)->type == nir_instr_type_intrinsic &&
|
||||
nir_instr_as_intrinsic(nir_def_instr(cur))->intrinsic ==
|
||||
nir_intrinsic_load_ubo) {
|
||||
return sum ? sum : nir_imm_int(b, 0);
|
||||
}
|
||||
|
||||
if (nir_def_instr(cur)->type == nir_instr_type_phi) {
|
||||
nir_phi_instr *phi = nir_instr_as_phi(nir_def_instr(cur));
|
||||
nir_phi_instr *new_phi = nir_phi_instr_create(b->shader);
|
||||
nir_def_init(&new_phi->instr, &new_phi->def, 1, 32);
|
||||
|
||||
nir_foreach_phi_src(phi_src, phi) {
|
||||
nir_builder pb = *b;
|
||||
pb.cursor = nir_after_block_before_jump(phi_src->pred);
|
||||
nir_def *branch_off =
|
||||
crocus_global_addr_build_rel_offset(&pb, &phi_src->src);
|
||||
nir_phi_instr_add_src(new_phi, phi_src->pred, branch_off);
|
||||
}
|
||||
|
||||
nir_instr_insert_before(&phi->instr, &new_phi->instr);
|
||||
nir_def *phi_result = &new_phi->def;
|
||||
return sum ? nir_iadd(b, sum, phi_result) : phi_result;
|
||||
}
|
||||
|
||||
nir_alu_instr *alu = nir_instr_as_alu(nir_def_instr(cur));
|
||||
nir_def *lhs = alu->src[0].src.ssa;
|
||||
nir_def *rhs = alu->src[1].src.ssa;
|
||||
|
||||
bool follow_lhs = crocus_def_leads_to_ubo(lhs);
|
||||
nir_def *peeled = follow_lhs ? rhs : lhs;
|
||||
sum = sum ? nir_iadd(b, sum, peeled) : peeled;
|
||||
cur = follow_lhs ? lhs : rhs;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
crocus_lower_cs_global_to_ssbo(nir_shader *nir)
|
||||
{
|
||||
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
|
||||
|
||||
uint32_t offsets[64];
|
||||
unsigned num_offsets = 0;
|
||||
|
||||
/* Pass 1: discover every distinct kernel_input offset used as a
|
||||
* load_global/store_global base. */
|
||||
nir_foreach_block(block, impl) {
|
||||
nir_foreach_instr(instr, block) {
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
continue;
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
|
||||
nir_src *addr_src;
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_load_global:
|
||||
case nir_intrinsic_load_global_constant:
|
||||
addr_src = &intrin->src[0];
|
||||
break;
|
||||
case nir_intrinsic_store_global:
|
||||
addr_src = &intrin->src[1];
|
||||
break;
|
||||
case nir_intrinsic_global_atomic:
|
||||
case nir_intrinsic_global_atomic_swap:
|
||||
addr_src = &intrin->src[0];
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t off;
|
||||
if (!crocus_global_addr_find_ubo_offset(addr_src, &off)) {
|
||||
fprintf(stderr, "=== UNRECOGNIZED GLOBAL PATTERN (intrinsic: %s) ===\n",
|
||||
nir_intrinsic_infos[intrin->intrinsic].name);
|
||||
nir_print_instr(&intrin->instr, stderr);
|
||||
fprintf(stderr, "\n--- addr_src def ---\n");
|
||||
nir_print_instr(nir_def_instr(addr_src->ssa), stderr);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
assert(!"crocus: unrecognized __global address pattern on IVB");
|
||||
}
|
||||
|
||||
|
||||
bool found = false;
|
||||
for (unsigned i = 0; i < num_offsets; i++) {
|
||||
if (offsets[i] == off) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(num_offsets < ARRAY_SIZE(offsets));
|
||||
offsets[num_offsets++] = off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_offsets == 0)
|
||||
return false;
|
||||
|
||||
/* Sort ascending: SSBO index = rank, matching rusticl's start_slot order */
|
||||
for (unsigned i = 1; i < num_offsets; i++) {
|
||||
uint32_t key = offsets[i];
|
||||
int j = i - 1;
|
||||
while (j >= 0 && offsets[j] > key) {
|
||||
offsets[j + 1] = offsets[j];
|
||||
j--;
|
||||
}
|
||||
offsets[j + 1] = key;
|
||||
}
|
||||
|
||||
/* Pass 2: rewrite load_global/store_global -> load_ssbo/store_ssbo */
|
||||
nir_builder b = nir_builder_create(impl);
|
||||
|
||||
nir_foreach_block_safe(block, impl) {
|
||||
nir_foreach_instr_safe(instr, block) {
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
continue;
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
|
||||
nir_src *addr_src;
|
||||
enum { OP_LOAD, OP_STORE, OP_ATOMIC, OP_ATOMIC_SWAP } kind;
|
||||
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_load_global:
|
||||
case nir_intrinsic_load_global_constant:
|
||||
kind = OP_LOAD;
|
||||
addr_src = &intrin->src[0];
|
||||
break;
|
||||
case nir_intrinsic_store_global:
|
||||
kind = OP_STORE;
|
||||
addr_src = &intrin->src[1];
|
||||
break;
|
||||
case nir_intrinsic_global_atomic:
|
||||
kind = OP_ATOMIC;
|
||||
addr_src = &intrin->src[0];
|
||||
break;
|
||||
case nir_intrinsic_global_atomic_swap:
|
||||
kind = OP_ATOMIC_SWAP;
|
||||
addr_src = &intrin->src[0];
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
b.cursor = nir_before_instr(instr);
|
||||
|
||||
uint32_t off;
|
||||
if (!crocus_global_addr_find_ubo_offset(addr_src, &off))
|
||||
assert(!"crocus: unrecognized __global address pattern on IVB");
|
||||
|
||||
nir_def *rel = crocus_global_addr_build_rel_offset(&b, addr_src);
|
||||
|
||||
unsigned ssbo_idx = 0;
|
||||
bool found = false;
|
||||
for (unsigned i = 0; i < num_offsets; i++) {
|
||||
if (offsets[i] == off) {
|
||||
ssbo_idx = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(found);
|
||||
|
||||
nir_def *idx_ssa = nir_imm_int(&b, ssbo_idx);
|
||||
nir_def *off_ssa = rel ? rel : nir_imm_int(&b, 0);
|
||||
|
||||
switch (kind) {
|
||||
case OP_LOAD: {
|
||||
nir_def *result =
|
||||
nir_load_ssbo(&b, intrin->def.num_components,
|
||||
intrin->def.bit_size, idx_ssa, off_ssa,
|
||||
.access = nir_intrinsic_access(intrin),
|
||||
.align_mul = nir_intrinsic_align_mul(intrin),
|
||||
.align_offset = nir_intrinsic_align_offset(intrin));
|
||||
nir_def_replace(&intrin->def, result);
|
||||
break;
|
||||
}
|
||||
case OP_STORE:
|
||||
nir_store_ssbo(&b, intrin->src[0].ssa, idx_ssa, off_ssa,
|
||||
.write_mask = nir_intrinsic_write_mask(intrin),
|
||||
.access = nir_intrinsic_access(intrin),
|
||||
.align_mul = nir_intrinsic_align_mul(intrin),
|
||||
.align_offset = nir_intrinsic_align_offset(intrin));
|
||||
nir_instr_remove(instr);
|
||||
break;
|
||||
case OP_ATOMIC: {
|
||||
nir_def *result =
|
||||
nir_ssbo_atomic(&b, intrin->def.bit_size, idx_ssa, off_ssa,
|
||||
intrin->src[1].ssa,
|
||||
.atomic_op = nir_intrinsic_atomic_op(intrin));
|
||||
nir_def_replace(&intrin->def, result);
|
||||
break;
|
||||
}
|
||||
case OP_ATOMIC_SWAP: {
|
||||
nir_def *result =
|
||||
nir_ssbo_atomic_swap(&b, intrin->def.bit_size, idx_ssa, off_ssa,
|
||||
intrin->src[1].ssa, intrin->src[2].ssa,
|
||||
.atomic_op = nir_intrinsic_atomic_op(intrin));
|
||||
nir_def_replace(&intrin->def, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nir->info.num_ssbos = num_offsets;
|
||||
nir_progress(true, impl, nir_metadata_none);
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct crocus_compiled_shader *
|
||||
crocus_compile_cs(struct crocus_context *ice,
|
||||
struct crocus_uncompiled_shader *ish,
|
||||
@@ -2522,6 +2853,9 @@ crocus_compile_cs(struct crocus_context *ice,
|
||||
|
||||
nir_shader *nir = nir_shader_clone(mem_ctx, ish->nir);
|
||||
|
||||
if (devinfo->ver < 8)
|
||||
NIR_PASS(_, nir, crocus_lower_cs_global_to_ssbo);
|
||||
|
||||
NIR_PASS(_, nir, elk_nir_lower_cs_intrinsics, devinfo, cs_prog_data);
|
||||
|
||||
crocus_setup_uniforms(devinfo, mem_ctx, nir, prog_data, &system_values,
|
||||
@@ -2620,11 +2954,14 @@ crocus_fill_cs_push_const_buffer(struct elk_cs_prog_data *cs_prog_data,
|
||||
uint32_t *dst)
|
||||
{
|
||||
assert(elk_cs_push_const_total_size(cs_prog_data, threads) > 0);
|
||||
assert(cs_prog_data->push.cross_thread.size == 0);
|
||||
assert(cs_prog_data->push.per_thread.dwords == 1);
|
||||
assert(cs_prog_data->base.param[0] == ELK_PARAM_BUILTIN_SUBGROUP_ID);
|
||||
for (unsigned t = 0; t < threads; t++)
|
||||
dst[8 * t] = t;
|
||||
|
||||
/* per_thread: subgroup_id -- cross_thread dwords'den sonra yaz */
|
||||
if (cs_prog_data->push.per_thread.dwords == 1 &&
|
||||
cs_prog_data->base.param[0] == ELK_PARAM_BUILTIN_SUBGROUP_ID) {
|
||||
unsigned cross_dwords = cs_prog_data->push.cross_thread.dwords;
|
||||
for (unsigned t = 0; t < threads; t++)
|
||||
dst[cross_dwords + 8 * t] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2906,6 +3243,9 @@ crocus_create_compute_state(struct pipe_context *ctx,
|
||||
struct crocus_uncompiled_shader *ish =
|
||||
crocus_create_uncompiled_shader(ctx, (void *) state->prog, NULL);
|
||||
|
||||
if (ish->nir->info.stage == MESA_SHADER_KERNEL)
|
||||
ish->nir->info.stage = MESA_SHADER_COMPUTE;
|
||||
|
||||
ish->nos |= (1ull << CROCUS_NOS_TEXTURES);
|
||||
// XXX: disallow more than 64KB of shared variables
|
||||
|
||||
@@ -3112,11 +3452,14 @@ crocus_get_compute_state_info(struct pipe_context *ctx, void *state,
|
||||
struct pipe_compute_state_object_info *info)
|
||||
{
|
||||
struct crocus_screen *screen = (void *) ctx->screen;
|
||||
info->max_threads = screen->devinfo.max_cs_threads *
|
||||
screen->devinfo.subslice_total;
|
||||
const struct intel_device_info *devinfo = &screen->devinfo;
|
||||
|
||||
const uint32_t simd_width = devinfo->ver >= 8 ? 32 : 8;
|
||||
|
||||
info->max_threads = simd_width * devinfo->max_cs_workgroup_threads;
|
||||
info->private_memory = 0;
|
||||
info->preferred_simd_size = 16;
|
||||
info->simd_sizes = 8 | 16;
|
||||
info->preferred_simd_size = simd_width;
|
||||
info->simd_sizes = devinfo->ver >= 8 ? (8 | 16 | 32) : (8 | 16);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -203,7 +203,12 @@ crocus_init_compute_caps(struct crocus_screen *screen)
|
||||
if (devinfo->ver < 7)
|
||||
return;
|
||||
|
||||
const uint32_t max_invocations = 32 * devinfo->max_cs_workgroup_threads;
|
||||
/* Gen7 (IVB/BYT/HSW) compute dispatch max SIMD width is 8;
|
||||
* Gfx9+ can reach SIMD32. Using 32 unconditionally overreports
|
||||
* the work-group size on Gen7 (2048 instead of the real 512).
|
||||
*/
|
||||
const uint32_t simd_width = devinfo->ver >= 8 ? 32 : 8;
|
||||
const uint32_t max_invocations = simd_width * devinfo->max_cs_workgroup_threads;
|
||||
|
||||
caps->address_bits = 32;
|
||||
|
||||
@@ -227,6 +232,22 @@ crocus_init_compute_caps(struct crocus_screen *screen)
|
||||
caps->subgroup_sizes = ELK_SUBGROUP_SIZE;
|
||||
|
||||
caps->max_variable_threads_per_block = max_invocations;
|
||||
|
||||
caps->max_compute_units = intel_device_info_eu_total(devinfo) > 0
|
||||
? intel_device_info_eu_total(devinfo)
|
||||
: (devinfo->gt == 2 ? 16 : 6);
|
||||
|
||||
/* Gen7 supports up to 2GB (1 << 31) buffers via stateless access.
|
||||
* Limit to 1GB to be safe with 32-bit addressing.
|
||||
*/
|
||||
caps->max_global_size = 1ULL << 30; /* 1 GB */
|
||||
caps->max_mem_alloc_size = 1ULL << 29; /* 512 MB — meets CL min for non-CUSTOM */
|
||||
|
||||
caps->max_clock_frequency = 1300; /* MHz, approximate for IVB GT2 */
|
||||
/* Gen7+ has a real, physically separate Shared Local Memory block
|
||||
* (accessed via Binding Table Index 254), unlike architectures where
|
||||
* "local" memory is just a region of global memory. */
|
||||
caps->has_dedicated_local_mem = true;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -289,6 +310,7 @@ crocus_init_screen_caps(struct crocus_screen *screen)
|
||||
caps->gl_clamp = true;
|
||||
caps->legacy_math_rules = true;
|
||||
caps->native_fence_fd = true;
|
||||
caps->cl_gl_sharing = true;
|
||||
|
||||
caps->int64 =
|
||||
caps->shader_ballot =
|
||||
@@ -493,63 +515,7 @@ crocus_query_memory_info(struct pipe_screen *pscreen,
|
||||
info->avail_staging_memory = info->total_staging_memory;
|
||||
}
|
||||
|
||||
static int
|
||||
crocus_get_compute_param(struct pipe_screen *pscreen,
|
||||
enum pipe_shader_ir ir_type,
|
||||
enum pipe_compute_cap param,
|
||||
void *ret)
|
||||
{
|
||||
struct crocus_screen *screen = (struct crocus_screen *) pscreen;
|
||||
const struct intel_device_info *devinfo = &screen->devinfo;
|
||||
|
||||
switch (param) {
|
||||
case PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS:
|
||||
if (ret) {
|
||||
uint32_t num_eu = devinfo->num_eu_total > 0 ? devinfo->num_eu_total : ((devinfo->gt == 2) ? 16 : 6);
|
||||
((uint32_t *)ret)[0] = num_eu;
|
||||
}
|
||||
return sizeof(uint32_t);
|
||||
|
||||
case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
|
||||
if (ret)
|
||||
((uint64_t *)ret)[0] = 1024;
|
||||
return sizeof(uint64_t);
|
||||
|
||||
case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:
|
||||
if (ret) {
|
||||
((uint64_t *)ret)[0] = 65535;
|
||||
((uint64_t *)ret)[1] = 65535;
|
||||
((uint64_t *)ret)[2] = 65535;
|
||||
}
|
||||
return 3 * sizeof(uint64_t);
|
||||
|
||||
case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE:
|
||||
if (ret) {
|
||||
((uint64_t *)ret)[0] = 1024;
|
||||
((uint64_t *)ret)[1] = 1024;
|
||||
((uint64_t *)ret)[2] = 1024;
|
||||
}
|
||||
return 3 * sizeof(uint64_t);
|
||||
|
||||
case PIPE_COMPUTE_CAP_PREFERRED_BLOCK_SIZE:
|
||||
if (ret)
|
||||
((uint64_t *)ret)[0] = 256;
|
||||
return sizeof(uint64_t);
|
||||
|
||||
case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED:
|
||||
if (ret)
|
||||
((uint32_t *)ret)[0] = 1;
|
||||
return sizeof(uint32_t);
|
||||
|
||||
case PIPE_COMPUTE_CAP_SUBGROUP_SIZE:
|
||||
if (ret)
|
||||
((uint32_t *)ret)[0] = devinfo->subgroup_size ? devinfo->subgroup_size : 16;
|
||||
return sizeof(uint32_t);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct disk_cache *
|
||||
crocus_get_disk_shader_cache(struct pipe_screen *pscreen)
|
||||
@@ -720,8 +686,6 @@ crocus_screen_create(int fd, const struct pipe_screen_config *config)
|
||||
pscreen->query_memory_info = crocus_query_memory_info;
|
||||
pscreen->get_driver_query_group_info = crocus_get_monitor_group_info;
|
||||
pscreen->get_driver_query_info = crocus_get_monitor_info;
|
||||
pscreen->get_compute_param = crocus_get_compute_param;
|
||||
|
||||
crocus_init_shader_caps(screen);
|
||||
crocus_init_compute_caps(screen);
|
||||
crocus_init_screen_caps(screen);
|
||||
|
||||
@@ -5513,6 +5513,35 @@ crocus_populate_binding_table(struct crocus_context *ice,
|
||||
s++;
|
||||
}
|
||||
|
||||
/* IVB Gen7: emit one surface per global binding using actual BO address.
|
||||
* handle[] holds relative offset (0), surface base = BO gtt address.
|
||||
* store_global(val, abs_addr) works because abs_addr = gtt_offset + rel,
|
||||
* and surface base = gtt_offset, so hw writes to gtt_offset + rel. */
|
||||
foreach_surface_used(i, CROCUS_SURFACE_GROUP_GLOBAL) {
|
||||
struct isl_device *isl_dev_g = &batch->screen->isl_dev;
|
||||
uint32_t g_offset = 0;
|
||||
uint32_t *g_surf = stream_state(batch, isl_dev_g->ss.size,
|
||||
isl_dev_g->ss.align, &g_offset);
|
||||
struct pipe_resource *global_res = ice->state.global_bindings[i];
|
||||
if (global_res) {
|
||||
struct crocus_resource *gres = (struct crocus_resource *) global_res;
|
||||
isl_buffer_fill_state(isl_dev_g, g_surf,
|
||||
.address = crocus_state_reloc(batch,
|
||||
g_offset + isl_dev_g->ss.addr_offset,
|
||||
gres->bo, 0,
|
||||
RELOC_32BIT | RELOC_WRITE),
|
||||
.size_B = gres->bo->size,
|
||||
.format = ISL_FORMAT_RAW,
|
||||
.swizzle = ISL_SWIZZLE_IDENTITY,
|
||||
.stride_B = 1,
|
||||
.mocs = crocus_mocs(gres->bo, isl_dev_g));
|
||||
} else {
|
||||
emit_null_surface(batch, &g_offset);
|
||||
}
|
||||
surf_offsets[s] = g_offset;
|
||||
s++;
|
||||
}
|
||||
|
||||
}
|
||||
/* ------------------------------------------------------------------- */
|
||||
static uint32_t
|
||||
@@ -5544,6 +5573,7 @@ crocus_update_surface_base_address(struct crocus_batch *batch)
|
||||
crocus_emit_cmd(batch, GENX(STATE_BASE_ADDRESS), sba) {
|
||||
/* Set base addresses */
|
||||
sba.GeneralStateBaseAddressModifyEnable = true;
|
||||
sba.GeneralStateBaseAddress = ro_bo(batch->state.bo, 0);
|
||||
|
||||
#if GFX_VER >= 6
|
||||
sba.DynamicStateBaseAddressModifyEnable = true;
|
||||
@@ -5587,6 +5617,7 @@ crocus_update_surface_base_address(struct crocus_batch *batch)
|
||||
*/
|
||||
sba.DynamicStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
||||
sba.DynamicStateAccessUpperBoundModifyEnable = true;
|
||||
sba.GeneralStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
||||
#else
|
||||
/* Same idea but using General State Base Address on Gen4-5 */
|
||||
sba.GeneralStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
||||
@@ -5598,7 +5629,10 @@ crocus_update_surface_base_address(struct crocus_batch *batch)
|
||||
* if you don't set the "Address Modify Enable" bit for the base.
|
||||
*/
|
||||
sba.GeneralStateMOCS = mocs;
|
||||
sba.StatelessDataPortAccessMOCS = mocs;
|
||||
sba.StatelessDataPortAccessMOCS = mocs ? mocs : 1; /* Try L3 cacheable if 0 */
|
||||
#if GFX_VERx10 == 70
|
||||
sba.StatelessDataPortAccessForceWriteThru = true;
|
||||
#endif
|
||||
sba.DynamicStateMOCS = mocs;
|
||||
sba.IndirectObjectMOCS = mocs;
|
||||
sba.InstructionMOCS = mocs;
|
||||
@@ -8073,8 +8107,15 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
||||
elk_cs_get_dispatch_info(devinfo, cs_prog_data, grid->block);
|
||||
|
||||
crocus_update_surface_base_address(batch);
|
||||
if ((stage_dirty & CROCUS_STAGE_DIRTY_CONSTANTS_CS) && shs->sysvals_need_upload)
|
||||
if ((stage_dirty & CROCUS_STAGE_DIRTY_CONSTANTS_CS) && shs->sysvals_need_upload) {
|
||||
for (unsigned i = 0; i < CROCUS_MAX_GLOBAL_BINDINGS; i++) {
|
||||
if (ice->state.global_bindings[i]) {
|
||||
struct crocus_resource *res = (struct crocus_resource *) ice->state.global_bindings[i];
|
||||
crocus_use_bo(batch, res->bo, true);
|
||||
}
|
||||
}
|
||||
upload_sysvals(ice, MESA_SHADER_COMPUTE);
|
||||
}
|
||||
|
||||
if (stage_dirty & CROCUS_STAGE_DIRTY_BINDINGS_CS) {
|
||||
crocus_populate_binding_table(ice, batch, MESA_SHADER_COMPUTE, false);
|
||||
@@ -8145,13 +8186,10 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Combine subgroup-id with cbuf0 so we can push regular uniforms */
|
||||
/* Push cross_thread (kernel args) + per_thread (subgroup_id) to CURBE */
|
||||
if ((stage_dirty & CROCUS_STAGE_DIRTY_CS) ||
|
||||
cs_prog_data->local_size[0] == 0 /* Variable local group size */) {
|
||||
uint32_t curbe_data_offset = 0;
|
||||
assert(cs_prog_data->push.cross_thread.dwords == 0 &&
|
||||
cs_prog_data->push.per_thread.dwords == 1 &&
|
||||
cs_prog_data->base.param[0] == ELK_PARAM_BUILTIN_SUBGROUP_ID);
|
||||
const unsigned push_const_size =
|
||||
elk_cs_push_const_total_size(cs_prog_data, dispatch.threads);
|
||||
uint32_t *curbe_data_map =
|
||||
@@ -8160,6 +8198,24 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
||||
&curbe_data_offset);
|
||||
assert(curbe_data_map);
|
||||
memset(curbe_data_map, 0x5a, align(push_const_size, 64));
|
||||
|
||||
if (cs_prog_data->push.cross_thread.size > 0) {
|
||||
struct pipe_constant_buffer *cbuf = &shs->constbufs[0];
|
||||
if (cbuf->user_buffer) {
|
||||
memcpy(curbe_data_map, cbuf->user_buffer,
|
||||
cs_prog_data->push.cross_thread.size);
|
||||
} else if (cbuf->buffer) {
|
||||
struct crocus_resource *res =
|
||||
(struct crocus_resource *) cbuf->buffer;
|
||||
void *map = crocus_bo_map(NULL, res->bo, MAP_READ);
|
||||
if (map) {
|
||||
memcpy(curbe_data_map,
|
||||
(uint8_t *)map + cbuf->buffer_offset,
|
||||
cs_prog_data->push.cross_thread.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crocus_fill_cs_push_const_buffer(cs_prog_data, dispatch.threads,
|
||||
curbe_data_map);
|
||||
|
||||
@@ -8184,7 +8240,8 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
||||
idd.ConstantURBEntryReadLength = cs_prog_data->push.per_thread.regs;
|
||||
idd.BarrierEnable = cs_prog_data->uses_barrier;
|
||||
idd.SharedLocalMemorySize = intel_compute_slm_encode_size(GFX_VER,
|
||||
prog_data->total_shared);
|
||||
prog_data->total_shared +
|
||||
grid->variable_shared_mem);
|
||||
#if GFX_VERx10 >= 75
|
||||
idd.CrossThreadConstantDataReadLength = cs_prog_data->push.cross_thread.regs;
|
||||
#endif
|
||||
@@ -8279,6 +8336,11 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
||||
|
||||
crocus_emit_cmd(batch, GENX(MEDIA_STATE_FLUSH), msf);
|
||||
|
||||
crocus_emit_pipe_control_flush(batch,
|
||||
"compute: flush DC after GPGPU_WALKER",
|
||||
PIPE_CONTROL_DATA_CACHE_FLUSH |
|
||||
PIPE_CONTROL_CS_STALL);
|
||||
|
||||
batch->contains_draw = true;
|
||||
}
|
||||
|
||||
@@ -8286,23 +8348,40 @@ static void
|
||||
crocus_set_global_binding(struct pipe_context *ctx,
|
||||
unsigned start_slot, unsigned count,
|
||||
struct pipe_resource **resources,
|
||||
uint32_t **handles)
|
||||
{
|
||||
uint32_t **handles) {
|
||||
struct crocus_context *ice = (struct crocus_context *) ctx;
|
||||
assert(start_slot + count <= CROCUS_MAX_GLOBAL_BINDINGS);
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (resources && resources[i]) {
|
||||
pipe_resource_reference(&ice->state.global_bindings[start_slot + i],
|
||||
resources[i]);
|
||||
struct crocus_resource *res = (struct crocus_resource *) resources[i];
|
||||
assert(res->base.b.target == PIPE_BUFFER);
|
||||
uint32_t addr = 0;
|
||||
memcpy(&addr, handles[i], sizeof(addr));
|
||||
addr += res->bo->gtt_offset;
|
||||
memcpy(handles[i], &addr, sizeof(addr));
|
||||
pipe_resource_reference(&ice->state.global_bindings[start_slot + i],
|
||||
resources[i]);
|
||||
struct crocus_resource *res = (struct crocus_resource *) resources[i];
|
||||
assert(res->base.b.target == PIPE_BUFFER);
|
||||
/* IVB: handle = 0 (offset from BO base = 0).
|
||||
* Surface base = BO real address via reloc.
|
||||
* store_global(val, 0 + i*4) -> surface[base=real_addr][offset=i*4] */
|
||||
|
||||
uint32_t addr = 0;
|
||||
memcpy(handles[i], &addr, sizeof(addr));
|
||||
ice->state.global_binding_handles[start_slot + i] = NULL;
|
||||
|
||||
/* IVB: also bind as SSBO at the same index, for the load_global ->
|
||||
* load_ssbo NIR redirect pass (crocus_lower_cs_global_to_ssbo). */
|
||||
struct crocus_shader_state *cs_shs =
|
||||
&ice->state.shaders[MESA_SHADER_COMPUTE];
|
||||
struct pipe_shader_buffer *ssbo = &cs_shs->ssbo[start_slot + i];
|
||||
pipe_resource_reference(&ssbo->buffer, &res->base.b);
|
||||
ssbo->buffer_offset = res->offset;
|
||||
ssbo->buffer_size = res->bo->size - res->offset;
|
||||
cs_shs->bound_ssbos |= 1u << (start_slot + i);
|
||||
cs_shs->writable_ssbos |= 1u << (start_slot + i);
|
||||
res->bind_history |= PIPE_BIND_SHADER_BUFFER;
|
||||
res->bind_stages |= 1u << MESA_SHADER_COMPUTE;
|
||||
} else {
|
||||
pipe_resource_reference(&ice->state.global_bindings[start_slot + i],
|
||||
NULL);
|
||||
ice->state.global_binding_handles[start_slot + i] = NULL;
|
||||
}
|
||||
}
|
||||
ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_BINDINGS_CS;
|
||||
|
||||
Reference in new issue
Block a user