wip: crocus/rusticl/elk/hasvk local changes before h264 cherry-pick

This commit is contained in:
elwrcl committed 2026-07-21 14:26:36 +03:00
1 parent 60a99fd3d3
commit 7e82b85d19
35 files changed
+1177 -191

No files matched your search

+8 -4
View File
@@ -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
+8 -1
View File
@@ -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;
+11 -3
View File
@@ -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) {
+353 -10
View File
@@ -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
+23 -59
View File
@@ -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);
+96 -17
View File
@@ -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;