From ce6f66242ad33be84c0a34519f18bdc15c195950 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Mon, 13 Apr 2020 07:50:37 -0700 Subject: [PATCH 1/7] nir/vtn: Add type constant to image intrinsics Since OpenCL supports untyped images, backends might need type info to be able to support the load/store ops. Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/glsl/glsl_to_nir.cpp | 2 ++ src/compiler/nir/nir.c | 5 +++++ src/compiler/nir/nir_intrinsics.py | 12 ++++++------ src/compiler/spirv/spirv_to_nir.c | 10 ++++++++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 9665a6c0ccb9..12ce0dec2e66 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -1334,6 +1334,8 @@ nir_visitor::visit(ir_call *ir) } else if (op == nir_intrinsic_image_deref_load || op == nir_intrinsic_image_deref_store) { instr->num_components = 4; + nir_intrinsic_set_type(instr, + nir_get_nir_type_for_glsl_base_type(type->sampled_type)); } if (op == nir_intrinsic_image_deref_size || diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 2ef15300b654..aa259806d541 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -2291,6 +2291,9 @@ nir_rewrite_image_intrinsic(nir_intrinsic_instr *intrin, nir_ssa_def *src, bool bindless) { enum gl_access_qualifier access = nir_intrinsic_access(intrin); + nir_alu_type type = nir_type_invalid; + if (nir_intrinsic_infos[intrin->intrinsic].index_map[NIR_INTRINSIC_TYPE]) + type = nir_intrinsic_type(intrin); switch (intrin->intrinsic) { #define CASE(op) \ @@ -2329,6 +2332,8 @@ nir_rewrite_image_intrinsic(nir_intrinsic_instr *intrin, nir_ssa_def *src, nir_intrinsic_set_image_array(intrin, glsl_sampler_type_is_array(deref->type)); nir_intrinsic_set_access(intrin, access | var->data.access); nir_intrinsic_set_format(intrin, var->data.image.format); + if (nir_intrinsic_infos[intrin->intrinsic].index_map[NIR_INTRINSIC_TYPE]) + nir_intrinsic_set_type(intrin, type); nir_instr_rewrite_src(&intrin->instr, &intrin->src[0], nir_src_for_ssa(src)); diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index a48b76bac107..546428eeef38 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -386,16 +386,16 @@ atomic3("atomic_counter_comp_swap") # argument with the value to be written, and image atomic operations take # either one or two additional scalar arguments with the same meaning as in # the ARB_shader_image_load_store specification. -def image(name, src_comp=[], **kwargs): +def image(name, src_comp=[], extra_indices=[], **kwargs): intrinsic("image_deref_" + name, src_comp=[1] + src_comp, - indices=[ACCESS], **kwargs) + indices=[ACCESS] + extra_indices, **kwargs) intrinsic("image_" + name, src_comp=[1] + src_comp, - indices=[IMAGE_DIM, IMAGE_ARRAY, FORMAT, ACCESS], **kwargs) + indices=[IMAGE_DIM, IMAGE_ARRAY, FORMAT, ACCESS] + extra_indices, **kwargs) intrinsic("bindless_image_" + name, src_comp=[1] + src_comp, - indices=[IMAGE_DIM, IMAGE_ARRAY, FORMAT, ACCESS], **kwargs) + indices=[IMAGE_DIM, IMAGE_ARRAY, FORMAT, ACCESS] + extra_indices, **kwargs) -image("load", src_comp=[4, 1, 1], dest_comp=0, flags=[CAN_ELIMINATE]) -image("store", src_comp=[4, 1, 0, 1]) +image("load", src_comp=[4, 1, 1], extra_indices=[TYPE], dest_comp=0, flags=[CAN_ELIMINATE]) +image("store", src_comp=[4, 1, 0, 1], extra_indices=[TYPE]) image("atomic_add", src_comp=[4, 1, 1], dest_comp=1) image("atomic_imin", src_comp=[4, 1, 1], dest_comp=1) image("atomic_umin", src_comp=[4, 1, 1], dest_comp=1) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 6dd18075c847..88b879cc89bb 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -3133,17 +3133,20 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, case SpvOpAtomicStore: case SpvOpImageWrite: { const uint32_t value_id = opcode == SpvOpAtomicStore ? w[4] : w[3]; - nir_ssa_def *value = vtn_get_nir_ssa(b, value_id); + struct vtn_ssa_value *value = vtn_ssa_value(b, value_id); /* nir_intrinsic_image_deref_store always takes a vec4 value */ assert(op == nir_intrinsic_image_deref_store); intrin->num_components = 4; - intrin->src[3] = nir_src_for_ssa(expand_to_vec4(&b->nb, value)); + intrin->src[3] = nir_src_for_ssa(expand_to_vec4(&b->nb, value->def)); /* Only OpImageWrite can support a lod parameter if * SPV_AMD_shader_image_load_store_lod is used but the current NIR * intrinsics definition for atomics requires us to set it for * OpAtomicStore. */ intrin->src[4] = nir_src_for_ssa(image.lod); + + if (opcode == SpvOpImageWrite) + nir_intrinsic_set_type(intrin, nir_get_nir_type_for_glsl_type(value->type)); break; } @@ -3196,6 +3199,9 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, result = nir_channels(&b->nb, result, (1 << dest_components) - 1); vtn_push_nir_ssa(b, w[2], result); + + if (opcode == SpvOpImageRead) + nir_intrinsic_set_type(intrin, nir_get_nir_type_for_glsl_type(type->type)); } else { nir_builder_instr_insert(&b->nb, &intrin->instr); } -- GitLab From de36b5b805be1732e6798afd1a12743df8d32718 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Mon, 13 Apr 2020 08:05:13 -0700 Subject: [PATCH 2/7] 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: --- src/compiler/builtin_type_macros.h | 8 +++++++ src/compiler/glsl_types.cpp | 13 +++++++++++ src/compiler/shader_info.h | 1 + src/compiler/spirv/spirv_to_nir.c | 35 +++++++++++++++++++++++++++--- 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/compiler/builtin_type_macros.h b/src/compiler/builtin_type_macros.h index b5598c0b2dcb..75be74b6d681 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 b631de5f3540..a5f5f5854e4c 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 760bc5556cbe..c49fed923e28 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 88b879cc89bb..059d4b777173 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)); } -- GitLab From a196f05fc22620be5809f7b28ce7f2671b1ef32c Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Mon, 13 Apr 2020 17:35:04 -0700 Subject: [PATCH 3/7] nir/vtn: Use return type rather than image type for tex ops Since OpenCL images don't have types, we can't use the image type here. Rather than special-casing and only using SPIR-V return type for CL images, we can just always use the return type to fill out the tex info. Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 059d4b777173..e2912809bb05 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -2801,9 +2801,18 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, if (sampler && (access & ACCESS_NON_UNIFORM)) instr->sampler_non_uniform = true; - /* for non-query ops, get dest_type from sampler type */ + /* for non-query ops, get dest_type from SPIR-V return type */ if (dest_type == nir_type_invalid) { - switch (glsl_get_sampler_result_type(image->type)) { + /* the return type should match the image type, unless the image type is + * VOID (CL image), in which case the return type dictates the sampler + */ + enum glsl_base_type sampler_base = + glsl_get_sampler_result_type(image->type); + enum glsl_base_type ret_base = glsl_get_base_type(ret_type->type); + vtn_fail_if(sampler_base != ret_base && sampler_base != GLSL_TYPE_VOID, + "SPIR-V return type mismatches image type. This is only valid " + "for untyped images (OpenCL)."); + switch (ret_base) { case GLSL_TYPE_FLOAT: dest_type = nir_type_float; break; case GLSL_TYPE_INT: dest_type = nir_type_int; break; case GLSL_TYPE_UINT: dest_type = nir_type_uint; break; -- GitLab From 701cb9d60c0350b0134e52cb1b51eefbbf27bd22 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Wed, 6 May 2020 17:20:26 -0700 Subject: [PATCH 4/7] nir/vtn: Handle integer sampling coordinates Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index e2912809bb05..8067c4194778 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -2632,9 +2632,21 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, if (is_array && texop != nir_texop_lod) coord_components++; - coord = vtn_get_nir_ssa(b, w[idx++]); + struct vtn_ssa_value *coord_val = vtn_ssa_value(b, w[idx++]); + coord = coord_val->def; p->src = nir_src_for_ssa(nir_channels(&b->nb, coord, (1 << coord_components) - 1)); + + /* OpenCL allows integer sampling coordinates */ + if (glsl_type_is_integer(coord_val->type) && + opcode == SpvOpImageSampleExplicitLod) { + vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL, + "Unless the Kernel capability is being used, the coordinate parameter " + "OpImageSampleExplicitLod must be floating point."); + + p->src = nir_src_for_ssa(nir_i2f32(&b->nb, p->src.ssa)); + } + p->src_type = nir_tex_src_coord; p++; break; -- GitLab From 5ce6821900f67f677cf7c7ec0ed6246893fdfdc9 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Mon, 11 May 2020 09:08:15 -0700 Subject: [PATCH 5/7] nir/vtn: ImageSizeLod op can be applied to images Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 38 +++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 8067c4194778..dfe325e89897 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -3000,6 +3000,14 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, access |= ACCESS_COHERENT; break; + case SpvOpImageQuerySizeLod: + res_val = vtn_untyped_value(b, w[3]); + image.image = vtn_get_image(b, w[3]); + image.coord = NULL; + image.sample = NULL; + image.lod = vtn_ssa_value(b, w[4])->def; + break; + case SpvOpImageQuerySize: res_val = vtn_untyped_value(b, w[3]); image.image = vtn_get_image(b, w[3]); @@ -3094,6 +3102,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, switch (opcode) { #define OP(S, N) case SpvOp##S: op = nir_intrinsic_image_deref_##N; break; OP(ImageQuerySize, size) + OP(ImageQuerySizeLod, size) OP(ImageRead, load) OP(ImageWrite, store) OP(AtomicLoad, load) @@ -3122,10 +3131,8 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, intrin->src[0] = nir_src_for_ssa(&image.image->dest.ssa); - if (opcode == SpvOpImageQuerySize) { - /* ImageQuerySize only has an LOD which is currently always 0 */ - intrin->src[1] = nir_src_for_ssa(nir_imm_int(&b->nb, 0)); - } else { + /* size doesn't take non-lod coordinate parameters */ + if (opcode != SpvOpImageQuerySize && opcode != SpvOpImageQuerySizeLod) { /* The image coordinate is always 4 components but we may not have that * many. Swizzle to compensate. */ @@ -3150,17 +3157,20 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, nir_intrinsic_set_access(intrin, access); switch (opcode) { - case SpvOpAtomicLoad: case SpvOpImageQuerySize: + intrin->src[1] = nir_src_for_ssa(nir_imm_int(&b->nb, 0)); + break; + case SpvOpImageQuerySizeLod: + intrin->src[1] = nir_src_for_ssa(image.lod); + break; + case SpvOpAtomicLoad: case SpvOpImageRead: - if (opcode == SpvOpImageRead || opcode == SpvOpAtomicLoad) { - /* Only OpImageRead can support a lod parameter if - * SPV_AMD_shader_image_load_store_lod is used but the current NIR - * intrinsics definition for atomics requires us to set it for - * OpAtomicLoad. - */ - intrin->src[3] = nir_src_for_ssa(image.lod); - } + /* Only OpImageRead can support a lod parameter if + * SPV_AMD_shader_image_load_store_lod is used but the current NIR + * intrinsics definition for atomics requires us to set it for + * OpAtomicLoad. + */ + intrin->src[3] = nir_src_for_ssa(image.lod); break; case SpvOpAtomicStore: case SpvOpImageWrite: { @@ -5068,7 +5078,6 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, case SpvOpImageFetch: case SpvOpImageGather: case SpvOpImageDrefGather: - case SpvOpImageQuerySizeLod: case SpvOpImageQueryLod: case SpvOpImageQueryLevels: case SpvOpImageQuerySamples: @@ -5081,6 +5090,7 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, vtn_handle_image(b, opcode, w, count); break; + case SpvOpImageQuerySizeLod: case SpvOpImageQuerySize: { struct vtn_type *image_type = vtn_get_value_type(b, w[3]); vtn_assert(image_type->base_type == vtn_base_type_image); -- GitLab From 397730edd5bac440853af8018dda76e0807bc51c Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Mon, 11 May 2020 09:09:47 -0700 Subject: [PATCH 6/7] nir/vtn: Add intrinsics for CL image format/order queries Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/nir/nir_intrinsics.py | 3 +++ src/compiler/spirv/spirv_to_nir.c | 27 +++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 546428eeef38..73a5bce6a273 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -411,6 +411,9 @@ image("size", dest_comp=0, src_comp=[1], flags=[CAN_ELIMINATE, CAN_REORDER]) image("samples", dest_comp=1, flags=[CAN_ELIMINATE, CAN_REORDER]) image("atomic_inc_wrap", src_comp=[4, 1, 1], dest_comp=1) image("atomic_dec_wrap", src_comp=[4, 1, 1], dest_comp=1) +# CL-specific format queries +image("format", dest_comp=1, flags=[CAN_ELIMINATE, CAN_REORDER]) +image("order", dest_comp=1, flags=[CAN_ELIMINATE, CAN_REORDER]) # Vulkan descriptor set intrinsics # diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index dfe325e89897..a2e132bda5cf 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -3016,6 +3016,15 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, image.lod = NULL; break; + case SpvOpImageQueryFormat: + case SpvOpImageQueryOrder: + res_val = vtn_untyped_value(b, w[3]); + image.image = vtn_get_image(b, w[3]); + image.coord = NULL; + image.sample = NULL; + image.lod = NULL; + break; + case SpvOpImageRead: { res_val = vtn_untyped_value(b, w[3]); image.image = vtn_get_image(b, w[3]); @@ -3122,6 +3131,8 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, OP(AtomicOr, atomic_or) OP(AtomicXor, atomic_xor) OP(AtomicFAddEXT, atomic_fadd) + OP(ImageQueryFormat, format) + OP(ImageQueryOrder, order) #undef OP default: vtn_fail_with_opcode("Invalid image opcode", opcode); @@ -3131,13 +3142,19 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, intrin->src[0] = nir_src_for_ssa(&image.image->dest.ssa); - /* size doesn't take non-lod coordinate parameters */ - if (opcode != SpvOpImageQuerySize && opcode != SpvOpImageQuerySizeLod) { + switch (opcode) { + case SpvOpImageQuerySize: + case SpvOpImageQuerySizeLod: + case SpvOpImageQueryFormat: + case SpvOpImageQueryOrder: + break; + default: /* The image coordinate is always 4 components but we may not have that * many. Swizzle to compensate. */ intrin->src[1] = nir_src_for_ssa(expand_to_vec4(&b->nb, image.coord)); intrin->src[2] = nir_src_for_ssa(image.sample); + break; } /* The Vulkan spec says: @@ -3157,6 +3174,10 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, nir_intrinsic_set_access(intrin, access); switch (opcode) { + case SpvOpImageQueryFormat: + case SpvOpImageQueryOrder: + /* No additional sources */ + break; case SpvOpImageQuerySize: intrin->src[1] = nir_src_for_ssa(nir_imm_int(&b->nb, 0)); break; @@ -5087,6 +5108,8 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, case SpvOpImageRead: case SpvOpImageWrite: case SpvOpImageTexelPointer: + case SpvOpImageQueryFormat: + case SpvOpImageQueryOrder: vtn_handle_image(b, opcode, w, count); break; -- GitLab From b778e7bd6c1d82ce739d7e278de00ee600532cd5 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Fri, 1 May 2020 10:47:58 -0700 Subject: [PATCH 7/7] nir/vtn: Convert constant samplers to variables with data Reviewd-by: Jason Ekstrand Part-of: --- src/compiler/nir/nir.h | 10 ++++++++++ src/compiler/nir/nir_print.c | 29 +++++++++++++++++++++++++++++ src/compiler/shader_enums.h | 17 +++++++++++++++++ src/compiler/shader_info.h | 1 + src/compiler/spirv/spirv_to_nir.c | 11 +++++------ src/compiler/spirv/vtn_variables.c | 26 ++++++++++++++++++++++++++ 6 files changed, 88 insertions(+), 6 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 73a083441971..e5091831350a 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -545,6 +545,16 @@ typedef struct nir_variable { enum pipe_format format; } image; + struct { + /** + * For OpenCL inline samplers. See cl_sampler_addressing_mode and cl_sampler_filter_mode + */ + unsigned is_inline_sampler : 1; + unsigned addressing_mode : 3; + unsigned normalized_coordinates : 1; + unsigned filter_mode : 1; + } sampler; + struct { /** * Transform feedback buffer. diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index c5a8efd1ec51..00cf235166b3 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -298,6 +298,29 @@ get_var_name(nir_variable *var, print_state *state) return name; } +static const char * +get_constant_sampler_addressing_mode(enum cl_sampler_addressing_mode mode) +{ + switch (mode) { + case SAMPLER_ADDRESSING_MODE_NONE: return "none"; + case SAMPLER_ADDRESSING_MODE_CLAMP_TO_EDGE: return "clamp_to_edge"; + case SAMPLER_ADDRESSING_MODE_CLAMP: return "clamp"; + case SAMPLER_ADDRESSING_MODE_REPEAT: return "repeat"; + case SAMPLER_ADDRESSING_MODE_REPEAT_MIRRORED: return "repeat_mirrored"; + default: unreachable("Invalid addressing mode"); + } +} + +static const char * +get_constant_sampler_filter_mode(enum cl_sampler_filter_mode mode) +{ + switch (mode) { + case SAMPLER_FILTER_MODE_NEAREST: return "nearest"; + case SAMPLER_FILTER_MODE_LINEAR: return "linear"; + default: unreachable("Invalid filter mode"); + } +} + static void print_constant(nir_constant *c, const struct glsl_type *type, print_state *state) { @@ -571,6 +594,12 @@ print_var_decl(nir_variable *var, print_state *state) print_constant(var->constant_initializer, var->type, state); fprintf(fp, " }"); } + if (glsl_type_is_sampler(var->type) && var->data.sampler.is_inline_sampler) { + fprintf(fp, " = { %s, %s, %s }", + get_constant_sampler_addressing_mode(var->data.sampler.addressing_mode), + var->data.sampler.normalized_coordinates ? "true" : "false", + get_constant_sampler_filter_mode(var->data.sampler.filter_mode)); + } if (var->pointer_initializer) fprintf(fp, " = &%s", get_var_name(var->pointer_initializer, state)); diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h index e2b9cd6f02e8..69240b4cb6ca 100644 --- a/src/compiler/shader_enums.h +++ b/src/compiler/shader_enums.h @@ -900,6 +900,23 @@ enum float_controls FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP64 = 0x4000, }; +/** +* Enums to describe sampler properties used by OpenCL's inline constant samplers. +* These values match the meanings described in the SPIR-V spec. +*/ +enum cl_sampler_addressing_mode { + SAMPLER_ADDRESSING_MODE_NONE = 0, + SAMPLER_ADDRESSING_MODE_CLAMP_TO_EDGE = 1, + SAMPLER_ADDRESSING_MODE_CLAMP = 2, + SAMPLER_ADDRESSING_MODE_REPEAT = 3, + SAMPLER_ADDRESSING_MODE_REPEAT_MIRRORED = 4, +}; + +enum cl_sampler_filter_mode { + SAMPLER_FILTER_MODE_NEAREST = 0, + SAMPLER_FILTER_MODE_LINEAR = 1, +}; + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h index c49fed923e28..eeb1cb0a7910 100644 --- a/src/compiler/shader_info.h +++ b/src/compiler/shader_info.h @@ -58,6 +58,7 @@ struct spirv_supported_capabilities { bool integer_functions2; bool kernel; bool kernel_image; + bool literal_sampler; 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 a2e132bda5cf..7324e9ca70b2 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -2095,10 +2095,6 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode, val->constant = vtn_null_constant(b, val->type); break; - case SpvOpConstantSampler: - vtn_fail("OpConstantSampler requires Kernel Capability"); - break; - default: vtn_fail_with_opcode("Unhandled opcode", opcode); } @@ -4237,11 +4233,14 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode, spv_check_supported(kernel_image, cap); break; + case SpvCapabilityLiteralSampler: + spv_check_supported(literal_sampler, cap); + break; + case SpvCapabilityImageReadWrite: case SpvCapabilityImageMipmap: case SpvCapabilityPipes: case SpvCapabilityDeviceEnqueue: - case SpvCapabilityLiteralSampler: case SpvCapabilityGenericPointer: vtn_warn("Unsupported OpenCL-style SPIR-V capability: %s", spirv_capability_to_string(cap)); @@ -4885,7 +4884,6 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode, case SpvOpConstantFalse: case SpvOpConstant: case SpvOpConstantComposite: - case SpvOpConstantSampler: case SpvOpConstantNull: case SpvOpSpecConstantTrue: case SpvOpSpecConstantFalse: @@ -4897,6 +4895,7 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode, case SpvOpUndef: case SpvOpVariable: + case SpvOpConstantSampler: vtn_handle_variables(b, opcode, w, count); break; diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index 68174abb6d82..535db712b377 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -2486,6 +2486,32 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, break; } + case SpvOpConstantSampler: { + /* Synthesize a pointer-to-sampler type, create a variable of that type, + * and give the variable a constant initializer with the sampler params */ + struct vtn_type *sampler_type = vtn_value(b, w[1], vtn_value_type_type)->type; + struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); + + struct vtn_type *ptr_type = rzalloc(b, struct vtn_type); + ptr_type = rzalloc(b, struct vtn_type); + ptr_type->base_type = vtn_base_type_pointer; + ptr_type->deref = sampler_type; + ptr_type->storage_class = SpvStorageClassUniform; + + ptr_type->type = nir_address_format_to_glsl_type( + vtn_mode_to_address_format(b, vtn_variable_mode_function)); + + vtn_create_variable(b, val, ptr_type, ptr_type->storage_class, NULL, NULL); + + nir_variable *nir_var = val->pointer->var->var; + nir_var->data.sampler.is_inline_sampler = true; + nir_var->data.sampler.addressing_mode = w[3]; + nir_var->data.sampler.normalized_coordinates = w[4]; + nir_var->data.sampler.filter_mode = w[5]; + + break; + } + case SpvOpAccessChain: case SpvOpPtrAccessChain: case SpvOpInBoundsAccessChain: -- GitLab