Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions libshaderc/include/shaderc/shaderc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,17 @@ using PreprocessedSourceCompilationResult = CompilationResult<char>;
// Contains any options that can have default values for a compilation.
class CompileOptions {
public:
CompileOptions() { options_ = shaderc_compile_options_initialize(); }
CompileOptions() : options_(shaderc_compile_options_initialize()) {}
~CompileOptions() { shaderc_compile_options_release(options_); }
CompileOptions(const CompileOptions& other) {
options_ = shaderc_compile_options_clone(other.options_);
CompileOptions(const CompileOptions& other)
: options_(shaderc_compile_options_clone(other.options_)),
includer_(other.includer_) {
if (includer_) RegisterIncluderCallbacks();
}
CompileOptions(CompileOptions&& other) {
options_ = other.options_;
CompileOptions(CompileOptions&& other)
: options_(other.options_), includer_(std::move(other.includer_)) {
other.options_ = nullptr;
if (includer_) RegisterIncluderCallbacks();
}

// Adds a predefined macro to the compilation options. It behaves the same as
Expand Down Expand Up @@ -198,20 +201,12 @@ class CompileOptions {
// are routed to this includer's methods.
void SetIncluder(std::unique_ptr<IncluderInterface>&& includer) {
includer_ = std::move(includer);
shaderc_compile_options_set_include_callbacks(
options_,
[](void* user_data, const char* requested_source, int type,
const char* requesting_source, size_t include_depth) {
auto* sub_includer = static_cast<IncluderInterface*>(user_data);
return sub_includer->GetInclude(
requested_source, static_cast<shaderc_include_type>(type),
requesting_source, include_depth);
},
[](void* user_data, shaderc_include_result* include_result) {
auto* sub_includer = static_cast<IncluderInterface*>(user_data);
return sub_includer->ReleaseInclude(include_result);
},
includer_.get());
if (includer_) {
RegisterIncluderCallbacks();
} else {
shaderc_compile_options_set_include_callbacks(options_, nullptr, nullptr,
nullptr);
}
}

// Forces the GLSL language version and profile to a given pair. The version
Expand Down Expand Up @@ -378,9 +373,26 @@ class CompileOptions {
}

private:
void RegisterIncluderCallbacks() {
shaderc_compile_options_set_include_callbacks(
options_,
[](void* user_data, const char* requested_source, int type,
const char* requesting_source, size_t include_depth) {
auto* sub_includer = static_cast<IncluderInterface*>(user_data);
return sub_includer->GetInclude(
requested_source, static_cast<shaderc_include_type>(type),
requesting_source, include_depth);
},
[](void* user_data, shaderc_include_result* include_result) {
auto* sub_includer = static_cast<IncluderInterface*>(user_data);
return sub_includer->ReleaseInclude(include_result);
},
includer_.get());
}

CompileOptions& operator=(const CompileOptions& other) = delete;
shaderc_compile_options_t options_;
std::unique_ptr<IncluderInterface> includer_;
std::shared_ptr<IncluderInterface> includer_;

friend class Compiler;
};
Expand Down
84 changes: 84 additions & 0 deletions libshaderc/src/shaderc_cpp_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,38 @@ class TestIncluder : public shaderc::CompileOptions::IncluderInterface {

using IncluderTests = testing::TestWithParam<IncluderTestCase>;

class LifetimeTrackedIncluder
: public shaderc::CompileOptions::IncluderInterface {
public:
LifetimeTrackedIncluder(std::shared_ptr<bool> alive, const FakeFS& fake_fs)
: alive_(std::move(alive)), fake_fs_(fake_fs), responses_({}) {
*alive_ = true;
}

~LifetimeTrackedIncluder() override { *alive_ = false; }

shaderc_include_result* GetInclude(const char* requested_source,
shaderc_include_type type,
const char* requesting_source,
size_t include_depth) override {
(void)type;
(void)requesting_source;
(void)include_depth;
responses_.emplace_back(shaderc_include_result{
requested_source, strlen(requested_source),
fake_fs_.at(std::string(requested_source)).c_str(),
fake_fs_.at(std::string(requested_source)).size()});
return &responses_.back();
}

void ReleaseInclude(shaderc_include_result*) override {}

private:
std::shared_ptr<bool> alive_;
const FakeFS& fake_fs_;
std::vector<shaderc_include_result> responses_;
};

// Parameterized tests for includer.
TEST_P(IncluderTests, SetIncluder) {
const IncluderTestCase& test_case = GetParam();
Expand Down Expand Up @@ -843,6 +875,58 @@ TEST_P(IncluderTests, SetIncluderClonedOptions) {
HasSubstr(test_case.expected_substring()));
}

TEST_F(CppInterface, CopiedOptionsKeepIncluderAliveAfterSourceDestroyed) {
const FakeFS fs = {
{"root",
"#version 150\n"
"void foo() {}\n"
"#include \"path/to/file_1\"\n"},
{"path/to/file_1", "content of file_1\n"},
};
const std::string& shader = fs.at("root");
auto alive = std::make_shared<bool>(false);
std::unique_ptr<CompileOptions> cloned_options;

{
CompileOptions options;
options.SetIncluder(std::unique_ptr<LifetimeTrackedIncluder>(
new LifetimeTrackedIncluder(alive, fs)));
cloned_options.reset(new CompileOptions(options));
}

ASSERT_TRUE(*alive);
const auto compilation_result = compiler_.PreprocessGlsl(
shader.c_str(), shaderc_glsl_vertex_shader, "shader", *cloned_options);
EXPECT_THAT(CompilerOutputAsString(compilation_result),
HasSubstr("content of file_1"));
}

TEST_F(CppInterface, MovedOptionsKeepIncluderAliveAfterSourceDestroyed) {
const FakeFS fs = {
{"root",
"#version 150\n"
"void foo() {}\n"
"#include \"path/to/file_1\"\n"},
{"path/to/file_1", "content of file_1\n"},
};
const std::string& shader = fs.at("root");
auto alive = std::make_shared<bool>(false);
std::unique_ptr<CompileOptions> moved_options;

{
CompileOptions options;
options.SetIncluder(std::unique_ptr<LifetimeTrackedIncluder>(
new LifetimeTrackedIncluder(alive, fs)));
moved_options.reset(new CompileOptions(std::move(options)));
}

ASSERT_TRUE(*alive);
const auto compilation_result = compiler_.PreprocessGlsl(
shader.c_str(), shaderc_glsl_vertex_shader, "shader", *moved_options);
EXPECT_THAT(CompilerOutputAsString(compilation_result),
HasSubstr("content of file_1"));
}

INSTANTIATE_TEST_SUITE_P(CppInterface, IncluderTests,
testing::ValuesIn(std::vector<IncluderTestCase>{
IncluderTestCase(
Expand Down