mirror of
https://gitee.com/openharmony/third_party_spirv-tools
synced 2024-11-23 07:20:28 +00:00
Add Vulkan validation rules for BuiltIn variables
Added a framework for validation of BuiltIn variables. The framework allows implementation of flexible abstract rules which are required for built-ins as the information (decoration, definition, reference) is not in one place, but is scattered all over the module. Validation rules are implemented as a map id -> list<functor(instrution)> Ids which are dependent on built-in types or objects receive a task list, such as "this id cannot be referenced from function which is called from entry point with execution model X; propagate this rule to your descendants in the global scope". Also refactored test/val/val_fixtures. All built-ins covered by tests
This commit is contained in:
parent
045cc8f75b
commit
fe9121f721
@ -39,6 +39,7 @@ SPVTOOLS_SRC_FILES := \
|
||||
source/validate_atomics.cpp \
|
||||
source/validate_barriers.cpp \
|
||||
source/validate_bitwise.cpp \
|
||||
source/validate_builtins.cpp \
|
||||
source/validate_capability.cpp \
|
||||
source/validate_cfg.cpp \
|
||||
source/validate_composites.cpp \
|
||||
|
@ -284,6 +284,7 @@ set(SPIRV_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_atomics.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_barriers.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_bitwise.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_builtins.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_capability.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_cfg.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_composites.cpp
|
||||
|
@ -66,6 +66,17 @@ class AssemblyGrammar {
|
||||
spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,
|
||||
spv_operand_desc* desc) const;
|
||||
|
||||
// Finds operand entry in the grammar table and returns its name.
|
||||
// Returns "Unknown" if not found.
|
||||
const char* lookupOperandName(spv_operand_type_t type,
|
||||
uint32_t operand) const {
|
||||
spv_operand_desc desc = nullptr;
|
||||
if (lookupOperand(type, operand, &desc) != SPV_SUCCESS || !desc) {
|
||||
return "Unknown";
|
||||
}
|
||||
return desc->name;
|
||||
}
|
||||
|
||||
// Finds the opcode for the given OpSpecConstantOp opcode name. The name
|
||||
// should not have the "Op" prefix. For example, "IAdd" corresponds to
|
||||
// the integer add opcode for OpSpecConstantOp. On success, returns
|
||||
|
@ -63,9 +63,7 @@ class Decoration {
|
||||
: dec_type_(t), params_(parameters), struct_member_index_(member_index) {}
|
||||
|
||||
void set_struct_member_index(uint32_t index) { struct_member_index_ = index; }
|
||||
int struct_member_index() { return struct_member_index_; }
|
||||
int struct_member_index() const { return struct_member_index_; }
|
||||
SpvDecoration dec_type() { return dec_type_; }
|
||||
SpvDecoration dec_type() const { return dec_type_; }
|
||||
std::vector<uint32_t>& params() { return params_; }
|
||||
const std::vector<uint32_t>& params() const { return params_; }
|
||||
|
@ -269,9 +269,17 @@ class ValidationState_t {
|
||||
return id_decorations_[id];
|
||||
}
|
||||
const std::vector<Decoration>& id_decorations(uint32_t id) const {
|
||||
// TODO: This would throw or generate SIGABRT if id has no
|
||||
// decorations. Remove/refactor this function.
|
||||
return id_decorations_.at(id);
|
||||
}
|
||||
|
||||
// Returns const pointer to the internal decoration container.
|
||||
const std::unordered_map<uint32_t, std::vector<Decoration>>& id_decorations()
|
||||
const {
|
||||
return id_decorations_;
|
||||
}
|
||||
|
||||
/// Finds id's def, if it exists. If found, returns the definition otherwise
|
||||
/// nullptr
|
||||
const Instruction* FindDef(uint32_t id) const;
|
||||
|
@ -336,8 +336,13 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
|
||||
}
|
||||
|
||||
position.index = SPV_INDEX_INSTRUCTION;
|
||||
return spvValidateIDs(instructions.data(), instructions.size(), *vstate,
|
||||
&position);
|
||||
if (auto error = spvValidateIDs(instructions.data(), instructions.size(),
|
||||
*vstate, &position))
|
||||
return error;
|
||||
|
||||
if (auto error = ValidateBuiltIns(*vstate)) return error;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -117,6 +117,9 @@ spv_result_t InstructionPass(ValidationState_t& _,
|
||||
/// Performs decoration validation.
|
||||
spv_result_t ValidateDecorations(ValidationState_t& _);
|
||||
|
||||
/// Performs validation of built-in variables.
|
||||
spv_result_t ValidateBuiltIns(const ValidationState_t& _);
|
||||
|
||||
/// Validates that type declarations are unique, unless multiple declarations
|
||||
/// of the same data type are allowed by the specification.
|
||||
/// (see section 2.8 Types and Variables)
|
||||
|
2471
source/validate_builtins.cpp
Normal file
2471
source/validate_builtins.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,6 @@ set(VAL_TEST_COMMON_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../test_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../unit_spirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val_fixtures.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val_fixtures.cpp
|
||||
)
|
||||
|
||||
|
||||
@ -110,6 +109,12 @@ add_spvtools_unittest(TARGET val_bitwise
|
||||
LIBS ${SPIRV_TOOLS}
|
||||
)
|
||||
|
||||
add_spvtools_unittest(TARGET val_builtins
|
||||
SRCS val_builtins_test.cpp
|
||||
${VAL_TEST_COMMON_SRCS}
|
||||
LIBS ${SPIRV_TOOLS}
|
||||
)
|
||||
|
||||
add_spvtools_unittest(TARGET val_image
|
||||
SRCS val_image_test.cpp
|
||||
${VAL_TEST_COMMON_SRCS}
|
||||
|
1680
test/val/val_builtins_test.cpp
Normal file
1680
test/val/val_builtins_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1336,20 +1336,30 @@ INSTANTIATE_TEST_CASE_P(BuiltIn, ValidateCapabilityVulkan10,
|
||||
ValuesIn(AllSpirV10Capabilities()),
|
||||
Values(
|
||||
make_pair(string(kGLSL450MemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" \n" +
|
||||
"OpDecorate %intt BuiltIn PointSize\n"
|
||||
"OpEntryPoint Vertex %func \"shader\" \n"
|
||||
"OpMemberDecorate %block 0 BuiltIn PointSize\n"
|
||||
"%f32 = OpTypeFloat 32\n"
|
||||
"%block = OpTypeStruct %f32\n"
|
||||
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
|
||||
// Capabilities which should succeed.
|
||||
AllVulkan10Capabilities()),
|
||||
make_pair(string(kGLSL450MemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" \n" +
|
||||
"OpDecorate %intt BuiltIn ClipDistance\n"
|
||||
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
|
||||
"OpEntryPoint Vertex %func \"shader\" \n"
|
||||
"OpMemberDecorate %block 0 BuiltIn ClipDistance\n"
|
||||
"%f32 = OpTypeFloat 32\n"
|
||||
"%intt = OpTypeInt 32 0\n"
|
||||
"%intt_4 = OpConstant %intt 4\n"
|
||||
"%f32arr4 = OpTypeArray %f32 %intt_4\n"
|
||||
"%block = OpTypeStruct %f32arr4\n" + string(kVoidFVoid),
|
||||
AllVulkan10Capabilities()),
|
||||
make_pair(string(kGLSL450MemoryModel) +
|
||||
"OpEntryPoint Vertex %func \"shader\" \n" +
|
||||
"OpDecorate %intt BuiltIn CullDistance\n"
|
||||
"%intt = OpTypeInt 32 0\n" + string(kVoidFVoid),
|
||||
"OpEntryPoint Vertex %func \"shader\" \n"
|
||||
"OpMemberDecorate %block 0 BuiltIn CullDistance\n"
|
||||
"%f32 = OpTypeFloat 32\n"
|
||||
"%intt = OpTypeInt 32 0\n"
|
||||
"%intt_4 = OpConstant %intt 4\n"
|
||||
"%f32arr4 = OpTypeArray %f32 %intt_4\n"
|
||||
"%block = OpTypeStruct %f32arr4\n" + string(kVoidFVoid),
|
||||
AllVulkan10Capabilities())
|
||||
)),);
|
||||
|
||||
@ -1598,8 +1608,9 @@ OpCapability DrawParameters
|
||||
OpExtension "SPV_KHR_shader_draw_parameters"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %func "shader"
|
||||
OpDecorate %intt BuiltIn PointSize
|
||||
%intt = OpTypeInt 32 0
|
||||
OpMemberDecorate %block 0 BuiltIn PointSize
|
||||
%f32 = OpTypeFloat 32
|
||||
%block = OpTypeStruct %f32
|
||||
)" + string(kVoidFVoid);
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
||||
|
@ -1,110 +0,0 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group 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.
|
||||
|
||||
// Common validation fixtures for unit tests
|
||||
|
||||
#include "val_fixtures.h"
|
||||
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include "test_fixture.h"
|
||||
|
||||
namespace spvtest {
|
||||
|
||||
template <typename T>
|
||||
ValidateBase<T>::ValidateBase() : binary_(), diagnostic_() {
|
||||
// Initialize to default command line options. Different tests can then
|
||||
// specialize specific options as necessary.
|
||||
options_ = spvValidatorOptionsCreate();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_const_binary ValidateBase<T>::get_const_binary() {
|
||||
return spv_const_binary(binary_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ValidateBase<T>::TearDown() {
|
||||
if (diagnostic_) {
|
||||
spvDiagnosticPrint(diagnostic_);
|
||||
}
|
||||
spvDiagnosticDestroy(diagnostic_);
|
||||
spvBinaryDestroy(binary_);
|
||||
spvValidatorOptionsDestroy(options_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ValidateBase<T>::CompileSuccessfully(std::string code,
|
||||
spv_target_env env) {
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvTextToBinary(ScopedContext(env).context, code.c_str(),
|
||||
code.size(), &binary_, &diagnostic))
|
||||
<< "ERROR: " << diagnostic->error
|
||||
<< "\nSPIR-V could not be compiled into binary:\n"
|
||||
<< code;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ValidateBase<T>::OverwriteAssembledBinary(uint32_t index, uint32_t word) {
|
||||
ASSERT_TRUE(index < binary_->wordCount)
|
||||
<< "OverwriteAssembledBinary: The given index is larger than the binary "
|
||||
"word count.";
|
||||
binary_->code[index] = word;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_result_t ValidateBase<T>::ValidateInstructions(spv_target_env env) {
|
||||
return spvValidateWithOptions(ScopedContext(env).context, options_,
|
||||
get_const_binary(), &diagnostic_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_result_t ValidateBase<T>::ValidateAndRetrieveValidationState(
|
||||
spv_target_env env) {
|
||||
return spvtools::ValidateBinaryAndKeepValidationState(
|
||||
ScopedContext(env).context, options_, get_const_binary()->code,
|
||||
get_const_binary()->wordCount, &diagnostic_, &vstate_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string ValidateBase<T>::getDiagnosticString() {
|
||||
return diagnostic_ == nullptr ? std::string()
|
||||
: std::string(diagnostic_->error);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_validator_options ValidateBase<T>::getValidatorOptions() {
|
||||
return options_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_position_t ValidateBase<T>::getErrorPosition() {
|
||||
return diagnostic_ == nullptr ? spv_position_t() : diagnostic_->position;
|
||||
}
|
||||
|
||||
template class spvtest::ValidateBase<bool>;
|
||||
template class spvtest::ValidateBase<int>;
|
||||
template class spvtest::ValidateBase<std::string>;
|
||||
template class spvtest::ValidateBase<std::pair<std::string, bool>>;
|
||||
template class spvtest::ValidateBase<
|
||||
std::tuple<std::string, std::pair<std::string, std::vector<std::string>>>>;
|
||||
template class spvtest::ValidateBase<
|
||||
std::tuple<int, std::tuple<std::string, std::function<spv_result_t(int)>,
|
||||
std::function<spv_result_t(int)>>>>;
|
||||
template class spvtest::ValidateBase<SpvCapability>;
|
||||
template class spvtest::ValidateBase<std::pair<std::string, std::string>>;
|
||||
} // namespace spvtest
|
@ -18,6 +18,7 @@
|
||||
#define LIBSPIRV_TEST_VALIDATE_FIXTURES_H_
|
||||
|
||||
#include "source/val/validation_state.h"
|
||||
#include "test_fixture.h"
|
||||
#include "unit_spirv.h"
|
||||
|
||||
namespace spvtest {
|
||||
@ -60,5 +61,78 @@ class ValidateBase : public ::testing::Test,
|
||||
spv_validator_options options_;
|
||||
std::unique_ptr<libspirv::ValidationState_t> vstate_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
ValidateBase<T>::ValidateBase() : binary_(), diagnostic_() {
|
||||
// Initialize to default command line options. Different tests can then
|
||||
// specialize specific options as necessary.
|
||||
options_ = spvValidatorOptionsCreate();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_const_binary ValidateBase<T>::get_const_binary() {
|
||||
return spv_const_binary(binary_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ValidateBase<T>::TearDown() {
|
||||
if (diagnostic_) {
|
||||
spvDiagnosticPrint(diagnostic_);
|
||||
}
|
||||
spvDiagnosticDestroy(diagnostic_);
|
||||
spvBinaryDestroy(binary_);
|
||||
spvValidatorOptionsDestroy(options_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ValidateBase<T>::CompileSuccessfully(std::string code,
|
||||
spv_target_env env) {
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvTextToBinary(ScopedContext(env).context, code.c_str(),
|
||||
code.size(), &binary_, &diagnostic))
|
||||
<< "ERROR: " << diagnostic->error
|
||||
<< "\nSPIR-V could not be compiled into binary:\n"
|
||||
<< code;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ValidateBase<T>::OverwriteAssembledBinary(uint32_t index, uint32_t word) {
|
||||
ASSERT_TRUE(index < binary_->wordCount)
|
||||
<< "OverwriteAssembledBinary: The given index is larger than the binary "
|
||||
"word count.";
|
||||
binary_->code[index] = word;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_result_t ValidateBase<T>::ValidateInstructions(spv_target_env env) {
|
||||
return spvValidateWithOptions(ScopedContext(env).context, options_,
|
||||
get_const_binary(), &diagnostic_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_result_t ValidateBase<T>::ValidateAndRetrieveValidationState(
|
||||
spv_target_env env) {
|
||||
return spvtools::ValidateBinaryAndKeepValidationState(
|
||||
ScopedContext(env).context, options_, get_const_binary()->code,
|
||||
get_const_binary()->wordCount, &diagnostic_, &vstate_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string ValidateBase<T>::getDiagnosticString() {
|
||||
return diagnostic_ == nullptr ? std::string()
|
||||
: std::string(diagnostic_->error);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_validator_options ValidateBase<T>::getValidatorOptions() {
|
||||
return options_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
spv_position_t ValidateBase<T>::getErrorPosition() {
|
||||
return diagnostic_ == nullptr ? spv_position_t() : diagnostic_->position;
|
||||
}
|
||||
|
||||
} // namespace spvtest
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user