mirror of https://github.com/auygun/kaliber.git
Vulkan: Spirv cache.
This commit is contained in:
parent
580ff678ec
commit
f332246ea9
|
@ -397,20 +397,30 @@ void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
|
|||
Primitive primitive) {
|
||||
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
|
||||
|
||||
VkShaderModule vert_shader_module;
|
||||
{
|
||||
// TODO: Reuse compiled spirv on context-lost.
|
||||
auto it = spirv_cache_.find(source->name());
|
||||
if (it == spirv_cache_.end()) {
|
||||
std::array<std::vector<uint8_t>, 2> spirv;
|
||||
std::string error;
|
||||
shader->spirv_vertex =
|
||||
CompileGlsl(EShLangVertex, source->GetVertexSource(), &error);
|
||||
spirv[0] = CompileGlsl(EShLangVertex, source->GetVertexSource(), &error);
|
||||
if (!error.empty())
|
||||
DLOG << source->name() << " vertex shader compile error: " << error;
|
||||
spirv[1] =
|
||||
CompileGlsl(EShLangFragment, source->GetFragmentSource(), &error);
|
||||
if (!error.empty())
|
||||
DLOG << source->name() << " fragment shader compile error: " << error;
|
||||
it = spirv_cache_.insert({source->name(), spirv}).first;
|
||||
}
|
||||
|
||||
auto& spirv_vertex = it->second[0];
|
||||
auto& spirv_fragment = it->second[1];
|
||||
|
||||
VkShaderModule vert_shader_module;
|
||||
{
|
||||
VkShaderModuleCreateInfo shader_module_info{};
|
||||
shader_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
shader_module_info.codeSize = shader->spirv_vertex.size();
|
||||
shader_module_info.codeSize = spirv_vertex.size();
|
||||
shader_module_info.pCode =
|
||||
reinterpret_cast<const uint32_t*>(shader->spirv_vertex.data());
|
||||
reinterpret_cast<const uint32_t*>(spirv_vertex.data());
|
||||
|
||||
if (vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&vert_shader_module) != VK_SUCCESS) {
|
||||
|
@ -421,18 +431,11 @@ void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
|
|||
|
||||
VkShaderModule frag_shader_module;
|
||||
{
|
||||
// TODO: Reuse compiled spirv on context-lost.
|
||||
std::string error;
|
||||
shader->spirv_fragment =
|
||||
CompileGlsl(EShLangFragment, source->GetFragmentSource(), &error);
|
||||
if (!error.empty())
|
||||
DLOG << source->name() << " fragment shader compile error: " << error;
|
||||
|
||||
VkShaderModuleCreateInfo shader_module_info{};
|
||||
shader_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
shader_module_info.codeSize = shader->spirv_fragment.size();
|
||||
shader_module_info.codeSize = spirv_fragment.size();
|
||||
shader_module_info.pCode =
|
||||
reinterpret_cast<const uint32_t*>(shader->spirv_fragment.data());
|
||||
reinterpret_cast<const uint32_t*>(spirv_fragment.data());
|
||||
|
||||
if (vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&frag_shader_module) != VK_SUCCESS) {
|
||||
|
@ -441,7 +444,7 @@ void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
|
|||
}
|
||||
}
|
||||
|
||||
if (!CreatePipelineLayout(shader))
|
||||
if (!CreatePipelineLayout(shader, spirv_vertex, spirv_fragment))
|
||||
return;
|
||||
|
||||
VkPipelineShaderStageCreateInfo vert_shader_stage_info{};
|
||||
|
@ -1505,19 +1508,21 @@ void RendererVulkan::ImageMemoryBarrier(VkImage image,
|
|||
nullptr, 1, &image_mem_barrier);
|
||||
}
|
||||
|
||||
bool RendererVulkan::CreatePipelineLayout(ShaderVulkan* shader) {
|
||||
bool RendererVulkan::CreatePipelineLayout(
|
||||
ShaderVulkan* shader,
|
||||
const std::vector<uint8_t>& spirv_vertex,
|
||||
const std::vector<uint8_t>& spirv_fragment) {
|
||||
SpvReflectShaderModule module_vertex;
|
||||
SpvReflectResult result = spvReflectCreateShaderModule(
|
||||
shader->spirv_vertex.size(), shader->spirv_vertex.data(), &module_vertex);
|
||||
spirv_vertex.size(), spirv_vertex.data(), &module_vertex);
|
||||
if (result != SPV_REFLECT_RESULT_SUCCESS) {
|
||||
DLOG << "SPIR-V reflection failed to parse vertex shader.";
|
||||
return false;
|
||||
}
|
||||
|
||||
SpvReflectShaderModule module_fragment;
|
||||
result = spvReflectCreateShaderModule(shader->spirv_fragment.size(),
|
||||
shader->spirv_fragment.data(),
|
||||
&module_fragment);
|
||||
result = spvReflectCreateShaderModule(
|
||||
spirv_fragment.size(), spirv_fragment.data(), &module_fragment);
|
||||
if (result != SPV_REFLECT_RESULT_SUCCESS) {
|
||||
DLOG << "SPIR-V reflection failed to parse fragment shader.";
|
||||
spvReflectDestroyShaderModule(&module_vertex);
|
||||
|
|
|
@ -101,6 +101,9 @@ class RendererVulkan : public Renderer {
|
|||
using PipelineDeathRow =
|
||||
std::vector<std::tuple<VkPipeline, VkPipelineLayout>>;
|
||||
|
||||
std::unordered_map<std::string, std::array<std::vector<uint8_t>, 2>>
|
||||
spirv_cache_;
|
||||
|
||||
struct GeometryVulkan {
|
||||
Buffer<VkBuffer> buffer;
|
||||
uint32_t num_vertices = 0;
|
||||
|
@ -115,8 +118,6 @@ class RendererVulkan : public Renderer {
|
|||
size_t push_constants_size = 0;
|
||||
std::vector<std::string> sampler_uniform_names;
|
||||
int desc_set_count = 0;
|
||||
std::vector<uint8_t> spirv_vertex;
|
||||
std::vector<uint8_t> spirv_fragment;
|
||||
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
};
|
||||
|
@ -248,7 +249,9 @@ class RendererVulkan : public Renderer {
|
|||
VkImageLayout old_layout,
|
||||
VkImageLayout new_layout);
|
||||
|
||||
bool CreatePipelineLayout(ShaderVulkan* shader);
|
||||
bool CreatePipelineLayout(ShaderVulkan* shader,
|
||||
const std::vector<uint8_t>& spirv_vertex,
|
||||
const std::vector<uint8_t>& spirv_fragment);
|
||||
|
||||
void DrawListBegin();
|
||||
void DrawListEnd();
|
||||
|
|
Loading…
Reference in New Issue