diff --git a/examples/VulkanTest/main.cpp b/examples/VulkanTest/main.cpp index e91a42ccc..e840227dc 100644 --- a/examples/VulkanTest/main.cpp +++ b/examples/VulkanTest/main.cpp @@ -56,29 +56,6 @@ int main() instance.vkCreateDebugReportCallbackEXT(instance, &callbackCreateInfo, nullptr, &callback); - Nz::File shaderFile; - std::vector vertexShaderCode; - std::vector fragmentShaderCode; - - if (!shaderFile.Open("resources/shaders/triangle.vert.spv", Nz::OpenMode_ReadOnly)) - { - NazaraError("Failed to open vertex shader code"); - return __LINE__; - } - - vertexShaderCode.resize(shaderFile.GetSize()); - shaderFile.Read(vertexShaderCode.data(), vertexShaderCode.size()); - - if (!shaderFile.Open("resources/shaders/triangle.frag.spv", Nz::OpenMode_ReadOnly)) - { - NazaraError("Failed to open fragment shader code"); - return __LINE__; - } - - fragmentShaderCode.resize(shaderFile.GetSize()); - shaderFile.Read(fragmentShaderCode.data(), fragmentShaderCode.size()); - - shaderFile.Close(); std::vector layerProperties; if (!Nz::Vk::Loader::EnumerateInstanceLayerProperties(&layerProperties)) @@ -124,6 +101,20 @@ int main() std::shared_ptr device = window.GetRenderDevice(); + auto fragmentShader = device->InstantiateShaderStage(Nz::ShaderStageType::Fragment, Nz::ShaderLanguage::SpirV, "resources/shaders/triangle.frag.spv"); + if (!fragmentShader) + { + std::cout << "Failed to instantiate fragment shader" << std::endl; + return __LINE__; + } + + auto vertexShader = device->InstantiateShaderStage(Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::SpirV, "resources/shaders/triangle.vert.spv"); + if (!vertexShader) + { + std::cout << "Failed to instantiate fragment shader" << std::endl; + return __LINE__; + } + Nz::VkRenderWindow& vulkanWindow = *static_cast(window.GetImpl()); /*VkPhysicalDeviceFeatures features; @@ -140,20 +131,6 @@ int main() Nz::VulkanDevice& vulkanDevice = vulkanWindow.GetDevice(); - Nz::Vk::ShaderModule vertexShader; - if (!vertexShader.Create(vulkanDevice.shared_from_this(), reinterpret_cast(vertexShaderCode.data()), vertexShaderCode.size())) - { - NazaraError("Failed to create vertex shader"); - return __LINE__; - } - - Nz::Vk::ShaderModule fragmentShader; - if (!fragmentShader.Create(vulkanDevice.shared_from_this(), reinterpret_cast(fragmentShaderCode.data()), fragmentShaderCode.size())) - { - NazaraError("Failed to create fragment shader"); - return __LINE__; - } - Nz::MeshRef drfreak = Nz::Mesh::LoadFromFile("resources/OILTANK1.md2", meshParams); if (!drfreak) @@ -297,7 +274,7 @@ int main() nullptr, 0, VK_SHADER_STAGE_VERTEX_BIT, - vertexShader, + static_cast(vertexShader.get())->GetHandle(), "main", nullptr }, @@ -306,7 +283,7 @@ int main() nullptr, 0, VK_SHADER_STAGE_FRAGMENT_BIT, - fragmentShader, + static_cast(fragmentShader.get())->GetHandle(), "main", nullptr } diff --git a/include/Nazara/Renderer.hpp b/include/Nazara/Renderer.hpp index 652538c6b..75c13cf0c 100644 --- a/include/Nazara/Renderer.hpp +++ b/include/Nazara/Renderer.hpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 2621081cd..3ea481e17 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -33,6 +33,20 @@ namespace Nz RenderDeviceType_Max = RenderDeviceType_Unknown }; + + enum class ShaderLanguage + { + GLSL, + HLSL, + MSL, + SpirV + }; + + enum class ShaderStageType + { + Fragment, + Vertex + }; } #endif // NAZARA_ENUMS_RENDERER_HPP diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 18f27bc5e..5df49c600 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -9,13 +9,16 @@ #include #include +#include #include #include #include +#include namespace Nz { class Buffer; + class ShaderStageImpl; class NAZARA_RENDERER_API RenderDevice { @@ -25,6 +28,8 @@ namespace Nz virtual std::unique_ptr InstantiateBuffer(Buffer* parent, BufferType type) = 0; virtual std::unique_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; + virtual std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; + std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath); }; } diff --git a/include/Nazara/Renderer/ShaderStageImpl.hpp b/include/Nazara/Renderer/ShaderStageImpl.hpp new file mode 100644 index 000000000..4bee731e2 --- /dev/null +++ b/include/Nazara/Renderer/ShaderStageImpl.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERER_SHADERSTAGEIMPL_HPP +#define NAZARA_RENDERER_SHADERSTAGEIMPL_HPP + +#include +#include +#include + +namespace Nz +{ + class NAZARA_RENDERER_API ShaderStageImpl + { + public: + ShaderStageImpl() = default; + virtual ~ShaderStageImpl(); + }; +} + +#endif // NAZARA_RENDERER_SHADERSTAGEIMPL_HPP diff --git a/include/Nazara/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer.hpp index 71c764abf..429629660 100644 --- a/include/Nazara/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer.hpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 291aa7b3e..9d625d634 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -25,6 +25,7 @@ namespace Nz std::unique_ptr InstantiateBuffer(Buffer* parent, BufferType type) override; std::unique_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; + std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; VulkanDevice& operator=(const VulkanDevice&) = delete; VulkanDevice& operator=(VulkanDevice&&) = delete; ///TODO? diff --git a/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp new file mode 100644 index 000000000..c7c4dcf92 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanShaderStage.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP +#define NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_VULKANRENDERER_API VulkanShaderStage : public ShaderStageImpl + { + public: + VulkanShaderStage() = default; + VulkanShaderStage(const VulkanShaderStage&) = delete; + VulkanShaderStage(VulkanShaderStage&&) noexcept = default; + ~VulkanShaderStage() = default; + + bool Create(const Vk::DeviceHandle& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize); + + inline const Vk::ShaderModule& GetHandle() const; + + VulkanShaderStage& operator=(const VulkanShaderStage&) = delete; + VulkanShaderStage& operator=(VulkanShaderStage&&) noexcept = default; + + private: + Vk::ShaderModule m_shaderModule; + ShaderStageType m_stage; + }; +} + +#include + +#endif // NAZARA_VULKANRENDERER_VULKANSHADERSTAGE_HPP diff --git a/include/Nazara/VulkanRenderer/VulkanShaderStage.inl b/include/Nazara/VulkanRenderer/VulkanShaderStage.inl new file mode 100644 index 000000000..5796071bb --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanShaderStage.inl @@ -0,0 +1,16 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline const Vk::ShaderModule& VulkanShaderStage::GetHandle() const + { + return m_shaderModule; + } +} + +#include diff --git a/src/Nazara/Renderer/RenderDevice.cpp b/src/Nazara/Renderer/RenderDevice.cpp index de5e5f82d..2ef01974a 100644 --- a/src/Nazara/Renderer/RenderDevice.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -3,9 +3,32 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include namespace Nz { RenderDevice::~RenderDevice() = default; + + std::shared_ptr RenderDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath) + { + File file(sourcePath); + if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) + { + NazaraError("Failed to open \"" + sourcePath.generic_u8string() + '"'); + return {}; + } + + std::size_t length = static_cast(file.GetSize()); + + std::vector source(length); + if (file.Read(&source[0], length) != length) + { + NazaraError("Failed to read program file"); + return {}; + } + + return InstantiateShaderStage(type, lang, source.data(), source.size()); + } } diff --git a/src/Nazara/Renderer/ShaderStageImpl.cpp b/src/Nazara/Renderer/ShaderStageImpl.cpp new file mode 100644 index 000000000..62ae7a7ed --- /dev/null +++ b/src/Nazara/Renderer/ShaderStageImpl.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + ShaderStageImpl::~ShaderStageImpl() = default; +} diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 43bb964fc..f2a802f4d 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -4,6 +4,7 @@ #include #include +#include #include namespace Nz @@ -19,4 +20,13 @@ namespace Nz { return std::make_unique(shared_from_this(), std::move(pipelineInfo)); } + + std::shared_ptr VulkanDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) + { + auto stage = std::make_shared(); + if (!stage->Create(shared_from_this(), type, lang, source, sourceSize)) + return {}; + + return stage; + } } diff --git a/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp b/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp new file mode 100644 index 000000000..b19bdca04 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VulkanShaderStage.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + bool VulkanShaderStage::Create(const Vk::DeviceHandle& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) + { + if (lang != ShaderLanguage::SpirV) + { + NazaraError("Only Spir-V is supported for now"); + return false; + } + + if (!m_shaderModule.Create(device, reinterpret_cast(source), sourceSize)) + { + NazaraError("Failed to create shader module"); + return false; + } + + m_stage = type; + return true; + } +}