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:
Caio Marcelo de Oliveira Filho
2021-07-02 01:01:45 -07:00
committed by Marge Bot
parent 219ac26ea3
commit cfdc7ee066
2 changed files with 61 additions and 28 deletions

View File

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

View File

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