Add GEVulkanShaderManager

This commit is contained in:
Benau
2022-03-18 16:24:33 +08:00
parent 89afd214e8
commit cb607a16ff
10 changed files with 190 additions and 9 deletions

View File

@@ -0,0 +1,12 @@
layout(location = 0) in vec4 f_color;
layout(location = 1) in vec2 f_uv;
layout(location = 2) flat in int f_sampler_index;
layout(binding = 0) uniform sampler2D f_tex[SAMPLER_SIZE];
layout(location = 0) out vec4 o_color;
void main()
{
o_color = texture(f_tex[f_sampler_index], f_uv) * f_color;
}

View File

@@ -0,0 +1,16 @@
layout(location = 0) in vec2 v_position;
layout(location = 1) in vec4 v_color;
layout(location = 2) in vec2 v_uv;
layout(location = 3) in int v_sampler_index;
layout(location = 0) out vec4 f_color;
layout(location = 1) out vec2 f_uv;
layout(location = 2) flat out int f_sampler_index;
void main()
{
gl_Position = vec4(v_position, 0.0, 1.0);
f_color = v_color.zyxw;
f_uv = v_uv;
f_sampler_index = v_sampler_index;
}

View File

@@ -26,6 +26,7 @@ set(GE_SOURCES
src/ge_texture.cpp
src/ge_dx9_texture.cpp
src/ge_vulkan_driver.cpp
src/ge_vulkan_shader_manager.cpp
src/ge_vulkan_texture.cpp
src/ge_gl_texture.cpp
)

View File

@@ -2,6 +2,7 @@
#define HEADER_GE_MAIN_HPP
#include <IVideoDriver.h>
#include <string>
namespace GE
{
@@ -11,9 +12,11 @@ struct GEConfig
bool m_disable_npot_texture;
};
void init(irr::video::IVideoDriver* driver);
void setVideoDriver(irr::video::IVideoDriver* driver);
void setShaderFolder(const std::string& path);
irr::video::IVideoDriver* getDriver();
GE::GEVulkanDriver* getVKDriver();
const std::string& getShaderFolder();
GEConfig* getGEConfig();
void deinit();
}

View File

@@ -275,18 +275,17 @@ namespace GE
return m_vk->samplers.at(s);
}
VkDevice getDevice() const { return m_vk->device; }
void destroyVulkan()
{
delete m_vk.get();
m_vk.release();
}
void destroyVulkan();
bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties, VkBuffer& buffer,
VkDeviceMemory& buffer_memory);
VkPhysicalDevice getPhysicalDevice() const { return m_physical_device; }
void waitIdle() { vkQueueWaitIdle(m_graphics_queue); }
const VkPhysicalDeviceProperties& getPhysicalDeviceProperties() const
{ return m_properties; }
VkCommandBuffer beginSingleTimeCommands();
void endSingleTimeCommands(VkCommandBuffer command_buffer);
io::IFileSystem* getFileSystem() const { return FileSystem; }
private:
struct SwapChainSupportDetails

View File

@@ -5,8 +5,9 @@ namespace GE
{
irr::video::IVideoDriver* g_driver = NULL;
GEConfig g_config = {};
std::string g_shader_folder = "";
void init(irr::video::IVideoDriver* driver)
void setVideoDriver(irr::video::IVideoDriver* driver)
{
g_driver = driver;
}
@@ -26,6 +27,16 @@ GEConfig* getGEConfig()
return &g_config;
}
void setShaderFolder(const std::string& path)
{
g_shader_folder = path + "ge_shaders/";
}
const std::string& getShaderFolder()
{
return g_shader_folder;
}
void deinit()
{
}

View File

@@ -1,5 +1,7 @@
#include "ge_vulkan_driver.hpp"
#include "ge_vulkan_shader_manager.hpp"
#ifdef _IRR_COMPILE_WITH_VULKAN_
const unsigned int MAX_FRAMES_IN_FLIGHT = 2;
#include "SDL_vulkan.h"
@@ -491,6 +493,7 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
createCommandPool();
createCommandBuffers();
createSamplers();
GEVulkanShaderManager::init(this);
os::Printer::log("Vulkan version", getVulkanVersionString().c_str());
os::Printer::log("Vulkan vendor", getVendorInfo().c_str());
os::Printer::log("Vulkan renderer", m_properties.deviceName);
@@ -504,6 +507,14 @@ GEVulkanDriver::~GEVulkanDriver()
{
} // ~GEVulkanDriver
// ----------------------------------------------------------------------------
void GEVulkanDriver::destroyVulkan()
{
GEVulkanShaderManager::destroy();
delete m_vk.get();
m_vk.release();
} // destroyVulkan
// ----------------------------------------------------------------------------
void GEVulkanDriver::createInstance(SDL_Window* window)
{

View File

@@ -0,0 +1,102 @@
#include "ge_vulkan_shader_manager.hpp"
#include "ge_main.hpp"
#include "ge_vulkan_driver.hpp"
#include <algorithm>
#include <sstream>
#include <string>
#include <stdexcept>
#include "IFileSystem.h"
namespace GE
{
// ============================================================================
GEVulkanDriver* g_vk = NULL;
irr::io::IFileSystem* g_file_system = NULL;
std::string g_predefines = "";
uint32_t g_sampler_size = 0;
VkShaderModule g_2d_render_vert = VK_NULL_HANDLE;
VkShaderModule g_2d_render_frag = VK_NULL_HANDLE;
// ============================================================================
void GEVulkanShaderManager::init(GEVulkanDriver* vk)
{
g_vk = vk;
g_file_system = vk->getFileSystem();
VkPhysicalDeviceLimits limit = g_vk->getPhysicalDeviceProperties().limits;
// According to https://vulkan.gpuinfo.org/displaydevicelimit.php?name=maxDescriptorSetSampledImages&platform=all
// almost all users have at least 96
if (limit.maxDescriptorSetSampledImages < 96)
throw std::runtime_error("maxDescriptorSetSampledImages is too low");
g_sampler_size = 96;
std::ostringstream oss;
oss << "#version 450\n";
oss << "#define SAMPLER_SIZE " << g_sampler_size << "\n";
g_predefines = oss.str();
// 2D rendering shader
g_2d_render_vert = loadShader(shaderc_vertex_shader, "2d_render.vert");
g_2d_render_frag = loadShader(shaderc_fragment_shader, "2d_render.frag");
} // init
// ----------------------------------------------------------------------------
void GEVulkanShaderManager::destroy()
{
vkDestroyShaderModule(g_vk->getDevice(), g_2d_render_vert, NULL);
vkDestroyShaderModule(g_vk->getDevice(), g_2d_render_frag, NULL);
} // destroy
// ----------------------------------------------------------------------------
VkShaderModule GEVulkanShaderManager::loadShader(shaderc_shader_kind kind,
const std::string& name)
{
std::string shader_fullpath = getShaderFolder() + name;
irr::io::IReadFile* r =
g_file_system->createAndOpenFile(shader_fullpath.c_str());
if (!r)
{
throw std::runtime_error(std::string("File ") + shader_fullpath +
" is missing");
}
std::string shader_data;
shader_data.resize(r->getSize());
int nb_read = 0;
if ((nb_read = r->read(&shader_data[0], r->getSize())) != r->getSize())
{
r->drop();
throw std::runtime_error(
std::string("File ") + name + " failed to be read");
}
r->drop();
shader_data = g_predefines + shader_data;
shaderc::Compiler compiler;
shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(
shader_data, kind, shader_fullpath.c_str());
if (module.GetCompilationStatus() != shaderc_compilation_status_success)
throw std::runtime_error(module.GetErrorMessage());
std::vector<uint32_t> shader_bytecode(module.cbegin(), module.cend());
VkShaderModuleCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
create_info.pNext = NULL;
create_info.codeSize = shader_bytecode.size() * sizeof(uint32_t);
create_info.pCode = shader_bytecode.data();
VkShaderModule shader_module;
if (vkCreateShaderModule(g_vk->getDevice(), &create_info, NULL,
&shader_module) != VK_SUCCESS)
{
throw std::runtime_error(
std::string("vkCreateShaderModule failed for ") + name);
}
return shader_module;
} // loadShader
}

View File

@@ -0,0 +1,23 @@
#ifndef HEADER_GE_VULKAN_SHADER_MANAGER_HPP
#define HEADER_GE_VULKAN_SHADER_MANAGER_HPP
#include "vulkan_wrapper.h"
#include <string>
#include <shaderc/shaderc.hpp>
namespace GE
{
class GEVulkanDriver;
namespace GEVulkanShaderManager
{
// ----------------------------------------------------------------------------
void init(GEVulkanDriver*);
// ----------------------------------------------------------------------------
void destroy();
// ----------------------------------------------------------------------------
VkShaderModule loadShader(shaderc_shader_kind, const std::string&);
}; // GEVulkanShaderManager
}
#endif

View File

@@ -388,6 +388,9 @@ void IrrDriver::createListOfVideoModes()
*/
void IrrDriver::initDevice()
{
#if !defined(SERVER_ONLY)
GE::setShaderFolder(file_manager->getShadersDir());
#endif
SIrrlichtCreationParameters params;
video::E_DRIVER_TYPE driver_created = video::EDT_NULL;
@@ -596,7 +599,7 @@ void IrrDriver::initDevice()
}
#ifndef SERVER_ONLY
GE::init(m_device->getVideoDriver());
GE::setVideoDriver(m_device->getVideoDriver());
// Assume sp is supported
CentralVideoSettings::m_supports_sp = true;
CVS->init();
@@ -635,7 +638,7 @@ void IrrDriver::initDevice()
Log::fatal("irr_driver", "Couldn't initialise irrlicht device. Quitting.\n");
}
GE::init(m_device->getVideoDriver());
GE::setVideoDriver(m_device->getVideoDriver());
CVS->init();
}
#endif