Update ZVulkan

This commit is contained in:
Magnus Norddahl 2023-03-21 20:23:10 +01:00
commit fabdc39ba7
2 changed files with 155 additions and 12 deletions

View file

@ -196,6 +196,26 @@ private:
VkDeviceSize minAlignment = 0;
};
enum class ShaderType
{
Vertex,
TessControl,
TessEvaluation,
Geometry,
Fragment,
Compute
};
class ShaderIncludeResult
{
public:
ShaderIncludeResult(std::string name, std::string text) : name(std::move(name)), text(std::move(text)) { }
ShaderIncludeResult(std::string error) : text(std::move(error)) { }
std::string name; // fully resolved name of the included header file
std::string text; // the file contents - or include error message if name is empty
};
class ShaderBuilder
{
public:
@ -204,16 +224,23 @@ public:
static void Init();
static void Deinit();
ShaderBuilder& VertexShader(const std::string &code);
ShaderBuilder& FragmentShader(const std::string&code);
ShaderBuilder& Type(ShaderType type);
ShaderBuilder& AddSource(const std::string& name, const std::string& code);
ShaderBuilder& OnIncludeSystem(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeSystem);
ShaderBuilder& OnIncludeLocal(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeLocal);
ShaderBuilder& DebugName(const char* name) { debugName = name; return *this; }
std::unique_ptr<VulkanShader> Create(const char *shadername, VulkanDevice *device);
private:
std::string code;
std::vector<std::pair<std::string, std::string>> sources;
std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeSystem;
std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeLocal;
int stage = 0;
const char* debugName = nullptr;
friend class ShaderBuilderIncluderImpl;
};
class AccelerationStructureBuilder

View file

@ -128,29 +128,143 @@ ShaderBuilder::ShaderBuilder()
{
}
ShaderBuilder& ShaderBuilder::VertexShader(const std::string& c)
ShaderBuilder& ShaderBuilder::Type(ShaderType type)
{
code = c;
stage = EShLanguage::EShLangVertex;
switch (type)
{
case ShaderType::Vertex: stage = EShLanguage::EShLangVertex; break;
case ShaderType::TessControl: stage = EShLanguage::EShLangTessControl; break;
case ShaderType::TessEvaluation: stage = EShLanguage::EShLangTessEvaluation; break;
case ShaderType::Geometry: stage = EShLanguage::EShLangGeometry; break;
case ShaderType::Fragment: stage = EShLanguage::EShLangFragment; break;
case ShaderType::Compute: stage = EShLanguage::EShLangCompute; break;
}
return *this;
}
ShaderBuilder& ShaderBuilder::FragmentShader(const std::string& c)
ShaderBuilder& ShaderBuilder::AddSource(const std::string& name, const std::string& code)
{
code = c;
stage = EShLanguage::EShLangFragment;
sources.push_back({ name, code });
return *this;
}
ShaderBuilder& ShaderBuilder::OnIncludeSystem(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeSystem)
{
this->onIncludeSystem = std::move(onIncludeSystem);
return *this;
}
ShaderBuilder& ShaderBuilder::OnIncludeLocal(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeLocal)
{
this->onIncludeLocal = std::move(onIncludeLocal);
return *this;
}
class ShaderBuilderIncluderImpl : public glslang::TShader::Includer
{
public:
ShaderBuilderIncluderImpl(ShaderBuilder* shaderBuilder) : shaderBuilder(shaderBuilder)
{
}
IncludeResult* includeSystem(const char* headerName, const char* includerName, size_t inclusionDepth) override
{
if (!shaderBuilder->onIncludeSystem)
{
return nullptr;
}
try
{
std::unique_ptr<ShaderIncludeResult> result;
try
{
result = std::make_unique<ShaderIncludeResult>(shaderBuilder->onIncludeSystem(headerName, includerName, inclusionDepth));
}
catch (const std::exception& e)
{
result = std::make_unique<ShaderIncludeResult>(e.what());
}
if (!result || (result->name.empty() && result->text.empty()))
{
return nullptr;
}
IncludeResult* outer = new IncludeResult(result->name, result->text.data(), result->text.size(), result.get());
result.release();
return outer;
}
catch (...)
{
return nullptr;
}
}
IncludeResult* includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override
{
if (!shaderBuilder->onIncludeLocal)
{
return nullptr;
}
try
{
std::unique_ptr<ShaderIncludeResult> result;
try
{
result = std::make_unique<ShaderIncludeResult>(shaderBuilder->onIncludeLocal(headerName, includerName, inclusionDepth));
}
catch (const std::exception& e)
{
result = std::make_unique<ShaderIncludeResult>(e.what());
}
if (!result || (result->name.empty() && result->text.empty()))
{
return nullptr;
}
IncludeResult* outer = new IncludeResult(result->name, result->text.data(), result->text.size(), result.get());
result.release();
return outer;
}
catch (...)
{
return nullptr;
}
}
void releaseInclude(IncludeResult* result) override
{
if (result)
{
delete (ShaderIncludeResult*)result->userData;
delete result;
}
}
private:
ShaderBuilder* shaderBuilder = nullptr;
};
std::unique_ptr<VulkanShader> ShaderBuilder::Create(const char *shadername, VulkanDevice *device)
{
EShLanguage stage = (EShLanguage)this->stage;
const char *sources[] = { code.c_str() };
std::vector<const char*> namesC, sourcesC;
std::vector<int> lengthsC;
for (const auto& s : sources)
{
namesC.push_back(s.first.c_str());
sourcesC.push_back(s.second.c_str());
lengthsC.push_back((int)s.second.size());
}
TBuiltInResource resources = DefaultTBuiltInResource;
glslang::TShader shader(stage);
shader.setStrings(sources, 1);
shader.setStringsWithLengthsAndNames(sourcesC.data(), lengthsC.data(), namesC.data(), (int)sources.size());
shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100);
if (device->Instance->ApiVersion >= VK_API_VERSION_1_2)
{
@ -162,7 +276,9 @@ std::unique_ptr<VulkanShader> ShaderBuilder::Create(const char *shadername, Vulk
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0);
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
}
bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules);
ShaderBuilderIncluderImpl includer(this);
bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules, includer);
if (!compileSuccess)
{
throw std::runtime_error(std::string("Shader compile failed: ") + shader.getInfoLog());