Skip to content

Commit

Permalink
Add new plugin: real time shader selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Dawid-Lorenz-Mobica committed Jul 25, 2023
1 parent 474016b commit 5058b97
Show file tree
Hide file tree
Showing 48 changed files with 701 additions and 854 deletions.
1 change: 1 addition & 0 deletions .copyrightignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ khrplatform.h
clang_format.py
run-clang-tidy.py
package-list.txt
.spv
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ RealTimeShaderSelection::RealTimeShaderSelection() :
"Enable dynamic shader selection for samples.",
{vkb::Hook::OnAppStart, vkb::Hook::OnUpdateUi},
{&realtimeshaderselection_flag}),
activeShader(0)
active_shader(0),
min_size_for_shaders(2)
{
}

Expand All @@ -41,59 +42,62 @@ void RealTimeShaderSelection::init(const vkb::CommandParser &parser)

void RealTimeShaderSelection::on_app_start(const std::string &app_info)
{
if (platform->get_available_shaders().size() < min_size_for_shaders)
if (platform->get_app().get_available_shaders().size() < min_size_for_shaders)
{
LOGE("Sample doesn't support RealTimeShaderSelection plugin, sample should add available shaders please see ApiVulkanSample::store_shader.");
LOGE("Sample, defined {} shaders, minimum number of defined shaders is {}", platform->get_available_shaders().size(), min_size_for_shaders);
LOGE("Sample doesn't support RealTimeShaderSelection plugin, sample should add available shaders please see Application::store_shaders.");
LOGE("Sample, defined {} shaders, minimum number of defined shaders is {}", platform->get_app().get_available_shaders().size(), min_size_for_shaders);
return;
}
availableShaders = platform->get_available_shaders();
for (auto const& shader : availableShaders)

for (auto const &shader : platform->get_app().get_available_shaders())
{
switch(shader.first)
switch (shader.first)
{
case vkb::ShaderSourceLanguage::VK_GLSL:
shaderName.emplace_back("GLSL");
break;
case vkb::ShaderSourceLanguage::VK_HLSL:
shaderName.emplace_back("HLSL");
break;
case vkb::ShaderSourceLanguage::VK_SPV:
shaderName.emplace_back("SPV");
break;
case vkb::ShaderSourceLanguage::GLSL:
language_names.emplace_back("GLSL");
break;
case vkb::ShaderSourceLanguage::HLSL:
language_names.emplace_back("HLSL");
break;
case vkb::ShaderSourceLanguage::SPV:
language_names.emplace_back("SPV");
break;
default:
LOGE("Not supported shader language");
assert(false);
}
}
}

void RealTimeShaderSelection::on_update_ui_overlay(vkb::Drawer &drawer)
{
if (availableShaders.size() >= min_size_for_shaders)
if (platform->get_app().get_available_shaders().size() >= min_size_for_shaders)
{
if (drawer.header("Real Time Shader Selection"))
{
if (drawer.combo_box("Shader language", &activeShader, shaderName))
if (drawer.combo_box("Shader language", &active_shader, language_names))
{
std::string selectedShader = shaderName[activeShader];
vkb::ShaderSourceLanguage shaderType = vkb::ShaderSourceLanguage::VK_GLSL;
std::string selectedShader = language_names[active_shader];
vkb::ShaderSourceLanguage shaderType = vkb::ShaderSourceLanguage::GLSL;
if (selectedShader == "GLSL")
{
shaderType = vkb::ShaderSourceLanguage::VK_GLSL;
shaderType = vkb::ShaderSourceLanguage::GLSL;
}
else if (selectedShader == "HLSL")
{
shaderType = vkb::ShaderSourceLanguage::VK_HLSL;
shaderType = vkb::ShaderSourceLanguage::HLSL;
}
else if (selectedShader == "SPV")
{
shaderType = vkb::ShaderSourceLanguage::VK_SPV;
shaderType = vkb::ShaderSourceLanguage::SPV;
}
else
{
return;
LOGE("Not supported shader language");
assert(false);
}
auto it = availableShaders.find(shaderType);
auto app = &platform->get_app();
app->change_shader(it->first, it->second);
auto it = platform->get_app().get_available_shaders().find(shaderType);
platform->get_app().change_shader(it->first);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

#pragma once

#include "platform/plugins/plugin_base.h"
#include "common/vk_common.h"
#include <vector>
#include "platform/plugins/plugin_base.h"
#include <map>
#include <vector>

namespace plugins
{
Expand All @@ -32,7 +32,7 @@ using RealTimeShaderSelectionTags = vkb::PluginBase<RealTimeShaderSelection, vkb
/**
* @brief Real Time Shader Selection
*
* When this option is enabled, the simples get the ability to dynamically choose which shaders are available for a given sample.
* When this option is enabled, the samples get the ability to dynamically choose which shaders are available for a given sample.
*
* Usage: vulkan_samples sample afbc --realtimeshaderselection
*
Expand All @@ -54,10 +54,9 @@ class RealTimeShaderSelection : public RealTimeShaderSelectionTags

vkb::FlagCommand realtimeshaderselection_flag = {vkb::FlagType::FlagOnly, "realtimeshaderselection", "", "Enable dynamic shader selection"};

private:
std::map<vkb::ShaderSourceLanguage, std::vector<std::pair<vkb::ShaderType, std::string>>> availableShaders;
std::vector<std::string> shaderName;
int activeShader;
static const int min_size_for_shaders = 2;
private:
std::vector<std::string> language_names;
int active_shader;
const int min_size_for_shaders;
};
} // namespace plugins
2 changes: 2 additions & 0 deletions framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ project(framework LANGUAGES C CXX)
set(FRAMEWORK_FILES
# Header Files
gui.h
drawer.h
glsl_compiler.h
spirv_reflection.h
gltf_loader.h
Expand Down Expand Up @@ -51,6 +52,7 @@ set(FRAMEWORK_FILES
hpp_vulkan_sample.h
# Source Files
gui.cpp
drawer.cpp
glsl_compiler.cpp
spirv_reflection.cpp
gltf_loader.cpp
Expand Down
47 changes: 21 additions & 26 deletions framework/api_vulkan_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,25 +100,6 @@ void ApiVulkanSample::update(float delta_time)
}
}

void ApiVulkanSample::update_overlay(float delta_time, const std::function<void()>& additional_ui)
{
if (gui)
{
gui->show_simple_window(get_name(), vkb::to_u32(1.0f / delta_time), [this, additional_ui]() {
on_update_ui_overlay(gui->get_drawer());
additional_ui();
});

gui->update(delta_time);

if (gui->update_buffers() || gui->get_drawer().is_dirty())
{
build_command_buffers();
gui->get_drawer().clear();
}
}
}

bool ApiVulkanSample::resize(const uint32_t _width, const uint32_t _height)
{
if (!prepared)
Expand Down Expand Up @@ -449,18 +430,37 @@ void ApiVulkanSample::create_pipeline_cache()
VK_CHECK(vkCreatePipelineCache(device->get_handle(), &pipeline_cache_create_info, nullptr, &pipeline_cache));
}

VkPipelineShaderStageCreateInfo ApiVulkanSample::load_shader(const std::string &file, VkShaderStageFlagBits stage)
VkPipelineShaderStageCreateInfo ApiVulkanSample::load_shader(const std::string &file, VkShaderStageFlagBits stage, vkb::ShaderSourceLanguage src_language)
{
VkPipelineShaderStageCreateInfo shader_stage = {};
shader_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stage.stage = stage;
shader_stage.module = vkb::load_shader(file.c_str(), device->get_handle(), stage);
shader_stage.module = vkb::load_shader(file.c_str(), device->get_handle(), stage, src_language);
shader_stage.pName = "main";
assert(shader_stage.module != VK_NULL_HANDLE);
shader_modules.push_back(shader_stage.module);
return shader_stage;
}

void ApiVulkanSample::update_overlay(float delta_time, const std::function<void()> &additional_ui)
{
if (gui)
{
gui->show_simple_window(get_name(), vkb::to_u32(1.0f / delta_time), [this, additional_ui]() {
on_update_ui_overlay(gui->get_drawer());
additional_ui();
});

gui->update(delta_time);

if (gui->update_buffers() || gui->get_drawer().is_dirty())
{
build_command_buffers();
gui->get_drawer().clear();
}
}
}

void ApiVulkanSample::draw_ui(const VkCommandBuffer command_buffer)
{
if (gui)
Expand Down Expand Up @@ -860,11 +860,6 @@ void ApiVulkanSample::update_render_pass_flags(uint32_t flags)
void ApiVulkanSample::on_update_ui_overlay(vkb::Drawer &drawer)
{}

void ApiVulkanSample::store_shader(const vkb::ShaderSourceLanguage& shaderLanguage, const std::vector<std::pair<vkb::ShaderType, std::string>>& listOfShader)
{
Application::get_available_shaders().insert({shaderLanguage, listOfShader});
}

void ApiVulkanSample::create_swapchain_buffers()
{
if (render_context->has_swapchain())
Expand Down
13 changes: 3 additions & 10 deletions framework/api_vulkan_sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class ApiVulkanSample : public vkb::VulkanSample

virtual void update(float delta_time) override;

virtual void update_overlay(float delta_time, const std::function<void()>& additional_ui) override;
virtual void update_overlay(float delta_time, const std::function<void()> &additional_ui) override;

virtual bool resize(const uint32_t width, const uint32_t height) override;

Expand Down Expand Up @@ -332,8 +332,9 @@ class ApiVulkanSample : public vkb::VulkanSample
* @brief Load a SPIR-V shader
* @param file The file location of the shader relative to the shaders folder
* @param stage The shader stage
* @param src_language The shader language
*/
VkPipelineShaderStageCreateInfo load_shader(const std::string &file, VkShaderStageFlagBits stage);
VkPipelineShaderStageCreateInfo load_shader(const std::string &file, VkShaderStageFlagBits stage, vkb::ShaderSourceLanguage src_language = vkb::ShaderSourceLanguage::GLSL);

/**
* @brief Updates the overlay
Expand Down Expand Up @@ -369,14 +370,6 @@ class ApiVulkanSample : public vkb::VulkanSample
*/
virtual void prepare_gui();

/**
* @brief Stores a list of shaders for the active sample, used by plugins to dynamically change the shader
*
* @param shaderLanguage The shader language for which the shader list will be provided
* @param listOfShader The shader list, where paths and shader types are provided
*/
void store_shader(const vkb::ShaderSourceLanguage& shaderLanguage, const std::vector<std::pair<vkb::ShaderType, std::string>>& listOfShader);

private:
/** brief Indicates that the view (position, rotation) has changed and buffers containing camera matrices need to be updated */
bool view_updated = false;
Expand Down
26 changes: 13 additions & 13 deletions framework/common/hpp_vk_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ inline bool is_dynamic_buffer_descriptor_type(vk::DescriptorType descriptor_type
return vkb::is_dynamic_buffer_descriptor_type(static_cast<VkDescriptorType>(descriptor_type));
}

inline vk::ShaderModule load_shader(const std::string &filename, vk::Device device, vk::ShaderStageFlagBits stage)
inline vk::ShaderModule load_shader(const std::string &filename, vk::Device device, vk::ShaderStageFlagBits stage, ShaderSourceLanguage src_language = ShaderSourceLanguage::GLSL)
{
return static_cast<vk::ShaderModule>(vkb::load_shader(filename, device, static_cast<VkShaderStageFlagBits>(stage)));
return static_cast<vk::ShaderModule>(vkb::load_shader(filename, device, static_cast<VkShaderStageFlagBits>(stage), src_language));
}

inline void set_image_layout(vk::CommandBuffer command_buffer,
Expand Down Expand Up @@ -135,17 +135,17 @@ inline vk::Framebuffer create_framebuffer(vk::Device device, vk::RenderPass rend
return device.createFramebuffer(framebuffer_create_info);
}

inline vk::Pipeline create_graphics_pipeline(vk::Device device,
vk::PipelineCache pipeline_cache,
std::array<vk::PipelineShaderStageCreateInfo, 2> const &shader_stages,
vk::PipelineVertexInputStateCreateInfo const &vertex_input_state,
vk::PrimitiveTopology primitive_topology,
vk::CullModeFlags cull_mode,
vk::FrontFace front_face,
std::vector<vk::PipelineColorBlendAttachmentState> const &blend_attachment_states,
vk::PipelineDepthStencilStateCreateInfo const &depth_stencil_state,
vk::PipelineLayout pipeline_layout,
vk::RenderPass render_pass)
inline vk::Pipeline create_graphics_pipeline(vk::Device device,
vk::PipelineCache pipeline_cache,
vk::ArrayProxyNoTemporaries<const vk::PipelineShaderStageCreateInfo> const &shader_stages,
vk::PipelineVertexInputStateCreateInfo const &vertex_input_state,
vk::PrimitiveTopology primitive_topology,
vk::CullModeFlags cull_mode,
vk::FrontFace front_face,
std::vector<vk::PipelineColorBlendAttachmentState> const &blend_attachment_states,
vk::PipelineDepthStencilStateCreateInfo const &depth_stencil_state,
vk::PipelineLayout pipeline_layout,
vk::RenderPass render_pass)
{
vk::PipelineInputAssemblyStateCreateInfo input_assembly_state({}, primitive_topology, false);

Expand Down
33 changes: 23 additions & 10 deletions framework/common/vk_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,24 +356,37 @@ int32_t get_bits_per_pixel(VkFormat format)
}
}

VkShaderModule load_shader(const std::string &filename, VkDevice device, VkShaderStageFlagBits stage)
VkShaderModule load_shader(const std::string &filename, VkDevice device, VkShaderStageFlagBits stage, vkb::ShaderSourceLanguage src_language)
{
vkb::GLSLCompiler glsl_compiler;

auto buffer = vkb::fs::read_shader_binary(filename);
auto buffer = vkb::fs::read_shader_binary(filename);
std::vector<uint32_t> spirv;

std::string file_ext = filename;
if (vkb::ShaderSourceLanguage::GLSL == src_language)
{
std::string file_ext = filename;

// Extract extension name from the glsl shader file
file_ext = file_ext.substr(file_ext.find_last_of(".") + 1);
// Extract extension name from the glsl shader file
file_ext = file_ext.substr(file_ext.find_last_of(".") + 1);

std::vector<uint32_t> spirv;
std::string info_log;
std::string info_log;

// Compile the GLSL source
if (!glsl_compiler.compile_to_spirv(vkb::find_shader_stage(file_ext), buffer, "main", {}, spirv, info_log))
// Compile the GLSL source
if (!glsl_compiler.compile_to_spirv(vkb::find_shader_stage(file_ext), buffer, "main", {}, spirv, info_log))
{
LOGE("Failed to compile shader, Error: {}", info_log.c_str());
return VK_NULL_HANDLE;
}
}
else if (vkb::ShaderSourceLanguage::SPV == src_language)
{
spirv = std::vector<uint32_t>(reinterpret_cast<uint32_t *>(buffer.data()),
reinterpret_cast<uint32_t *>(buffer.data()) + buffer.size() / sizeof(uint32_t));
}
else
{
LOGE("Failed to compile shader, Error: {}", info_log.c_str());
LOGE("The format is not supported");
return VK_NULL_HANDLE;
}

Expand Down
Loading

0 comments on commit 5058b97

Please sign in to comment.