spirv: Implement SPV_KHR_workgroup_memory_explicit_layout
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8699>
This commit is contained in:

committed by
Marge Bot

parent
a9d230077f
commit
5de6c5973a
@@ -2303,8 +2303,12 @@ nir_lower_vars_to_explicit_types(nir_shader *shader,
|
||||
|
||||
if (modes & nir_var_uniform)
|
||||
progress |= lower_vars_to_explicit(shader, &shader->variables, nir_var_uniform, type_info);
|
||||
if (modes & nir_var_mem_shared)
|
||||
|
||||
if (modes & nir_var_mem_shared) {
|
||||
assert(!shader->info.cs.shared_memory_explicit_layout);
|
||||
progress |= lower_vars_to_explicit(shader, &shader->variables, nir_var_mem_shared, type_info);
|
||||
}
|
||||
|
||||
if (modes & nir_var_shader_temp)
|
||||
progress |= lower_vars_to_explicit(shader, &shader->variables, nir_var_shader_temp, type_info);
|
||||
if (modes & nir_var_mem_constant)
|
||||
|
@@ -93,6 +93,7 @@ struct spirv_supported_capabilities {
|
||||
bool variable_pointers;
|
||||
bool vk_memory_model;
|
||||
bool vk_memory_model_device_scope;
|
||||
bool workgroup_memory_explicit_layout;
|
||||
bool float16;
|
||||
bool amd_fragment_mask;
|
||||
bool amd_gcn_shader;
|
||||
@@ -384,6 +385,12 @@ typedef struct shader_info {
|
||||
* Uses subgroup intrinsics which can communicate across a quad.
|
||||
*/
|
||||
bool uses_wide_subgroup_intrinsics;
|
||||
|
||||
/**
|
||||
* Shared memory types have explicit layout set. Used for
|
||||
* SPV_KHR_workgroup_storage_explicit_layout.
|
||||
*/
|
||||
bool shared_memory_explicit_layout;
|
||||
} cs;
|
||||
|
||||
/* Applies to both TCS and TES. */
|
||||
|
@@ -826,7 +826,8 @@ wrap_type_in_array(const struct glsl_type *type,
|
||||
}
|
||||
|
||||
static bool
|
||||
vtn_type_needs_explicit_layout(struct vtn_builder *b, enum vtn_variable_mode mode)
|
||||
vtn_type_needs_explicit_layout(struct vtn_builder *b, struct vtn_type *type,
|
||||
enum vtn_variable_mode mode)
|
||||
{
|
||||
/* For OpenCL we never want to strip the info from the types, and it makes
|
||||
* type comparisons easier in later stages.
|
||||
@@ -849,6 +850,9 @@ vtn_type_needs_explicit_layout(struct vtn_builder *b, enum vtn_variable_mode mod
|
||||
case vtn_variable_mode_shader_record:
|
||||
return true;
|
||||
|
||||
case vtn_variable_mode_workgroup:
|
||||
return b->options->caps.workgroup_memory_explicit_layout;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -922,7 +926,7 @@ vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type,
|
||||
* to allow SPIR-V generators perform type deduplication. Discard
|
||||
* unnecessary ones when passing to NIR.
|
||||
*/
|
||||
if (!vtn_type_needs_explicit_layout(b, mode))
|
||||
if (!vtn_type_needs_explicit_layout(b, type, mode))
|
||||
return glsl_get_bare_type(type->type);
|
||||
|
||||
return type->type;
|
||||
@@ -1575,16 +1579,20 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
|
||||
|
||||
val->type->deref = deref_type;
|
||||
|
||||
/* Only certain storage classes use ArrayStride. The others (in
|
||||
* particular Workgroup) are expected to be laid out by the driver.
|
||||
*/
|
||||
/* Only certain storage classes use ArrayStride. */
|
||||
switch (storage_class) {
|
||||
case SpvStorageClassWorkgroup:
|
||||
if (!b->options->caps.workgroup_memory_explicit_layout)
|
||||
break;
|
||||
FALLTHROUGH;
|
||||
|
||||
case SpvStorageClassUniform:
|
||||
case SpvStorageClassPushConstant:
|
||||
case SpvStorageClassStorageBuffer:
|
||||
case SpvStorageClassPhysicalStorageBuffer:
|
||||
vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
@@ -4539,6 +4547,20 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
|
||||
spv_check_supported(fragment_shading_rate, cap);
|
||||
break;
|
||||
|
||||
case SpvCapabilityWorkgroupMemoryExplicitLayoutKHR:
|
||||
spv_check_supported(workgroup_memory_explicit_layout, cap);
|
||||
break;
|
||||
|
||||
case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:
|
||||
spv_check_supported(workgroup_memory_explicit_layout, cap);
|
||||
spv_check_supported(storage_8bit, cap);
|
||||
break;
|
||||
|
||||
case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR:
|
||||
spv_check_supported(workgroup_memory_explicit_layout, cap);
|
||||
spv_check_supported(storage_16bit, cap);
|
||||
break;
|
||||
|
||||
default:
|
||||
vtn_fail("Unhandled capability: %s (%u)",
|
||||
spirv_capability_to_string(cap), cap);
|
||||
@@ -5968,6 +5990,27 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
|
||||
*/
|
||||
nir_opt_dce(b->shader);
|
||||
|
||||
/* Per SPV_KHR_workgroup_storage_explicit_layout, if one shared variable is
|
||||
* a Block, all of them will be and Blocks are explicitly laid out.
|
||||
*/
|
||||
nir_foreach_variable_with_modes(var, b->shader, nir_var_mem_shared) {
|
||||
if (glsl_type_is_interface(var->type)) {
|
||||
assert(b->options->caps.workgroup_memory_explicit_layout);
|
||||
b->shader->info.cs.shared_memory_explicit_layout = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (b->shader->info.cs.shared_memory_explicit_layout) {
|
||||
unsigned size = 0;
|
||||
nir_foreach_variable_with_modes(var, b->shader, nir_var_mem_shared) {
|
||||
assert(glsl_type_is_interface(var->type));
|
||||
const bool align_to_stride = false;
|
||||
size = MAX2(size, glsl_get_explicit_size(var->type, align_to_stride));
|
||||
}
|
||||
b->shader->info.cs.shared_size = size;
|
||||
b->shader->shared_size = size;
|
||||
}
|
||||
|
||||
/* Unparent the shader from the vtn_builder before we delete the builder */
|
||||
ralloc_steal(NULL, b->shader);
|
||||
|
||||
|
Reference in New Issue
Block a user