19#include "impeller/shader_bundle/shader_bundle_flatbuffers.h"
20#include "third_party/json/include/nlohmann/json.hpp"
26 const std::string& bundle_config_json,
27 std::ostream& error_stream) {
28 auto json = nlohmann::json::parse(bundle_config_json,
nullptr,
false);
29 if (json.is_discarded() || !json.is_object()) {
30 error_stream <<
"The shader bundle is not a valid JSON object."
36 for (
auto& [shader_name, shader_value] : json.items()) {
37 if (bundle.find(shader_name) != bundle.end()) {
38 error_stream <<
"Duplicate shader \"" << shader_name <<
"\"."
42 if (!shader_value.is_object()) {
43 error_stream <<
"Invalid shader entry \"" << shader_name
44 <<
"\": Entry is not a JSON object." << std::endl;
50 if (!shader_value.contains(
"file")) {
51 error_stream <<
"Invalid shader entry \"" << shader_name
52 <<
"\": Missing required \"file\" field." << std::endl;
57 if (!shader_value.contains(
"type")) {
58 error_stream <<
"Invalid shader entry \"" << shader_name
59 <<
"\": Missing required \"type\" field." << std::endl;
64 error_stream <<
"Invalid shader entry \"" << shader_name
65 <<
"\": Shader type " << shader_value[
"type"]
66 <<
" is unknown." << std::endl;
70 shader.
language = shader_value.contains(
"language")
74 error_stream <<
"Invalid shader entry \"" << shader_name
75 <<
"\": Unknown language type " << shader_value[
"language"]
80 shader.
entry_point = shader_value.contains(
"entry_point")
81 ? shader_value[
"entry_point"]
84 bundle[shader_name] = shader;
90static std::unique_ptr<fb::shaderbundle::BackendShaderT>
93 const std::string& shader_name,
95 std::set<std::string>* out_dependencies) {
96 auto result = std::make_unique<fb::shaderbundle::BackendShaderT>();
98 std::shared_ptr<fml::FileMapping> source_file_mapping =
100 if (!source_file_mapping) {
101 std::cerr <<
"Could not open file for bundled shader \"" << shader_name
102 <<
"\"." << std::endl;
120 Compiler compiler(source_file_mapping, options, reflector_options);
122 std::cerr <<
"Compilation failed for bundled shader \"" << shader_name
123 <<
"\"." << std::endl;
132 if (out_dependencies) {
135 out_dependencies->insert(included);
140 if (reflector ==
nullptr) {
141 std::cerr <<
"Could not create reflector for bundled shader \""
142 << shader_name <<
"\"." << std::endl;
148 std::cerr <<
"Bundled shader information was nil for \"" << shader_name
149 <<
"\"." << std::endl;
153 result = bundle_data->CreateFlatbuffer();
155 std::cerr <<
"Failed to create flatbuffer for bundled shader \""
156 << shader_name <<
"\"." << std::endl;
165 const std::string& shader_name,
167 std::set<std::string>* out_dependencies) {
168 auto result = std::make_unique<fb::shaderbundle::ShaderT>();
169 result->name = shader_name;
172 shader_config, out_dependencies);
173 if (!result->metal_ios) {
176 result->metal_desktop =
178 shader_name, shader_config, out_dependencies);
179 if (!result->metal_desktop) {
184 shader_config, out_dependencies);
185 if (!result->opengl_es) {
188 result->opengl_desktop =
190 shader_name, shader_config, out_dependencies);
191 if (!result->opengl_desktop) {
196 shader_config, out_dependencies);
197 if (!result->vulkan) {
204 const std::string& bundle_config_json,
206 std::set<std::string>* out_dependencies) {
211 std::optional<ShaderBundleConfig> bundle_config =
213 if (!bundle_config) {
221 fb::shaderbundle::ShaderBundleT shader_bundle;
222 shader_bundle.format_version =
static_cast<uint32_t
>(
223 fb::shaderbundle::ShaderBundleFormatVersion::kVersion);
225 for (
const auto& [shader_name, shader_config] : bundle_config.value()) {
226 std::unique_ptr<fb::shaderbundle::ShaderT> shader =
231 shader_bundle.shaders.push_back(std::move(shader));
234 return shader_bundle;
246 const std::string&
target,
247 const std::set<std::string>& dependencies) {
248 std::stringstream stream;
250 for (
const auto& dep : dependencies) {
251 stream <<
" " << dep;
254 const auto contents = std::make_shared<std::string>(stream.str());
256 reinterpret_cast<const uint8_t*
>(contents->data()), contents->size(),
257 [contents](
auto,
auto) {});
266 std::cerr <<
"Could not write depfile to " << switches.
depfile_path
282 std::set<std::string> dependencies;
283 const bool want_depfile = !switches.
depfile_path.empty();
286 want_depfile ? &dependencies :
nullptr);
287 if (!shader_bundle.has_value()) {
297 auto builder = std::make_shared<flatbuffers::FlatBufferBuilder>();
298 builder->Finish(fb::shaderbundle::ShaderBundle::Pack(*builder.get(),
299 &shader_bundle.value()),
300 fb::shaderbundle::ShaderBundleIdentifier());
301 auto mapping = std::make_shared<fml::NonOwnedMapping>(
302 builder->GetBufferPointer(), builder->GetSize(),
303 [builder](
auto,
auto) {});
305 auto sl_file_name = std::filesystem::absolute(
306 std::filesystem::current_path() / switches.
sl_file_name);
312 std::cerr <<
"Could not write file to " << switches.
sl_file_name
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
const Reflector * GetReflector() const
const std::vector< std::string > & GetIncludedFileNames() const
std::string GetErrorMessages() const
std::shared_ptr< ShaderBundleData > GetShaderBundleData() const
std::filesystem::path sl_file_name
std::string shader_bundle
std::shared_ptr< fml::UniqueFD > working_directory
SourceOptions CreateSourceOptions() const
std::filesystem::path depfile_path
bool WriteAtomically(const fml::UniqueFD &base_directory, const char *file_name, const Mapping &mapping)
bool SetPermissiveAccess(const std::filesystem::path &p)
Sets the file access mode of the file at path 'p' to 0644.
static std::unique_ptr< fb::shaderbundle::ShaderT > GenerateShaderFB(SourceOptions options, const std::string &shader_name, const ShaderConfig &shader_config, std::set< std::string > *out_dependencies)
static std::unique_ptr< fb::shaderbundle::BackendShaderT > GenerateShaderBackendFB(TargetPlatform target_platform, SourceOptions &options, const std::string &shader_name, const ShaderConfig &shader_config, std::set< std::string > *out_dependencies)
std::optional< fb::shaderbundle::ShaderBundleT > GenerateShaderBundleFlatbuffer(const std::string &bundle_config_json, const SourceOptions &options, std::set< std::string > *out_dependencies)
Parses the JSON shader bundle configuration and invokes the compiler multiple times to produce a shad...
bool GenerateShaderBundle(Switches &switches)
Parses the JSON shader bundle configuration and invokes the compiler multiple times to produce a shad...
std::unordered_map< std::string, ShaderConfig > ShaderBundleConfig
std::string EntryPointFunctionNameFromSourceName(const std::filesystem::path &file_name, SourceType type, SourceLanguage source_language, const std::string &entry_point_name)
SourceType SourceTypeFromString(std::string name)
std::optional< ShaderBundleConfig > ParseShaderBundleConfig(const std::string &bundle_config_json, std::ostream &error_stream)
Parse a shader bundle configuration from a given JSON string.
static bool OutputBundleDepfile(const Switches &switches, const std::string &target, const std::set< std::string > &dependencies)
std::string Utf8FromPath(const std::filesystem::path &path)
Converts a native format path to a utf8 string.
SourceLanguage ToSourceLanguage(const std::string &source_language)
TargetPlatform target_platform
std::string entry_point_name
A shader config parsed as part of a ShaderBundleConfig.
std::string source_file_name
SourceLanguage source_language
std::filesystem::path file_name
std::string entry_point_name
TargetPlatform target_platform