diff --git a/Vulkan/Vulkan.vcxproj b/Vulkan/Vulkan.vcxproj
index 6d5e667..8708a94 100644
--- a/Vulkan/Vulkan.vcxproj
+++ b/Vulkan/Vulkan.vcxproj
@@ -123,7 +123,7 @@
Console
true
$(ProjectDir)ext/lib/;C:/VulkanSDK/1.3.236.0/Lib;%(AdditionalLibraryDirectories)
- vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)
+ vulkan-1.lib;glfw3.lib;shaderc_combinedd.lib;%(AdditionalDependencies)
@@ -150,7 +150,7 @@
true
true
$(ProjectDir)ext/lib/;C:/VulkanSDK/1.3.236.0/Lib;%(AdditionalLibraryDirectories)
- vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)
+ vulkan-1.lib;glfw3.lib;shaderc_combinedd.lib;%(AdditionalDependencies)
@@ -166,15 +166,19 @@
+
+
-
+
+
+
diff --git a/Vulkan/Vulkan.vcxproj.filters b/Vulkan/Vulkan.vcxproj.filters
index eeb7862..841e1ff 100644
--- a/Vulkan/Vulkan.vcxproj.filters
+++ b/Vulkan/Vulkan.vcxproj.filters
@@ -74,7 +74,7 @@
Header Files
-
+
Header Files
@@ -83,6 +83,18 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
diff --git a/Vulkan/res/shaders/frag.spv b/Vulkan/res/shaders/frag.spv
deleted file mode 100644
index 841eb58..0000000
Binary files a/Vulkan/res/shaders/frag.spv and /dev/null differ
diff --git a/Vulkan/res/shaders/shader.frag b/Vulkan/res/shaders/shader.frag
index 500463e..27f1330 100644
--- a/Vulkan/res/shaders/shader.frag
+++ b/Vulkan/res/shaders/shader.frag
@@ -1,12 +1,15 @@
#version 450
-layout(set = 1, binding = 0) uniform sampler2D texSampler;
+layout(set = 0, binding = 1) uniform sampler2D texSampler;
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
+layout(location = 2) in vec3 fragPosition;
+layout(location = 3) in vec3 fragLightPos;
layout(location = 0) out vec4 outColor;
void main() {
- outColor = vec4(fragColor, 1.0) * texture(texSampler, fragTexCoord);
+ float scale = 0.45 + max(dot(vec3(0, 1, 0), normalize(fragLightPos - fragPosition)), 0.0);
+ outColor = vec4(fragColor, 1.0) * texture(texSampler, fragTexCoord) * scale;
}
diff --git a/Vulkan/res/shaders/shader.vert b/Vulkan/res/shaders/shader.vert
index a537cc4..e2f1a3a 100644
--- a/Vulkan/res/shaders/shader.vert
+++ b/Vulkan/res/shaders/shader.vert
@@ -8,15 +8,19 @@ layout(set = 0, binding = 0) uniform SceneUniformBufferObject
vec3 lightPos;
} ubo;
-layout(location = 0) in vec2 inPosition;
+layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
+layout(location = 2) out vec3 fragPosition;
+layout(location = 3) out vec3 fragLightPos;
void main() {
- gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPosition.x, 0.0, inPosition.y, 1.0);
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPosition, 1.0);
fragColor = inColor;
fragTexCoord = inTexCoord;
+ fragPosition = vec3(ubo.model * vec4(inPosition, 1.0));
+ fragLightPos = ubo.lightPos;
}
\ No newline at end of file
diff --git a/Vulkan/res/shaders/vert.spv b/Vulkan/res/shaders/vert.spv
deleted file mode 100644
index 5fadf46..0000000
Binary files a/Vulkan/res/shaders/vert.spv and /dev/null differ
diff --git a/Vulkan/src/CommandBuffer.h b/Vulkan/src/CommandBuffer.h
new file mode 100644
index 0000000..c417a4f
--- /dev/null
+++ b/Vulkan/src/CommandBuffer.h
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "Common.h"
+#include "Instance.h"
+#include
+
+enum class CommandBufferType
+{
+ SingleUse, Dynamic
+};
+
+class CommandBuffer
+{
+ CP_DELETE_COPY_AND_MOVE_CTOR(CommandBuffer);
+private:
+ Instance& instance;
+
+ std::vector commandBuffers;
+ const CommandBufferType type;
+ VkCommandBuffer currentCommandBuffer{VK_NULL_HANDLE};
+
+public:
+ CommandBuffer(Instance& instance, CommandBufferType type)
+ : instance{instance}, type{type}
+ {
+ if (type == CommandBufferType::Dynamic)
+ commandBuffers.resize(instance.GetMaxFramesInFlight());
+ else
+ commandBuffers.resize(1);
+
+ VkCommandBufferAllocateInfo allocateInfo{};
+ allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ allocateInfo.commandPool = instance.GetCommandPool();
+ allocateInfo.commandBufferCount = commandBuffers.size();
+ CP_VK_ASSERT(vkAllocateCommandBuffers(instance.GetDevice(), &allocateInfo, commandBuffers.data()), "Failed to allocate CommandBuffer");
+ }
+
+ ~CommandBuffer()
+ {
+ vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), commandBuffers.size(), commandBuffers.data());
+ }
+
+ // TODO: Test as constexpr function to see if it avoids the switch case
+ void Begin()
+ {
+ VkCommandBufferBeginInfo beginInfo{};
+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ beginInfo.flags = 0;
+ beginInfo.pInheritanceInfo = nullptr;
+ switch(type)
+ {
+ case CommandBufferType::SingleUse:
+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ currentCommandBuffer = commandBuffers.front();
+ break;
+ case CommandBufferType::Dynamic:
+ currentCommandBuffer = commandBuffers[instance.GetFlightIndex()];
+ break;
+ default:
+ CP_WARN("Unhandled enum case: %d", (int)type);
+ }
+
+ vkResetCommandBuffer(currentCommandBuffer, 0);
+ CP_VK_ASSERT(vkBeginCommandBuffer(currentCommandBuffer, &beginInfo), "Failed to begin command buffer");
+ }
+
+ void End()
+ {
+ vkEndCommandBuffer(currentCommandBuffer);
+ }
+
+ void Submit()
+ {
+ VkSubmitInfo submitInfo{};
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = ¤tCommandBuffer;
+
+ vkQueueSubmit(instance.GetGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
+ // TODO: if singleUse?
+ vkQueueWaitIdle(instance.GetGraphicsQueue());
+ }
+
+ void SubmitAsGraphicsQueue()
+ {
+ instance.SubmitGraphicsQueue({currentCommandBuffer});
+ }
+
+ VkCommandBuffer GetHandle()
+ {
+ return currentCommandBuffer;
+ }
+};
diff --git a/Vulkan/src/CommandBufferScoped.h b/Vulkan/src/CommandBufferScoped.h
new file mode 100644
index 0000000..7461755
--- /dev/null
+++ b/Vulkan/src/CommandBufferScoped.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "Common.h"
+#include "CommandBuffer.h"
+
+class CommandBufferScoped : public CommandBuffer
+{
+ CP_DELETE_COPY_AND_MOVE_CTOR(CommandBufferScoped);
+public:
+ CommandBufferScoped(Instance& instance)
+ : CommandBuffer{instance, CommandBufferType::SingleUse}
+ {
+ CommandBuffer::Begin();
+ }
+
+ ~CommandBufferScoped()
+ {
+ CommandBuffer::End();
+ CommandBuffer::Submit();
+ }
+};
diff --git a/Vulkan/src/Common.h b/Vulkan/src/Common.h
index f8ad6f4..2788b96 100644
--- a/Vulkan/src/Common.h
+++ b/Vulkan/src/Common.h
@@ -1,43 +1,50 @@
#pragma once
#include "VulkanException.h"
-#include
#include
-#define CP_DEBUG(format, ...) std::cout << "[DBG] " << StringFormat(format, __VA_ARGS__) << std::endl
-#define CP_INFO(format, ...) std::cout << "[INF] " << StringFormat(format, __VA_ARGS__) << std::endl
-#define CP_WARN(format, ...) std::cout << "[WRN] " << StringFormat(format, __VA_ARGS__) << std::endl
-#define CP_ERR(format, ...) std::cout << "[ERR] " << StringFormat(format, __VA_ARGS__) << std::endl
+#define TERM_RED "\x1B[31m"
+#define TERM_GREEN "\x1B[32m"
+#define TERM_YELLOW "\x1B[33m"
+#define TERM_GRAY "\x1B[90m"
+#define TERM_CLEAR "\033[0m"
+
+#define CP_DEBUG(format, ...) std::cout << TERM_GRAY << "[DBG] " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl
+#define CP_INFO(format, ...) std::cout << "[INF] " << StringFormat(format, __VA_ARGS__) << std::endl
+#define CP_WARN(format, ...) std::cout << TERM_YELLOW << "[WRN] " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl
+#define CP_ERR(format, ...) std::cout << TERM_RED << "[ERR] " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl
+
+// Continue traces, will not print the [XXX] tag before the log
+#define CP_DEBUG_CONT(format, ...) std::cout << TERM_GRAY << " " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl
+#define CP_INFO_CONT(format, ...) std::cout << " " << StringFormat(format, __VA_ARGS__) << std::endl
+#define CP_WARN_CONT(format, ...) std::cout << TERM_YELLOW << " " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl
+#define CP_ERR_CONT(format, ...) std::cout << TERM_RED << " " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl
#define CP_UNIMPLEMENTED() CP_WARN("%s is unimplemented", __FUNCTION__)
-#define CP_ASSERT(Function, format, ...) if(!(Function)) { throw std::runtime_error(StringFormat(format, __VA_ARGS__)); } while(false)
-#define CP_VK_ASSERT(Function, format, ...) if(Function != VK_SUCCESS) { throw VulkanException(StringFormat(format, __VA_ARGS__)); } while(false)
+#define CP_ASSERT(Function, format, ...) \
+ do \
+ { \
+ if(!(Function)) \
+ { \
+ CP_ERR(format, __VA_ARGS__); \
+ throw std::runtime_error(StringFormat(format, __VA_ARGS__)); \
+ } \
+ } while(false)
+#define CP_VK_ASSERT(Function, format, ...) \
+ do \
+ { \
+ if(Function != VK_SUCCESS) \
+ { \
+ CP_ERR(format, __VA_ARGS__); \
+ throw VulkanException(StringFormat(format, __VA_ARGS__)); \
+ } \
+ } while(false)
#define CP_DELETE_COPY_AND_MOVE_CTOR(ClassName) \
ClassName(ClassName&&) = delete; \
ClassName(const ClassName&) = delete; \
ClassName& operator=(ClassName&&) = delete; \
ClassName& operator=(const ClassName&) = delete
-static VkResult vkCreateDebugUtilsMessengerEXT(VkInstance instance,
- const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkDebugUtilsMessengerEXT* pDebugMessenger)
-{
- auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
- if (func != nullptr)
- return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
- return VK_ERROR_EXTENSION_NOT_PRESENT;
-}
-
-static void vkDestroyDebugUtilsMessengerEXT(VkInstance instance,
- VkDebugUtilsMessengerEXT debugMessenger,
- const VkAllocationCallbacks* pAllocator) {
- auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
- if (func != nullptr) {
- func(instance, debugMessenger, pAllocator);
- }
-}
-
template
std::string StringFormat(const std::string& format, Args... args)
{
diff --git a/Vulkan/src/DebugMessenger.h b/Vulkan/src/DebugMessenger.h
index cb6402c..7cb3a54 100644
--- a/Vulkan/src/DebugMessenger.h
+++ b/Vulkan/src/DebugMessenger.h
@@ -4,63 +4,85 @@
class DebugMessenger
{
- CP_DELETE_COPY_AND_MOVE_CTOR(DebugMessenger);
+ CP_DELETE_COPY_AND_MOVE_CTOR(DebugMessenger);
public:
- VkInstance instance;
- VkDebugUtilsMessengerEXT debugMessenger;
+ VkInstance instance;
+ VkDebugUtilsMessengerEXT debugMessenger;
- DebugMessenger(VkInstance instance)
- : instance{instance}
- {
+ DebugMessenger(VkInstance instance)
+ : instance{instance}
+ {
#ifndef NDEBUG
- VkDebugUtilsMessengerCreateInfoEXT createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
- createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
- createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
- createInfo.pfnUserCallback = DebugCallback;
- createInfo.pUserData = nullptr;
- CP_VK_ASSERT(vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger), "Failed to initialze debug messenger");
+ VkDebugUtilsMessengerCreateInfoEXT createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+ createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ createInfo.pfnUserCallback = DebugCallback;
+ createInfo.pUserData = nullptr;
+ CP_VK_ASSERT(vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger), "Failed to initialze debug messenger");
#endif
- }
+ }
- ~DebugMessenger()
- {
+ ~DebugMessenger()
+ {
#ifndef NDEBUG
- vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
+ vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
#endif
- }
+ }
- static void AddRequiredExtensions(std::vector* extensions)
- {
+ static void AddRequiredExtensions(std::vector* extensions)
+ {
#ifndef NDEBUG
- extensions->emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ extensions->emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
- }
+ }
- static void AddRequiredLayers(std::vector* layers)
- {
+ static void AddRequiredLayers(std::vector* layers)
+ {
#ifndef NDEBUG
- layers->emplace_back("VK_LAYER_KHRONOS_validation");
+ layers->emplace_back("VK_LAYER_KHRONOS_validation");
#endif
- }
+ }
private:
- static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
- VkDebugUtilsMessageTypeFlagsEXT messageType,
- const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
- void* pUserData)
- {
- if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
- {
- std::cerr << pCallbackData->pMessage << std::endl;
- if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
- throw VulkanException(pCallbackData->pMessage);
- }
- return VK_FALSE;
- }
+ static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageType,
+ const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
+ void* pUserData)
+ {
+ if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
+ {
+ if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
+ {
+ CP_ERR(pCallbackData->pMessage);
+ throw VulkanException(pCallbackData->pMessage);
+ }
+ CP_WARN(pCallbackData->pMessage);
+ }
+ return VK_FALSE;
+ }
+ static VkResult vkCreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDebugUtilsMessengerEXT* pDebugMessenger)
+ {
+ auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
+ if (func != nullptr)
+ return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ static void vkDestroyDebugUtilsMessengerEXT(VkInstance instance,
+ VkDebugUtilsMessengerEXT debugMessenger,
+ const VkAllocationCallbacks* pAllocator) {
+ auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
+ if (func != nullptr) {
+ func(instance, debugMessenger, pAllocator);
+ }
+ }
};
diff --git a/Vulkan/src/DescriptorPool.h b/Vulkan/src/DescriptorPool.h
index 0d7438f..b35c19e 100644
--- a/Vulkan/src/DescriptorPool.h
+++ b/Vulkan/src/DescriptorPool.h
@@ -28,6 +28,7 @@ public:
createInfo.poolSizeCount = poolSizes.size();
createInfo.pPoolSizes = poolSizes.data();
createInfo.maxSets = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight();
+ createInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "Failed to initialize descriptor pool");
}
@@ -52,4 +53,9 @@ public:
return descriptorSets;
}
+
+ void FreeDescriptorSets(const std::vector& descriptorSets)
+ {
+ vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data());
+ }
};
diff --git a/Vulkan/src/DescriptorSet.h b/Vulkan/src/DescriptorSet.h
index 5c23fe5..b4dd783 100644
--- a/Vulkan/src/DescriptorSet.h
+++ b/Vulkan/src/DescriptorSet.h
@@ -2,11 +2,11 @@
#include "Common.h"
#include "DescriptorPool.h"
-#include "Sampler.h"
+#include "Texture2D.h"
#include "UniformBuffer.h"
#include
-class DescriptorSet
+class DescriptorSet final
{
CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorSet);
private:
@@ -23,6 +23,11 @@ public:
descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout);
}
+ ~DescriptorSet()
+ {
+ descriptorPool.FreeDescriptorSets(descriptorSets);
+ }
+
void AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding)
{
for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
@@ -42,9 +47,9 @@ public:
}
}
- void AddSampler(const Sampler& sampler, uint32_t binding)
+ void AddTexture2D(const Texture2D& texture2D, uint32_t binding)
{
- VkDescriptorImageInfo imageInfo = sampler.GetDescriptorImageInfo();
+ VkDescriptorImageInfo imageInfo = texture2D.GetDescriptorImageInfo();
for (auto&& descriptorSet : descriptorSets) {
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
diff --git a/Vulkan/src/FileSystem.h b/Vulkan/src/FileSystem.h
index ca2c92f..bb3eff8 100644
--- a/Vulkan/src/FileSystem.h
+++ b/Vulkan/src/FileSystem.h
@@ -1,12 +1,15 @@
#pragma once
+#include
+#include
+
#include "Common.h"
#include
namespace FileSystem
{
- static std::vector ReadFile(const std::string& filename)
+ static std::vector ReadFile(const std::string& filename)
{
std::ifstream file(filename, std::ios::ate | std::ios::binary);
CP_ASSERT(file.is_open(), "Failed to open file");
@@ -19,4 +22,48 @@ namespace FileSystem
return buffer;
}
+
+ static std::string ReadFileStr(const std::string& filename)
+ {
+ std::ifstream file(filename, std::ios::ate | std::ios::binary);
+ CP_ASSERT(file.is_open(), "Failed to open file");
+
+ size_t fileSize = (size_t) file.tellg();
+ std::string buffer;
+ buffer.resize(fileSize);
+
+ file.seekg(0);
+ file.read(buffer.data(), fileSize);
+
+ return buffer;
+ }
+
+ static void WriteFile(const std::string& filename, const std::string& data)
+ {
+ std::ofstream file(filename, std::ios::binary);
+ CP_ASSERT(file.is_open(), "Failed to open file");
+
+ file.write(data.c_str(), data.size());
+ }
+
+ static void WriteFile(const std::string& filename, const char* data, size_t size)
+ {
+ std::ofstream file(filename, std::ios::binary);
+ CP_ASSERT(file.is_open(), "Failed to open file");
+
+ file.write(data, size);
+ }
+
+ static bool FileExists(const std::string& filename)
+ {
+ std::ifstream file(filename);
+ return file.good();
+ }
+
+ static int64_t DateModified(const std::string& filename)
+ {
+ struct stat result;
+ CP_ASSERT(stat(filename.c_str(), &result) == 0, "Cannot stat file %s", filename.c_str());
+ return (int64_t)result.st_mtime;
+ }
}
\ No newline at end of file
diff --git a/Vulkan/src/Image.h b/Vulkan/src/Image.h
new file mode 100644
index 0000000..024071b
--- /dev/null
+++ b/Vulkan/src/Image.h
@@ -0,0 +1,151 @@
+#pragma once
+
+#include
+#include "Buffer.h"
+#include "Common.h"
+#include "CommandBufferScoped.h"
+#include "Instance.h"
+
+class Image
+{
+ Image() = delete;
+public:
+ static void InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory)
+ {
+ VkImageCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ createInfo.imageType = VK_IMAGE_TYPE_2D;
+ createInfo.extent.width = width;
+ createInfo.extent.height = height;
+ createInfo.extent.depth = 1;
+ createInfo.mipLevels = 1;
+ createInfo.arrayLayers = 1;
+ createInfo.format = format;
+ createInfo.tiling = tiling;
+ createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ createInfo.usage = usage;
+ createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ createInfo.flags = 0;
+
+ CP_VK_ASSERT(vkCreateImage(instance.GetDevice(), &createInfo, nullptr, image), "Failed to initialize image");
+
+ VkMemoryRequirements memoryRequirements;
+ vkGetImageMemoryRequirements(instance.GetDevice(), *image, &memoryRequirements);
+
+ VkMemoryAllocateInfo allocateInfo{};
+ allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocateInfo.allocationSize = memoryRequirements.size;
+ allocateInfo.memoryTypeIndex = instance.FindMemoryType(memoryRequirements.memoryTypeBits, properties);
+
+ CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, imageMemory), "Failed to initiallizse image memory");
+
+ vkBindImageMemory(instance.GetDevice(), *image, *imageMemory, 0);
+ }
+
+ static VkImageView InitializeImageView(Instance& instance, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
+ {
+ VkImageView imageView;
+ VkImageViewCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ createInfo.image = image;
+ createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ createInfo.format = format;
+ createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.subresourceRange.aspectMask = aspectFlags;
+ createInfo.subresourceRange.baseMipLevel = 0;
+ createInfo.subresourceRange.levelCount = 1;
+ createInfo.subresourceRange.baseArrayLayer = 0;
+ createInfo.subresourceRange.layerCount = 1;
+ CP_VK_ASSERT(vkCreateImageView(instance.GetDevice(), &createInfo, nullptr, &imageView), "Failed to initialize image view");
+ return imageView;
+ }
+
+ static void TransitionImageLayout(Instance& instance, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout)
+ {
+ CommandBufferScoped commandBuffer{instance};
+
+ VkImageMemoryBarrier barrier{};
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.oldLayout = oldLayout;
+ barrier.newLayout = newLayout;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = image;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = 1;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = 1;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = 0;
+
+ VkPipelineStageFlags srcStage;
+ VkPipelineStageFlags dstStage;
+
+ if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ if (HasStencilComponent(format)) {
+ barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ }
+ } else {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+
+ if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ }
+ else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ }
+ else
+ {
+ throw std::invalid_argument("Unsupported layout transition");
+ }
+
+ vkCmdPipelineBarrier(commandBuffer.GetHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
+ }
+
+ static void CopyBufferToImage(Instance& instance, const Buffer& buffer, VkImage image, uint32_t width, uint32_t height)
+ {
+ CommandBufferScoped commandBuffer{instance};
+
+ VkBufferImageCopy region{};
+ region.bufferOffset = 0;
+ region.bufferRowLength = 0;
+ region.bufferImageHeight = 0;
+
+ region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.imageSubresource.mipLevel = 0;
+ region.imageSubresource.baseArrayLayer = 0;
+ region.imageSubresource.layerCount = 1;
+
+ region.imageOffset = {0, 0, 0};
+ region.imageExtent = {width, height, 1};
+
+ vkCmdCopyBufferToImage(commandBuffer.GetHandle(), buffer.GetHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+ }
+
+private:
+ static bool HasStencilComponent(VkFormat format)
+ {
+ return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
+ }
+};
\ No newline at end of file
diff --git a/Vulkan/src/Instance.h b/Vulkan/src/Instance.h
index 855e58a..177693c 100644
--- a/Vulkan/src/Instance.h
+++ b/Vulkan/src/Instance.h
@@ -48,10 +48,10 @@ public:
InitializeSurface();
SelectPhysicalDevice();
InitializeLogicalDevice();
- InitializeSwapChain();
InitializeCommandPool();
+ InitializeSwapChain();
InitializeSyncObjects();
- std::cout << "Initialized Vulkan in " << timer.Elapsed() << " seconds" << std::endl;
+ CP_INFO("Initialized Vulkan in %f seconds", timer.Elapsed());
}
~Instance()
@@ -211,10 +211,10 @@ private:
std::vector extensions{extensionCount};
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
- std::cout << "Supported Extensions: " << std::endl;
+ CP_INFO("Supported Extensions:");
for (auto&& extension : extensions)
{
- std::cout << "\t" << extension.extensionName << std::endl;
+ CP_INFO_CONT("\t%s", extension.extensionName);
}
std::vector layers{};
@@ -249,12 +249,12 @@ private:
std::vector devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
- std::cout << "Available devices: " << std::endl;
+ CP_INFO("Available devices:");
for (auto&& device : devices)
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
- std::cout << "\t" << deviceProperties.deviceName << std::endl;
+ CP_INFO_CONT("\t%s", deviceProperties.deviceName);
}
for (auto&& device : devices)
{
@@ -263,7 +263,7 @@ private:
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
physicalDevice = device;
- std::cout << "Selecting device: " << deviceProperties.deviceName << std::endl;
+ CP_INFO("Selecting device: %s", deviceProperties.deviceName);
break;
}
}
@@ -362,10 +362,10 @@ private:
std::vector availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
- std::cout << "Supported Layers: " << std::endl;
+ CP_INFO("Supported Layers:");
for (auto&& availableLayer : availableLayers)
{
- std::cout << "\t" << availableLayer.layerName << std::endl;
+ CP_INFO_CONT("\t%s", availableLayer.layerName);
}
for (auto&& layer : layers)
diff --git a/Vulkan/src/Pipeline.h b/Vulkan/src/Pipeline.h
index f6d9238..ac66894 100644
--- a/Vulkan/src/Pipeline.h
+++ b/Vulkan/src/Pipeline.h
@@ -3,7 +3,9 @@
#include "Common.h"
#include "Instance.h"
#include "FileSystem.h"
+#include "DescriptorSet.h"
#include "PipelineCreator.h"
+#include "Shader.h"
#include
#include