nir/vtn: Add support for kernel images to SPIRV-to-NIR.
There's a few quirks: kernel images are untyped, whether they're sampled is unknown, and they're passed as inputs to the kernel even though SPIR-V declares their address space as UniformConstant. Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5242>
This commit is contained in:
@@ -167,6 +167,14 @@ DECL_TYPE(uimageCubeArray, GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE
|
|||||||
DECL_TYPE(uimage2DMS, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT)
|
DECL_TYPE(uimage2DMS, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT)
|
||||||
DECL_TYPE(uimage2DMSArray, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT)
|
DECL_TYPE(uimage2DMSArray, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT)
|
||||||
|
|
||||||
|
/* OpenCL image types */
|
||||||
|
DECL_TYPE(vbuffer, GL_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_VOID)
|
||||||
|
DECL_TYPE(vimage1D, GL_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_VOID)
|
||||||
|
DECL_TYPE(vimage2D, GL_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_VOID)
|
||||||
|
DECL_TYPE(vimage3D, GL_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_VOID)
|
||||||
|
DECL_TYPE(vimage1DArray, GL_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_VOID)
|
||||||
|
DECL_TYPE(vimage2DArray, GL_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_VOID)
|
||||||
|
|
||||||
DECL_TYPE(subpassInput, 0, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_SUBPASS, 0, 0, GLSL_TYPE_FLOAT)
|
DECL_TYPE(subpassInput, 0, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_SUBPASS, 0, 0, GLSL_TYPE_FLOAT)
|
||||||
DECL_TYPE(subpassInputMS, 0, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_SUBPASS_MS, 0, 0, GLSL_TYPE_FLOAT)
|
DECL_TYPE(subpassInputMS, 0, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_SUBPASS_MS, 0, 0, GLSL_TYPE_FLOAT)
|
||||||
DECL_TYPE(isubpassInput, 0, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_SUBPASS, 0, 0, GLSL_TYPE_INT)
|
DECL_TYPE(isubpassInput, 0, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_SUBPASS, 0, 0, GLSL_TYPE_INT)
|
||||||
|
@@ -1018,6 +1018,19 @@ glsl_type::get_image_instance(enum glsl_sampler_dim dim,
|
|||||||
case GLSL_SAMPLER_DIM_EXTERNAL:
|
case GLSL_SAMPLER_DIM_EXTERNAL:
|
||||||
return error_type;
|
return error_type;
|
||||||
}
|
}
|
||||||
|
case GLSL_TYPE_VOID:
|
||||||
|
switch (dim) {
|
||||||
|
case GLSL_SAMPLER_DIM_1D:
|
||||||
|
return (array ? vimage1DArray_type : vimage1D_type);
|
||||||
|
case GLSL_SAMPLER_DIM_2D:
|
||||||
|
return (array ? vimage2DArray_type : vimage2D_type);
|
||||||
|
case GLSL_SAMPLER_DIM_3D:
|
||||||
|
return (array ? error_type : vimage3D_type);
|
||||||
|
case GLSL_SAMPLER_DIM_BUF:
|
||||||
|
return (array ? error_type : vbuffer_type);
|
||||||
|
default:
|
||||||
|
return error_type;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return error_type;
|
return error_type;
|
||||||
}
|
}
|
||||||
|
@@ -57,6 +57,7 @@ struct spirv_supported_capabilities {
|
|||||||
bool int64_atomics;
|
bool int64_atomics;
|
||||||
bool integer_functions2;
|
bool integer_functions2;
|
||||||
bool kernel;
|
bool kernel;
|
||||||
|
bool kernel_image;
|
||||||
bool min_lod;
|
bool min_lod;
|
||||||
bool multiview;
|
bool multiview;
|
||||||
bool physical_storage_buffer_address;
|
bool physical_storage_buffer_address;
|
||||||
|
@@ -1569,9 +1569,14 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
|
|||||||
vtn_mode_to_address_format(b, vtn_variable_mode_function));
|
vtn_mode_to_address_format(b, vtn_variable_mode_function));
|
||||||
|
|
||||||
const struct vtn_type *sampled_type = vtn_get_type(b, w[2]);
|
const struct vtn_type *sampled_type = vtn_get_type(b, w[2]);
|
||||||
|
if (b->shader->info.stage == MESA_SHADER_KERNEL) {
|
||||||
|
vtn_fail_if(sampled_type->base_type != vtn_base_type_void,
|
||||||
|
"Sampled type of OpTypeImage must be void for kernels");
|
||||||
|
} else {
|
||||||
vtn_fail_if(sampled_type->base_type != vtn_base_type_scalar ||
|
vtn_fail_if(sampled_type->base_type != vtn_base_type_scalar ||
|
||||||
glsl_get_bit_size(sampled_type->type) != 32,
|
glsl_get_bit_size(sampled_type->type) != 32,
|
||||||
"Sampled type of OpTypeImage must be a 32-bit scalar");
|
"Sampled type of OpTypeImage must be a 32-bit scalar");
|
||||||
|
}
|
||||||
|
|
||||||
enum glsl_sampler_dim dim;
|
enum glsl_sampler_dim dim;
|
||||||
switch ((SpvDim)w[3]) {
|
switch ((SpvDim)w[3]) {
|
||||||
@@ -1597,6 +1602,9 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
|
|||||||
|
|
||||||
if (count > 9)
|
if (count > 9)
|
||||||
val->type->access_qualifier = w[9];
|
val->type->access_qualifier = w[9];
|
||||||
|
else if (b->shader->info.stage == MESA_SHADER_KERNEL)
|
||||||
|
/* Per the CL C spec: If no qualifier is provided, read_only is assumed. */
|
||||||
|
val->type->access_qualifier = SpvAccessQualifierReadOnly;
|
||||||
else
|
else
|
||||||
val->type->access_qualifier = SpvAccessQualifierReadWrite;
|
val->type->access_qualifier = SpvAccessQualifierReadWrite;
|
||||||
|
|
||||||
@@ -1619,6 +1627,9 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
|
|||||||
} else if (sampled == 2) {
|
} else if (sampled == 2) {
|
||||||
val->type->glsl_image = glsl_image_type(dim, is_array,
|
val->type->glsl_image = glsl_image_type(dim, is_array,
|
||||||
sampled_base_type);
|
sampled_base_type);
|
||||||
|
} else if (b->shader->info.stage == MESA_SHADER_KERNEL) {
|
||||||
|
val->type->glsl_image = glsl_image_type(dim, is_array,
|
||||||
|
GLSL_TYPE_VOID);
|
||||||
} else {
|
} else {
|
||||||
vtn_fail("We need to know if the image will be sampled");
|
vtn_fail("We need to know if the image will be sampled");
|
||||||
}
|
}
|
||||||
@@ -4171,6 +4182,9 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SpvCapabilityImageBasic:
|
case SpvCapabilityImageBasic:
|
||||||
|
spv_check_supported(kernel_image, cap);
|
||||||
|
break;
|
||||||
|
|
||||||
case SpvCapabilityImageReadWrite:
|
case SpvCapabilityImageReadWrite:
|
||||||
case SpvCapabilityImageMipmap:
|
case SpvCapabilityImageMipmap:
|
||||||
case SpvCapabilityPipes:
|
case SpvCapabilityPipes:
|
||||||
@@ -5484,9 +5498,20 @@ vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,
|
|||||||
in_var->data.mode = nir_var_uniform;
|
in_var->data.mode = nir_var_uniform;
|
||||||
in_var->data.read_only = true;
|
in_var->data.read_only = true;
|
||||||
in_var->data.location = i;
|
in_var->data.location = i;
|
||||||
|
if (param_type->base_type == vtn_base_type_image) {
|
||||||
|
in_var->data.access = 0;
|
||||||
|
if (param_type->access_qualifier & SpvAccessQualifierReadOnly)
|
||||||
|
in_var->data.access |= ACCESS_NON_WRITEABLE;
|
||||||
|
if (param_type->access_qualifier & SpvAccessQualifierWriteOnly)
|
||||||
|
in_var->data.access |= ACCESS_NON_READABLE;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_by_val)
|
if (is_by_val)
|
||||||
in_var->type = param_type->deref->type;
|
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
|
else
|
||||||
in_var->type = param_type->type;
|
in_var->type = param_type->type;
|
||||||
|
|
||||||
@@ -5501,6 +5526,10 @@ vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b,
|
|||||||
nir_copy_var(&b->nb, copy_var, in_var);
|
nir_copy_var(&b->nb, copy_var, in_var);
|
||||||
call->params[i] =
|
call->params[i] =
|
||||||
nir_src_for_ssa(&nir_build_deref_var(&b->nb, copy_var)->dest.ssa);
|
nir_src_for_ssa(&nir_build_deref_var(&b->nb, copy_var)->dest.ssa);
|
||||||
|
} else if (param_type->base_type == vtn_base_type_image ||
|
||||||
|
param_type->base_type == vtn_base_type_sampler) {
|
||||||
|
/* Don't load the var, just pass a deref of it */
|
||||||
|
call->params[i] = nir_src_for_ssa(&nir_build_deref_var(&b->nb, in_var)->dest.ssa);
|
||||||
} else {
|
} else {
|
||||||
call->params[i] = nir_src_for_ssa(nir_load_var(&b->nb, in_var));
|
call->params[i] = nir_src_for_ssa(nir_load_var(&b->nb, in_var));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user