diff options
Diffstat (limited to 'source/Shader.cpp')
-rw-r--r-- | source/Shader.cpp | 214 |
1 files changed, 106 insertions, 108 deletions
diff --git a/source/Shader.cpp b/source/Shader.cpp index 61e80a1..fd68a0c 100644 --- a/source/Shader.cpp +++ b/source/Shader.cpp @@ -6,16 +6,13 @@ #include "Utils.hpp" #include <imgui.h> +#include <misc/cpp/imgui_stdlib.h> #include <rapidjson/document.h> -#include <rapidjson/filereadstream.h> -#include <rapidjson/filewritestream.h> -#include <rapidjson/writer.h> #include <cassert> #include <cstddef> #include <cstdlib> #include <utility> -namespace fs = std::filesystem; using namespace std::literals; void ShaderMathVariable::ShowInfo() const { @@ -70,8 +67,7 @@ ShaderVariable* ShaderInfo::FindVariable(const ShaderThingId& thing) { return nullptr; } -Shader::Shader(std::string name) - : mName{ name } { +Shader::Shader() { } Shader::~Shader() { @@ -304,14 +300,6 @@ Shader::ErrorCode Shader::InitFromSource(std::string_view source) { #undef CATCH_ERROR -void Shader::GetDesignatedMetadataPath(char* buffer, int bufferSize) { - snprintf(buffer, bufferSize, "%s/Shaders/%s.json", AppConfig::assetDir.c_str(), mName.c_str()); -} - -fs::path Shader::GetDesignatedMetadataPath() { - return AppConfig::assetDirPath / "Shaders" / fs::path(mName).replace_extension(".json"); -} - namespace ProjectBrussel_UNITY_ID { bool QueryMathInfo(GLenum type, GLenum& scalarType, int& width, int& height) { auto DoOutput = [&](GLenum scalarTypeIn, int widthIn, int heightIn) { @@ -508,10 +496,6 @@ bool Shader::GatherInfoShaderIntrospection() { return true; } -bool Shader::IsAnnoymous() const { - return mName.empty(); -} - bool Shader::IsValid() const { return mProgram != 0; } @@ -570,10 +554,70 @@ bool ReadShaderSamplerVariable(const rapidjson::Value& value, ShaderSamplerVaria } } // namespace ProjectBrussel_UNITY_ID -bool Shader::SaveMetadataToFile(const fs::path& filePath) const { +IresShader::IresShader() + : IresObject(KD_Shader) { + InvalidateInstance(); +} + +Shader* IresShader::GetInstance() const { + return mInstance.Get(); +} + +void IresShader::InvalidateInstance() { + if (mInstance != nullptr) { + mInstance->mIres = nullptr; + } + mInstance.Attach(new Shader()); + mInstance->mIres = this; +} + +void IresShader::ShowEditor(EditorInstance& editor) { + using namespace Tags; + + IresObject::ShowEditor(editor); + + if (ImGui::Button("Gather info")) { + mInstance->GatherInfoShaderIntrospection(); + } + + if (ImGui::InputText("Source file", &mSourceFile, ImGuiInputTextFlags_EnterReturnsTrue)) { + InvalidateInstance(); + } + // In other cases, mSourceFile will be reverted to before edit + + // TODO macros + + ImGui::Separator(); + + auto& info = mInstance->GetInfo(); + if (ImGui::CollapsingHeader("General")) { + ImGui::Text("OpenGL program ID: %u", mInstance->GetProgram()); + } + if (ImGui::CollapsingHeader("Inputs")) { + for (auto& input : info.inputs) { + input.ShowInfo(); + } + } + if (ImGui::CollapsingHeader("Outputs")) { + for (auto& output : info.outputs) { + output.ShowInfo(); + } + } + if (ImGui::CollapsingHeader("Uniforms")) { + for (auto& uniform : info.uniforms) { + uniform->ShowInfo(); + } + } +} + +void IresShader::Write(IresWritingContext& ctx, rapidjson::Value& value, rapidjson::Document& root) const { using namespace ProjectBrussel_UNITY_ID; - rapidjson::Document root(rapidjson::kObjectType); + IresObject::Write(ctx, value, root); + + auto& shaderInfo = mInstance->mInfo; + + value.AddMember("SourceFile", mSourceFile, root.GetAllocator()); auto SaveMathVars = [&](const char* name, const std::vector<ShaderMathVariable>& vars) { rapidjson::Value rvThings(rapidjson::kArrayType); @@ -583,42 +627,52 @@ bool Shader::SaveMetadataToFile(const fs::path& filePath) const { rvThings.PushBack(rvThing, root.GetAllocator()); } - root.AddMember(rapidjson::StringRef(name), rvThings, root.GetAllocator()); + value.AddMember(rapidjson::StringRef(name), rvThings, root.GetAllocator()); }; - SaveMathVars("Inputs", mInfo.inputs); - SaveMathVars("Outputs", mInfo.outputs); + SaveMathVars("Inputs", shaderInfo.inputs); + SaveMathVars("Outputs", shaderInfo.outputs); // TODO uniforms +} - auto file = Utils::OpenCstdioFile(filePath, Utils::WriteTruncate); - if (!file) return false; - DEFER { fclose(file); }; +void IresShader::Read(IresLoadingContext& ctx, const rapidjson::Value& value) { + using namespace ProjectBrussel_UNITY_ID; - char writerBuffer[65536]; - rapidjson::FileWriteStream stream(file, writerBuffer, sizeof(writerBuffer)); - rapidjson::Writer<rapidjson::FileWriteStream> writer(stream); - root.Accept(writer); + IresObject::Read(ctx, value); - return true; -} + auto rvSourceFile = rapidjson::GetProperty(value, rapidjson::kStringType, "SourceFile"sv); + if (!rvSourceFile) { + return; + } else { + this->mSourceFile = rapidjson::AsString(*rvSourceFile); -bool Shader::LoadMetadataFromFile(const fs::path& filePath) { - using namespace ProjectBrussel_UNITY_ID; + char shaderFilePath[256]; + snprintf(shaderFilePath, sizeof(shaderFilePath), "%s/%s", AppConfig::assetDir.c_str(), rvSourceFile->GetString()); - mInfo = {}; + auto shaderFile = Utils::OpenCstdioFile(shaderFilePath, Utils::Read); + if (!shaderFile) return; + DEFER { fclose(shaderFile); }; + + fseek(shaderFile, 0, SEEK_END); + auto shaderFileSize = ftell(shaderFile); + rewind(shaderFile); - auto file = Utils::OpenCstdioFile(filePath, Utils::Read); - if (!file) return false; - DEFER { fclose(file); }; + // Also add \0 ourselves + auto buffer = std::make_unique<char[]>(shaderFileSize + 1); + fread(buffer.get(), shaderFileSize, 1, shaderFile); + buffer[shaderFileSize] = '\0'; + std::string_view source(buffer.get(), shaderFileSize); - char readerBuffer[65536]; - rapidjson::FileReadStream stream(file, readerBuffer, sizeof(readerBuffer)); + if (mInstance->InitFromSource(source) != Shader::EC_Success) { + return; + } + } - rapidjson::Document root; - root.ParseStream(stream); + auto& shaderInfo = mInstance->mInfo; + auto shaderProgram = mInstance->GetProgram(); auto LoadMathVars = [&](std::string_view name, ShaderThingId::Kind kind, std::vector<ShaderMathVariable>& vars) { - auto rvThings = rapidjson::GetProperty(root, rapidjson::kArrayType, name); + auto rvThings = rapidjson::GetProperty(value, rapidjson::kArrayType, name); if (!rvThings) return; for (auto& rv : rvThings->GetArray()) { @@ -626,15 +680,15 @@ bool Shader::LoadMetadataFromFile(const fs::path& filePath) { ShaderMathVariable thing; ReadShaderMathVariable(rv, thing); - mInfo.things.try_emplace(thing.name, ShaderThingId{ kind, (int)vars.size() }); + shaderInfo.things.try_emplace(thing.name, ShaderThingId{ kind, (int)vars.size() }); vars.push_back(std::move(thing)); } }; - LoadMathVars("Inputs"sv, ShaderThingId::KD_Input, mInfo.inputs); - LoadMathVars("Outputs"sv, ShaderThingId::KD_Output, mInfo.outputs); + LoadMathVars("Inputs"sv, ShaderThingId::KD_Input, shaderInfo.inputs); + LoadMathVars("Outputs"sv, ShaderThingId::KD_Output, shaderInfo.outputs); - auto rvUniforms = rapidjson::GetProperty(root, rapidjson::kArrayType, "Uniforms"sv); - if (!rvUniforms) return false; + auto rvUniforms = rapidjson::GetProperty(value, rapidjson::kArrayType, "Uniforms"sv); + if (!rvUniforms) return; for (auto& rvUniform : rvUniforms->GetArray()) { if (!rvUniform.IsObject()) continue; @@ -665,68 +719,12 @@ bool Shader::LoadMetadataFromFile(const fs::path& filePath) { return nullptr; }(); if (uniform) { - mInfo.things.try_emplace(uniform->name, ShaderThingId{ ShaderThingId::KD_Uniform, (int)mInfo.uniforms.size() }); - mInfo.uniforms.emplace_back(std::move(uniform)); - } - } - - for (auto& uniform : mInfo.uniforms) { - uniform->location = glGetUniformLocation(mProgram, uniform->name.c_str()); - } - - return true; -} - -void ShaderManager::DiscoverShaders() { - mShaders.clear(); - - auto path = AppConfig::assetDirPath / "Shaders"; - if (!fs::exists(path)) { - return; - } - - for (auto& item : fs::directory_iterator(path)) { - if (item.is_regular_file() && item.path().extension() == ".glsl") { - auto shaderFile = Utils::OpenCstdioFile(item.path(), Utils::Read); - if (!shaderFile) continue; - DEFER { fclose(shaderFile); }; - - fseek(shaderFile, 0, SEEK_END); - auto shaderFileSize = ftell(shaderFile); - rewind(shaderFile); - - // Also add \0 ourselves - auto buffer = std::make_unique<char[]>(shaderFileSize + 1); - fread(buffer.get(), shaderFileSize, 1, shaderFile); - buffer[shaderFileSize] = '\0'; - std::string_view source(buffer.get(), shaderFileSize); - - RcPtr shader(new Shader(item.path().stem().string())); - std::string_view shaderName(shader->GetName()); - - // Load shader - auto err = shader->InitFromSource(source); - if (err != Shader::EC_Success) { - continue; - } - - // Load shader info if present - fs::path infoPath(item.path()); - infoPath.replace_extension(".json"); - if (fs::exists(infoPath)) { - shader->LoadMetadataFromFile(infoPath); - } - - mShaders.try_emplace(shaderName, std::move(shader)); + shaderInfo.things.try_emplace(uniform->name, ShaderThingId{ ShaderThingId::KD_Uniform, (int)shaderInfo.uniforms.size() }); + shaderInfo.uniforms.emplace_back(std::move(uniform)); } } -} -Shader* ShaderManager::FindShader(std::string_view name) { - auto iter = mShaders.find(name); - if (iter != mShaders.end()) { - return iter->second.Get(); - } else { - return nullptr; + for (auto& uniform : shaderInfo.uniforms) { + uniform->location = glGetUniformLocation(shaderProgram, uniform->name.c_str()); } } |