From: Jesse Natalie Date: Mon, 13 Apr 2020 15:05:13 +0000 (-0700) Subject: nir/vtn: Add support for kernel images to SPIRV-to-NIR. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=de36b5b805be1732e6798afd1a12743df8d32718;p=mesa.git 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 Part-of: --- diff --git a/src/compiler/builtin_type_macros.h b/src/compiler/builtin_type_macros.h index b5598c0b2dc..75be74b6d68 100644 --- a/src/compiler/builtin_type_macros.h +++ b/src/compiler/builtin_type_macros.h @@ -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(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(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) diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp index b631de5f354..a5f5f5854e4 100644 --- a/src/compiler/glsl_types.cpp +++ b/src/compiler/glsl_types.cpp @@ -1018,6 +1018,19 @@ glsl_type::get_image_instance(enum glsl_sampler_dim dim, case GLSL_SAMPLER_DIM_EXTERNAL: 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: return error_type; } diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h index 760bc5556cb..c49fed923e2 100644 --- a/src/compiler/shader_info.h +++ b/src/compiler/shader_info.h @@ -57,6 +57,7 @@ struct spirv_supported_capabilities { bool int64_atomics; bool integer_functions2; bool kernel; + bool kernel_image; bool min_lod; bool multiview; bool physical_storage_buffer_address; diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 88b879cc89b..059d4b77717 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -1569,9 +1569,14 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode, vtn_mode_to_address_format(b, vtn_variable_mode_function)); const struct vtn_type *sampled_type = vtn_get_type(b, w[2]); - vtn_fail_if(sampled_type->base_type != vtn_base_type_scalar || - glsl_get_bit_size(sampled_type->type) != 32, - "Sampled type of OpTypeImage must be a 32-bit scalar"); + 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 || + glsl_get_bit_size(sampled_type->type) != 32, + "Sampled type of OpTypeImage must be a 32-bit scalar"); + } enum glsl_sampler_dim dim; switch ((SpvDim)w[3]) { @@ -1597,6 +1602,9 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode, if (count > 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 val->type->access_qualifier = SpvAccessQualifierReadWrite; @@ -1619,6 +1627,9 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode, } else if (sampled == 2) { val->type->glsl_image = glsl_image_type(dim, is_array, 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 { 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; case SpvCapabilityImageBasic: + spv_check_supported(kernel_image, cap); + break; + case SpvCapabilityImageReadWrite: case SpvCapabilityImageMipmap: 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.read_only = true; 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) 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; @@ -5501,6 +5526,10 @@ vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b, nir_copy_var(&b->nb, copy_var, in_var); call->params[i] = 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 { call->params[i] = nir_src_for_ssa(nir_load_var(&b->nb, in_var)); }