12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790 |
- // Copyright (c) 2017 Google Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // Validates correctness of image instructions.
- #include "source/val/validate.h"
- #include <string>
- #include "source/diagnostic.h"
- #include "source/opcode.h"
- #include "source/spirv_target_env.h"
- #include "source/util/bitutils.h"
- #include "source/val/instruction.h"
- #include "source/val/validate_scopes.h"
- #include "source/val/validation_state.h"
- namespace spvtools {
- namespace val {
- namespace {
- // Performs compile time check that all SpvImageOperandsXXX cases are handled in
- // this module. If SpvImageOperandsXXX list changes, this function will fail the
- // build.
- // For all other purposes this is a dummy function.
- bool CheckAllImageOperandsHandled() {
- SpvImageOperandsMask enum_val = SpvImageOperandsBiasMask;
- // Some improvised code to prevent the compiler from considering enum_val
- // constant and optimizing the switch away.
- uint32_t stack_var = 0;
- if (reinterpret_cast<uintptr_t>(&stack_var) % 256)
- enum_val = SpvImageOperandsLodMask;
- switch (enum_val) {
- // Please update the validation rules in this module if you are changing
- // the list of image operands, and add new enum values to this switch.
- case SpvImageOperandsMaskNone:
- return false;
- case SpvImageOperandsBiasMask:
- case SpvImageOperandsLodMask:
- case SpvImageOperandsGradMask:
- case SpvImageOperandsConstOffsetMask:
- case SpvImageOperandsOffsetMask:
- case SpvImageOperandsConstOffsetsMask:
- case SpvImageOperandsSampleMask:
- case SpvImageOperandsMinLodMask:
- // TODO(dneto): Support image operands related to the Vulkan memory model.
- // https://gitlab.khronos.org/spirv/spirv-tools/issues/32
- case SpvImageOperandsMakeTexelAvailableKHRMask:
- case SpvImageOperandsMakeTexelVisibleKHRMask:
- case SpvImageOperandsNonPrivateTexelKHRMask:
- case SpvImageOperandsVolatileTexelKHRMask:
- return true;
- }
- return false;
- }
- // Used by GetImageTypeInfo. See OpTypeImage spec for more information.
- struct ImageTypeInfo {
- uint32_t sampled_type = 0;
- SpvDim dim = SpvDimMax;
- uint32_t depth = 0;
- uint32_t arrayed = 0;
- uint32_t multisampled = 0;
- uint32_t sampled = 0;
- SpvImageFormat format = SpvImageFormatMax;
- SpvAccessQualifier access_qualifier = SpvAccessQualifierMax;
- };
- // Provides information on image type. |id| should be object of either
- // OpTypeImage or OpTypeSampledImage type. Returns false in case of failure
- // (not a valid id, failed to parse the instruction, etc).
- bool GetImageTypeInfo(const ValidationState_t& _, uint32_t id,
- ImageTypeInfo* info) {
- if (!id || !info) return false;
- const Instruction* inst = _.FindDef(id);
- assert(inst);
- if (inst->opcode() == SpvOpTypeSampledImage) {
- inst = _.FindDef(inst->word(2));
- assert(inst);
- }
- if (inst->opcode() != SpvOpTypeImage) return false;
- const size_t num_words = inst->words().size();
- if (num_words != 9 && num_words != 10) return false;
- info->sampled_type = inst->word(2);
- info->dim = static_cast<SpvDim>(inst->word(3));
- info->depth = inst->word(4);
- info->arrayed = inst->word(5);
- info->multisampled = inst->word(6);
- info->sampled = inst->word(7);
- info->format = static_cast<SpvImageFormat>(inst->word(8));
- info->access_qualifier = num_words < 10
- ? SpvAccessQualifierMax
- : static_cast<SpvAccessQualifier>(inst->word(9));
- return true;
- }
- bool IsImplicitLod(SpvOp opcode) {
- switch (opcode) {
- case SpvOpImageSampleImplicitLod:
- case SpvOpImageSampleDrefImplicitLod:
- case SpvOpImageSampleProjImplicitLod:
- case SpvOpImageSampleProjDrefImplicitLod:
- case SpvOpImageSparseSampleImplicitLod:
- case SpvOpImageSparseSampleDrefImplicitLod:
- case SpvOpImageSparseSampleProjImplicitLod:
- case SpvOpImageSparseSampleProjDrefImplicitLod:
- return true;
- default:
- break;
- }
- return false;
- }
- bool IsExplicitLod(SpvOp opcode) {
- switch (opcode) {
- case SpvOpImageSampleExplicitLod:
- case SpvOpImageSampleDrefExplicitLod:
- case SpvOpImageSampleProjExplicitLod:
- case SpvOpImageSampleProjDrefExplicitLod:
- case SpvOpImageSparseSampleExplicitLod:
- case SpvOpImageSparseSampleDrefExplicitLod:
- case SpvOpImageSparseSampleProjExplicitLod:
- case SpvOpImageSparseSampleProjDrefExplicitLod:
- return true;
- default:
- break;
- }
- return false;
- }
- // Returns true if the opcode is a Image instruction which applies
- // homogenous projection to the coordinates.
- bool IsProj(SpvOp opcode) {
- switch (opcode) {
- case SpvOpImageSampleProjImplicitLod:
- case SpvOpImageSampleProjDrefImplicitLod:
- case SpvOpImageSparseSampleProjImplicitLod:
- case SpvOpImageSparseSampleProjDrefImplicitLod:
- case SpvOpImageSampleProjExplicitLod:
- case SpvOpImageSampleProjDrefExplicitLod:
- case SpvOpImageSparseSampleProjExplicitLod:
- case SpvOpImageSparseSampleProjDrefExplicitLod:
- return true;
- default:
- break;
- }
- return false;
- }
- // Returns the number of components in a coordinate used to access a texel in
- // a single plane of an image with the given parameters.
- uint32_t GetPlaneCoordSize(const ImageTypeInfo& info) {
- uint32_t plane_size = 0;
- // If this switch breaks your build, please add new values below.
- switch (info.dim) {
- case SpvDim1D:
- case SpvDimBuffer:
- plane_size = 1;
- break;
- case SpvDim2D:
- case SpvDimRect:
- case SpvDimSubpassData:
- plane_size = 2;
- break;
- case SpvDim3D:
- case SpvDimCube:
- // For Cube direction vector is used instead of UV.
- plane_size = 3;
- break;
- case SpvDimMax:
- assert(0);
- break;
- }
- return plane_size;
- }
- // Returns minimal number of coordinates based on image dim, arrayed and whether
- // the instruction uses projection coordinates.
- uint32_t GetMinCoordSize(SpvOp opcode, const ImageTypeInfo& info) {
- if (info.dim == SpvDimCube &&
- (opcode == SpvOpImageRead || opcode == SpvOpImageWrite ||
- opcode == SpvOpImageSparseRead)) {
- // These opcodes use UV for Cube, not direction vector.
- return 3;
- }
- return GetPlaneCoordSize(info) + info.arrayed + (IsProj(opcode) ? 1 : 0);
- }
- // Checks ImageOperand bitfield and respective operands.
- spv_result_t ValidateImageOperands(ValidationState_t& _,
- const Instruction* inst,
- const ImageTypeInfo& info, uint32_t mask,
- uint32_t word_index) {
- static const bool kAllImageOperandsHandled = CheckAllImageOperandsHandled();
- (void)kAllImageOperandsHandled;
- const SpvOp opcode = inst->opcode();
- const size_t num_words = inst->words().size();
- // NonPrivate and Volatile take no operand words.
- const uint32_t mask_bits_having_operands =
- mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
- SpvImageOperandsVolatileTexelKHRMask);
- size_t expected_num_image_operand_words =
- spvtools::utils::CountSetBits(mask_bits_having_operands);
- if (mask & SpvImageOperandsGradMask) {
- // Grad uses two words.
- ++expected_num_image_operand_words;
- }
- if (expected_num_image_operand_words != num_words - word_index) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Number of image operand ids doesn't correspond to the bit mask";
- }
- if (spvtools::utils::CountSetBits(
- mask & (SpvImageOperandsOffsetMask | SpvImageOperandsConstOffsetMask |
- SpvImageOperandsConstOffsetsMask)) > 1) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operands Offset, ConstOffset, ConstOffsets cannot be used "
- << "together";
- }
- const bool is_implicit_lod = IsImplicitLod(opcode);
- const bool is_explicit_lod = IsExplicitLod(opcode);
- // The checks should be done in the order of definition of OperandImage.
- if (mask & SpvImageOperandsBiasMask) {
- if (!is_implicit_lod) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Bias can only be used with ImplicitLod opcodes";
- }
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
- if (!_.IsFloatScalarType(type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Bias to be float scalar";
- }
- if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
- info.dim != SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Bias requires 'Dim' parameter to be 1D, 2D, 3D "
- "or Cube";
- }
- if (info.multisampled != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Bias requires 'MS' parameter to be 0";
- }
- }
- if (mask & SpvImageOperandsLodMask) {
- if (!is_explicit_lod && opcode != SpvOpImageFetch &&
- opcode != SpvOpImageSparseFetch) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Lod can only be used with ExplicitLod opcodes "
- << "and OpImageFetch";
- }
- if (mask & SpvImageOperandsGradMask) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand bits Lod and Grad cannot be set at the same "
- "time";
- }
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
- if (is_explicit_lod) {
- if (!_.IsFloatScalarType(type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Lod to be float scalar when used "
- << "with ExplicitLod";
- }
- } else {
- if (!_.IsIntScalarType(type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Lod to be int scalar when used with "
- << "OpImageFetch";
- }
- }
- if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
- info.dim != SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Lod requires 'Dim' parameter to be 1D, 2D, 3D "
- "or Cube";
- }
- if (info.multisampled != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Lod requires 'MS' parameter to be 0";
- }
- }
- if (mask & SpvImageOperandsGradMask) {
- if (!is_explicit_lod) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Grad can only be used with ExplicitLod opcodes";
- }
- const uint32_t dx_type_id = _.GetTypeId(inst->word(word_index++));
- const uint32_t dy_type_id = _.GetTypeId(inst->word(word_index++));
- if (!_.IsFloatScalarOrVectorType(dx_type_id) ||
- !_.IsFloatScalarOrVectorType(dy_type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected both Image Operand Grad ids to be float scalars or "
- << "vectors";
- }
- const uint32_t plane_size = GetPlaneCoordSize(info);
- const uint32_t dx_size = _.GetDimension(dx_type_id);
- const uint32_t dy_size = _.GetDimension(dy_type_id);
- if (plane_size != dx_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Grad dx to have " << plane_size
- << " components, but given " << dx_size;
- }
- if (plane_size != dy_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Grad dy to have " << plane_size
- << " components, but given " << dy_size;
- }
- if (info.multisampled != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Grad requires 'MS' parameter to be 0";
- }
- }
- if (mask & SpvImageOperandsConstOffsetMask) {
- if (info.dim == SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand ConstOffset cannot be used with Cube Image "
- "'Dim'";
- }
- const uint32_t id = inst->word(word_index++);
- const uint32_t type_id = _.GetTypeId(id);
- if (!_.IsIntScalarOrVectorType(type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand ConstOffset to be int scalar or "
- << "vector";
- }
- if (!spvOpcodeIsConstant(_.GetIdOpcode(id))) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand ConstOffset to be a const object";
- }
- const uint32_t plane_size = GetPlaneCoordSize(info);
- const uint32_t offset_size = _.GetDimension(type_id);
- if (plane_size != offset_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand ConstOffset to have " << plane_size
- << " components, but given " << offset_size;
- }
- }
- if (mask & SpvImageOperandsOffsetMask) {
- if (info.dim == SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Offset cannot be used with Cube Image 'Dim'";
- }
- const uint32_t id = inst->word(word_index++);
- const uint32_t type_id = _.GetTypeId(id);
- if (!_.IsIntScalarOrVectorType(type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Offset to be int scalar or "
- << "vector";
- }
- const uint32_t plane_size = GetPlaneCoordSize(info);
- const uint32_t offset_size = _.GetDimension(type_id);
- if (plane_size != offset_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Offset to have " << plane_size
- << " components, but given " << offset_size;
- }
- }
- if (mask & SpvImageOperandsConstOffsetsMask) {
- if (opcode != SpvOpImageGather && opcode != SpvOpImageDrefGather &&
- opcode != SpvOpImageSparseGather &&
- opcode != SpvOpImageSparseDrefGather) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand ConstOffsets can only be used with "
- "OpImageGather and OpImageDrefGather";
- }
- if (info.dim == SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand ConstOffsets cannot be used with Cube Image "
- "'Dim'";
- }
- const uint32_t id = inst->word(word_index++);
- const uint32_t type_id = _.GetTypeId(id);
- const Instruction* type_inst = _.FindDef(type_id);
- assert(type_inst);
- if (type_inst->opcode() != SpvOpTypeArray) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand ConstOffsets to be an array of size 4";
- }
- uint64_t array_size = 0;
- if (!_.GetConstantValUint64(type_inst->word(3), &array_size)) {
- assert(0 && "Array type definition is corrupt");
- }
- if (array_size != 4) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand ConstOffsets to be an array of size 4";
- }
- const uint32_t component_type = type_inst->word(2);
- if (!_.IsIntVectorType(component_type) ||
- _.GetDimension(component_type) != 2) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand ConstOffsets array componenets to be "
- "int vectors of size 2";
- }
- if (!spvOpcodeIsConstant(_.GetIdOpcode(id))) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand ConstOffsets to be a const object";
- }
- }
- if (mask & SpvImageOperandsSampleMask) {
- if (opcode != SpvOpImageFetch && opcode != SpvOpImageRead &&
- opcode != SpvOpImageWrite && opcode != SpvOpImageSparseFetch &&
- opcode != SpvOpImageSparseRead) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Sample can only be used with OpImageFetch, "
- << "OpImageRead, OpImageWrite, OpImageSparseFetch and "
- << "OpImageSparseRead";
- }
- if (info.multisampled == 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand Sample requires non-zero 'MS' parameter";
- }
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
- if (!_.IsIntScalarType(type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand Sample to be int scalar";
- }
- }
- if (mask & SpvImageOperandsMinLodMask) {
- if (!is_implicit_lod && !(mask & SpvImageOperandsGradMask)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand MinLod can only be used with ImplicitLod "
- << "opcodes or together with Image Operand Grad";
- }
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
- if (!_.IsFloatScalarType(type_id)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image Operand MinLod to be float scalar";
- }
- if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
- info.dim != SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand MinLod requires 'Dim' parameter to be 1D, 2D, "
- "3D or Cube";
- }
- if (info.multisampled != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand MinLod requires 'MS' parameter to be 0";
- }
- }
- if (mask & SpvImageOperandsMakeTexelAvailableKHRMask) {
- // Checked elsewhere: capability and memory model are correct.
- if (opcode != SpvOpImageWrite) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand MakeTexelAvailableKHR can only be used with Op"
- << spvOpcodeString(SpvOpImageWrite) << ": Op"
- << spvOpcodeString(opcode);
- }
- if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand MakeTexelAvailableKHR requires "
- "NonPrivateTexelKHR is also specified: Op"
- << spvOpcodeString(opcode);
- }
- const auto available_scope = inst->word(word_index++);
- if (auto error = ValidateMemoryScope(_, inst, available_scope))
- return error;
- }
- if (mask & SpvImageOperandsMakeTexelVisibleKHRMask) {
- // Checked elsewhere: capability and memory model are correct.
- if (opcode != SpvOpImageRead && opcode != SpvOpImageSparseRead) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand MakeTexelVisibleKHR can only be used with Op"
- << spvOpcodeString(SpvOpImageRead) << " or Op"
- << spvOpcodeString(SpvOpImageSparseRead) << ": Op"
- << spvOpcodeString(opcode);
- }
- if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Operand MakeTexelVisibleKHR requires NonPrivateTexelKHR "
- "is also specified: Op"
- << spvOpcodeString(opcode);
- }
- const auto visible_scope = inst->word(word_index++);
- if (auto error = ValidateMemoryScope(_, inst, visible_scope)) return error;
- }
- return SPV_SUCCESS;
- }
- // Checks some of the validation rules which are common to multiple opcodes.
- spv_result_t ValidateImageCommon(ValidationState_t& _, const Instruction* inst,
- const ImageTypeInfo& info) {
- const SpvOp opcode = inst->opcode();
- if (IsProj(opcode)) {
- if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
- info.dim != SpvDimRect) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Dim' parameter to be 1D, 2D, 3D or Rect";
- }
- if (info.multisampled != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Image 'MS' parameter to be 0";
- }
- if (info.arrayed != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Image 'arrayed' parameter to be 0";
- }
- }
- if (opcode == SpvOpImageRead || opcode == SpvOpImageSparseRead ||
- opcode == SpvOpImageWrite) {
- if (info.sampled == 0) {
- } else if (info.sampled == 2) {
- if (info.dim == SpvDim1D && !_.HasCapability(SpvCapabilityImage1D)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Capability Image1D is required to access storage image";
- } else if (info.dim == SpvDimRect &&
- !_.HasCapability(SpvCapabilityImageRect)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Capability ImageRect is required to access storage image";
- } else if (info.dim == SpvDimBuffer &&
- !_.HasCapability(SpvCapabilityImageBuffer)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Capability ImageBuffer is required to access storage image";
- } else if (info.dim == SpvDimCube && info.arrayed == 1 &&
- !_.HasCapability(SpvCapabilityImageCubeArray)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Capability ImageCubeArray is required to access "
- << "storage image";
- }
- if (info.multisampled == 1 &&
- !_.HasCapability(SpvCapabilityImageMSArray)) {
- #if 0
- // TODO(atgoo@github.com) The description of this rule in the spec
- // is unclear and Glslang doesn't declare ImageMSArray. Need to clarify
- // and reenable.
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Capability ImageMSArray is required to access storage "
- << "image";
- #endif
- }
- } else {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled' parameter to be 0 or 2";
- }
- }
- return SPV_SUCCESS;
- }
- // Returns true if opcode is *ImageSparse*, false otherwise.
- bool IsSparse(SpvOp opcode) {
- switch (opcode) {
- case SpvOpImageSparseSampleImplicitLod:
- case SpvOpImageSparseSampleExplicitLod:
- case SpvOpImageSparseSampleDrefImplicitLod:
- case SpvOpImageSparseSampleDrefExplicitLod:
- case SpvOpImageSparseSampleProjImplicitLod:
- case SpvOpImageSparseSampleProjExplicitLod:
- case SpvOpImageSparseSampleProjDrefImplicitLod:
- case SpvOpImageSparseSampleProjDrefExplicitLod:
- case SpvOpImageSparseFetch:
- case SpvOpImageSparseGather:
- case SpvOpImageSparseDrefGather:
- case SpvOpImageSparseTexelsResident:
- case SpvOpImageSparseRead: {
- return true;
- }
- default: { return false; }
- }
- return false;
- }
- // Checks sparse image opcode result type and returns the second struct member.
- // Returns inst.type_id for non-sparse image opcodes.
- // Not valid for sparse image opcodes which do not return a struct.
- spv_result_t GetActualResultType(ValidationState_t& _, const Instruction* inst,
- uint32_t* actual_result_type) {
- const SpvOp opcode = inst->opcode();
- if (IsSparse(opcode)) {
- const Instruction* const type_inst = _.FindDef(inst->type_id());
- assert(type_inst);
- if (!type_inst || type_inst->opcode() != SpvOpTypeStruct) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be OpTypeStruct";
- }
- if (type_inst->words().size() != 4 ||
- !_.IsIntScalarType(type_inst->word(2))) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be a struct containing an int "
- "scalar and a texel";
- }
- *actual_result_type = type_inst->word(3);
- } else {
- *actual_result_type = inst->type_id();
- }
- return SPV_SUCCESS;
- }
- // Returns a string describing actual result type of an opcode.
- // Not valid for sparse image opcodes which do not return a struct.
- const char* GetActualResultTypeStr(SpvOp opcode) {
- if (IsSparse(opcode)) return "Result Type's second member";
- return "Result Type";
- }
- spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
- assert(inst->type_id() == 0);
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, inst->word(1), &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (spvIsVulkanEnv(_.context()->target_env)) {
- if ((!_.IsFloatScalarType(info.sampled_type) &&
- !_.IsIntScalarType(info.sampled_type)) ||
- 32 != _.GetBitWidth(info.sampled_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sampled Type to be a 32-bit int or float "
- "scalar type for Vulkan environment";
- }
- } else {
- const SpvOp sampled_type_opcode = _.GetIdOpcode(info.sampled_type);
- if (sampled_type_opcode != SpvOpTypeVoid &&
- sampled_type_opcode != SpvOpTypeInt &&
- sampled_type_opcode != SpvOpTypeFloat) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sampled Type to be either void or"
- << " numerical scalar type";
- }
- }
- // Dim is checked elsewhere.
- if (info.depth > 2) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Invalid Depth " << info.depth << " (must be 0, 1 or 2)";
- }
- if (info.arrayed > 1) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Invalid Arrayed " << info.arrayed << " (must be 0 or 1)";
- }
- if (info.multisampled > 1) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Invalid MS " << info.multisampled << " (must be 0 or 1)";
- }
- if (info.sampled > 2) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Invalid Sampled " << info.sampled << " (must be 0, 1 or 2)";
- }
- if (info.dim == SpvDimSubpassData) {
- if (info.sampled != 2) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Dim SubpassData requires Sampled to be 2";
- }
- if (info.format != SpvImageFormatUnknown) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Dim SubpassData requires format Unknown";
- }
- }
- // Format and Access Qualifier are checked elsewhere.
- return SPV_SUCCESS;
- }
- spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
- const Instruction* inst) {
- const uint32_t image_type = inst->word(2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage";
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateSampledImage(ValidationState_t& _,
- const Instruction* inst) {
- if (_.GetIdOpcode(inst->type_id()) != SpvOpTypeSampledImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be OpTypeSampledImage.";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage.";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- // TODO(atgoo@github.com) Check compatibility of result type and received
- // image.
- if (spvIsVulkanEnv(_.context()->target_env)) {
- if (info.sampled != 1) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled' parameter to be 1 "
- << "for Vulkan environment.";
- }
- } else {
- if (info.sampled != 0 && info.sampled != 1) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled' parameter to be 0 or 1";
- }
- }
- if (info.dim == SpvDimSubpassData) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Dim' parameter to be not SubpassData.";
- }
- if (_.GetIdOpcode(_.GetOperandTypeId(inst, 3)) != SpvOpTypeSampler) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sampler to be of type OpTypeSampler";
- }
- // We need to validate 2 things:
- // * All OpSampledImage instructions must be in the same block in which their
- // Result <id> are consumed.
- // * Result <id> from OpSampledImage instructions must not appear as operands
- // to OpPhi instructions or OpSelect instructions, or any instructions other
- // than the image lookup and query instructions specified to take an operand
- // whose type is OpTypeSampledImage.
- std::vector<uint32_t> consumers = _.getSampledImageConsumers(inst->id());
- if (!consumers.empty()) {
- for (auto consumer_id : consumers) {
- const auto consumer_instr = _.FindDef(consumer_id);
- const auto consumer_opcode = consumer_instr->opcode();
- if (consumer_instr->block() != inst->block()) {
- return _.diag(SPV_ERROR_INVALID_ID, inst)
- << "All OpSampledImage instructions must be in the same block "
- "in "
- "which their Result <id> are consumed. OpSampledImage Result "
- "Type <id> '"
- << _.getIdName(inst->id())
- << "' has a consumer in a different basic "
- "block. The consumer instruction <id> is '"
- << _.getIdName(consumer_id) << "'.";
- }
- // TODO: The following check is incomplete. We should also check that the
- // Sampled Image is not used by instructions that should not take
- // SampledImage as an argument. We could find the list of valid
- // instructions by scanning for "Sampled Image" in the operand description
- // field in the grammar file.
- if (consumer_opcode == SpvOpPhi || consumer_opcode == SpvOpSelect) {
- return _.diag(SPV_ERROR_INVALID_ID, inst)
- << "Result <id> from OpSampledImage instruction must not appear "
- "as "
- "operands of Op"
- << spvOpcodeString(static_cast<SpvOp>(consumer_opcode)) << "."
- << " Found result <id> '" << _.getIdName(inst->id())
- << "' as an operand of <id> '" << _.getIdName(consumer_id)
- << "'.";
- }
- }
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
- const Instruction* inst) {
- const auto result_type = _.FindDef(inst->type_id());
- if (result_type->opcode() != SpvOpTypePointer) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be OpTypePointer";
- }
- const auto storage_class = result_type->GetOperandAs<uint32_t>(1);
- if (storage_class != SpvStorageClassImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be OpTypePointer whose Storage Class "
- "operand is Image";
- }
- const auto ptr_type = result_type->GetOperandAs<uint32_t>(2);
- const auto ptr_opcode = _.GetIdOpcode(ptr_type);
- if (ptr_opcode != SpvOpTypeInt && ptr_opcode != SpvOpTypeFloat &&
- ptr_opcode != SpvOpTypeVoid) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be OpTypePointer whose Type operand "
- "must be a scalar numerical type or OpTypeVoid";
- }
- const auto image_ptr = _.FindDef(_.GetOperandTypeId(inst, 2));
- if (!image_ptr || image_ptr->opcode() != SpvOpTypePointer) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be OpTypePointer";
- }
- const auto image_type = image_ptr->GetOperandAs<uint32_t>(2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be OpTypePointer with Type OpTypeImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (info.sampled_type != ptr_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled Type' to be the same as the Type "
- "pointed to by Result Type";
- }
- if (info.dim == SpvDimSubpassData) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Dim SubpassData cannot be used with OpImageTexelPointer";
- }
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
- if (!coord_type || !_.IsIntScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be integer scalar or vector";
- }
- uint32_t expected_coord_size = 0;
- if (info.arrayed == 0) {
- expected_coord_size = GetPlaneCoordSize(info);
- } else if (info.arrayed == 1) {
- switch (info.dim) {
- case SpvDim1D:
- expected_coord_size = 2;
- break;
- case SpvDimCube:
- case SpvDim2D:
- expected_coord_size = 3;
- break;
- default:
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Dim' must be one of 1D, 2D, or Cube when "
- "Arrayed is 1";
- break;
- }
- }
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (expected_coord_size != actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have " << expected_coord_size
- << " components, but given " << actual_coord_size;
- }
- const uint32_t sample_type = _.GetOperandTypeId(inst, 4);
- if (!sample_type || !_.IsIntScalarType(sample_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sample to be integer scalar";
- }
- if (info.multisampled == 0) {
- uint64_t ms = 0;
- if (!_.GetConstantValUint64(inst->GetOperandAs<uint32_t>(4), &ms) ||
- ms != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sample for Image with MS 0 to be a valid <id> for "
- "the value 0";
- }
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
- const SpvOp opcode = inst->opcode();
- uint32_t actual_result_type = 0;
- if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
- return error;
- }
- if (!_.IsIntVectorType(actual_result_type) &&
- !_.IsFloatVectorType(actual_result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to be int or float vector type";
- }
- if (_.GetDimension(actual_result_type) != 4) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to have 4 components";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sampled Image to be of type OpTypeSampledImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
- if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
- const uint32_t texel_component_type =
- _.GetComponentType(actual_result_type);
- if (texel_component_type != info.sampled_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled Type' to be the same as "
- << GetActualResultTypeStr(opcode) << " components";
- }
- }
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
- if ((opcode == SpvOpImageSampleExplicitLod ||
- opcode == SpvOpImageSparseSampleExplicitLod) &&
- _.HasCapability(SpvCapabilityKernel)) {
- if (!_.IsFloatScalarOrVectorType(coord_type) &&
- !_.IsIntScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be int or float scalar or vector";
- }
- } else {
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be float scalar or vector";
- }
- }
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (min_coord_size > actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have at least " << min_coord_size
- << " components, but given only " << actual_coord_size;
- }
- if (inst->words().size() <= 5) {
- assert(IsImplicitLod(opcode));
- return SPV_SUCCESS;
- }
- const uint32_t mask = inst->word(5);
- if (spv_result_t result =
- ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
- return result;
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageDrefLod(ValidationState_t& _,
- const Instruction* inst) {
- const SpvOp opcode = inst->opcode();
- uint32_t actual_result_type = 0;
- if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
- return error;
- }
- if (!_.IsIntScalarType(actual_result_type) &&
- !_.IsFloatScalarType(actual_result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to be int or float scalar type";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sampled Image to be of type OpTypeSampledImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
- if (actual_result_type != info.sampled_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled Type' to be the same as "
- << GetActualResultTypeStr(opcode);
- }
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be float scalar or vector";
- }
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (min_coord_size > actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have at least " << min_coord_size
- << " components, but given only " << actual_coord_size;
- }
- const uint32_t dref_type = _.GetOperandTypeId(inst, 4);
- if (!_.IsFloatScalarType(dref_type) || _.GetBitWidth(dref_type) != 32) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Dref to be of 32-bit float type";
- }
- if (inst->words().size() <= 6) {
- assert(IsImplicitLod(opcode));
- return SPV_SUCCESS;
- }
- const uint32_t mask = inst->word(6);
- if (spv_result_t result =
- ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
- return result;
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageFetch(ValidationState_t& _, const Instruction* inst) {
- uint32_t actual_result_type = 0;
- if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
- return error;
- }
- const SpvOp opcode = inst->opcode();
- if (!_.IsIntVectorType(actual_result_type) &&
- !_.IsFloatVectorType(actual_result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to be int or float vector type";
- }
- if (_.GetDimension(actual_result_type) != 4) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to have 4 components";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
- const uint32_t result_component_type =
- _.GetComponentType(actual_result_type);
- if (result_component_type != info.sampled_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled Type' to be the same as "
- << GetActualResultTypeStr(opcode) << " components";
- }
- }
- if (info.dim == SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'Dim' cannot be Cube";
- }
- if (info.sampled != 1) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled' parameter to be 1";
- }
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
- if (!_.IsIntScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be int scalar or vector";
- }
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (min_coord_size > actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have at least " << min_coord_size
- << " components, but given only " << actual_coord_size;
- }
- if (inst->words().size() <= 5) return SPV_SUCCESS;
- const uint32_t mask = inst->word(5);
- if (spv_result_t result =
- ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
- return result;
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageGather(ValidationState_t& _,
- const Instruction* inst) {
- uint32_t actual_result_type = 0;
- if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type))
- return error;
- const SpvOp opcode = inst->opcode();
- if (!_.IsIntVectorType(actual_result_type) &&
- !_.IsFloatVectorType(actual_result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to be int or float vector type";
- }
- if (_.GetDimension(actual_result_type) != 4) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to have 4 components";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sampled Image to be of type OpTypeSampledImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (opcode == SpvOpImageDrefGather || opcode == SpvOpImageSparseDrefGather ||
- _.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
- const uint32_t result_component_type =
- _.GetComponentType(actual_result_type);
- if (result_component_type != info.sampled_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled Type' to be the same as "
- << GetActualResultTypeStr(opcode) << " components";
- }
- }
- if (info.dim != SpvDim2D && info.dim != SpvDimCube &&
- info.dim != SpvDimRect) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Dim' cannot be Cube";
- }
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be float scalar or vector";
- }
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (min_coord_size > actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have at least " << min_coord_size
- << " components, but given only " << actual_coord_size;
- }
- if (opcode == SpvOpImageGather || opcode == SpvOpImageSparseGather) {
- const uint32_t component_index_type = _.GetOperandTypeId(inst, 4);
- if (!_.IsIntScalarType(component_index_type) ||
- _.GetBitWidth(component_index_type) != 32) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Component to be 32-bit int scalar";
- }
- } else {
- assert(opcode == SpvOpImageDrefGather ||
- opcode == SpvOpImageSparseDrefGather);
- const uint32_t dref_type = _.GetOperandTypeId(inst, 4);
- if (!_.IsFloatScalarType(dref_type) || _.GetBitWidth(dref_type) != 32) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Dref to be of 32-bit float type";
- }
- }
- if (inst->words().size() <= 6) return SPV_SUCCESS;
- const uint32_t mask = inst->word(6);
- if (spv_result_t result =
- ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
- return result;
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
- const SpvOp opcode = inst->opcode();
- uint32_t actual_result_type = 0;
- if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
- return error;
- }
- if (!_.IsIntScalarOrVectorType(actual_result_type) &&
- !_.IsFloatScalarOrVectorType(actual_result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to be int or float scalar or vector type";
- }
- #if 0
- // TODO(atgoo@github.com) Disabled until the spec is clarified.
- if (_.GetDimension(actual_result_type) != 4) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected " << GetActualResultTypeStr(opcode)
- << " to have 4 components";
- }
- #endif
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (info.dim == SpvDimSubpassData) {
- if (opcode == SpvOpImageSparseRead) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image Dim SubpassData cannot be used with ImageSparseRead";
- }
- _.function(inst->function()->id())
- ->RegisterExecutionModelLimitation(
- SpvExecutionModelFragment,
- std::string("Dim SubpassData requires Fragment execution model: ") +
- spvOpcodeString(opcode));
- }
- if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
- const uint32_t result_component_type =
- _.GetComponentType(actual_result_type);
- if (result_component_type != info.sampled_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled Type' to be the same as "
- << GetActualResultTypeStr(opcode) << " components";
- }
- }
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
- if (!_.IsIntScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be int scalar or vector";
- }
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (min_coord_size > actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have at least " << min_coord_size
- << " components, but given only " << actual_coord_size;
- }
- if (info.format == SpvImageFormatUnknown && info.dim != SpvDimSubpassData &&
- !_.HasCapability(SpvCapabilityStorageImageReadWithoutFormat)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Capability StorageImageReadWithoutFormat is required to "
- << "read storage image";
- }
- if (inst->words().size() <= 5) return SPV_SUCCESS;
- const uint32_t mask = inst->word(5);
- if (spv_result_t result =
- ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
- return result;
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
- const uint32_t image_type = _.GetOperandTypeId(inst, 0);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (info.dim == SpvDimSubpassData) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image 'Dim' cannot be SubpassData";
- }
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
- const uint32_t coord_type = _.GetOperandTypeId(inst, 1);
- if (!_.IsIntScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be int scalar or vector";
- }
- const uint32_t min_coord_size = GetMinCoordSize(inst->opcode(), info);
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (min_coord_size > actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have at least " << min_coord_size
- << " components, but given only " << actual_coord_size;
- }
- // TODO(atgoo@github.com) The spec doesn't explicitely say what the type
- // of texel should be.
- const uint32_t texel_type = _.GetOperandTypeId(inst, 2);
- if (!_.IsIntScalarOrVectorType(texel_type) &&
- !_.IsFloatScalarOrVectorType(texel_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Texel to be int or float vector or scalar";
- }
- #if 0
- // TODO: See above.
- if (_.GetDimension(texel_type) != 4) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Texel to have 4 components";
- }
- #endif
- if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
- const uint32_t texel_component_type = _.GetComponentType(texel_type);
- if (texel_component_type != info.sampled_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image 'Sampled Type' to be the same as Texel "
- << "components";
- }
- }
- if (info.format == SpvImageFormatUnknown && info.dim != SpvDimSubpassData &&
- !_.HasCapability(SpvCapabilityStorageImageWriteWithoutFormat)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Capability StorageImageWriteWithoutFormat is required to "
- "write "
- << "to storage image";
- }
- if (inst->words().size() <= 4) return SPV_SUCCESS;
- const uint32_t mask = inst->word(4);
- if (spv_result_t result =
- ValidateImageOperands(_, inst, info, mask, /* word_index = */ 5))
- return result;
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImage(ValidationState_t& _, const Instruction* inst) {
- const uint32_t result_type = inst->type_id();
- if (_.GetIdOpcode(result_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be OpTypeImage";
- }
- const uint32_t sampled_image_type = _.GetOperandTypeId(inst, 2);
- const Instruction* sampled_image_type_inst = _.FindDef(sampled_image_type);
- assert(sampled_image_type_inst);
- if (sampled_image_type_inst->opcode() != SpvOpTypeSampledImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sample Image to be of type OpTypeSampleImage";
- }
- if (sampled_image_type_inst->word(2) != result_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Sample Image image type to be equal to Result Type";
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageQuerySizeLod(ValidationState_t& _,
- const Instruction* inst) {
- const uint32_t result_type = inst->type_id();
- if (!_.IsIntScalarOrVectorType(result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be int scalar or vector type";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- uint32_t expected_num_components = info.arrayed;
- switch (info.dim) {
- case SpvDim1D:
- expected_num_components += 1;
- break;
- case SpvDim2D:
- case SpvDimCube:
- expected_num_components += 2;
- break;
- case SpvDim3D:
- expected_num_components += 3;
- break;
- default:
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image 'Dim' must be 1D, 2D, 3D or Cube";
- }
- if (info.multisampled != 0) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'MS' must be 0";
- }
- uint32_t result_num_components = _.GetDimension(result_type);
- if (result_num_components != expected_num_components) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Result Type has " << result_num_components << " components, "
- << "but " << expected_num_components << " expected";
- }
- const uint32_t lod_type = _.GetOperandTypeId(inst, 3);
- if (!_.IsIntScalarType(lod_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Level of Detail to be int scalar";
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageQuerySize(ValidationState_t& _,
- const Instruction* inst) {
- const uint32_t result_type = inst->type_id();
- if (!_.IsIntScalarOrVectorType(result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be int scalar or vector type";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- uint32_t expected_num_components = info.arrayed;
- switch (info.dim) {
- case SpvDim1D:
- case SpvDimBuffer:
- expected_num_components += 1;
- break;
- case SpvDim2D:
- case SpvDimCube:
- case SpvDimRect:
- expected_num_components += 2;
- break;
- case SpvDim3D:
- expected_num_components += 3;
- break;
- default:
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect";
- }
- if (info.dim == SpvDim1D || info.dim == SpvDim2D || info.dim == SpvDim3D ||
- info.dim == SpvDimCube) {
- if (info.multisampled != 1 && info.sampled != 0 && info.sampled != 2) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2";
- }
- }
- uint32_t result_num_components = _.GetDimension(result_type);
- if (result_num_components != expected_num_components) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Result Type has " << result_num_components << " components, "
- << "but " << expected_num_components << " expected";
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageQueryFormatOrOrder(ValidationState_t& _,
- const Instruction* inst) {
- if (!_.IsIntScalarType(inst->type_id())) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be int scalar type";
- }
- if (_.GetIdOpcode(_.GetOperandTypeId(inst, 2)) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected operand to be of type OpTypeImage";
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageQueryLod(ValidationState_t& _,
- const Instruction* inst) {
- _.function(inst->function()->id())
- ->RegisterExecutionModelLimitation(
- SpvExecutionModelFragment,
- "OpImageQueryLod requires Fragment execution model");
- const uint32_t result_type = inst->type_id();
- if (!_.IsFloatVectorType(result_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be float vector type";
- }
- if (_.GetDimension(result_type) != 2) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to have 2 components";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image operand to be of type OpTypeSampledImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
- info.dim != SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image 'Dim' must be 1D, 2D, 3D or Cube";
- }
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
- if (_.HasCapability(SpvCapabilityKernel)) {
- if (!_.IsFloatScalarOrVectorType(coord_type) &&
- !_.IsIntScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be int or float scalar or vector";
- }
- } else {
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to be float scalar or vector";
- }
- }
- const uint32_t min_coord_size = GetPlaneCoordSize(info);
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
- if (min_coord_size > actual_coord_size) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Coordinate to have at least " << min_coord_size
- << " components, but given only " << actual_coord_size;
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageSparseLod(ValidationState_t& _,
- const Instruction* inst) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Instruction reserved for future use, use of this instruction "
- << "is invalid";
- }
- spv_result_t ValidateImageQueryLevelsOrSamples(ValidationState_t& _,
- const Instruction* inst) {
- if (!_.IsIntScalarType(inst->type_id())) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be int scalar type";
- }
- const uint32_t image_type = _.GetOperandTypeId(inst, 2);
- if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Image to be of type OpTypeImage";
- }
- ImageTypeInfo info;
- if (!GetImageTypeInfo(_, image_type, &info)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Corrupt image type definition";
- }
- const SpvOp opcode = inst->opcode();
- if (opcode == SpvOpImageQueryLevels) {
- if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
- info.dim != SpvDimCube) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Image 'Dim' must be 1D, 2D, 3D or Cube";
- }
- } else {
- assert(opcode == SpvOpImageQuerySamples);
- if (info.dim != SpvDim2D) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'Dim' must be 2D";
- }
- if (info.multisampled != 1) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'MS' must be 1";
- }
- }
- return SPV_SUCCESS;
- }
- spv_result_t ValidateImageSparseTexelsResident(ValidationState_t& _,
- const Instruction* inst) {
- if (!_.IsBoolScalarType(inst->type_id())) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Result Type to be bool scalar type";
- }
- const uint32_t resident_code_type = _.GetOperandTypeId(inst, 2);
- if (!_.IsIntScalarType(resident_code_type)) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << "Expected Resident Code to be int scalar";
- }
- return SPV_SUCCESS;
- }
- } // namespace
- // Validates correctness of image instructions.
- spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) {
- const SpvOp opcode = inst->opcode();
- if (IsImplicitLod(opcode)) {
- _.function(inst->function()->id())
- ->RegisterExecutionModelLimitation(
- SpvExecutionModelFragment,
- "ImplicitLod instructions require Fragment execution model");
- }
- switch (opcode) {
- case SpvOpTypeImage:
- return ValidateTypeImage(_, inst);
- case SpvOpTypeSampledImage:
- return ValidateTypeSampledImage(_, inst);
- case SpvOpSampledImage:
- return ValidateSampledImage(_, inst);
- case SpvOpImageTexelPointer:
- return ValidateImageTexelPointer(_, inst);
- case SpvOpImageSampleImplicitLod:
- case SpvOpImageSampleExplicitLod:
- case SpvOpImageSampleProjImplicitLod:
- case SpvOpImageSampleProjExplicitLod:
- case SpvOpImageSparseSampleImplicitLod:
- case SpvOpImageSparseSampleExplicitLod:
- return ValidateImageLod(_, inst);
- case SpvOpImageSampleDrefImplicitLod:
- case SpvOpImageSampleDrefExplicitLod:
- case SpvOpImageSampleProjDrefImplicitLod:
- case SpvOpImageSampleProjDrefExplicitLod:
- case SpvOpImageSparseSampleDrefImplicitLod:
- case SpvOpImageSparseSampleDrefExplicitLod:
- return ValidateImageDrefLod(_, inst);
- case SpvOpImageFetch:
- case SpvOpImageSparseFetch:
- return ValidateImageFetch(_, inst);
- case SpvOpImageGather:
- case SpvOpImageDrefGather:
- case SpvOpImageSparseGather:
- case SpvOpImageSparseDrefGather:
- return ValidateImageGather(_, inst);
- case SpvOpImageRead:
- case SpvOpImageSparseRead:
- return ValidateImageRead(_, inst);
- case SpvOpImageWrite:
- return ValidateImageWrite(_, inst);
- case SpvOpImage:
- return ValidateImage(_, inst);
- case SpvOpImageQueryFormat:
- case SpvOpImageQueryOrder:
- return ValidateImageQueryFormatOrOrder(_, inst);
- case SpvOpImageQuerySizeLod:
- return ValidateImageQuerySizeLod(_, inst);
- case SpvOpImageQuerySize:
- return ValidateImageQuerySize(_, inst);
- case SpvOpImageQueryLod:
- return ValidateImageQueryLod(_, inst);
- case SpvOpImageQueryLevels:
- case SpvOpImageQuerySamples:
- return ValidateImageQueryLevelsOrSamples(_, inst);
- case SpvOpImageSparseSampleProjImplicitLod:
- case SpvOpImageSparseSampleProjExplicitLod:
- case SpvOpImageSparseSampleProjDrefImplicitLod:
- case SpvOpImageSparseSampleProjDrefExplicitLod:
- return ValidateImageSparseLod(_, inst);
- case SpvOpImageSparseTexelsResident:
- return ValidateImageSparseTexelsResident(_, inst);
- default:
- break;
- }
- return SPV_SUCCESS;
- }
- } // namespace val
- } // namespace spvtools
|