diff --git a/.idea/sonarlint.xml b/.idea/sonarlint.xml
index 29837d2..20dac8f 100644
--- a/.idea/sonarlint.xml
+++ b/.idea/sonarlint.xml
@@ -3,6 +3,6 @@
-
+
\ No newline at end of file
diff --git a/src/engine/vk/CMakeLists.txt b/src/engine/vk/CMakeLists.txt
index 4650323..59d7f9f 100644
--- a/src/engine/vk/CMakeLists.txt
+++ b/src/engine/vk/CMakeLists.txt
@@ -53,6 +53,10 @@ add_library(
VkImageView.h
VkSemaphore.cpp
VkSemaphore.h
+ VkDescriptorPool.cpp
+ VkDescriptorPool.h
+ VkDescriptorSetLayout.cpp
+ VkDescriptorSetLayout.h
)
target_link_libraries(
VkVixen
diff --git a/src/engine/vk/VkCommandBuffer.h b/src/engine/vk/VkCommandBuffer.h
index 37d16db..f43dd49 100644
--- a/src/engine/vk/VkCommandBuffer.h
+++ b/src/engine/vk/VkCommandBuffer.h
@@ -17,16 +17,16 @@ namespace Vixen::Vk {
};
private:
- ::VkDevice device;
+ VkDevice device;
- ::VkCommandPool commandPool;
+ VkCommandPool commandPool;
::VkCommandBuffer commandBuffer;
VkFence fence;
public:
- VkCommandBuffer(::VkDevice device, ::VkCommandPool commandPool, ::VkCommandBuffer commandBuffer);
+ VkCommandBuffer(VkDevice device, VkCommandPool commandPool, ::VkCommandBuffer commandBuffer);
VkCommandBuffer(VkCommandBuffer &) = delete;
diff --git a/src/engine/vk/VkDescriptorPool.cpp b/src/engine/vk/VkDescriptorPool.cpp
new file mode 100644
index 0000000..fef2d66
--- /dev/null
+++ b/src/engine/vk/VkDescriptorPool.cpp
@@ -0,0 +1,28 @@
+#include "VkDescriptorPool.h"
+
+namespace Vixen::Vk {
+ VkDescriptorPool::VkDescriptorPool(
+ const std::shared_ptr& device,
+ const std::vector& sizes,
+ const uint32_t maxSets
+ ) : device(device),
+ pool(VK_NULL_HANDLE) {
+ const VkDescriptorPoolCreateInfo info{
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .maxSets = maxSets,
+ .poolSizeCount = static_cast(sizes.size()),
+ .pPoolSizes = sizes.data()
+ };
+
+ checkVulkanResult(
+ vkCreateDescriptorPool(device->getDevice(), &info, nullptr, &pool),
+ "Failed to create descriptor pool"
+ );
+ }
+
+ VkDescriptorPool::~VkDescriptorPool() {
+ vkDestroyDescriptorPool(device->getDevice(), pool, nullptr);
+ }
+}
diff --git a/src/engine/vk/VkDescriptorPool.h b/src/engine/vk/VkDescriptorPool.h
new file mode 100644
index 0000000..33ead08
--- /dev/null
+++ b/src/engine/vk/VkDescriptorPool.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "Device.h"
+
+namespace Vixen::Vk {
+ class VkDescriptorPool {
+ std::shared_ptr device;
+
+ ::VkDescriptorPool pool;
+
+ public:
+ VkDescriptorPool(
+ const std::shared_ptr& device,
+ const std::vector& sizes,
+ uint32_t maxSets
+ );
+
+ VkDescriptorPool(const VkDescriptorPool& other) = delete;
+
+ VkDescriptorPool(VkDescriptorPool&& other) noexcept = delete;
+
+ VkDescriptorPool& operator=(VkDescriptorPool other) = delete;
+
+ ~VkDescriptorPool();
+ };
+}
diff --git a/src/engine/vk/VkDescriptorSetLayout.cpp b/src/engine/vk/VkDescriptorSetLayout.cpp
new file mode 100644
index 0000000..03e169f
--- /dev/null
+++ b/src/engine/vk/VkDescriptorSetLayout.cpp
@@ -0,0 +1,5 @@
+#include "VkDescriptorSetLayout.h"
+
+namespace Vixen::Vk {
+
+}
diff --git a/src/engine/vk/VkDescriptorSetLayout.h b/src/engine/vk/VkDescriptorSetLayout.h
new file mode 100644
index 0000000..62e5042
--- /dev/null
+++ b/src/engine/vk/VkDescriptorSetLayout.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "Device.h"
+
+namespace Vixen::Vk {
+ class VkDescriptorSetLayout {
+ public:
+
+ };
+}
diff --git a/src/engine/vk/VkShaderModule.cpp b/src/engine/vk/VkShaderModule.cpp
index 6933f75..50b80f1 100644
--- a/src/engine/vk/VkShaderModule.cpp
+++ b/src/engine/vk/VkShaderModule.cpp
@@ -2,24 +2,24 @@
namespace Vixen::Vk {
VkShaderModule::VkShaderModule(
- const std::shared_ptr &device,
- Stage stage,
- const std::vector &binary,
- const std::vector &bindings,
- const std::vector &inputs,
- const std::string &entrypoint
+ const std::shared_ptr& device,
+ const Stage stage,
+ const std::vector& binary,
+ const std::vector& bindings,
+ const std::vector& inputs,
+ const std::string& entrypoint
) : ShaderModule(stage, entrypoint, bindings, inputs),
device(device),
module(VK_NULL_HANDLE) {
- VkShaderModuleCreateInfo info{
- .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- .codeSize = binary.size() * sizeof(uint32_t),
- .pCode = binary.data()
+ const VkShaderModuleCreateInfo info{
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .codeSize = binary.size() * sizeof(uint32_t),
+ .pCode = binary.data()
};
checkVulkanResult(
- vkCreateShaderModule(device->getDevice(), &info, nullptr, &module),
- "Failed to create shader module"
+ vkCreateShaderModule(device->getDevice(), &info, nullptr, &module),
+ "Failed to create shader module"
);
}
@@ -27,15 +27,37 @@ namespace Vixen::Vk {
vkDestroyShaderModule(device->getDevice(), module, nullptr);
}
- VkPipelineShaderStageCreateInfo VkShaderModule::createInfo() {
+ VkPipelineShaderStageCreateInfo VkShaderModule::createInfo() const {
return {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .pNext = VK_NULL_HANDLE,
- .flags = 0,
- .stage = getVulkanShaderStage(getStage()),
- .module = module,
- .pName = getEntrypoint().c_str(),
- .pSpecializationInfo = VK_NULL_HANDLE
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .pNext = VK_NULL_HANDLE,
+ .flags = 0,
+ .stage = getVulkanShaderStage(getStage()),
+ .module = module,
+ .pName = getEntrypoint().c_str(),
+ .pSpecializationInfo = VK_NULL_HANDLE
};
}
+
+ std::vector VkShaderModule::createBindings() const {
+ const auto& bindings = getBindings();
+
+ std::vector b{bindings.size()};
+ for (const auto& [binding, stride, rate] : bindings) {
+ const VkShaderStageFlags& stage = getVulkanShaderStage(getStage());
+
+ b.push_back(
+ VkDescriptorSetLayoutBinding{
+ .binding = binding,
+ .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ // TODO: This count value is used for array bindings
+ .descriptorCount = 1,
+ .stageFlags = stage,
+ .pImmutableSamplers = nullptr
+ }
+ );
+ }
+
+ return b;
+ }
}
diff --git a/src/engine/vk/VkShaderModule.h b/src/engine/vk/VkShaderModule.h
index 5f97e21..60c2d8d 100644
--- a/src/engine/vk/VkShaderModule.h
+++ b/src/engine/vk/VkShaderModule.h
@@ -28,28 +28,29 @@ namespace Vixen::Vk {
public:
VkShaderModule(
- const std::shared_ptr &device,
- Stage stage,
- const std::vector &binary,
- const std::vector &bindings,
- const std::vector &inputs,
- const std::string &entrypoint = "main"
+ const std::shared_ptr& device,
+ Stage stage,
+ const std::vector& binary,
+ const std::vector& bindings,
+ const std::vector& inputs,
+ const std::string& entrypoint = "main"
);
- VkShaderModule(const VkShaderModule &) = delete;
+ VkShaderModule(const VkShaderModule&) = delete;
- VkShaderModule &operator=(const VkShaderModule &) = delete;
+ VkShaderModule& operator=(const VkShaderModule&) = delete;
~VkShaderModule();
- VkPipelineShaderStageCreateInfo createInfo();
+ [[nodiscard]] VkPipelineShaderStageCreateInfo createInfo() const;
+
+ [[nodiscard]] std::vector createBindings() const;
class Builder {
// TODO: This builder has slightly confusing API, you can compile before setting the stage meaning its possible to mistakenly have the wrong stage set at compile time
- private:
Stage stage;
- std::vector binary;
+ std::vector binary{};
std::string entrypoint = "main";
@@ -59,129 +60,46 @@ namespace Vixen::Vk {
std::vector uniformBuffers{};
- static uint32_t getTypeSize(const glslang::TType *type) {
- uint32_t size;
-
- switch (type->getBasicType()) {
- case glslang::EbtVoid:
- size = 0;
- break;
- case glslang::EbtFloat:
- size = sizeof(float);
- break;
- case glslang::EbtDouble:
- size = sizeof(double);
- break;
- case glslang::EbtFloat16:
- size = sizeof(long);
- break;
- case glslang::EbtInt8:
- size = sizeof(int8_t);
- break;
- case glslang::EbtUint8:
- size = sizeof(uint8_t);
- break;
- case glslang::EbtInt16:
- size = sizeof(int16_t);
- break;
- case glslang::EbtUint16:
- size = sizeof(uint16_t);
- break;
- case glslang::EbtInt:
- size = sizeof(int32_t);
- break;
- case glslang::EbtUint:
- size = sizeof(uint32_t);
- break;
- case glslang::EbtInt64:
- size = sizeof(int64_t);
- break;
- case glslang::EbtUint64:
- size = sizeof(uint64_t);
- break;
- case glslang::EbtBool:
- size = sizeof(bool);
- break;
- case glslang::EbtAtomicUint:
- // TODO
- size = 0;
- break;
- case glslang::EbtSampler:
- size = 0;
- break;
- case glslang::EbtStruct:
- size = 0;
- break;
- case glslang::EbtBlock:
- size = 0;
- break;
- case glslang::EbtAccStruct:
- size = 0;
- break;
- case glslang::EbtReference:
- size = 0;
- break;
- case glslang::EbtRayQuery:
- size = 0;
- break;
- case glslang::EbtSpirvType:
- size = 0;
- break;
- case glslang::EbtString:
- size = 0;
- break;
- case glslang::EbtNumTypes:
- size = 0;
- break;
- default:
- size = 0;
- break;
- }
-
- if (type->isVector())
- size *= type->getVectorSize();
-
- return size;
- }
-
public:
- Builder &setStage(Stage s) {
+ explicit Builder(const Stage stage) : stage(stage) {}
+
+ Builder& setStage(const Stage s) {
stage = s;
return *this;
}
- Builder &setBinary(const std::vector &data) {
+ Builder& setBinary(const std::vector& data) {
binary = data;
return *this;
}
- Builder &setEntrypoint(const std::string &entry) {
+ Builder& setEntrypoint(const std::string& entry) {
entrypoint = entry;
return *this;
}
- Builder &addBinding(Binding binding) {
+ Builder& addBinding(const Binding& binding) {
bindings.push_back(binding);
return *this;
}
- Builder &addInput(const IO &input) {
+ Builder& addInput(const IO& input) {
inputs.push_back(input);
return *this;
}
- std::shared_ptr compile(const std::shared_ptr &d, const std::vector &source) {
+ std::shared_ptr compile(const std::shared_ptr& d, const std::vector& source) {
EShLanguage s;
switch (stage) {
- case Stage::VERTEX:
- s = EShLanguage::EShLangVertex;
- break;
- case Stage::FRAGMENT:
- s = EShLanguage::EShLangFragment;
- break;
- default:
- spdlog::error("Unsupported stage for shader module");
- throw std::runtime_error("Unsupported stage for shader module");
+ case Stage::VERTEX:
+ s = EShLangVertex;
+ break;
+ case Stage::FRAGMENT:
+ s = EShLangFragment;
+ break;
+ default:
+ spdlog::error("Unsupported stage for shader module");
+ throw std::runtime_error("Unsupported stage for shader module");
}
spdlog::trace("Passed in shader source\n{}", source.data());
@@ -200,7 +118,7 @@ namespace Vixen::Vk {
shader.setEntryPoint(entrypoint.c_str());
shader.setSourceEntryPoint(entrypoint.c_str());
- auto messages = (EShMessages) (EShMsgSpvRules | EShMsgVulkanRules);
+ auto messages = static_cast(EShMsgSpvRules | EShMsgVulkanRules);
// TODO: Add actual includer
glslang::TShader::ForbidIncluder includer;
@@ -214,23 +132,23 @@ namespace Vixen::Vk {
glslang::SpvOptions options{
#ifdef DEBUG
- .generateDebugInfo = true,
- .stripDebugInfo = false,
- .disableOptimizer = true,
- .optimizeSize = false,
- .disassemble = true,
+ .generateDebugInfo = true,
+ .stripDebugInfo = false,
+ .disableOptimizer = true,
+ .optimizeSize = false,
+ .disassemble = true,
#else
- .generateDebugInfo = false,
- .stripDebugInfo = true,
- .disableOptimizer = false,
- .optimizeSize = true,
- .disassemble = false,
+ .generateDebugInfo = false,
+ .stripDebugInfo = true,
+ .disableOptimizer = false,
+ .optimizeSize = true,
+ .disassemble = false,
#endif
- .validate = true,
+ .validate = true,
};
spv::SpvBuildLogger logger;
- glslang::GlslangToSpv(*program.getIntermediate(s), binary, &logger, &options);
+ GlslangToSpv(*program.getIntermediate(s), binary, &logger, &options);
#ifdef DEBUG
std::stringstream stream;
@@ -240,19 +158,19 @@ namespace Vixen::Vk {
#endif
spirv_cross::CompilerReflection c{binary};
- auto resources = c.get_shader_resources();
- for (const auto &uniformBuffer: resources.uniform_buffers) {
- uint32_t binding = c.get_decoration(uniformBuffer.id, spv::DecorationBinding);
- uint32_t location = c.get_decoration(uniformBuffer.id, spv::DecorationLocation);
+ for (auto resources = c.get_shader_resources();
+ const auto& [id, type_id, base_type_id, name] : resources.uniform_buffers) {
+ uint32_t binding = c.get_decoration(id, spv::DecorationBinding);
+ uint32_t location = c.get_decoration(id, spv::DecorationLocation);
uniformBuffers.push_back({
- .binding = binding,
- .location = location,
- .size = 0,
- .offset = 0,
- });
+ .binding = binding,
+ .location = location,
+ .size = 0,
+ .offset = 0,
+ });
}
if (!logger.getAllMessages().empty())
@@ -265,16 +183,16 @@ namespace Vixen::Vk {
return std::make_shared(d, stage, binary, bindings, inputs, entrypoint);
}
- std::shared_ptr compile(const std::shared_ptr &d, const std::string &source) {
+ std::shared_ptr compile(const std::shared_ptr& d, const std::string& source) {
return compile(d, std::vector(source.begin(), source.end()));
}
- std::shared_ptr compileFromFile(const std::shared_ptr &d, const std::string &path) {
+ std::shared_ptr compileFromFile(const std::shared_ptr& d, const std::string& path) {
std::ifstream file(path, std::ios::ate);
if (!file.is_open())
throw std::runtime_error("Failed to read from file");
- std::streamsize size = file.tellg();
+ const std::streamsize size = file.tellg();
std::vector buffer(size);
file.seekg(0, std::ios_base::beg);
file.read(buffer.data(), size);
diff --git a/src/engine/vk/Vulkan.h b/src/engine/vk/Vulkan.h
index 0715e91..f4e6527 100644
--- a/src/engine/vk/Vulkan.h
+++ b/src/engine/vk/Vulkan.h
@@ -16,20 +16,20 @@
namespace Vixen::Vk {
template
- static inline void checkVulkanResult(VkResult result, const std::string &message) {
+ static void checkVulkanResult(VkResult result, const std::string &message) {
if (result != VK_SUCCESS)
error("{} ({})", message, string_VkResult(result));
}
- static inline std::string getVersionString(glm::ivec3 version) {
+ static std::string getVersionString(glm::ivec3 version) {
return fmt::format("{}.{}.{}", version.x, version.y, version.z);
}
- static inline std::string getVersionString(uint32_t version) {
+ static std::string getVersionString(const uint32_t version) {
return fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(version), VK_API_VERSION_MINOR(version), VK_API_VERSION_PATCH(version));
}
- static inline VkShaderStageFlagBits getVulkanShaderStage(ShaderModule::Stage stage) {
+ static VkShaderStageFlagBits getVulkanShaderStage(const ShaderModule::Stage stage) {
switch (stage) {
case ShaderModule::Stage::VERTEX:
return VK_SHADER_STAGE_VERTEX_BIT;
diff --git a/src/engine/vk/test/main.cpp b/src/engine/vk/test/main.cpp
index 182ed76..a98937e 100644
--- a/src/engine/vk/test/main.cpp
+++ b/src/engine/vk/test/main.cpp
@@ -9,6 +9,7 @@
#include "VkVixen.h"
#include "VkPipeline.h"
#include "VkRenderer.h"
+#include "VkDescriptorPool.h"
struct Vertex {
glm::vec3 position;
@@ -26,8 +27,7 @@ int main() {
auto vixen = Vixen::Vk::VkVixen("Vixen Vulkan Test", {1, 0, 0});
- const auto vertex = Vixen::Vk::VkShaderModule::Builder()
- .setStage(Vixen::ShaderModule::Stage::VERTEX)
+ const auto vertex = Vixen::Vk::VkShaderModule::Builder(Vixen::ShaderModule::Stage::VERTEX)
.addBinding({
.binding = 0,
.stride = sizeof(Vertex),
@@ -44,8 +44,7 @@ int main() {
.offset = offsetof(Vertex, color),
})
.compileFromFile(vixen.device, "../../src/editor/shaders/triangle.vert");
- const auto fragment = Vixen::Vk::VkShaderModule::Builder()
- .setStage(Vixen::ShaderModule::Stage::FRAGMENT)
+ const auto fragment = Vixen::Vk::VkShaderModule::Builder(Vixen::ShaderModule::Stage::FRAGMENT)
.compileFromFile(vixen.device, "../../src/editor/shaders/triangle.frag");
const auto program = Vixen::Vk::VkShaderProgram(vertex, fragment);
@@ -93,6 +92,14 @@ int main() {
}
);
+ const std::vector sizes{
+ {
+ .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ .descriptorCount = 1
+ }
+ };
+ const auto pool = Vixen::Vk::VkDescriptorPool(vixen.device, sizes, 1);
+
double old = glfwGetTime();
uint32_t fps = 0;
while (!vixen.window.shouldClose()) {