ACMX 2.139.0
Dual-Backend Real-Time GPU Video Synthesis
Loading...
Searching...
No Matches
resource_paths.cpp
Go to the documentation of this file.
1#include "resource_paths.hpp"
2
3#include <algorithm>
4#include <cstdlib>
5#include <stdexcept>
6#include <string>
7
8#ifdef _WIN32
9#ifndef NOMINMAX
10#define NOMINMAX
11#endif
12#include <vector>
13#include <windows.h>
14#endif
15
16#ifndef ACMXVK_BUILD_RESOURCE_DIRECTORY
17#define ACMXVK_BUILD_RESOURCE_DIRECTORY "."
18#endif
19
20#ifndef ACMXVK_INSTALL_RESOURCE_DIRECTORY
21#define ACMXVK_INSTALL_RESOURCE_DIRECTORY "."
22#endif
23
24#ifndef ACMXVK_BUILD_SPRITE_VERTEX_SHADER
25#define ACMXVK_BUILD_SPRITE_VERTEX_SHADER "sprite.vert.spv"
26#endif
27
28#ifndef ACMXVK_INSTALL_SPRITE_VERTEX_SHADER
29#define ACMXVK_INSTALL_SPRITE_VERTEX_SHADER "sprite.vert.spv"
30#endif
31
32#ifndef ACMXVK_BUILD_ECHO_CACHE_SHADER
33#define ACMXVK_BUILD_ECHO_CACHE_SHADER "echo_cache.frag.spv"
34#endif
35
36#ifndef ACMXVK_INSTALL_ECHO_CACHE_SHADER
37#define ACMXVK_INSTALL_ECHO_CACHE_SHADER "echo_cache.frag.spv"
38#endif
39
40#ifndef ACMXVK_BUILD_FLIP_SHADER
41#define ACMXVK_BUILD_FLIP_SHADER "flip.frag.spv"
42#endif
43
44#ifndef ACMXVK_INSTALL_FLIP_SHADER
45#define ACMXVK_INSTALL_FLIP_SHADER "flip.frag.spv"
46#endif
47
48#ifndef ACMXVK_BUILD_PASSTHROUGH_SHADER
49#define ACMXVK_BUILD_PASSTHROUGH_SHADER "passthrough.frag.spv"
50#endif
51
52#ifndef ACMXVK_INSTALL_PASSTHROUGH_SHADER
53#define ACMXVK_INSTALL_PASSTHROUGH_SHADER "passthrough.frag.spv"
54#endif
55
56#ifndef ACMXVK_BUILD_STABLE_DIFFUSION_UPSCALE_SHADER
57#define ACMXVK_BUILD_STABLE_DIFFUSION_UPSCALE_SHADER "sd_upscale.comp.spv"
58#endif
59
60#ifndef ACMXVK_INSTALL_STABLE_DIFFUSION_UPSCALE_SHADER
61#define ACMXVK_INSTALL_STABLE_DIFFUSION_UPSCALE_SHADER "sd_upscale.comp.spv"
62#endif
63
64#ifndef ACMXVK_BUILD_HDR_TRANSFER_DIRECTORY
65#define ACMXVK_BUILD_HDR_TRANSFER_DIRECTORY "."
66#endif
67
68#ifndef ACMXVK_INSTALL_HDR_TRANSFER_DIRECTORY
69#define ACMXVK_INSTALL_HDR_TRANSFER_DIRECTORY "."
70#endif
71
72#ifndef ACMXVK_BUILD_HUMAN_COMPOSITE_SHADER
73#define ACMXVK_BUILD_HUMAN_COMPOSITE_SHADER "human_composite.frag.spv"
74#endif
75
76#ifndef ACMXVK_INSTALL_HUMAN_COMPOSITE_SHADER
77#define ACMXVK_INSTALL_HUMAN_COMPOSITE_SHADER "human_composite.frag.spv"
78#endif
79
80#ifndef ACMXVK_BUILD_MODEL_VERTEX_SHADER
81#define ACMXVK_BUILD_MODEL_VERTEX_SHADER "model.vert.spv"
82#endif
83
84#ifndef ACMXVK_INSTALL_MODEL_VERTEX_SHADER
85#define ACMXVK_INSTALL_MODEL_VERTEX_SHADER "model.vert.spv"
86#endif
87
88#ifndef ACMXVK_BUILD_MODEL_FRAGMENT_SHADER
89#define ACMXVK_BUILD_MODEL_FRAGMENT_SHADER "model.frag.spv"
90#endif
91
92#ifndef ACMXVK_INSTALL_MODEL_FRAGMENT_SHADER
93#define ACMXVK_INSTALL_MODEL_FRAGMENT_SHADER "model.frag.spv"
94#endif
95
96#ifndef ACMXVK_BUILD_DEFAULT_MODEL
97#define ACMXVK_BUILD_DEFAULT_MODEL "cube.obj"
98#endif
99
100#ifndef ACMXVK_INSTALL_DEFAULT_MODEL
101#define ACMXVK_INSTALL_DEFAULT_MODEL "cube.obj"
102#endif
103
104#ifndef ACMXVK_BUILD_OVERLAY_FONT
105#define ACMXVK_BUILD_OVERLAY_FONT "font.ttf"
106#endif
107
108#ifndef ACMXVK_INSTALL_OVERLAY_FONT
109#define ACMXVK_INSTALL_OVERLAY_FONT "font.ttf"
110#endif
111
112#ifndef ACMXVK_BUILD_CROSSFADE_DIRECTORY
113#define ACMXVK_BUILD_CROSSFADE_DIRECTORY "shaders/xfade"
114#endif
115
116#ifndef ACMXVK_INSTALL_CROSSFADE_DIRECTORY
117#define ACMXVK_INSTALL_CROSSFADE_DIRECTORY "shaders/xfade"
118#endif
119
120namespace acmxvk {
121 namespace {
122#ifdef _WIN32
123 [[nodiscard]] fs::path executable_resource_directory() {
124 std::vector<wchar_t> buffer(MAX_PATH);
125 for (;;) {
126 const DWORD length = GetModuleFileNameW(nullptr, buffer.data(), static_cast<DWORD>(buffer.size()));
127 if (length == 0U) {
128 return {};
129 }
130 if (length < buffer.size() - 1U) {
131 const std::wstring executable_name(buffer.data(), length);
132 const fs::path executable(executable_name);
133 return executable.parent_path().parent_path() / "share" / "acmxvk";
134 }
135 if (buffer.size() >= 32768U) {
136 return {};
137 }
138 buffer.resize(buffer.size() * 2U);
139 }
140 }
141#endif
142
143 [[nodiscard]] fs::path resolve_resource(const Options &options, const fs::path &relative_path, const fs::path &installed_path, const fs::path &built_path) {
144 const fs::path resource = find_resource(options, relative_path);
145 if (!resource.empty()) {
146 return resource;
147 }
148 if (fs::is_regular_file(installed_path)) {
149 return installed_path;
150 }
151 return built_path;
152 }
153 } // namespace
154
155 std::vector<fs::path> resource_directories(const Options &options) {
156 std::vector<fs::path> directories;
157 const auto append = [&](const fs::path &directory) {
158 if (directory.empty()) {
159 return;
160 }
161 const fs::path normalized = fs::absolute(directory).lexically_normal();
162 if (std::find(directories.begin(), directories.end(), normalized) == directories.end()) {
163 directories.push_back(normalized);
164 }
165 };
166 append(options.resource_directory);
169#ifdef _WIN32
170 append(executable_resource_directory());
171#endif
172 append(fs::current_path());
173 return directories;
174 }
175
176 fs::path find_resource(const Options &options, const fs::path &relative_path) {
177 if (relative_path.empty() || relative_path.is_absolute()) {
178 return {};
179 }
180 const fs::path normalized_relative = relative_path.lexically_normal();
181 const std::string relative_text = normalized_relative.generic_string();
182 if (relative_text == ".." || relative_text.starts_with("../") || relative_text.find("/../") != std::string::npos) {
183 return {};
184 }
185 for (const fs::path &directory : resource_directories(options)) {
186 const fs::path candidate = (directory / normalized_relative).lexically_normal();
187 if (fs::is_regular_file(candidate)) {
188 return candidate;
189 }
190 }
191 return {};
192 }
193
194 fs::path mxvk_shader_directory(const Options &options) {
195 for (const fs::path &resource_directory : resource_directories(options)) {
196 const fs::path candidate = resource_directory.parent_path() / "mxvk" / "shaders";
197 if (fs::is_directory(candidate)) {
198 return candidate;
199 }
200 }
201 return {};
202 }
203
204 fs::path sprite_vertex_shader_path(const Options &options) { return resolve_resource(options, "shaders/sprite.vert.spv", ACMXVK_INSTALL_SPRITE_VERTEX_SHADER, ACMXVK_BUILD_SPRITE_VERTEX_SHADER); }
205
206 fs::path echo_cache_shader_path(const Options &options) { return resolve_resource(options, "shaders/echo_cache.frag.spv", ACMXVK_INSTALL_ECHO_CACHE_SHADER, ACMXVK_BUILD_ECHO_CACHE_SHADER); }
207
208 fs::path flip_shader_path(const Options &options) { return resolve_resource(options, "shaders/flip.frag.spv", ACMXVK_INSTALL_FLIP_SHADER, ACMXVK_BUILD_FLIP_SHADER); }
209
210 fs::path passthrough_shader_path(const Options &options) { return resolve_resource(options, "shaders/passthrough.frag.spv", ACMXVK_INSTALL_PASSTHROUGH_SHADER, ACMXVK_BUILD_PASSTHROUGH_SHADER); }
211
212 fs::path stable_diffusion_upscale_shader_path(const Options &options) { return resolve_resource(options, "shaders/sd_upscale.comp.spv", ACMXVK_INSTALL_STABLE_DIFFUSION_UPSCALE_SHADER, ACMXVK_BUILD_STABLE_DIFFUSION_UPSCALE_SHADER); }
213
214 fs::path hdr_transfer_shader_path(const Options &options, bool hlg, bool encode) {
215 const std::string filename = std::string("hdr_") + (hlg ? "hlg_" : "pq_") + (encode ? "encode.frag.spv" : "decode.frag.spv");
216 return resolve_resource(options, fs::path("shaders") / filename, fs::path(ACMXVK_INSTALL_HDR_TRANSFER_DIRECTORY) / filename, fs::path(ACMXVK_BUILD_HDR_TRANSFER_DIRECTORY) / filename);
217 }
218
219 fs::path hdr_preview_shader_path(const Options &options, bool hlg) {
220 const std::string filename = std::string("hdr_preview_") + (hlg ? "hlg" : "pq") + ".frag.spv";
221 return resolve_resource(options, fs::path("shaders") / filename, fs::path(ACMXVK_INSTALL_HDR_TRANSFER_DIRECTORY) / filename, fs::path(ACMXVK_BUILD_HDR_TRANSFER_DIRECTORY) / filename);
222 }
223
224 fs::path human_composite_shader_path(const Options &options) { return resolve_resource(options, "shaders/human_composite.frag.spv", ACMXVK_INSTALL_HUMAN_COMPOSITE_SHADER, ACMXVK_BUILD_HUMAN_COMPOSITE_SHADER); }
225
226 fs::path crossfade_shader_path(const Options &options, std::size_t shader_index) {
227 if (shader_index >= CROSSFADE_NAMES.size()) {
228 throw std::out_of_range("crossfade shader index is out of range");
229 }
230 const std::string filename = std::string(CROSSFADE_NAMES[shader_index]) + ".frag.spv";
231 const fs::path resource = find_resource(options, fs::path("shaders/xfade") / filename);
232 if (!resource.empty()) {
233 return resource;
234 }
235 const fs::path installed = fs::path(ACMXVK_INSTALL_CROSSFADE_DIRECTORY) / filename;
236 if (fs::is_regular_file(installed)) {
237 return installed;
238 }
239 const fs::path built = fs::path(ACMXVK_BUILD_CROSSFADE_DIRECTORY) / filename;
240 if (fs::is_regular_file(built)) {
241 return built;
242 }
243 throw std::runtime_error("crossfade shader was not found: " + filename);
244 }
245
246 fs::path model_vertex_shader_path(const Options &options) { return resolve_resource(options, "shaders/model.vert.spv", ACMXVK_INSTALL_MODEL_VERTEX_SHADER, ACMXVK_BUILD_MODEL_VERTEX_SHADER); }
247
248 fs::path model_fragment_shader_path(const Options &options) { return resolve_resource(options, "shaders/model.frag.spv", ACMXVK_INSTALL_MODEL_FRAGMENT_SHADER, ACMXVK_BUILD_MODEL_FRAGMENT_SHADER); }
249
250 fs::path default_model_path(const Options &options) { return resolve_resource(options, "models/cube.obj", ACMXVK_INSTALL_DEFAULT_MODEL, ACMXVK_BUILD_DEFAULT_MODEL); }
251
252 fs::path overlay_font_path(const Options &options) { return resolve_resource(options, "data/font.ttf", ACMXVK_INSTALL_OVERLAY_FONT, ACMXVK_BUILD_OVERLAY_FONT); }
253} // namespace acmxvk
GLsizei GLsizei * length
fs::path resolve_resource(const Options &options, const fs::path &relative_path, const fs::path &installed_path, const fs::path &built_path)
fs::path default_model_path(const Options &options)
fs::path echo_cache_shader_path(const Options &options)
fs::path human_composite_shader_path(const Options &options)
std::vector< fs::path > resource_directories(const Options &options)
fs::path model_fragment_shader_path(const Options &options)
fs::path model_vertex_shader_path(const Options &options)
fs::path passthrough_shader_path(const Options &options)
fs::path hdr_preview_shader_path(const Options &options, bool hlg)
fs::path crossfade_shader_path(const Options &options, std::size_t shader_index)
fs::path stable_diffusion_upscale_shader_path(const Options &options)
fs::path sprite_vertex_shader_path(const Options &options)
fs::path hdr_transfer_shader_path(const Options &options, bool hlg, bool encode)
fs::path mxvk_shader_directory(const Options &options)
constexpr std::array< std::string_view, 35 > CROSSFADE_NAMES
Definition options.hpp:15
fs::path overlay_font_path(const Options &options)
fs::path flip_shader_path(const Options &options)
fs::path find_resource(const Options &options, const fs::path &relative_path)
#define ACMXVK_BUILD_MODEL_VERTEX_SHADER
#define ACMXVK_INSTALL_HDR_TRANSFER_DIRECTORY
#define ACMXVK_INSTALL_PASSTHROUGH_SHADER
#define ACMXVK_INSTALL_OVERLAY_FONT
#define ACMXVK_BUILD_HUMAN_COMPOSITE_SHADER
#define ACMXVK_BUILD_CROSSFADE_DIRECTORY
#define ACMXVK_BUILD_PASSTHROUGH_SHADER
#define ACMXVK_BUILD_ECHO_CACHE_SHADER
#define ACMXVK_BUILD_RESOURCE_DIRECTORY
#define ACMXVK_INSTALL_MODEL_VERTEX_SHADER
#define ACMXVK_INSTALL_RESOURCE_DIRECTORY
#define ACMXVK_INSTALL_STABLE_DIFFUSION_UPSCALE_SHADER
#define ACMXVK_INSTALL_SPRITE_VERTEX_SHADER
#define ACMXVK_BUILD_DEFAULT_MODEL
#define ACMXVK_INSTALL_HUMAN_COMPOSITE_SHADER
#define ACMXVK_INSTALL_MODEL_FRAGMENT_SHADER
#define ACMXVK_BUILD_FLIP_SHADER
#define ACMXVK_INSTALL_ECHO_CACHE_SHADER
#define ACMXVK_BUILD_SPRITE_VERTEX_SHADER
#define ACMXVK_INSTALL_FLIP_SHADER
#define ACMXVK_BUILD_STABLE_DIFFUSION_UPSCALE_SHADER
#define ACMXVK_BUILD_OVERLAY_FONT
#define ACMXVK_INSTALL_CROSSFADE_DIRECTORY
#define ACMXVK_BUILD_MODEL_FRAGMENT_SHADER
#define ACMXVK_INSTALL_DEFAULT_MODEL
#define ACMXVK_BUILD_HDR_TRANSFER_DIRECTORY
std::string resource_directory
Definition options.hpp:206