diff --git a/src/reshade_uniforms.cpp b/src/reshade_uniforms.cpp index b66670d..32bbc2b 100644 --- a/src/reshade_uniforms.cpp +++ b/src/reshade_uniforms.cpp @@ -4,11 +4,15 @@ #include #include #include +#include #include +#include #include "logger.hpp" +const std::string defaultRuntimePathnamePrefix = "/tmp/shader_runtime_"; + namespace vkBasalt { void enumerateReshadeUniforms(reshadefx::module module) @@ -76,6 +80,10 @@ namespace vkBasalt { uniforms.push_back(std::shared_ptr(new DepthUniform(uniform))); } + else if (!source.empty()) + { + uniforms.push_back(std::shared_ptr(new RuntimeUniform(uniform))); + } } return uniforms; } @@ -380,4 +388,113 @@ namespace vkBasalt DepthUniform::~DepthUniform() { } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////// + RuntimeUniform::RuntimeUniform(reshadefx::uniform_info uniformInfo) + { + offset = uniformInfo.offset; + size = uniformInfo.size; + type = uniformInfo.type; + auto source = std::find_if(uniformInfo.annotations.begin(), uniformInfo.annotations.end(), [](const auto& a) { return a.name == "source"; }); + if (auto pathnameAnnotation = + std::find_if(uniformInfo.annotations.begin(), uniformInfo.annotations.end(), [](const auto& a) { return a.name == "pathname"; }); + pathnameAnnotation != uniformInfo.annotations.end()) + { + pathname = new char[pathnameAnnotation->value.string_data.length() + 1]; + strcpy(pathname, pathnameAnnotation->value.string_data.c_str()); + } + else + { + pathname = new char[defaultRuntimePathnamePrefix.length() + source->value.string_data.length() + 1]; + std::string tmp_pathname = defaultRuntimePathnamePrefix + source->value.string_data; + strcpy(pathname, tmp_pathname.c_str()); + } + + projId = 0; + if (auto projIdAnnotation = + std::find_if(uniformInfo.annotations.begin(), uniformInfo.annotations.end(), [](const auto& a) { return a.name == "projId"; }); + projIdAnnotation != uniformInfo.annotations.end()) + { + projId = projIdAnnotation->value.as_int[0]; + } + shmKey = ftok(pathname, projId); + + if (auto defaultValueAnnotation = + std::find_if(uniformInfo.annotations.begin(), uniformInfo.annotations.end(), [](const auto& a) { return a.name == "defaultValue"; }); + defaultValueAnnotation != uniformInfo.annotations.end()) + { + reshadefx::constant value = defaultValueAnnotation->value; + if (type.is_floating_point()) { + defaultValue = std::vector(value.as_float, value.as_float + type.components()); + Logger::debug(std::string("Found float* runtime uniform: ") + pathname + " " + std::to_string(projId) + + " of size " + std::to_string(type.components()) + "\n"); + } else if (type.is_boolean()) { + defaultValue = std::vector(value.as_uint, value.as_uint + type.components()); + Logger::debug(std::string("Found bool* runtime uniform: ") + pathname + " " + std::to_string(projId) + + " of size " + std::to_string(type.components()) + "\n"); + } else if (type.is_numeric()) { + if (type.is_signed()) { + defaultValue = std::vector(value.as_int, value.as_int + type.components()); + Logger::debug(std::string("Found int32_t* runtime uniform: ") + pathname + " " + std::to_string(projId) + + " of size " + std::to_string(type.components()) + "\n"); + } else { + defaultValue = std::vector(value.as_uint, value.as_uint + type.components()); + Logger::debug(std::string("Found uint32_t* runtime uniform: ") + pathname + " " + std::to_string(projId) + + " of size " + std::to_string(type.components()) + "\n"); + } + } else { + Logger::err("Tried to create a runtime uniform variable of an unsupported type"); + } + } + } + void RuntimeUniform::update(void* mapedBuffer) + { + std::variant, std::vector, std::vector, bool> value; + if (shmKey != -1) { + int shmId = shmget(shmKey,size,0444); // read-only + if (shmId != -1) { + if (type.is_floating_point()) { + float* raw_ptr = static_cast(shmat(shmId, nullptr, 0)); + value = std::vector(raw_ptr, raw_ptr + type.components()); + shmdt(raw_ptr); + } else if (type.is_boolean()) { + bool* raw_ptr = static_cast(shmat(shmId, nullptr, 0)); + + // convert to a uint32_t vector, that's how the reshade uniform code understands booleans + std::vector bools_as_uint; + for(size_t i = 0; i < type.components(); ++i) { + bools_as_uint.push_back(static_cast(raw_ptr[i])); + } + value = bools_as_uint; + shmdt(raw_ptr); + } else if (type.is_numeric()) { + if (type.is_signed()) { + int32_t* raw_ptr = static_cast(shmat(shmId, nullptr, 0)); + value = std::vector(raw_ptr, raw_ptr + type.components()); + shmdt(raw_ptr); + } else { + uint32_t* raw_ptr = static_cast(shmat(shmId, nullptr, 0)); + value = std::vector(raw_ptr, raw_ptr + type.components()); + shmdt(raw_ptr); + } + } + } + } + if (std::holds_alternative(value)) { + value = defaultValue; + } + if (std::holds_alternative>(value)) { + std::vector& vec = std::get>(value); + std::memcpy((uint8_t*) mapedBuffer + offset, vec.data(), vec.size() * sizeof(float)); + } else if (std::holds_alternative>(value)) { + std::vector& vec = std::get>(value); + std::memcpy((uint8_t*) mapedBuffer + offset, vec.data(), vec.size() * sizeof(int32_t)); + } else if (std::holds_alternative>(value)) { + std::vector& vec = std::get>(value); + std::memcpy((uint8_t*) mapedBuffer + offset, vec.data(), vec.size() * sizeof(uint32_t)); + } + } + RuntimeUniform::~RuntimeUniform() + { + } } // namespace vkBasalt diff --git a/src/reshade_uniforms.hpp b/src/reshade_uniforms.hpp index a41b28c..2d9d222 100644 --- a/src/reshade_uniforms.hpp +++ b/src/reshade_uniforms.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "vulkan_include.hpp" @@ -139,6 +140,21 @@ namespace vkBasalt void virtual update(void* mapedBuffer) override; virtual ~DepthUniform(); }; + + class RuntimeUniform : public ReshadeUniform + { + public: + RuntimeUniform(reshadefx::uniform_info uniformInfo); + void virtual update(void* mapedBuffer) override; + virtual ~RuntimeUniform(); + + private: + reshadefx::type type; + std::variant, std::vector, std::vector, bool> defaultValue; + char* pathname; + int projId; + key_t shmKey; + }; } // namespace vkBasalt #endif // RESHADE_UNIFORMS_HPP_INCLUDED