diff options
| author | JMC47 <JMC4789@gmail.com> | 2025-11-02 13:17:28 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-02 13:17:28 -0500 |
| commit | 1d9c743ef793d88b53d31bb31079435c9a2b8e5f (patch) | |
| tree | 688446cbc0c2d68d5369f7f1f1d824e3833c1ca2 /Source/Core/VideoCommon/ShaderCompileUtils.cpp | |
| parent | 8a0a8bb8745008b43e7efe44f2b271c187fc6048 (diff) | |
| parent | 96fe6a157549761c37dd65e28f76938b4934a997 (diff) | |
Merge pull request #13975 from iwubcode/shader_includes
VideoBackends / VideoCommon: add support for specifying include files in shader code
Diffstat (limited to 'Source/Core/VideoCommon/ShaderCompileUtils.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/ShaderCompileUtils.cpp | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/ShaderCompileUtils.cpp b/Source/Core/VideoCommon/ShaderCompileUtils.cpp new file mode 100644 index 0000000000..ea17162ce9 --- /dev/null +++ b/Source/Core/VideoCommon/ShaderCompileUtils.cpp @@ -0,0 +1,93 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "VideoCommon/ShaderCompileUtils.h" + +#include <fstream> +#include <ranges> + +#include "Common/FileUtil.h" +#include "Common/StringUtil.h" + +namespace VideoCommon +{ +ShaderIncluder::ShaderIncluder(const std::string& user_path, const std::string& system_path) + : m_root_user_path(user_path), m_root_system_path(system_path) +{ +} + +std::vector<std::string> ShaderIncluder::GetIncludes() const +{ + const auto keys = std::views::keys(m_include_results); + return {keys.begin(), keys.end()}; +} + +ShaderIncluder::IncludeResult* +ShaderIncluder::includeLocal(const char* header_name, const char* includer_name, std::size_t depth) +{ + return ProcessInclude(m_root_user_path, header_name, includer_name, depth); +} + +ShaderIncluder::IncludeResult* +ShaderIncluder::includeSystem(const char* header_name, const char* includer_name, std::size_t depth) +{ + return ProcessInclude(m_root_system_path, header_name, includer_name, depth); +} + +void ShaderIncluder::releaseInclude(IncludeResult* result) +{ + m_include_results.erase(result->headerName); +} + +ShaderIncluder::IncludeResult* ShaderIncluder::ProcessInclude(const std::string& root, + const char* header_name, + const char* includer_name, + std::size_t depth) +{ + m_dirs.resize(depth); + if (depth == 1) + { + const auto includer_dir = GetDirectory(includer_name); + if (includer_dir == ".") + { + m_dirs.push_back(root); + } + else + { + m_dirs.push_back(std::string{includer_dir}); + } + } + + // Search through directories back to front + for (auto iter = m_dirs.rbegin(); iter != m_dirs.rend(); iter++) + { + const std::string full_path = WithUnifiedPathSeparators(*iter + '/' + header_name); + + std::string file_data; + if (File::ReadFileToString(full_path, file_data)) + { + m_dirs.push_back(std::string{GetDirectory(full_path)}); + + const char* file_bytes = file_data.data(); + const std::size_t file_size = file_data.size(); + IncludeResultData result_data{ + .result = std::make_unique<IncludeResult>(full_path, file_bytes, file_size, nullptr), + .file_data = std::move(file_data)}; + + auto ptr = result_data.result.get(); + m_include_results[full_path] = std::move(result_data); + return ptr; + } + } + return nullptr; +} + +std::string_view ShaderIncluder::GetDirectory(std::string_view path) const +{ + const auto last_pos = path.find_last_of('/'); + if (last_pos == std::string_view::npos) + return "."; + + return path.substr(0, last_pos); +} +} // namespace VideoCommon |
