diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index 4a6350d77a..0e7db13f31 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -2859,7 +2859,7 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { // Handle combinatorial instructions. const auto* def_info = GetDefInfo(result_id); if (def_info) { - if (def_info->skip_generation) { + if (def_info->skip != SkipReason::kDontSkip) { return true; } auto combinatorial_expr = MaybeEmitCombinatorialValue(inst); @@ -3532,13 +3532,13 @@ bool FunctionEmitter::RegisterLocallyDefinedValues() { << inst.PrettyPrint(); } if (info->storage_class == ast::StorageClass::kUniformConstant) { - info->skip_generation = true; + info->skip = SkipReason::kOpaqueObject; } } if (type->AsSampler() || type->AsImage() || type->AsSampledImage()) { // Defer code generation until the instruction that actually acts on // the image. - info->skip_generation = true; + info->skip = SkipReason::kOpaqueObject; } } } diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h index c9804750cc..29f407618b 100644 --- a/src/reader/spirv/function.h +++ b/src/reader/spirv/function.h @@ -195,6 +195,31 @@ inline std::ostream& operator<<(std::ostream& o, const BlockInfo& bi) { return o; } +/// Reasons for avoiding generating an intermediate value. +enum class SkipReason { + /// `kDontSkip`: The value should be generated. Used for most values. + kDontSkip, + + /// For remaining cases, the value is not generated. + + /// `kOpaqueObject`: used for any intermediate value which is an sampler, + /// image, + /// or sampled image, or any pointer to such object. Code is generated + /// for those objects only when emitting the image instructions that access + /// the image (read, write, sample, gather, fetch, or query). For example, + /// when encountering an OpImageSampleExplicitLod, a call to the + /// textureSampleLevel builtin function will be emitted, and the call will + /// directly reference the underlying texture and sampler (variable or + /// function parameter). + kOpaqueObject, + + /// `kPointSizeBuiltin`: the value is a pointer to the Position builtin + /// variable. Don't generate its address. Avoid generating stores to + /// this pointer. When loading from the pointer, yield the value 1, + /// the only supported value for PointSize. + kPointSizeBuiltin +}; + /// Bookkeeping info for a SPIR-V ID defined in the function. /// This will be valid for result IDs for: /// - instructions that are not OpLabel, and not OpFunctionParameter @@ -262,16 +287,7 @@ struct DefInfo { /// This is kNone for non-pointers. ast::StorageClass storage_class = ast::StorageClass::kNone; - /// Should this instruction be skipped when generating code? - /// This is true for any intermediate value which is an sampler, image, - /// or sampled image, or any pointer to such object. Code is generated - /// for those objects only when emitting the image instructions that access - /// the image (read, write, sample, gather, fetch, or query). For example, - /// when encountering an OpImageSampleExplicitLod, a call to the - /// textureSampleLevel builtin function will be emitted, and the call will - /// directly reference the underlying texture and sampler (variable or - /// function parameter). - bool skip_generation = false; + SkipReason skip = SkipReason::kDontSkip; }; inline std::ostream& operator<<(std::ostream& o, const DefInfo& di) { @@ -285,6 +301,16 @@ inline std::ostream& operator<<(std::ostream& o, const DefInfo& di) { if (di.storage_class != ast::StorageClass::kNone) { o << " sc:" << int(di.storage_class); } + switch (di.skip) { + case SkipReason::kDontSkip: + break; + case SkipReason::kOpaqueObject: + o << " skip:opaque"; + break; + case SkipReason::kPointSizeBuiltin: + o << " skip:pointsize"; + break; + } o << "}"; return o; }