From b778e7bd6c1d82ce739d7e278de00ee600532cd5 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Fri, 1 May 2020 10:47:58 -0700 Subject: [PATCH] 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 73a08344197..e5091831350 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 c5a8efd1ec5..00cf235166b 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 e2b9cd6f02e..69240b4cb6c 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 c49fed923e2..eeb1cb0a791 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 a2e132bda5c..7324e9ca70b 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 68174abb6d8..535db712b37 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: -- 2.30.2