mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-05-10 03:01:40 +00:00
feat(bindless): Implement lsfg-vk shader library
This commit is contained in:
parent
8a47213020
commit
75a186c10e
4 changed files with 213 additions and 0 deletions
113
lsfg-vk-backend/src/modules/library.cpp
Normal file
113
lsfg-vk-backend/src/modules/library.cpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "library.hpp"
|
||||
#include "library/dll.hpp"
|
||||
#include "utility/logger.hpp"
|
||||
#include "utility/vkhelper.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <iomanip>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/// All base shaders in the library.
|
||||
const std::array<std::pair<std::string_view, uint32_t>, 3> BASE_LIBRARY{{
|
||||
{ "mipmaps", 0 },
|
||||
{ "generate_8bit", 1 },
|
||||
{ "generate_16bit", 2 },
|
||||
}};
|
||||
|
||||
/// All non-base shaders in the library.
|
||||
const std::array<std::pair<std::string_view, uint32_t>, 24> LIBRARY{{
|
||||
{ "alpha0", 13 },
|
||||
{ "alpha1", 14 },
|
||||
{ "alpha2", 15 },
|
||||
{ "alpha3", 16 },
|
||||
{ "beta0", 22 },
|
||||
{ "beta1", 23 },
|
||||
{ "beta2", 24 },
|
||||
{ "beta3", 25 },
|
||||
{ "beta4", 26 },
|
||||
{ "gamma0", 3 },
|
||||
{ "gamma1", 4 },
|
||||
{ "gamma2", 5 },
|
||||
{ "gamma3", 6 },
|
||||
{ "gamma4", 7 },
|
||||
{ "delta0", 8 },
|
||||
{ "delta1", 9 },
|
||||
{ "delta2", 10 },
|
||||
{ "delta3", 11 },
|
||||
{ "delta4", 12 },
|
||||
{ "epsilon0", 17 },
|
||||
{ "epsilon1", 18 },
|
||||
{ "epsilon2", 19 },
|
||||
{ "epsilon3", 20 },
|
||||
{ "epsilon4", 21 }
|
||||
}};
|
||||
|
||||
using namespace lsfgvk::library;
|
||||
|
||||
ShaderLibrary::ShaderLibrary(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
bool halfPrecision,
|
||||
const std::filesystem::path& dll
|
||||
) {
|
||||
LOG_DEBUG("Loading shader library from DLL: " << dll)
|
||||
|
||||
if (!std::filesystem::exists(dll)) {
|
||||
throw std::runtime_error("The specified shader DLL does not exist");
|
||||
}
|
||||
// Create shader modules for each shader in the library
|
||||
const auto resources = priv::parseDll(dll);
|
||||
for (const auto& [name, idx] : BASE_LIBRARY) {
|
||||
const uint32_t rid{idx};
|
||||
|
||||
const auto& it = resources.find(rid == 0 ? 2147488584U : rid);
|
||||
if (it == resources.end())
|
||||
throw std::runtime_error(
|
||||
"Unable to find base shader '" + std::string(name) + "' in DLL"
|
||||
);
|
||||
|
||||
LOG_DEBUG(" " << std::setw(2) << idx
|
||||
<< ": name=" << name
|
||||
<< ", rid=" << rid
|
||||
<< ", size=" << it->second.size() << " bytes")
|
||||
|
||||
this->m_baseShaders[name] = vkhelper::createShaderModule(dld, device, it->second);
|
||||
}
|
||||
|
||||
for (const auto& [name, idx] : LIBRARY) {
|
||||
const std::pair<uint32_t, uint32_t> rid{
|
||||
idx + (halfPrecision ? 48 : 0),
|
||||
idx + (halfPrecision ? 48 : 0) + 24
|
||||
};
|
||||
|
||||
const auto& qit{resources.find(rid.first)};
|
||||
const auto& pit{resources.find(rid.second)};
|
||||
if (qit == resources.end() || pit == resources.end())
|
||||
throw std::runtime_error(
|
||||
"Unable to find shader '" + std::string(name) + "' in DLL"
|
||||
);
|
||||
|
||||
LOG_DEBUG(" " << std::setw(2) << idx
|
||||
<< ": name=" << std::setw(8) << name
|
||||
<< ", [Q] "
|
||||
<< "rid="<< std::setw(2) << rid.first
|
||||
<< ", size="<< std::setw(5) << qit->second.size() << " bytes"
|
||||
<< ", [P] "
|
||||
<< "rid="<< std::setw(2) << rid.second
|
||||
<< ", size="<< std::setw(5) << pit->second.size() << " bytes")
|
||||
|
||||
this->m_qualityShaders[name] = vkhelper::createShaderModule(dld, device, qit->second);
|
||||
this->m_performanceShaders[name] = vkhelper::createShaderModule(dld, device, pit->second);
|
||||
|
||||
}
|
||||
|
||||
LOG_DEBUG("Finished loading shader library")
|
||||
}
|
||||
67
lsfg-vk-backend/src/modules/library.hpp
Normal file
67
lsfg-vk-backend/src/modules/library.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utility/vkhelper.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace lsfgvk::library {
|
||||
|
||||
///
|
||||
/// The lsfg-vk shader library
|
||||
///
|
||||
class ShaderLibrary {
|
||||
public:
|
||||
///
|
||||
/// Create the shader library
|
||||
///
|
||||
/// @param dld Vulkan dynamic dispatch loader
|
||||
/// @param device Vulkan device
|
||||
/// @param halfPrecision Whether to load the half-precision shader variants
|
||||
/// @param dll Path to the shader DLL file
|
||||
/// @throws std::runtime_error on failure
|
||||
///
|
||||
explicit ShaderLibrary(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
bool halfPrecision,
|
||||
const std::filesystem::path& dll
|
||||
);
|
||||
|
||||
///
|
||||
/// Get a base shader by name
|
||||
///
|
||||
/// @param name Shader name
|
||||
/// @return A reference to the shader
|
||||
/// @throws std::out_of_range if the shader is not found
|
||||
///
|
||||
[[nodiscard]] const auto& baseShader(std::string_view name) const {
|
||||
return this->m_baseShaders.at(name);
|
||||
}
|
||||
|
||||
///
|
||||
/// Get a shader by name
|
||||
///
|
||||
/// @param name Shader name
|
||||
/// @param perf Whether to get the performance variant of the shader
|
||||
/// @return A reference to the shader
|
||||
/// @throws std::out_of_range if the shader is not found
|
||||
///
|
||||
[[nodiscard]] const auto& shader(std::string_view name, bool perf) const {
|
||||
auto it{this->m_baseShaders.find(name)};
|
||||
if (it != this->m_baseShaders.end())
|
||||
return it->second;
|
||||
|
||||
return perf ? this->m_performanceShaders.at(name) : this->m_qualityShaders.at(name);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string_view, vk::UniqueShaderModule> m_baseShaders;
|
||||
std::unordered_map<std::string_view, vk::UniqueShaderModule> m_qualityShaders;
|
||||
std::unordered_map<std::string_view, vk::UniqueShaderModule> m_performanceShaders;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <span>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
|
@ -155,3 +156,17 @@ std::pair<vk::UniqueDevice, vk::Queue> vkhelper::createDevice(
|
|||
device->getQueue(qfi, 0, dld)
|
||||
};
|
||||
}
|
||||
|
||||
/* Shader modules & pipelines */
|
||||
|
||||
vk::UniqueShaderModule vkhelper::createShaderModule(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
const std::span<const uint32_t>& code
|
||||
) {
|
||||
const vk::ShaderModuleCreateInfo shaderInfo{
|
||||
.codeSize = code.size() * sizeof(uint32_t),
|
||||
.pCode = code.data()
|
||||
};
|
||||
return device.createShaderModuleUnique(shaderInfo, nullptr, dld);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
// IWYU pragma: end_exports
|
||||
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
|
@ -98,4 +99,21 @@ namespace vkhelper {
|
|||
bool fp16
|
||||
);
|
||||
|
||||
/* Shader modules & pipelines */
|
||||
|
||||
///
|
||||
/// Create a Vulkan shader module from SPIR-V bytecode
|
||||
///
|
||||
/// @param dld Dynamic dispatch loader
|
||||
/// @param device Vulkan device
|
||||
/// @param code SPIR-V bytecode
|
||||
/// @return RAII-wrapped Vulkan shader module
|
||||
/// @throws std::runtime_error on failure
|
||||
///
|
||||
vk::UniqueShaderModule createShaderModule(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
const std::span<const uint32_t>& code
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue