Validator checks if operands require extension
If required extension is not found, returning new error SPV_ERROR_MISSING_EXTENSION.
This commit is contained in:
Родитель
1fb8c37b57
Коммит
b011633171
|
@ -54,6 +54,7 @@ typedef enum spv_result_t {
|
|||
SPV_ERROR_INVALID_LAYOUT = -12,
|
||||
SPV_ERROR_INVALID_CAPABILITY = -13,
|
||||
SPV_ERROR_INVALID_DATA = -14, // Indicates data rules validation failure.
|
||||
SPV_ERROR_MISSING_EXTENSION = -15,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_result_t)
|
||||
} spv_result_t;
|
||||
|
||||
|
|
|
@ -149,11 +149,13 @@ set(SPIRV_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/util/bitutils.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/hex_float.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/parse_number.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/string_utils.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/binary.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/diagnostic.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/enum_set.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/extensions.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/instruction.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/macro.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/name_mapper.h
|
||||
|
@ -172,6 +174,7 @@ set(SPIRV_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/validate.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/parse_number.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/string_utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/diagnostic.cpp
|
||||
|
|
|
@ -14,10 +14,25 @@
|
|||
|
||||
#include "extensions.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
|
||||
if (inst->opcode != SpvOpExtension)
|
||||
return "ERROR_not_op_extension";
|
||||
|
||||
assert(inst->num_operands == 1);
|
||||
|
||||
const auto& operand = inst->operands[0];
|
||||
assert(operand.type == SPV_OPERAND_TYPE_LITERAL_STRING);
|
||||
assert(inst->num_words > operand.offset);
|
||||
|
||||
return reinterpret_cast<const char*>(inst->words + operand.offset);
|
||||
}
|
||||
|
||||
bool ParseSpvExtensionFromString(const std::string& str, Extension* extension) {
|
||||
if (str == "SPV_KHR_shader_ballot") {
|
||||
*extension = Extension::kSPV_KHR_shader_ballot;
|
||||
|
@ -48,4 +63,41 @@ bool ParseSpvExtensionFromString(const std::string& str, Extension* extension) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string ExtensionToString(Extension extension) {
|
||||
switch (extension) {
|
||||
case Extension::kSPV_KHR_shader_ballot:
|
||||
return "SPV_KHR_shader_ballot";
|
||||
case Extension::kSPV_KHR_shader_draw_parameters:
|
||||
return "SPV_KHR_shader_draw_parameters";
|
||||
case Extension::kSPV_KHR_subgroup_vote:
|
||||
return "SPV_KHR_subgroup_vote";
|
||||
case Extension::kSPV_KHR_16bit_storage:
|
||||
return "SPV_KHR_16bit_storage";
|
||||
case Extension::kSPV_KHR_device_group:
|
||||
return "SPV_KHR_device_group";
|
||||
case Extension::kSPV_KHR_multiview:
|
||||
return "SPV_KHR_multiview";
|
||||
case Extension::kSPV_NV_sample_mask_override_coverage:
|
||||
return "SPV_NV_sample_mask_override_coverage";
|
||||
case Extension::kSPV_NV_geometry_shader_passthrough:
|
||||
return "SPV_NV_geometry_shader_passthrough";
|
||||
case Extension::kSPV_NV_viewport_array2:
|
||||
return "SPV_NV_viewport_array2";
|
||||
case Extension::kSPV_NV_stereo_view_rendering:
|
||||
return "SPV_NV_stereo_view_rendering";
|
||||
case Extension::kSPV_NVX_multiview_per_view_attributes:
|
||||
return "SPV_NVX_multiview_per_view_attributes";
|
||||
}
|
||||
|
||||
return "ERROR_unknown_extension";
|
||||
}
|
||||
|
||||
std::string ExtensionSetToString(const ExtensionSet& extensions) {
|
||||
std::stringstream ss;
|
||||
extensions.ForEach([&ss](Extension ext) {
|
||||
ss << ExtensionToString(ext) << " ";
|
||||
});
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace libspirv
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
#include <string>
|
||||
|
||||
#include "enum_set.h"
|
||||
#include "message.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
// The known SPIR-V extensions.
|
||||
// TODO(dneto): Consider auto-generating this list?
|
||||
// When updating this list, consider also updating ParseSpvExtensionFromString.
|
||||
// When updating this list, consider also updating ParseSpvExtensionFromString
|
||||
// and SpvExtensionToString.
|
||||
enum class Extension {
|
||||
kSPV_KHR_shader_ballot,
|
||||
kSPV_KHR_shader_draw_parameters,
|
||||
|
@ -42,9 +42,18 @@ enum class Extension {
|
|||
|
||||
using ExtensionSet = EnumSet<Extension>;
|
||||
|
||||
// Returns literal string operand of OpExtension instruction.
|
||||
std::string GetExtensionString(const spv_parsed_instruction_t* inst);
|
||||
|
||||
// Finds Extension enum corresponding to |str|. Returns false if not found.
|
||||
bool ParseSpvExtensionFromString(const std::string& str, Extension* extension);
|
||||
|
||||
// Returns text string corresponding to |extension|.
|
||||
std::string ExtensionToString(Extension extension);
|
||||
|
||||
// Returns text string listing |extensions| separated by whitespace.
|
||||
std::string ExtensionSetToString(const ExtensionSet& extensions);
|
||||
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // LIBSPIRV_EXTENSIONS_H_
|
||||
|
|
|
@ -41,10 +41,9 @@ typedef struct spv_operand_desc_t {
|
|||
const uint32_t value;
|
||||
const libspirv::CapabilitySet capabilities;
|
||||
// A set of extensions that enable this feature. If empty then this operand
|
||||
// value is always enabled, i.e. it's in core. The assembler, binary parser,
|
||||
// value is always enabled, i.e. it's in core. The assembler, binary parser,
|
||||
// and disassembler ignore this rule, so you can freely process invalid
|
||||
// modules.
|
||||
// TODO(dneto): Add validator support to check extensions.
|
||||
const libspirv::ExtensionSet extensions;
|
||||
const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
|
||||
} spv_operand_desc_t;
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// 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.
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include "util/string_utils.h"
|
||||
|
||||
namespace spvutils {
|
||||
|
||||
std::string CardinalToOrdinal(size_t cardinal) {
|
||||
const size_t mod10 = cardinal % 10;
|
||||
const size_t mod100 = cardinal % 100;
|
||||
std::string suffix;
|
||||
if (mod10 == 1 && mod100 != 11)
|
||||
suffix = "st";
|
||||
else if (mod10 == 2 && mod100 != 12)
|
||||
suffix = "nd";
|
||||
else if (mod10 == 3 && mod100 != 13)
|
||||
suffix = "rd";
|
||||
else
|
||||
suffix = "th";
|
||||
|
||||
return ToString(cardinal) + suffix;
|
||||
}
|
||||
|
||||
} // namespace spvutils
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// 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.
|
||||
|
||||
#ifndef LIBSPIRV_UTIL_STRING_UTILS_H_
|
||||
#define LIBSPIRV_UTIL_STRING_UTILS_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "util/string_utils.h"
|
||||
|
||||
namespace spvutils {
|
||||
|
||||
// Converts arithmetic value |val| to its default string representation.
|
||||
template <class T>
|
||||
std::string ToString(T val) {
|
||||
static_assert(std::is_arithmetic<T>::value,
|
||||
"spvutils::ToString is restricted to only arithmetic values");
|
||||
std::stringstream os;
|
||||
os << val;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// Converts cardinal number to ordinal number string.
|
||||
std::string CardinalToOrdinal(size_t cardinal);
|
||||
|
||||
} // namespace spvutils
|
||||
|
||||
#endif // LIBSPIRV_UTIL_STRING_UTILS_H_
|
|
@ -311,14 +311,14 @@ void ValidationState_t::RegisterExtension(Extension ext) {
|
|||
module_extensions_.Add(ext);
|
||||
}
|
||||
|
||||
bool ValidationState_t::HasAnyOf(const CapabilitySet& capabilities) const {
|
||||
bool found = false;
|
||||
bool any_queried = false;
|
||||
capabilities.ForEach([&found, &any_queried, this](SpvCapability c) {
|
||||
any_queried = true;
|
||||
found = found || this->module_capabilities_.Contains(c);
|
||||
});
|
||||
return !any_queried || found;
|
||||
bool ValidationState_t::HasAnyOfCapabilities(
|
||||
const CapabilitySet& capabilities) const {
|
||||
return module_capabilities_.HasAnyOf(capabilities);
|
||||
}
|
||||
|
||||
bool ValidationState_t::HasAnyOfExtensions(
|
||||
const ExtensionSet& extensions) const {
|
||||
return module_extensions_.HasAnyOf(extensions);
|
||||
}
|
||||
|
||||
void ValidationState_t::set_addressing_model(SpvAddressingModel am) {
|
||||
|
|
|
@ -192,9 +192,18 @@ class ValidationState_t {
|
|||
return module_capabilities_.Contains(cap);
|
||||
}
|
||||
|
||||
/// Returns true if any of the capabilities are enabled, or if the given
|
||||
/// capabilities is the empty set.
|
||||
bool HasAnyOf(const libspirv::CapabilitySet& capabilities) const;
|
||||
/// Returns true if the extension is enabled in the module.
|
||||
bool HasExtension(Extension ext) const {
|
||||
return module_extensions_.Contains(ext);
|
||||
}
|
||||
|
||||
/// Returns true if any of the capabilities is enabled, or if |capabilities|
|
||||
/// is an empty set.
|
||||
bool HasAnyOfCapabilities(const libspirv::CapabilitySet& capabilities) const;
|
||||
|
||||
/// Returns true if any of the extensions is enabled, or if |extensions|
|
||||
/// is an empty set.
|
||||
bool HasAnyOfExtensions(const libspirv::ExtensionSet& extensions) const;
|
||||
|
||||
/// Sets the addressing model of this module (logical/physical).
|
||||
void set_addressing_model(SpvAddressingModel am);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "binary.h"
|
||||
#include "diagnostic.h"
|
||||
#include "extensions.h"
|
||||
#include "instruction.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
|
@ -46,6 +47,7 @@ using std::transform;
|
|||
using std::vector;
|
||||
|
||||
using libspirv::CfgPass;
|
||||
using libspirv::Extension;
|
||||
using libspirv::InstructionPass;
|
||||
using libspirv::ModuleLayoutPass;
|
||||
using libspirv::DataRulesPass;
|
||||
|
@ -117,6 +119,40 @@ void DebugInstructionPass(ValidationState_t& _,
|
|||
}
|
||||
}
|
||||
|
||||
// Parses OpExtension instruction and registers extension.
|
||||
void RegisterExtension(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const std::string extension_str = libspirv::GetExtensionString(inst);
|
||||
Extension extension;
|
||||
if (!ParseSpvExtensionFromString(extension_str, &extension)) {
|
||||
// The error will be logged in the ProcessInstruction pass.
|
||||
return;
|
||||
}
|
||||
|
||||
_.RegisterExtension(extension);
|
||||
}
|
||||
|
||||
// Parses the beginning of the module searching for OpExtension instructions.
|
||||
// Registers extensions if recognized. Returns SPV_REQUESTED_TERMINATION
|
||||
// once an instruction which is not SpvOpCapability and SpvOpExtension is
|
||||
// encountered. According to the SPIR-V spec extensions are declared after
|
||||
// capabilities and before everything else.
|
||||
spv_result_t ProcessExtensions(
|
||||
void* user_data, const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (opcode == SpvOpCapability)
|
||||
return SPV_SUCCESS;
|
||||
|
||||
if (opcode == SpvOpExtension) {
|
||||
ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
|
||||
RegisterExtension(_, inst);
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// OpExtension block is finished, requesting termination.
|
||||
return SPV_REQUESTED_TERMINATION;
|
||||
}
|
||||
|
||||
spv_result_t ProcessInstruction(void* user_data,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
|
||||
|
@ -215,6 +251,12 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
|
|||
<< "Invalid SPIR-V header.";
|
||||
}
|
||||
|
||||
// Look for OpExtension instructions and register extensions.
|
||||
// Diagnostics if any will be produced in the next pass (ProcessInstruction).
|
||||
spvBinaryParse(&context, vstate, words, num_words,
|
||||
/* parsed_header = */ nullptr, ProcessExtensions,
|
||||
/* diagnostic = */ nullptr);
|
||||
|
||||
// NOTE: Parse the module and perform inline validation checks. These
|
||||
// checks do not require the the knowledge of the whole module.
|
||||
if (auto error = spvBinaryParse(&context, vstate, words, num_words,
|
||||
|
|
|
@ -25,16 +25,19 @@
|
|||
#include "binary.h"
|
||||
#include "diagnostic.h"
|
||||
#include "enum_set.h"
|
||||
#include "extensions.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "spirv_definition.h"
|
||||
#include "spirv_validator_options.h"
|
||||
#include "util/string_utils.h"
|
||||
#include "val/function.h"
|
||||
#include "val/validation_state.h"
|
||||
|
||||
using libspirv::AssemblyGrammar;
|
||||
using libspirv::CapabilitySet;
|
||||
using libspirv::DiagnosticStream;
|
||||
using libspirv::ExtensionSet;
|
||||
using libspirv::ValidationState_t;
|
||||
|
||||
namespace {
|
||||
|
@ -104,16 +107,29 @@ CapabilitySet RequiredCapabilities(const ValidationState_t& state,
|
|||
return CapabilitySet();
|
||||
}
|
||||
|
||||
// Returns operand's required extensions.
|
||||
ExtensionSet RequiredExtensions(const ValidationState_t& state,
|
||||
spv_operand_type_t type, uint32_t operand) {
|
||||
spv_operand_desc operand_desc;
|
||||
if (state.grammar().lookupOperand(type, operand, &operand_desc) ==
|
||||
SPV_SUCCESS) {
|
||||
assert(operand_desc);
|
||||
return operand_desc->extensions;
|
||||
}
|
||||
|
||||
return ExtensionSet();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
spv_result_t CapCheck(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
spv_result_t CapabilityCheck(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
spv_opcode_desc opcode_desc;
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (SPV_SUCCESS == _.grammar().lookupOpcode(opcode, &opcode_desc) &&
|
||||
!_.HasAnyOf(opcode_desc->capabilities))
|
||||
!_.HasAnyOfCapabilities(opcode_desc->capabilities))
|
||||
return _.diag(SPV_ERROR_INVALID_CAPABILITY)
|
||||
<< "Opcode " << spvOpcodeString(opcode)
|
||||
<< " requires one of these capabilities: "
|
||||
|
@ -126,7 +142,7 @@ spv_result_t CapCheck(ValidationState_t& _,
|
|||
for (uint32_t mask_bit = 0x80000000; mask_bit; mask_bit >>= 1) {
|
||||
if (word & mask_bit) {
|
||||
const auto caps = RequiredCapabilities(_, operand.type, mask_bit);
|
||||
if (!_.HasAnyOf(caps)) {
|
||||
if (!_.HasAnyOfCapabilities(caps)) {
|
||||
return CapabilityError(_, i + 1, opcode,
|
||||
ToString(caps, _.grammar()));
|
||||
}
|
||||
|
@ -139,7 +155,7 @@ spv_result_t CapCheck(ValidationState_t& _,
|
|||
} else {
|
||||
// Check the operand word as a whole.
|
||||
const auto caps = RequiredCapabilities(_, operand.type, word);
|
||||
if (!_.HasAnyOf(caps)) {
|
||||
if (!_.HasAnyOfCapabilities(caps)) {
|
||||
return CapabilityError(_, i + 1, opcode, ToString(caps, _.grammar()));
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +163,27 @@ spv_result_t CapCheck(ValidationState_t& _,
|
|||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Checks that all required extensions were declared in the module.
|
||||
spv_result_t ExtensionCheck(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
for (size_t operand_index = 0; operand_index < inst->num_operands;
|
||||
++operand_index) {
|
||||
const auto& operand = inst->operands[operand_index];
|
||||
const uint32_t word = inst->words[operand.offset];
|
||||
const ExtensionSet required_extensions =
|
||||
RequiredExtensions(_, operand.type, word);
|
||||
if (!_.HasAnyOfExtensions(required_extensions)) {
|
||||
return _.diag(SPV_ERROR_MISSING_EXTENSION)
|
||||
<< spvutils::CardinalToOrdinal(operand_index + 1) << " operand of "
|
||||
<< spvOpcodeString(opcode) << ": operand " << word
|
||||
<< " requires one of these extensions: "
|
||||
<< ExtensionSetToString(required_extensions);
|
||||
}
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Checks that the instruction is not reserved for future use.
|
||||
spv_result_t ReservedCheck(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
|
@ -341,33 +378,22 @@ spv_result_t RegisterDecorations(ValidationState_t& _,
|
|||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Parses OpExtension instruction and registers extension.
|
||||
void RegisterExtension(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
assert(inst->opcode == SpvOpExtension);
|
||||
assert(inst->num_operands == 1);
|
||||
|
||||
const auto& operand = inst->operands[0];
|
||||
assert(operand.type == SPV_OPERAND_TYPE_LITERAL_STRING);
|
||||
assert(inst->num_words > operand.offset);
|
||||
|
||||
const char* extension_str =
|
||||
reinterpret_cast<const char*>(inst->words + operand.offset);
|
||||
|
||||
// Parses OpExtension instruction and logs warnings if unsuccessful.
|
||||
void CheckIfKnownExtension(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const std::string extension_str = GetExtensionString(inst);
|
||||
Extension extension;
|
||||
if (!ParseSpvExtensionFromString(extension_str, &extension)) {
|
||||
_.diag(SPV_SUCCESS) << "Failed to parse OpExtension " << extension_str;
|
||||
_.diag(SPV_SUCCESS) << "Found unrecognized extension " << extension_str;
|
||||
return;
|
||||
}
|
||||
|
||||
_.RegisterExtension(extension);
|
||||
}
|
||||
|
||||
spv_result_t InstructionPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (opcode == SpvOpExtension)
|
||||
RegisterExtension(_, inst);
|
||||
CheckIfKnownExtension(_, inst);
|
||||
if (opcode == SpvOpCapability)
|
||||
_.RegisterCapability(
|
||||
static_cast<SpvCapability>(inst->words[inst->operands[0].offset]));
|
||||
|
@ -420,7 +446,8 @@ spv_result_t InstructionPass(ValidationState_t& _,
|
|||
// that are applied to any given <id>.
|
||||
RegisterDecorations(_, inst);
|
||||
|
||||
if (auto error = CapCheck(_, inst)) return error;
|
||||
if (auto error = ExtensionCheck(_, inst)) return error;
|
||||
if (auto error = CapabilityCheck(_, inst)) return error;
|
||||
if (auto error = LimitCheckIdBound(_, inst)) return error;
|
||||
if (auto error = LimitCheckStruct(_, inst)) return error;
|
||||
if (auto error = LimitCheckSwitch(_, inst)) return error;
|
||||
|
|
|
@ -146,6 +146,11 @@ add_spvtools_unittest(
|
|||
SRCS parse_number_test.cpp
|
||||
LIBS ${SPIRV_TOOLS})
|
||||
|
||||
add_spvtools_unittest(
|
||||
TARGET string_utils
|
||||
SRCS string_utils_test.cpp
|
||||
LIBS ${SPIRV_TOOLS})
|
||||
|
||||
add_spvtools_unittest(
|
||||
TARGET log
|
||||
SRCS log_test.cpp
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
// 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.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "source/util/string_utils.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using ::spvutils::CardinalToOrdinal;
|
||||
using ::spvutils::ToString;
|
||||
|
||||
TEST(ToString, Int) {
|
||||
EXPECT_EQ("0", ToString(0));
|
||||
EXPECT_EQ("1000", ToString(1000));
|
||||
EXPECT_EQ("-1", ToString(-1));
|
||||
EXPECT_EQ("0", ToString(0LL));
|
||||
EXPECT_EQ("1000", ToString(1000LL));
|
||||
EXPECT_EQ("-1", ToString(-1LL));
|
||||
}
|
||||
|
||||
TEST(ToString, Uint) {
|
||||
EXPECT_EQ("0", ToString(0U));
|
||||
EXPECT_EQ("1000", ToString(1000U));
|
||||
EXPECT_EQ("0", ToString(0ULL));
|
||||
EXPECT_EQ("1000", ToString(1000ULL));
|
||||
}
|
||||
|
||||
TEST(ToString, Float) {
|
||||
EXPECT_EQ("0", ToString(0.f));
|
||||
EXPECT_EQ("1000", ToString(1000.f));
|
||||
EXPECT_EQ("-1.5", ToString(-1.5f));
|
||||
}
|
||||
|
||||
TEST(ToString, Double) {
|
||||
EXPECT_EQ("0", ToString(0.));
|
||||
EXPECT_EQ("1000", ToString(1000.));
|
||||
EXPECT_EQ("-1.5", ToString(-1.5));
|
||||
}
|
||||
|
||||
TEST(CardinalToOrdinal, Test) {
|
||||
EXPECT_EQ("1st", CardinalToOrdinal(1));
|
||||
EXPECT_EQ("2nd", CardinalToOrdinal(2));
|
||||
EXPECT_EQ("3rd", CardinalToOrdinal(3));
|
||||
EXPECT_EQ("4th", CardinalToOrdinal(4));
|
||||
EXPECT_EQ("5th", CardinalToOrdinal(5));
|
||||
EXPECT_EQ("6th", CardinalToOrdinal(6));
|
||||
EXPECT_EQ("7th", CardinalToOrdinal(7));
|
||||
EXPECT_EQ("8th", CardinalToOrdinal(8));
|
||||
EXPECT_EQ("9th", CardinalToOrdinal(9));
|
||||
EXPECT_EQ("10th", CardinalToOrdinal(10));
|
||||
EXPECT_EQ("11th", CardinalToOrdinal(11));
|
||||
EXPECT_EQ("12th", CardinalToOrdinal(12));
|
||||
EXPECT_EQ("13th", CardinalToOrdinal(13));
|
||||
EXPECT_EQ("14th", CardinalToOrdinal(14));
|
||||
EXPECT_EQ("15th", CardinalToOrdinal(15));
|
||||
EXPECT_EQ("16th", CardinalToOrdinal(16));
|
||||
EXPECT_EQ("17th", CardinalToOrdinal(17));
|
||||
EXPECT_EQ("18th", CardinalToOrdinal(18));
|
||||
EXPECT_EQ("19th", CardinalToOrdinal(19));
|
||||
EXPECT_EQ("20th", CardinalToOrdinal(20));
|
||||
EXPECT_EQ("21st", CardinalToOrdinal(21));
|
||||
EXPECT_EQ("22nd", CardinalToOrdinal(22));
|
||||
EXPECT_EQ("23rd", CardinalToOrdinal(23));
|
||||
EXPECT_EQ("24th", CardinalToOrdinal(24));
|
||||
EXPECT_EQ("25th", CardinalToOrdinal(25));
|
||||
EXPECT_EQ("26th", CardinalToOrdinal(26));
|
||||
EXPECT_EQ("27th", CardinalToOrdinal(27));
|
||||
EXPECT_EQ("28th", CardinalToOrdinal(28));
|
||||
EXPECT_EQ("29th", CardinalToOrdinal(29));
|
||||
EXPECT_EQ("30th", CardinalToOrdinal(30));
|
||||
EXPECT_EQ("31st", CardinalToOrdinal(31));
|
||||
EXPECT_EQ("32nd", CardinalToOrdinal(32));
|
||||
EXPECT_EQ("33rd", CardinalToOrdinal(33));
|
||||
EXPECT_EQ("34th", CardinalToOrdinal(34));
|
||||
EXPECT_EQ("35th", CardinalToOrdinal(35));
|
||||
EXPECT_EQ("100th", CardinalToOrdinal(100));
|
||||
EXPECT_EQ("101st", CardinalToOrdinal(101));
|
||||
EXPECT_EQ("102nd", CardinalToOrdinal(102));
|
||||
EXPECT_EQ("103rd", CardinalToOrdinal(103));
|
||||
EXPECT_EQ("104th", CardinalToOrdinal(104));
|
||||
EXPECT_EQ("105th", CardinalToOrdinal(105));
|
||||
EXPECT_EQ("106th", CardinalToOrdinal(106));
|
||||
EXPECT_EQ("107th", CardinalToOrdinal(107));
|
||||
EXPECT_EQ("108th", CardinalToOrdinal(108));
|
||||
EXPECT_EQ("109th", CardinalToOrdinal(109));
|
||||
EXPECT_EQ("110th", CardinalToOrdinal(110));
|
||||
EXPECT_EQ("111th", CardinalToOrdinal(111));
|
||||
EXPECT_EQ("112th", CardinalToOrdinal(112));
|
||||
EXPECT_EQ("113th", CardinalToOrdinal(113));
|
||||
EXPECT_EQ("114th", CardinalToOrdinal(114));
|
||||
EXPECT_EQ("115th", CardinalToOrdinal(115));
|
||||
EXPECT_EQ("116th", CardinalToOrdinal(116));
|
||||
EXPECT_EQ("117th", CardinalToOrdinal(117));
|
||||
EXPECT_EQ("118th", CardinalToOrdinal(118));
|
||||
EXPECT_EQ("119th", CardinalToOrdinal(119));
|
||||
EXPECT_EQ("120th", CardinalToOrdinal(120));
|
||||
EXPECT_EQ("121st", CardinalToOrdinal(121));
|
||||
EXPECT_EQ("122nd", CardinalToOrdinal(122));
|
||||
EXPECT_EQ("123rd", CardinalToOrdinal(123));
|
||||
EXPECT_EQ("124th", CardinalToOrdinal(124));
|
||||
EXPECT_EQ("125th", CardinalToOrdinal(125));
|
||||
EXPECT_EQ("126th", CardinalToOrdinal(126));
|
||||
EXPECT_EQ("127th", CardinalToOrdinal(127));
|
||||
EXPECT_EQ("128th", CardinalToOrdinal(128));
|
||||
EXPECT_EQ("129th", CardinalToOrdinal(129));
|
||||
EXPECT_EQ("130th", CardinalToOrdinal(130));
|
||||
EXPECT_EQ("131st", CardinalToOrdinal(131));
|
||||
EXPECT_EQ("132nd", CardinalToOrdinal(132));
|
||||
EXPECT_EQ("133rd", CardinalToOrdinal(133));
|
||||
EXPECT_EQ("134th", CardinalToOrdinal(134));
|
||||
EXPECT_EQ("135th", CardinalToOrdinal(135));
|
||||
EXPECT_EQ("1000th", CardinalToOrdinal(1000));
|
||||
EXPECT_EQ("1001st", CardinalToOrdinal(1001));
|
||||
EXPECT_EQ("1002nd", CardinalToOrdinal(1002));
|
||||
EXPECT_EQ("1003rd", CardinalToOrdinal(1003));
|
||||
EXPECT_EQ("1004th", CardinalToOrdinal(1004));
|
||||
EXPECT_EQ("1005th", CardinalToOrdinal(1005));
|
||||
EXPECT_EQ("1006th", CardinalToOrdinal(1006));
|
||||
EXPECT_EQ("1007th", CardinalToOrdinal(1007));
|
||||
EXPECT_EQ("1008th", CardinalToOrdinal(1008));
|
||||
EXPECT_EQ("1009th", CardinalToOrdinal(1009));
|
||||
EXPECT_EQ("1010th", CardinalToOrdinal(1010));
|
||||
EXPECT_EQ("1011th", CardinalToOrdinal(1011));
|
||||
EXPECT_EQ("1012th", CardinalToOrdinal(1012));
|
||||
EXPECT_EQ("1013th", CardinalToOrdinal(1013));
|
||||
EXPECT_EQ("1014th", CardinalToOrdinal(1014));
|
||||
EXPECT_EQ("1015th", CardinalToOrdinal(1015));
|
||||
EXPECT_EQ("1016th", CardinalToOrdinal(1016));
|
||||
EXPECT_EQ("1017th", CardinalToOrdinal(1017));
|
||||
EXPECT_EQ("1018th", CardinalToOrdinal(1018));
|
||||
EXPECT_EQ("1019th", CardinalToOrdinal(1019));
|
||||
EXPECT_EQ("1020th", CardinalToOrdinal(1020));
|
||||
EXPECT_EQ("1021st", CardinalToOrdinal(1021));
|
||||
EXPECT_EQ("1022nd", CardinalToOrdinal(1022));
|
||||
EXPECT_EQ("1023rd", CardinalToOrdinal(1023));
|
||||
EXPECT_EQ("1024th", CardinalToOrdinal(1024));
|
||||
EXPECT_EQ("1025th", CardinalToOrdinal(1025));
|
||||
EXPECT_EQ("1026th", CardinalToOrdinal(1026));
|
||||
EXPECT_EQ("1027th", CardinalToOrdinal(1027));
|
||||
EXPECT_EQ("1028th", CardinalToOrdinal(1028));
|
||||
EXPECT_EQ("1029th", CardinalToOrdinal(1029));
|
||||
EXPECT_EQ("1030th", CardinalToOrdinal(1030));
|
||||
EXPECT_EQ("1031st", CardinalToOrdinal(1031));
|
||||
EXPECT_EQ("1032nd", CardinalToOrdinal(1032));
|
||||
EXPECT_EQ("1033rd", CardinalToOrdinal(1033));
|
||||
EXPECT_EQ("1034th", CardinalToOrdinal(1034));
|
||||
EXPECT_EQ("1035th", CardinalToOrdinal(1035));
|
||||
EXPECT_EQ("1200th", CardinalToOrdinal(1200));
|
||||
EXPECT_EQ("1201st", CardinalToOrdinal(1201));
|
||||
EXPECT_EQ("1202nd", CardinalToOrdinal(1202));
|
||||
EXPECT_EQ("1203rd", CardinalToOrdinal(1203));
|
||||
EXPECT_EQ("1204th", CardinalToOrdinal(1204));
|
||||
EXPECT_EQ("1205th", CardinalToOrdinal(1205));
|
||||
EXPECT_EQ("1206th", CardinalToOrdinal(1206));
|
||||
EXPECT_EQ("1207th", CardinalToOrdinal(1207));
|
||||
EXPECT_EQ("1208th", CardinalToOrdinal(1208));
|
||||
EXPECT_EQ("1209th", CardinalToOrdinal(1209));
|
||||
EXPECT_EQ("1210th", CardinalToOrdinal(1210));
|
||||
EXPECT_EQ("1211th", CardinalToOrdinal(1211));
|
||||
EXPECT_EQ("1212th", CardinalToOrdinal(1212));
|
||||
EXPECT_EQ("1213th", CardinalToOrdinal(1213));
|
||||
EXPECT_EQ("1214th", CardinalToOrdinal(1214));
|
||||
EXPECT_EQ("1215th", CardinalToOrdinal(1215));
|
||||
EXPECT_EQ("1216th", CardinalToOrdinal(1216));
|
||||
EXPECT_EQ("1217th", CardinalToOrdinal(1217));
|
||||
EXPECT_EQ("1218th", CardinalToOrdinal(1218));
|
||||
EXPECT_EQ("1219th", CardinalToOrdinal(1219));
|
||||
EXPECT_EQ("1220th", CardinalToOrdinal(1220));
|
||||
EXPECT_EQ("1221st", CardinalToOrdinal(1221));
|
||||
EXPECT_EQ("1222nd", CardinalToOrdinal(1222));
|
||||
EXPECT_EQ("1223rd", CardinalToOrdinal(1223));
|
||||
EXPECT_EQ("1224th", CardinalToOrdinal(1224));
|
||||
EXPECT_EQ("1225th", CardinalToOrdinal(1225));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
|
@ -231,29 +231,33 @@ TEST_F(ValidateData, int16_good) {
|
|||
}
|
||||
|
||||
TEST_F(ValidateData, storage_uniform_buffer_block_16_good) {
|
||||
string str = HeaderWith("StorageUniformBufferBlock16") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
string str = HeaderWith("StorageUniformBufferBlock16 "
|
||||
"OpExtension \"SPV_KHR_16bit_storage\"") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, storage_uniform_16_good) {
|
||||
string str = HeaderWith("StorageUniform16") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
string str =
|
||||
HeaderWith("StorageUniform16 OpExtension \"SPV_KHR_16bit_storage\"") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, storage_push_constant_16_good) {
|
||||
string str = HeaderWith("StoragePushConstant16") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
string str = HeaderWith("StoragePushConstant16 "
|
||||
"OpExtension \"SPV_KHR_16bit_storage\"") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, storage_input_output_16_good) {
|
||||
string str = HeaderWith("StorageInputOutput16") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
string str = HeaderWith("StorageInputOutput16 "
|
||||
"OpExtension \"SPV_KHR_16bit_storage\"") +
|
||||
"%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
@ -550,6 +554,7 @@ TEST_F(ValidateData, ext_16bit_storage_caps_allow_free_fp_rounding_mode) {
|
|||
OpCapability Linkage
|
||||
OpCapability )") +
|
||||
cap + R"(
|
||||
OpExtension "SPV_KHR_16bit_storage"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpDecorate %2 FPRoundingMode )" +
|
||||
mode + R"(
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "extensions.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "test_fixture.h"
|
||||
#include "unit_spirv.h"
|
||||
|
@ -23,6 +24,8 @@
|
|||
|
||||
namespace {
|
||||
|
||||
using ::libspirv::Extension;
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Not;
|
||||
using ::testing::Values;
|
||||
|
@ -31,10 +34,11 @@ using std::string;
|
|||
|
||||
using ValidateKnownExtensions = spvtest::ValidateBase<string>;
|
||||
using ValidateUnknownExtensions = spvtest::ValidateBase<string>;
|
||||
using ValidateExtensionCapabilities = spvtest::ValidateBase<bool>;
|
||||
|
||||
// Returns expected error string if |extension| is not recognized.
|
||||
string GetErrorString(const std::string& extension) {
|
||||
return "Failed to parse OpExtension " + extension;
|
||||
return "Found unrecognized extension " + extension;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ExpectSuccess, ValidateKnownExtensions, Values(
|
||||
|
@ -77,4 +81,32 @@ TEST_P(ValidateUnknownExtensions, FailSilently) {
|
|||
EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(extension)));
|
||||
}
|
||||
|
||||
TEST_P(ValidateKnownExtensions, ToAndFromString) {
|
||||
const std::string extension_str = GetParam();
|
||||
Extension extension;
|
||||
ASSERT_TRUE(ParseSpvExtensionFromString(extension_str, &extension));
|
||||
const std::string result_str = ExtensionToString(extension);
|
||||
EXPECT_EQ(extension_str, result_str);
|
||||
}
|
||||
|
||||
TEST_F(ValidateExtensionCapabilities, DeclCapabilitySuccess) {
|
||||
const string str =
|
||||
"OpCapability Shader\nOpCapability Linkage\nOpCapability DeviceGroup\n"
|
||||
"OpExtension \"SPV_KHR_device_group\""
|
||||
"\nOpMemoryModel Logical GLSL450";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateExtensionCapabilities, DeclCapabilityFailure) {
|
||||
const string str =
|
||||
"OpCapability Shader\nOpCapability Linkage\nOpCapability DeviceGroup\n"
|
||||
"\nOpMemoryModel Logical GLSL450";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr("1st operand of Capability"));
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr("requires one of these extensions"));
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr("SPV_KHR_device_group"));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "spirv/1.1/spirv.h"
|
||||
|
||||
#include "enum_set.h"
|
||||
#include "extensions.h"
|
||||
#include "spirv_validator_options.h"
|
||||
#include "val/construct.h"
|
||||
#include "val/function.h"
|
||||
|
@ -29,6 +30,8 @@
|
|||
|
||||
namespace {
|
||||
using libspirv::CapabilitySet;
|
||||
using libspirv::Extension;
|
||||
using libspirv::ExtensionSet;
|
||||
using libspirv::ValidationState_t;
|
||||
using std::vector;
|
||||
|
||||
|
@ -50,46 +53,88 @@ class ValidationStateTest : public testing::Test {
|
|||
ValidationState_t state_;
|
||||
};
|
||||
|
||||
// A test of ValidationState_t::HasAnyOf().
|
||||
using ValidationState_HasAnyOfTest = ValidationStateTest;
|
||||
// A test of ValidationState_t::HasAnyOfCapabilities().
|
||||
using ValidationState_HasAnyOfCapabilities = ValidationStateTest;
|
||||
|
||||
TEST_F(ValidationState_HasAnyOfTest, EmptyMask) {
|
||||
EXPECT_TRUE(state_.HasAnyOf({}));
|
||||
TEST_F(ValidationState_HasAnyOfCapabilities, EmptyMask) {
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
|
||||
state_.RegisterCapability(SpvCapabilityMatrix);
|
||||
EXPECT_TRUE(state_.HasAnyOf({}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
|
||||
state_.RegisterCapability(SpvCapabilityImageMipmap);
|
||||
EXPECT_TRUE(state_.HasAnyOf({}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
|
||||
state_.RegisterCapability(SpvCapabilityPipes);
|
||||
EXPECT_TRUE(state_.HasAnyOf({}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
|
||||
state_.RegisterCapability(SpvCapabilityStorageImageArrayDynamicIndexing);
|
||||
EXPECT_TRUE(state_.HasAnyOf({}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
|
||||
state_.RegisterCapability(SpvCapabilityClipDistance);
|
||||
EXPECT_TRUE(state_.HasAnyOf({}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
|
||||
state_.RegisterCapability(SpvCapabilityStorageImageWriteWithoutFormat);
|
||||
EXPECT_TRUE(state_.HasAnyOf({}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
|
||||
}
|
||||
|
||||
TEST_F(ValidationState_HasAnyOfTest, SingleCapMask) {
|
||||
EXPECT_FALSE(state_.HasAnyOf({SpvCapabilityMatrix}));
|
||||
EXPECT_FALSE(state_.HasAnyOf({SpvCapabilityImageMipmap}));
|
||||
TEST_F(ValidationState_HasAnyOfCapabilities, SingleCapMask) {
|
||||
EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
|
||||
EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
|
||||
state_.RegisterCapability(SpvCapabilityMatrix);
|
||||
EXPECT_TRUE(state_.HasAnyOf({SpvCapabilityMatrix}));
|
||||
EXPECT_FALSE(state_.HasAnyOf({SpvCapabilityImageMipmap}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
|
||||
EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
|
||||
state_.RegisterCapability(SpvCapabilityImageMipmap);
|
||||
EXPECT_TRUE(state_.HasAnyOf({SpvCapabilityMatrix}));
|
||||
EXPECT_TRUE(state_.HasAnyOf({SpvCapabilityImageMipmap}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
|
||||
}
|
||||
|
||||
TEST_F(ValidationState_HasAnyOfTest, MultiCapMask) {
|
||||
TEST_F(ValidationState_HasAnyOfCapabilities, MultiCapMask) {
|
||||
const auto set1 =
|
||||
CapabilitySet{SpvCapabilitySampledRect, SpvCapabilityImageBuffer};
|
||||
const auto set2 = CapabilitySet{SpvCapabilityStorageImageWriteWithoutFormat,
|
||||
SpvCapabilityStorageImageReadWithoutFormat,
|
||||
SpvCapabilityGeometryStreams};
|
||||
EXPECT_FALSE(state_.HasAnyOf(set1));
|
||||
EXPECT_FALSE(state_.HasAnyOf(set2));
|
||||
EXPECT_FALSE(state_.HasAnyOfCapabilities(set1));
|
||||
EXPECT_FALSE(state_.HasAnyOfCapabilities(set2));
|
||||
state_.RegisterCapability(SpvCapabilityImageBuffer);
|
||||
EXPECT_TRUE(state_.HasAnyOf(set1));
|
||||
EXPECT_FALSE(state_.HasAnyOf(set2));
|
||||
EXPECT_TRUE(state_.HasAnyOfCapabilities(set1));
|
||||
EXPECT_FALSE(state_.HasAnyOfCapabilities(set2));
|
||||
}
|
||||
|
||||
// A test of ValidationState_t::HasAnyOfExtensions().
|
||||
using ValidationState_HasAnyOfExtensions = ValidationStateTest;
|
||||
|
||||
TEST_F(ValidationState_HasAnyOfExtensions, EmptyMask) {
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions({}));
|
||||
state_.RegisterExtension(Extension::kSPV_KHR_shader_ballot);
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions({}));
|
||||
state_.RegisterExtension(Extension::kSPV_KHR_16bit_storage);
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions({}));
|
||||
state_.RegisterExtension(Extension::kSPV_NV_viewport_array2);
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions({}));
|
||||
}
|
||||
|
||||
TEST_F(ValidationState_HasAnyOfExtensions, SingleCapMask) {
|
||||
EXPECT_FALSE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_shader_ballot}));
|
||||
EXPECT_FALSE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_16bit_storage}));
|
||||
state_.RegisterExtension(Extension::kSPV_KHR_shader_ballot);
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_shader_ballot}));
|
||||
EXPECT_FALSE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_16bit_storage}));
|
||||
state_.RegisterExtension(Extension::kSPV_KHR_16bit_storage);
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_shader_ballot}));
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions({Extension::kSPV_KHR_16bit_storage}));
|
||||
}
|
||||
|
||||
TEST_F(ValidationState_HasAnyOfExtensions, MultiCapMask) {
|
||||
const auto set1 = ExtensionSet {
|
||||
Extension::kSPV_KHR_multiview,
|
||||
Extension::kSPV_KHR_16bit_storage
|
||||
};
|
||||
const auto set2 = ExtensionSet {
|
||||
Extension::kSPV_KHR_shader_draw_parameters,
|
||||
Extension::kSPV_NV_stereo_view_rendering,
|
||||
Extension::kSPV_KHR_shader_ballot
|
||||
};
|
||||
EXPECT_FALSE(state_.HasAnyOfExtensions(set1));
|
||||
EXPECT_FALSE(state_.HasAnyOfExtensions(set2));
|
||||
state_.RegisterExtension(Extension::kSPV_KHR_multiview);
|
||||
EXPECT_TRUE(state_.HasAnyOfExtensions(set1));
|
||||
EXPECT_FALSE(state_.HasAnyOfExtensions(set2));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче