spirv: Use nir_var_mem_image
Use the new nir_var_mem_image mode for images that are not known to be used with a sampler (i.e. storage images). Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Reviewed-by: Jesse Natalie <jenatali@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4743>
This commit is contained in:

committed by
Marge Bot

parent
219ac26ea3
commit
cfdc7ee066
@@ -367,8 +367,10 @@ vtn_get_image(struct vtn_builder *b, uint32_t value_id,
|
||||
vtn_assert(type->base_type == vtn_base_type_image);
|
||||
if (access)
|
||||
*access |= spirv_to_gl_access_qualifier(b, type->access_qualifier);
|
||||
nir_variable_mode mode = glsl_type_is_image(type->glsl_image) ?
|
||||
nir_var_mem_image : nir_var_uniform;
|
||||
return nir_build_deref_cast(&b->nb, vtn_get_nir_ssa(b, value_id),
|
||||
nir_var_uniform, type->glsl_image, 0);
|
||||
mode, type->glsl_image, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -415,10 +417,16 @@ vtn_get_sampled_image(struct vtn_builder *b, uint32_t value_id)
|
||||
vtn_assert(type->base_type == vtn_base_type_sampled_image);
|
||||
nir_ssa_def *si_vec2 = vtn_get_nir_ssa(b, value_id);
|
||||
|
||||
/* Even though this is a sampled image, we can end up here with a storage
|
||||
* image because OpenCL doesn't distinguish between the two.
|
||||
*/
|
||||
const struct glsl_type *image_type = type->image->glsl_image;
|
||||
nir_variable_mode image_mode = glsl_type_is_image(image_type) ?
|
||||
nir_var_mem_image : nir_var_uniform;
|
||||
|
||||
struct vtn_sampled_image si = { NULL, };
|
||||
si.image = nir_build_deref_cast(&b->nb, nir_channel(&b->nb, si_vec2, 0),
|
||||
nir_var_uniform,
|
||||
type->image->glsl_image, 0);
|
||||
image_mode, image_type, 0);
|
||||
si.sampler = nir_build_deref_cast(&b->nb, nir_channel(&b->nb, si_vec2, 1),
|
||||
nir_var_uniform,
|
||||
glsl_bare_sampler_type(), 0);
|
||||
@@ -942,6 +950,7 @@ vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type,
|
||||
}
|
||||
|
||||
case vtn_base_type_image:
|
||||
vtn_assert(glsl_type_is_sampler(type->glsl_image));
|
||||
return type->glsl_image;
|
||||
|
||||
case vtn_base_type_sampler:
|
||||
@@ -955,6 +964,12 @@ vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type,
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == vtn_variable_mode_image) {
|
||||
struct vtn_type *image_type = vtn_type_without_array(type);
|
||||
vtn_assert(image_type->base_type == vtn_base_type_image);
|
||||
return wrap_type_in_array(image_type->glsl_image, type->type);
|
||||
}
|
||||
|
||||
/* Layout decorations are allowed but ignored in certain conditions,
|
||||
* to allow SPIR-V generators perform type deduplication. Discard
|
||||
* unnecessary ones when passing to NIR.
|
||||
@@ -2397,18 +2412,15 @@ vtn_mem_semantics_to_nir_var_modes(struct vtn_builder *b,
|
||||
SpvMemorySemanticsAtomicCounterMemoryMask);
|
||||
}
|
||||
|
||||
/* TODO: Consider adding nir_var_mem_image mode to NIR so it can be used
|
||||
* for SpvMemorySemanticsImageMemoryMask.
|
||||
*/
|
||||
|
||||
nir_variable_mode modes = 0;
|
||||
if (semantics & (SpvMemorySemanticsUniformMemoryMask |
|
||||
SpvMemorySemanticsImageMemoryMask)) {
|
||||
if (semantics & SpvMemorySemanticsUniformMemoryMask) {
|
||||
modes |= nir_var_uniform |
|
||||
nir_var_mem_ubo |
|
||||
nir_var_mem_ssbo |
|
||||
nir_var_mem_global;
|
||||
}
|
||||
if (semantics & SpvMemorySemanticsImageMemoryMask)
|
||||
modes |= nir_var_mem_image;
|
||||
if (semantics & SpvMemorySemanticsWorkgroupMemoryMask)
|
||||
modes |= nir_var_mem_shared;
|
||||
if (semantics & SpvMemorySemanticsCrossWorkgroupMemoryMask)
|
||||
@@ -6121,22 +6133,25 @@ vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,
|
||||
|
||||
/* input variable */
|
||||
nir_variable *in_var = rzalloc(b->nb.shader, nir_variable);
|
||||
in_var->data.mode = nir_var_uniform;
|
||||
in_var->data.read_only = true;
|
||||
in_var->data.location = i;
|
||||
if (param_type->base_type == vtn_base_type_image) {
|
||||
|
||||
if (is_by_val) {
|
||||
in_var->data.mode = nir_var_uniform;
|
||||
in_var->type = param_type->deref->type;
|
||||
} else if (param_type->base_type == vtn_base_type_image) {
|
||||
in_var->data.mode = nir_var_mem_image;
|
||||
in_var->type = param_type->glsl_image;
|
||||
in_var->data.access =
|
||||
spirv_to_gl_access_qualifier(b, param_type->access_qualifier);
|
||||
} else if (param_type->base_type == vtn_base_type_sampler) {
|
||||
in_var->data.mode = nir_var_uniform;
|
||||
in_var->type = glsl_bare_sampler_type();
|
||||
} else {
|
||||
in_var->data.mode = nir_var_uniform;
|
||||
in_var->type = param_type->type;
|
||||
}
|
||||
|
||||
if (is_by_val)
|
||||
in_var->type = param_type->deref->type;
|
||||
else if (param_type->base_type == vtn_base_type_image)
|
||||
in_var->type = param_type->glsl_image;
|
||||
else if (param_type->base_type == vtn_base_type_sampler)
|
||||
in_var->type = glsl_bare_sampler_type();
|
||||
else
|
||||
in_var->type = param_type->type;
|
||||
in_var->data.read_only = true;
|
||||
in_var->data.location = i;
|
||||
|
||||
nir_shader_add_variable(b->nb.shader, in_var);
|
||||
|
||||
|
@@ -597,7 +597,8 @@ _vtn_variable_load_store(struct vtn_builder *b, bool load,
|
||||
enum gl_access_qualifier access,
|
||||
struct vtn_ssa_value **inout)
|
||||
{
|
||||
if (ptr->mode == vtn_variable_mode_uniform) {
|
||||
if (ptr->mode == vtn_variable_mode_uniform ||
|
||||
ptr->mode == vtn_variable_mode_image) {
|
||||
if (ptr->type->base_type == vtn_base_type_image ||
|
||||
ptr->type->base_type == vtn_base_type_sampler) {
|
||||
/* See also our handling of OpTypeSampler and OpTypeImage */
|
||||
@@ -1415,7 +1416,8 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
|
||||
} else if (vtn_var->mode == vtn_variable_mode_call_data ||
|
||||
vtn_var->mode == vtn_variable_mode_ray_payload) {
|
||||
/* This location is fine as-is */
|
||||
} else if (vtn_var->mode != vtn_variable_mode_uniform) {
|
||||
} else if (vtn_var->mode != vtn_variable_mode_uniform &&
|
||||
vtn_var->mode != vtn_variable_mode_image) {
|
||||
vtn_warn("Location must be on input, output, uniform, sampler or "
|
||||
"image variable");
|
||||
return;
|
||||
@@ -1498,7 +1500,19 @@ vtn_storage_class_to_mode(struct vtn_builder *b,
|
||||
nir_mode = nir_var_mem_global;
|
||||
break;
|
||||
case SpvStorageClassUniformConstant:
|
||||
if (b->shader->info.stage == MESA_SHADER_KERNEL) {
|
||||
/* interface_type is only NULL when OpTypeForwardPointer is used and
|
||||
* OpTypeForwardPointer can only be used for struct types, not images or
|
||||
* acceleration structures.
|
||||
*/
|
||||
if (interface_type)
|
||||
interface_type = vtn_type_without_array(interface_type);
|
||||
|
||||
if (interface_type &&
|
||||
interface_type->base_type == vtn_base_type_image &&
|
||||
glsl_type_is_image(interface_type->glsl_image)) {
|
||||
mode = vtn_variable_mode_image;
|
||||
nir_mode = nir_var_mem_image;
|
||||
} else if (b->shader->info.stage == MESA_SHADER_KERNEL) {
|
||||
mode = vtn_variable_mode_constant;
|
||||
nir_mode = nir_var_mem_constant;
|
||||
} else {
|
||||
@@ -1507,7 +1521,6 @@ vtn_storage_class_to_mode(struct vtn_builder *b,
|
||||
* storage class.
|
||||
*/
|
||||
assert(interface_type != NULL);
|
||||
interface_type = vtn_type_without_array(interface_type);
|
||||
if (interface_type->base_type == vtn_base_type_accel_struct) {
|
||||
mode = vtn_variable_mode_accel_struct;
|
||||
nir_mode = nir_var_uniform;
|
||||
@@ -1551,7 +1564,7 @@ vtn_storage_class_to_mode(struct vtn_builder *b,
|
||||
break;
|
||||
case SpvStorageClassImage:
|
||||
mode = vtn_variable_mode_image;
|
||||
nir_mode = nir_var_mem_ubo;
|
||||
nir_mode = nir_var_mem_image;
|
||||
break;
|
||||
case SpvStorageClassCallableDataKHR:
|
||||
mode = vtn_variable_mode_call_data;
|
||||
@@ -1833,7 +1846,10 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
|
||||
break;
|
||||
|
||||
case vtn_variable_mode_image:
|
||||
vtn_fail("Cannot create a variable with the Image storage class");
|
||||
if (storage_class == SpvStorageClassImage)
|
||||
vtn_fail("Cannot create a variable with the Image storage class");
|
||||
else
|
||||
vtn_assert(storage_class == SpvStorageClassUniformConstant);
|
||||
break;
|
||||
|
||||
case vtn_variable_mode_phys_ssbo:
|
||||
@@ -1866,6 +1882,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
|
||||
case vtn_variable_mode_constant:
|
||||
case vtn_variable_mode_call_data:
|
||||
case vtn_variable_mode_call_data_in:
|
||||
case vtn_variable_mode_image:
|
||||
case vtn_variable_mode_ray_payload:
|
||||
case vtn_variable_mode_ray_payload_in:
|
||||
case vtn_variable_mode_hit_attrib:
|
||||
@@ -2006,7 +2023,6 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
|
||||
break;
|
||||
}
|
||||
|
||||
case vtn_variable_mode_image:
|
||||
case vtn_variable_mode_phys_ssbo:
|
||||
case vtn_variable_mode_generic:
|
||||
unreachable("Should have been caught before");
|
||||
@@ -2105,6 +2121,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
|
||||
}
|
||||
|
||||
if (var->mode == vtn_variable_mode_uniform ||
|
||||
var->mode == vtn_variable_mode_image ||
|
||||
var->mode == vtn_variable_mode_ssbo) {
|
||||
/* SSBOs and images are assumed to not alias in the Simple, GLSL and Vulkan memory models */
|
||||
var->var->data.access |= b->mem_model != SpvMemoryModelOpenCL ? ACCESS_RESTRICT : 0;
|
||||
@@ -2123,6 +2140,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
|
||||
}
|
||||
|
||||
if (var->mode == vtn_variable_mode_uniform ||
|
||||
var->mode == vtn_variable_mode_image ||
|
||||
var->mode == vtn_variable_mode_ubo ||
|
||||
var->mode == vtn_variable_mode_ssbo ||
|
||||
var->mode == vtn_variable_mode_atomic_counter) {
|
||||
|
Reference in New Issue
Block a user