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:
Caio Marcelo de Oliveira Filho
2020-10-28 14:55:05 -07:00
committed by Marge Bot
parent a9d230077f
commit 5de6c5973a
3 changed files with 60 additions and 6 deletions

View File

@@ -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)

View File

@@ -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. */

View File

@@ -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);