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)
}
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.
case vtn_variable_mode_shader_record:
return true;
+ case vtn_variable_mode_workgroup:
+ return b->options->caps.workgroup_memory_explicit_layout;
+
default:
return false;
}
* 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;
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;
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);
*/
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);