mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-26 09:41:03 +00:00
300 lines
14 KiB
C++
300 lines
14 KiB
C++
// Copyright (c) 2019 Google LLC
|
|
//
|
|
// 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.
|
|
|
|
// Test validation of constants.
|
|
//
|
|
// This file contains newer tests. Older tests may be in other files such as
|
|
// val_id_test.cpp.
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "test/unit_spirv.h"
|
|
#include "test/val/val_fixtures.h"
|
|
|
|
namespace spvtools {
|
|
namespace val {
|
|
namespace {
|
|
|
|
using ::testing::Eq;
|
|
using ::testing::HasSubstr;
|
|
using ::testing::ValuesIn;
|
|
|
|
using ValidateConstant = spvtest::ValidateBase<bool>;
|
|
|
|
#define kBasicTypes \
|
|
"%bool = OpTypeBool " \
|
|
"%uint = OpTypeInt 32 0 " \
|
|
"%uint2 = OpTypeVector %uint 2 " \
|
|
"%float = OpTypeFloat 32 " \
|
|
"%_ptr_uint = OpTypePointer Workgroup %uint " \
|
|
"%uint_0 = OpConstantNull %uint " \
|
|
"%uint2_0 = OpConstantNull %uint " \
|
|
"%float_0 = OpConstantNull %float " \
|
|
"%false = OpConstantFalse %bool " \
|
|
"%true = OpConstantTrue %bool " \
|
|
"%null = OpConstantNull %_ptr_uint "
|
|
|
|
#define kShaderPreamble \
|
|
"OpCapability Shader\n" \
|
|
"OpCapability Linkage\n" \
|
|
"OpMemoryModel Logical Simple\n"
|
|
|
|
#define kKernelPreamble \
|
|
"OpCapability Kernel\n" \
|
|
"OpCapability Linkage\n" \
|
|
"OpCapability Addresses\n" \
|
|
"OpMemoryModel Physical32 OpenCL\n"
|
|
|
|
struct ConstantOpCase {
|
|
spv_target_env env;
|
|
std::string assembly;
|
|
bool expect_success;
|
|
std::string expect_err;
|
|
};
|
|
|
|
using ValidateConstantOp = spvtest::ValidateBase<ConstantOpCase>;
|
|
|
|
TEST_P(ValidateConstantOp, Samples) {
|
|
const auto env = GetParam().env;
|
|
CompileSuccessfully(GetParam().assembly, env);
|
|
const auto result = ValidateInstructions(env);
|
|
if (GetParam().expect_success) {
|
|
EXPECT_EQ(SPV_SUCCESS, result);
|
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
|
} else {
|
|
EXPECT_EQ(SPV_ERROR_INVALID_ID, result);
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr(GetParam().expect_err));
|
|
}
|
|
}
|
|
|
|
#define GOOD_SHADER_10(STR) \
|
|
{ SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, true, "" }
|
|
#define GOOD_KERNEL_10(STR) \
|
|
{ SPV_ENV_UNIVERSAL_1_0, kKernelPreamble kBasicTypes STR, true, "" }
|
|
INSTANTIATE_TEST_CASE_P(
|
|
UniversalInShader, ValidateConstantOp,
|
|
ValuesIn(std::vector<ConstantOpCase>{
|
|
// TODO(dneto): Conversions must change width.
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %float FConvert %float_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint Not %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
|
|
GOOD_SHADER_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
|
|
GOOD_SHADER_10(
|
|
"%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
|
|
}));
|
|
|
|
INSTANTIATE_TEST_CASE_P(
|
|
UniversalInKernel, ValidateConstantOp,
|
|
ValuesIn(std::vector<ConstantOpCase>{
|
|
// TODO(dneto): Conversions must change width.
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FConvert %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Not %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
|
|
}));
|
|
|
|
INSTANTIATE_TEST_CASE_P(
|
|
KernelInKernel, ValidateConstantOp,
|
|
ValuesIn(std::vector<ConstantOpCase>{
|
|
// TODO(dneto): Conversions must change width.
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UConvert %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Bitcast %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FNegate %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
|
|
"%null %uint_0"),
|
|
GOOD_KERNEL_10(
|
|
"%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0"),
|
|
GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint "
|
|
"InBoundsPtrAccessChain %null %uint_0"),
|
|
}));
|
|
|
|
#define BAD_SHADER_10(STR, NAME) \
|
|
{ \
|
|
SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, false, \
|
|
"Specialization constant operation " NAME \
|
|
" requires Kernel capability" \
|
|
}
|
|
INSTANTIATE_TEST_CASE_P(
|
|
KernelInShader, ValidateConstantOp,
|
|
ValuesIn(std::vector<ConstantOpCase>{
|
|
// TODO(dneto): Conversions must change width.
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0",
|
|
"ConvertFToS"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0",
|
|
"ConvertSToF"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0",
|
|
"ConvertFToU"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0",
|
|
"ConvertUToF"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null",
|
|
"GenericCastToPtr"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null",
|
|
"PtrCastToGeneric"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %uint Bitcast %uint_0", "Bitcast"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float FNegate %float_0",
|
|
"FNegate"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0",
|
|
"FAdd"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0",
|
|
"FSub"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0",
|
|
"FMul"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0",
|
|
"FDiv"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0",
|
|
"FRem"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0",
|
|
"FMod"),
|
|
BAD_SHADER_10(
|
|
"%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0",
|
|
"AccessChain"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
|
|
"%null %uint_0",
|
|
"InBoundsAccessChain"),
|
|
BAD_SHADER_10(
|
|
"%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0",
|
|
"PtrAccessChain"),
|
|
BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint "
|
|
"InBoundsPtrAccessChain %null %uint_0",
|
|
"InBoundsPtrAccessChain"),
|
|
}));
|
|
|
|
INSTANTIATE_TEST_CASE_P(
|
|
UConvertInAMD_gpu_shader_int16, ValidateConstantOp,
|
|
ValuesIn(std::vector<ConstantOpCase>{
|
|
// SPV_AMD_gpu_shader_int16 should enable UConvert for OpSpecConstantOp
|
|
// https://github.com/KhronosGroup/glslang/issues/848
|
|
{SPV_ENV_UNIVERSAL_1_0,
|
|
"OpCapability Shader "
|
|
"OpCapability Linkage ; So we don't need to define a function\n"
|
|
"OpExtension \"SPV_AMD_gpu_shader_int16\" "
|
|
"OpMemoryModel Logical Simple " kBasicTypes
|
|
"%v = OpSpecConstantOp %uint UConvert %uint_0",
|
|
true, ""},
|
|
}));
|
|
|
|
} // namespace
|
|
} // namespace val
|
|
} // namespace spvtools
|