mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-21 19:20:07 +00:00
Add C interface for Optimizer (#5030)
This commit is contained in:
parent
8a0fe779e5
commit
0994ca45b6
@ -441,6 +441,8 @@ typedef struct spv_reducer_options_t spv_reducer_options_t;
|
||||
|
||||
typedef struct spv_fuzzer_options_t spv_fuzzer_options_t;
|
||||
|
||||
typedef struct spv_optimizer_t spv_optimizer_t;
|
||||
|
||||
// Type Definitions
|
||||
|
||||
typedef spv_const_binary_t* spv_const_binary;
|
||||
@ -900,6 +902,63 @@ SPIRV_TOOLS_EXPORT spv_result_t spvBinaryParse(
|
||||
const size_t num_words, spv_parsed_header_fn_t parse_header,
|
||||
spv_parsed_instruction_fn_t parse_instruction, spv_diagnostic* diagnostic);
|
||||
|
||||
// The optimizer interface.
|
||||
|
||||
// A pointer to a function that accepts a log message from an optimizer.
|
||||
typedef void (*spv_message_consumer)(
|
||||
spv_message_level_t, const char*, const spv_position_t*, const char*);
|
||||
|
||||
// Creates and returns an optimizer object. This object must be passed to
|
||||
// optimizer APIs below and is valid until passed to spvOptimizerDestroy.
|
||||
SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env);
|
||||
|
||||
// Destroys the given optimizer object.
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer);
|
||||
|
||||
// Sets an spv_message_consumer on an optimizer object.
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
|
||||
spv_optimizer_t* optimizer, spv_message_consumer consumer);
|
||||
|
||||
// Registers passes that attempt to legalize the generated code.
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
|
||||
spv_optimizer_t* optimizer);
|
||||
|
||||
// Registers passes that attempt to improve performance of generated code.
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
|
||||
spv_optimizer_t* optimizer);
|
||||
|
||||
// Registers passes that attempt to improve the size of generated code.
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
|
||||
spv_optimizer_t* optimizer);
|
||||
|
||||
// Registers a pass specified by a flag in an optimizer object.
|
||||
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
|
||||
spv_optimizer_t* optimizer, const char* flag);
|
||||
|
||||
// Registers passes specified by length number of flags in an optimizer object.
|
||||
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
|
||||
spv_optimizer_t* optimizer, const char** flags, const size_t flag_count);
|
||||
|
||||
// Optimizes the SPIR-V code of size |word_count| pointed to by |binary| and
|
||||
// returns an optimized spv_binary in |optimized_binary|.
|
||||
//
|
||||
// Returns SPV_SUCCESS on successful optimization, whether or not the module is
|
||||
// modified. Returns an SPV_ERROR_* if the module fails to validate or if
|
||||
// errors occur when processing using any of the registered passes. In that
|
||||
// case, no further passes are executed and the |optimized_binary| contents may
|
||||
// be invalid.
|
||||
//
|
||||
// By default, the binary is validated before any transforms are performed,
|
||||
// and optionally after each transform. Validation uses SPIR-V spec rules
|
||||
// for the SPIR-V version named in the binary's header (at word offset 1).
|
||||
// Additionally, if the target environment is a client API (such as
|
||||
// Vulkan 1.1), then validate for that client API version, to the extent
|
||||
// that it is verifiable from data in the binary itself, or from the
|
||||
// validator options set on the optimizer options.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t spvOptimizerRun(
|
||||
spv_optimizer_t* optimizer, const uint32_t* binary, const size_t word_count,
|
||||
spv_binary* optimized_binary, const spv_optimizer_options options);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1065,3 +1065,95 @@ Optimizer::PassToken CreateFixFuncCallArgumentsPass() {
|
||||
MakeUnique<opt::FixFuncCallArgumentsPass>());
|
||||
}
|
||||
} // namespace spvtools
|
||||
|
||||
extern "C" {
|
||||
|
||||
SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env) {
|
||||
return reinterpret_cast<spv_optimizer_t*>(new spvtools::Optimizer(env));
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer) {
|
||||
delete reinterpret_cast<spvtools::Optimizer*>(optimizer);
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
|
||||
spv_optimizer_t* optimizer, spv_message_consumer consumer) {
|
||||
reinterpret_cast<spvtools::Optimizer*>(optimizer)->
|
||||
SetMessageConsumer(
|
||||
[consumer](spv_message_level_t level, const char* source,
|
||||
const spv_position_t& position, const char* message) {
|
||||
return consumer(level, source, &position, message);
|
||||
});
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
|
||||
spv_optimizer_t* optimizer) {
|
||||
reinterpret_cast<spvtools::Optimizer*>(optimizer)->
|
||||
RegisterLegalizationPasses();
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
|
||||
spv_optimizer_t* optimizer) {
|
||||
reinterpret_cast<spvtools::Optimizer*>(optimizer)->
|
||||
RegisterPerformancePasses();
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
|
||||
spv_optimizer_t* optimizer) {
|
||||
reinterpret_cast<spvtools::Optimizer*>(optimizer)->RegisterSizePasses();
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
|
||||
spv_optimizer_t* optimizer, const char* flag)
|
||||
{
|
||||
return reinterpret_cast<spvtools::Optimizer*>(optimizer)->
|
||||
RegisterPassFromFlag(flag);
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
|
||||
spv_optimizer_t* optimizer, const char** flags, const size_t flag_count) {
|
||||
std::vector<std::string> opt_flags;
|
||||
for (uint32_t i = 0; i < flag_count; i++) {
|
||||
opt_flags.emplace_back(flags[i]);
|
||||
}
|
||||
|
||||
return reinterpret_cast<spvtools::Optimizer*>(optimizer)->
|
||||
RegisterPassesFromFlags(opt_flags);
|
||||
}
|
||||
|
||||
SPIRV_TOOLS_EXPORT
|
||||
spv_result_t spvOptimizerRun(spv_optimizer_t* optimizer,
|
||||
const uint32_t* binary,
|
||||
const size_t word_count,
|
||||
spv_binary* optimized_binary,
|
||||
const spv_optimizer_options options) {
|
||||
std::vector<uint32_t> optimized;
|
||||
|
||||
if (!reinterpret_cast<spvtools::Optimizer*>(optimizer)->
|
||||
Run(binary, word_count, &optimized, options)) {
|
||||
return SPV_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
auto result_binary = new spv_binary_t();
|
||||
if (!result_binary) {
|
||||
*optimized_binary = nullptr;
|
||||
return SPV_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
result_binary->code = new uint32_t[optimized.size()];
|
||||
if (!result_binary->code) {
|
||||
delete result_binary;
|
||||
*optimized_binary = nullptr;
|
||||
return SPV_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
result_binary->wordCount = optimized.size();
|
||||
|
||||
memcpy(result_binary->code, optimized.data(),
|
||||
optimized.size() * sizeof(uint32_t));
|
||||
|
||||
*optimized_binary = result_binary;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
@ -21,6 +21,7 @@ add_spvtools_unittest(TARGET opt
|
||||
analyze_live_input_test.cpp
|
||||
assembly_builder_test.cpp
|
||||
block_merge_test.cpp
|
||||
c_interface_test.cpp
|
||||
ccp_test.cpp
|
||||
cfg_cleanup_test.cpp
|
||||
cfg_test.cpp
|
||||
|
534
test/opt/c_interface_test.cpp
Normal file
534
test/opt/c_interface_test.cpp
Normal file
@ -0,0 +1,534 @@
|
||||
// Copyright (c) 2023 Nintendo
|
||||
//
|
||||
// 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 <iostream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace {
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForInvalidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0xDEADFEED, // Invalid Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x01000000, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001 // GLSL450
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
// Do not register any passes
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, true);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_NE(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_EQ(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, SpecifyConsumerWithValidationNoPassesForInvalidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0xDEADFEED, // Invalid Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x01000000, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001 // GLSL450
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
spvOptimizerSetMessageConsumer(
|
||||
optimizer,
|
||||
[](spv_message_level_t, const char*, const spv_position_t*,
|
||||
const char* message) {
|
||||
std::cout << message << std::endl;
|
||||
});
|
||||
|
||||
// Do not register any passes
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, true);
|
||||
|
||||
testing::internal::CaptureStdout();
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_NE(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_EQ(binary, nullptr);
|
||||
|
||||
auto output = testing::internal::GetCapturedStdout();
|
||||
EXPECT_STRNE(output.c_str(), "");
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForValidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000001, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001 // GLSL450
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
// Do not register any passes
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, true);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_NE(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
// Should remain unchanged
|
||||
EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t));
|
||||
EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0);
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerNoPassesForValidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000003, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001, // GLSL450
|
||||
0x00040015, // OpTypeInt
|
||||
0x00000001, // %1
|
||||
0x00000020, // 32 Bits
|
||||
0x00000000, // Unsigned
|
||||
0x0004002B, // OpConstant
|
||||
0x00000001, // %1
|
||||
0x00000002, // %2
|
||||
0x00000001 // 1
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
// Do not register any passes
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, true);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_NE(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
// Should remain unchanged
|
||||
EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t));
|
||||
EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0);
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerLegalizationPassesForValidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000003, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001, // GLSL450
|
||||
0x00040015, // OpTypeInt
|
||||
0x00000001, // %1
|
||||
0x00000020, // 32 Bits
|
||||
0x00000000, // Unsigned
|
||||
0x0004002B, // OpConstant
|
||||
0x00000001, // %1
|
||||
0x00000002, // %2
|
||||
0x00000001 // 1
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
spvOptimizerRegisterLegalizationPasses(optimizer);
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, false);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_NE(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
// Only check that SPV_SUCCESS is returned, do not verify output
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerPerformancePassesForValidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000003, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001, // GLSL450
|
||||
0x00040015, // OpTypeInt
|
||||
0x00000001, // %1
|
||||
0x00000020, // 32 Bits
|
||||
0x00000000, // Unsigned
|
||||
0x0004002B, // OpConstant
|
||||
0x00000001, // %1
|
||||
0x00000002, // %2
|
||||
0x00000001 // 1
|
||||
};
|
||||
const uint32_t expected_spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000001, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001 // GLSL450
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
spvOptimizerRegisterPerformancePasses(optimizer);
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, false);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_NE(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
// Unreferenced OpTypeInt and OpConstant should be removed
|
||||
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
|
||||
EXPECT_EQ(memcmp(binary->code, expected_spirv,
|
||||
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerSizePassesForValidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000003, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001, // GLSL450
|
||||
0x00040015, // OpTypeInt
|
||||
0x00000001, // %1
|
||||
0x00000020, // 32 Bits
|
||||
0x00000000, // Unsigned
|
||||
0x0004002B, // OpConstant
|
||||
0x00000001, // %1
|
||||
0x00000002, // %2
|
||||
0x00000001 // 1
|
||||
};
|
||||
const uint32_t expected_spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000001, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001 // GLSL450
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
spvOptimizerRegisterSizePasses(optimizer);
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, false);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_NE(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
// Unreferenced OpTypeInt and OpConstant should be removed
|
||||
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
|
||||
EXPECT_EQ(memcmp(binary->code, expected_spirv,
|
||||
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerPassFromFlagForValidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000003, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001, // GLSL450
|
||||
0x00040015, // OpTypeInt
|
||||
0x00000001, // %1
|
||||
0x00000020, // 32 Bits
|
||||
0x00000000, // Unsigned
|
||||
0x0004002B, // OpConstant
|
||||
0x00000001, // %1
|
||||
0x00000002, // %2
|
||||
0x00000001 // 1
|
||||
};
|
||||
const uint32_t expected_spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000001, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001 // GLSL450
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
EXPECT_TRUE(spvOptimizerRegisterPassFromFlag(
|
||||
optimizer, "--eliminate-dead-code-aggressive"));
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, false);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_NE(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
// Unreferenced OpTypeInt and OpConstant should be removed
|
||||
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
|
||||
EXPECT_EQ(memcmp(binary->code, expected_spirv,
|
||||
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerPassesFromFlagsForValidInput) {
|
||||
const uint32_t spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000003, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001, // GLSL450
|
||||
0x00040015, // OpTypeInt
|
||||
0x00000001, // %1
|
||||
0x00000020, // 32 Bits
|
||||
0x00000000, // Unsigned
|
||||
0x0004002B, // OpConstant
|
||||
0x00000001, // %1
|
||||
0x00000002, // %2
|
||||
0x00000001 // 1
|
||||
};
|
||||
const uint32_t expected_spirv[] = {
|
||||
0x07230203, // Magic
|
||||
0x00010100, // Version 1.1
|
||||
0x00000000, // No Generator
|
||||
0x00000001, // Bound
|
||||
0x00000000, // Schema
|
||||
0x00020011, // OpCapability
|
||||
0x00000001, // Shader
|
||||
0x00020011, // OpCapability
|
||||
0x00000005, // Linkage
|
||||
0x0003000E, // OpMemoryModel
|
||||
0x00000000, // Logical
|
||||
0x00000001 // GLSL450
|
||||
};
|
||||
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
const char* flags[2] = {
|
||||
"--eliminate-dead-const",
|
||||
"--eliminate-dead-code-aggressive"
|
||||
};
|
||||
|
||||
EXPECT_TRUE(spvOptimizerRegisterPassesFromFlags(
|
||||
optimizer, flags, sizeof(flags) / sizeof(const char*)));
|
||||
|
||||
auto options = spvOptimizerOptionsCreate();
|
||||
ASSERT_NE(options, nullptr);
|
||||
spvOptimizerOptionsSetRunValidator(options, false);
|
||||
|
||||
spv_binary binary = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
|
||||
&binary, options));
|
||||
ASSERT_NE(binary, nullptr);
|
||||
|
||||
spvOptimizerOptionsDestroy(options);
|
||||
|
||||
// Unreferenced OpTypeInt and OpConstant should be removed
|
||||
EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
|
||||
EXPECT_EQ(memcmp(binary->code, expected_spirv,
|
||||
sizeof(expected_spirv) / sizeof(uint32_t)), 0);
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerInvalidPassFromFlag) {
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
EXPECT_FALSE(spvOptimizerRegisterPassFromFlag(
|
||||
optimizer, "--this-is-not-a-valid-pass"));
|
||||
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
TEST(OptimizerCInterface, DefaultConsumerInvalidPassesFromFlags) {
|
||||
auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
|
||||
ASSERT_NE(optimizer, nullptr);
|
||||
|
||||
const char* flags[2] = {
|
||||
"--eliminate-dead-const",
|
||||
"--this-is-not-a-valid-pass"
|
||||
};
|
||||
|
||||
EXPECT_FALSE(spvOptimizerRegisterPassesFromFlags(
|
||||
optimizer, flags, sizeof(flags) / sizeof(const char*)));
|
||||
|
||||
spvOptimizerDestroy(optimizer);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace spvtools
|
@ -41,8 +41,9 @@ AUTHORS = ['The Khronos Group Inc.',
|
||||
'Alastair F. Donaldson',
|
||||
'Mostafa Ashraf',
|
||||
'Shiyu Liu',
|
||||
'ZHOU He']
|
||||
CURRENT_YEAR = 2022
|
||||
'ZHOU He',
|
||||
'Nintendo']
|
||||
CURRENT_YEAR = 2023
|
||||
|
||||
FIRST_YEAR = 2014
|
||||
FINAL_YEAR = CURRENT_YEAR + 5
|
||||
|
Loading…
Reference in New Issue
Block a user