Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Bundle parsing routine
  • Loading branch information
bdero committed Dec 11, 2023
commit cf6148328ec16e2e5b99d949fc5e6687d6ef7417
106 changes: 57 additions & 49 deletions impeller/compiler/shader_bundle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,68 +10,76 @@
namespace impeller {
namespace compiler {

/// Compiles and outputs a
bool GenerateShaderBundle(Switches& switches) {
auto json = nlohmann::json::parse(switches.iplr_bundle);
static std::optional<ShaderBundleConfig> ParseShaderBundleConfig(
std::string& json_config) {
auto json = nlohmann::json::parse(json_config);
if (!json.is_object()) {
std::cerr << "The shader bundle must be a JSON object." << std::endl;
return false;
return std::nullopt;
}

/// Bundle parsing.

IPLRBundleEntries bundle_entries_result;
for (auto& [bundle_name, bundle_value] : json.items()) {
if (!bundle_value.is_object()) {
std::cerr << "Invalid bundle entry \"" << bundle_name
ShaderBundleConfig bundle;
for (auto& [shader_name, shader_value] : json.items()) {
if (bundle.find(shader_name) == bundle.end()) {
std::cerr << "Duplicate shader \"" << shader_name << "\"." << std::endl;
return std::nullopt;
}
if (!shader_value.is_object()) {
std::cerr << "Invalid shader entry \"" << shader_name
<< "\": Entry is not a JSON object." << std::endl;
return false;
return std::nullopt;
}

/// Shader parsing.
ShaderConfig shader;

IPLRBundleEntry bundle_entry_result;
for (auto& [shader_name, shader_value] : bundle_value.items()) {
if (bundle_entry_result.find(shader_name) == bundle_entry_result.end()) {
std::cerr << "Duplicate shader \"" << shader_name << "\" in bundle \""
<< bundle_name << "\"." << std::endl;
return false;
}
if (!bundle_value.is_object()) {
std::cerr << "Invalid shader entry \"" << shader_name
<< "\" in bundle \"" << bundle_name
<< "\": Entry is not a JSON object." << std::endl;
return false;
}
if (!shader_value.contains("file")) {
std::cerr << "Invalid shader entry \"" << shader_name
<< "\": Missing required \"file\" field. \"" << std::endl;
return std::nullopt;
}
shader.source_file_name = shader_value["file"];

if (!shader_value.contains("type")) {
std::cerr << "Invalid shader entry \"" << shader_name
<< "\": Missing required \"type\" field. \"" << std::endl;
return std::nullopt;
}
shader.type = shader_value["type"];
if (shader.type == SourceType::kUnknown) {
std::cerr << "Invalid shader entry \"" << shader_name
<< "\": Shader type \"" << shader_value["type"]
<< "\" is unknown. \"" << std::endl;
return std::nullopt;
}

IPLRShaderEntry stage_result;
shader.language = shader_value.contains("language")
? ToSourceLanguage(shader_value["language"])
: SourceLanguage::kGLSL;
if (shader.language == SourceLanguage::kUnknown) {
std::cerr << "Invalid shader entry \"" << shader_name
<< "\": Unknown language type \"" << shader_value["language"]
<< "\"." << std::endl;
return std::nullopt;
}

stage_result.language = shader_value.contains("language")
? ToSourceLanguage(shader_value["language"])
: SourceLanguage::kGLSL;
if (stage_result.language == SourceLanguage::kUnknown) {
std::cerr << "Invalid shader entry \"" << shader_name
<< "\" in bundle \"" << bundle_name
<< "\": Unknown language type \"" << shader_value["language"]
<< "\"." << std::endl;
return false;
}
shader.entry_point = shader_value.contains("entry_point")
? shader_value["entry_point"]
: "main";

if (!shader_value.contains("name")) {
std::cerr << "Duplicate IPLR bundle stage entry \"" << shader_name
<< "\" in bundle \"" << bundle_name << "\": Entry ."
<< std::endl;
return false;
}
stage_result.source_file_name = shader_value["name"];
bundle[shader_name] = shader;
}

stage_result.entry_point = shader_value.contains("entry_point")
? shader_value["entry_point"]
: "main";
return bundle;
}

bundle_entry_result[shader_name] = stage_result;
}
bundle_entries_result[bundle_name] = bundle_entry_result;
/// Parses the given JSON shader bundle configuration and invokes the compiler
/// multiple times to produce a shader bundle file.
bool GenerateShaderBundle(Switches& switches) {
/// Parse the bundle files.
std::optional<ShaderBundleConfig> bundle_config =
ParseShaderBundleConfig(switches.iplr_bundle);
if (!bundle_config) {
return false;
}

return true;
Expand Down
29 changes: 29 additions & 0 deletions impeller/compiler/types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "impeller/compiler/types.h"

#include <cctype>
#include <filesystem>
#include <sstream>

Expand Down Expand Up @@ -42,6 +43,34 @@ SourceType SourceTypeFromFileName(const std::string& file_name) {
return SourceType::kUnknown;
}

SourceType SourceTypeFromString(std::string name) {
for (auto it = name.begin(); it != name.end(); it++) {
*it = std::tolower(static_cast<unsigned char>(*it));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need to lowercase the string I think there is a utility for doing that explicitly instead of mutating the function arg

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't manage to find one, but I did notice another place where I did this same thing in the compiler like a year ago. So I went ahead and added one to use in both places.


if (name == "vertex") {
return SourceType::kVertexShader;
}

if (name == "fragment") {
return SourceType::kFragmentShader;
}

if (name == "tessellationcontrol") {
return SourceType::kTessellationControlShader;
}

if (name == "tessellationevaluation") {
return SourceType::kTessellationEvaluationShader;
}

if (name == "compute") {
return SourceType::kComputeShader;
}

return SourceType::kUnknown;
}

SourceLanguage ToSourceLanguage(const std::string& source_language) {
if (source_language == "glsl") {
return SourceLanguage::kGLSL;
Expand Down
9 changes: 5 additions & 4 deletions impeller/compiler/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,15 @@ enum class SourceLanguage {
kHLSL,
};

struct IPLRShaderEntry {
/// A shader config parsed as part of a ShaderBundleConfig.
struct ShaderConfig {
std::string source_file_name;
SourceType type;
SourceLanguage language;
std::string entry_point;
};

using IPLRBundleEntry = std::map<std::string, IPLRShaderEntry>;

using IPLRBundleEntries = std::map<std::string, IPLRBundleEntry>;
using ShaderBundleConfig = std::map<std::string, ShaderConfig>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that it is super important but this should probably be an unordered_map unless you need the ordering properties.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah order isn't important for this, done.


bool TargetPlatformIsMetal(TargetPlatform platform);

Expand All @@ -62,6 +61,8 @@ bool TargetPlatformIsVulkan(TargetPlatform platform);

SourceType SourceTypeFromFileName(const std::string& file_name);

SourceType SourceTypeFromString(const std::string& name);

std::string SourceTypeToString(SourceType type);

std::string TargetPlatformToString(TargetPlatform platform);
Expand Down