diff --git a/.gitignore b/.gitignore
index 516effa..0a2c069 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ Release/
*/Release/
bin/
.ycm_extra_conf.py
+.cache
diff --git a/Vulkan/Vulkan.vcxproj b/Vulkan/Vulkan.vcxproj
index 8708a94..8b10657 100644
--- a/Vulkan/Vulkan.vcxproj
+++ b/Vulkan/Vulkan.vcxproj
@@ -130,7 +130,8 @@
- glslc res/shaders/shader.vert -o res/shaders/vert.spv && glslc res/shaders/shader.frag -o res/shaders/frag.spv
+
+
@@ -157,12 +158,14 @@
- glslc res/shaders/shader.vert -o res/shaders/vert.spv && glslc res/shaders/shader.frag -o res/shaders/frag.spv
+
+
+
@@ -172,6 +175,7 @@
+
@@ -189,13 +193,14 @@
+
-
+
+
-
diff --git a/Vulkan/Vulkan.vcxproj.filters b/Vulkan/Vulkan.vcxproj.filters
index 841e1ff..b63afde 100644
--- a/Vulkan/Vulkan.vcxproj.filters
+++ b/Vulkan/Vulkan.vcxproj.filters
@@ -21,6 +21,9 @@
Source Files
+
+ Source Files
+
@@ -95,6 +98,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
@@ -102,7 +111,7 @@
Source Files
-
-
+
+
\ No newline at end of file
diff --git a/Vulkan/res/shaders/passthrough.frag b/Vulkan/res/shaders/passthrough.frag
new file mode 100644
index 0000000..886651e
--- /dev/null
+++ b/Vulkan/res/shaders/passthrough.frag
@@ -0,0 +1,11 @@
+#version 450
+
+layout(set = 0, binding = 0) uniform sampler2D texSampler;
+layout(location = 0) in vec2 fragTexCoord;
+
+layout(location = 0) out vec4 outColor;
+
+void main()
+{
+ outColor = texture(texSampler, fragTexCoord);
+}
\ No newline at end of file
diff --git a/Vulkan/res/shaders/passthrough.vert b/Vulkan/res/shaders/passthrough.vert
new file mode 100644
index 0000000..544e962
--- /dev/null
+++ b/Vulkan/res/shaders/passthrough.vert
@@ -0,0 +1,11 @@
+#version 450
+
+layout(location = 0) in vec2 inPosition;
+
+layout(location = 0) out vec2 fragTexCoord;
+
+void main()
+{
+ gl_Position = vec4(inPosition* 0.5, 0.999, 1.0);
+ fragTexCoord = inPosition * 0.5 + 0.5;
+}
\ No newline at end of file
diff --git a/Vulkan/res/shaders/shader.frag b/Vulkan/res/shaders/shader.frag
index 27f1330..5b6e065 100644
--- a/Vulkan/res/shaders/shader.frag
+++ b/Vulkan/res/shaders/shader.frag
@@ -10,6 +10,6 @@ layout(location = 3) in vec3 fragLightPos;
layout(location = 0) out vec4 outColor;
void main() {
- float scale = 0.45 + max(dot(vec3(0, 1, 0), normalize(fragLightPos - fragPosition)), 0.0);
- outColor = vec4(fragColor, 1.0) * texture(texSampler, fragTexCoord) * scale;
+ 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 e2f1a3a..86e76e9 100644
--- a/Vulkan/res/shaders/shader.vert
+++ b/Vulkan/res/shaders/shader.vert
@@ -2,10 +2,10 @@
layout(set = 0, binding = 0) uniform SceneUniformBufferObject
{
- mat4 projection;
- mat4 view;
- mat4 model;
- vec3 lightPos;
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ vec3 lightPos;
} ubo;
layout(location = 0) in vec3 inPosition;
@@ -18,9 +18,9 @@ layout(location = 2) out vec3 fragPosition;
layout(location = 3) out vec3 fragLightPos;
void main() {
- 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;
+ 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/src/Buffer.h b/Vulkan/src/Buffer.h
index 9298bb8..b6252ef 100644
--- a/Vulkan/src/Buffer.h
+++ b/Vulkan/src/Buffer.h
@@ -100,7 +100,7 @@ public:
mappedData = nullptr;
}
- virtual void Bind(VkCommandBuffer commandBuffer) { CP_UNIMPLEMENTED(); };
+ virtual void Bind(const CommandBuffer& commandBuffer) { CP_UNIMPLEMENTED(); };
void BindAsVertexBuffer(VkCommandBuffer commandBuffer)
{
diff --git a/Vulkan/src/CommandBuffer.h b/Vulkan/src/CommandBuffer.h
index c417a4f..1050e4d 100644
--- a/Vulkan/src/CommandBuffer.h
+++ b/Vulkan/src/CommandBuffer.h
@@ -41,6 +41,11 @@ public:
vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), commandBuffers.size(), commandBuffers.data());
}
+ operator VkCommandBuffer() const
+ {
+ return currentCommandBuffer;
+ }
+
// TODO: Test as constexpr function to see if it avoids the switch case
void Begin()
{
@@ -87,7 +92,7 @@ public:
instance.SubmitGraphicsQueue({currentCommandBuffer});
}
- VkCommandBuffer GetHandle()
+ VkCommandBuffer GetHandle() const
{
return currentCommandBuffer;
}
diff --git a/Vulkan/src/Common.h b/Vulkan/src/Common.h
index 2788b96..c98a280 100644
--- a/Vulkan/src/Common.h
+++ b/Vulkan/src/Common.h
@@ -21,11 +21,17 @@
#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_ABORT(format, ...) \
+ do \
+ { \
+ CP_ERR(format, __VA_ARGS__); \
+ throw std::runtime_error(StringFormat(format, __VA_ARGS__)); \
+ } while(false)
#define CP_ASSERT(Function, format, ...) \
- do \
+ do \
{ \
if(!(Function)) \
- { \
+ { \
CP_ERR(format, __VA_ARGS__); \
throw std::runtime_error(StringFormat(format, __VA_ARGS__)); \
} \
@@ -40,16 +46,16 @@
} \
} 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
+ ClassName(ClassName&&) = delete; \
+ ClassName(const ClassName&) = delete; \
+ ClassName& operator=(ClassName&&) = delete; \
+ ClassName& operator=(const ClassName&) = delete
template
std::string StringFormat(const std::string& format, Args... args)
{
int size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
- CP_ASSERT(size > 0, "Error during formatting");
+ CP_ASSERT(size > 0, "Error during formatting");
std::unique_ptr buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1);
diff --git a/Vulkan/src/DescriptorSet.h b/Vulkan/src/DescriptorSet.h
index b4dd783..8d12ac7 100644
--- a/Vulkan/src/DescriptorSet.h
+++ b/Vulkan/src/DescriptorSet.h
@@ -49,11 +49,11 @@ public:
void AddTexture2D(const Texture2D& texture2D, uint32_t binding)
{
- VkDescriptorImageInfo imageInfo = texture2D.GetDescriptorImageInfo();
- for (auto&& descriptorSet : descriptorSets) {
+ for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
+ VkDescriptorImageInfo imageInfo = texture2D.GetDescriptorImageInfo(i);
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- descriptorWrite.dstSet = descriptorSet;
+ descriptorWrite.dstSet = descriptorSets[i];
descriptorWrite.dstBinding = binding;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
diff --git a/Vulkan/src/FileSystem.h b/Vulkan/src/FileSystem.h
index bb3eff8..f5fb64e 100644
--- a/Vulkan/src/FileSystem.h
+++ b/Vulkan/src/FileSystem.h
@@ -2,6 +2,7 @@
#include
#include
+#include
#include "Common.h"
@@ -48,6 +49,8 @@ namespace FileSystem
static void WriteFile(const std::string& filename, const char* data, size_t size)
{
+ std::filesystem::path path{filename};
+ std::filesystem::create_directories(path.parent_path());
std::ofstream file(filename, std::ios::binary);
CP_ASSERT(file.is_open(), "Failed to open file");
diff --git a/Vulkan/src/Framebuffer.h b/Vulkan/src/Framebuffer.h
new file mode 100644
index 0000000..b9c7a06
--- /dev/null
+++ b/Vulkan/src/Framebuffer.h
@@ -0,0 +1,174 @@
+#pragma once
+
+#include "Common.h"
+#include "Image.h"
+#include "Instance.h"
+#include "Texture2D.h"
+
+#include
+
+// TODO: Add resizing (recreate image, depthImage, framebuffers)
+class Framebuffer
+{
+ CP_DELETE_COPY_AND_MOVE_CTOR(Framebuffer);
+private:
+ Instance& instance;
+
+ std::unique_ptr image;
+ std::unique_ptr depthImage;
+ std::vector framebuffers;
+ VkRenderPass renderPass;
+
+ uint32_t width;
+ uint32_t height;
+public:
+ Framebuffer(Instance& instance, uint32_t width, uint32_t height)
+ : instance{instance}, width{width}, height{height}
+ {
+ InitializeImages();
+ InitializeDepthBuffer();
+ InitializeRenderPass();
+ InitializeFramebuffers();
+ }
+
+ ~Framebuffer()
+ {
+ for (auto& framebuffer : framebuffers)
+ vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr);
+ vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr);
+ }
+
+ void Bind(const CommandBuffer& commandBuffer)
+ {
+ std::vector clearValues{2};
+ clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
+ clearValues[1].depthStencil = {1.0f, 0};
+
+ VkRenderPassBeginInfo renderPassBeginInfo{};
+ renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ renderPassBeginInfo.renderPass = renderPass;
+ renderPassBeginInfo.framebuffer = framebuffers[instance.GetFlightIndex()];
+ renderPassBeginInfo.renderArea.offset = {0, 0};
+ renderPassBeginInfo.renderArea.extent = {width, height};
+ renderPassBeginInfo.clearValueCount = clearValues.size();
+ renderPassBeginInfo.pClearValues = clearValues.data();
+ vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+ }
+
+ void Unbind(const CommandBuffer& commandBuffer)
+ {
+ vkCmdEndRenderPass(commandBuffer);
+ }
+
+ VkRenderPass GetRenderPass() const
+ {
+ return renderPass;
+ }
+
+ VkFramebuffer GetFramebuffer() const
+ {
+ return framebuffers[instance.GetFlightIndex()];
+ }
+
+ const Texture2D& GetTexture2D() const
+ {
+ return *image;
+ }
+
+private:
+
+ void InitializeImages()
+ {
+ image = std::make_unique(instance, width, height, Texture2D::Type::Dynamic, Texture2D::Format::Color);
+ }
+
+ void InitializeDepthBuffer()
+ {
+ depthImage = std::make_unique(instance, width, height, Texture2D::Type::Static, Texture2D::Format::Depth);
+ }
+
+ void InitializeRenderPass()
+ {
+ VkAttachmentDescription colorAttachment{};
+ colorAttachment.format = VK_FORMAT_R8G8B8A8_SRGB;
+ colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ VkAttachmentDescription depthAttachment{};
+ depthAttachment.format = Image::SelectDepthFormat(instance);
+ depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference colorAttachmentRef{};
+ colorAttachmentRef.attachment = 0;
+ colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference depthAttachmentRef{};
+ depthAttachmentRef.attachment = 1;
+ depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass{};
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &colorAttachmentRef;
+ subpass.pDepthStencilAttachment = &depthAttachmentRef;
+
+ std::vector dependencies{2};
+ dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependencies[0].dstSubpass = 0;
+ dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ dependencies[1].srcSubpass = 0;
+ dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
+ dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ std::vector attachments{colorAttachment, depthAttachment};
+ VkRenderPassCreateInfo renderPassCreateInfo{};
+ renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassCreateInfo.attachmentCount = attachments.size();
+ renderPassCreateInfo.pAttachments = attachments.data();
+ renderPassCreateInfo.subpassCount = 1;
+ renderPassCreateInfo.pSubpasses = &subpass;
+ renderPassCreateInfo.dependencyCount = dependencies.size();
+ renderPassCreateInfo.pDependencies = dependencies.data();
+
+ CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "InitializeRenderPass : Failed to initialze render pass");
+ }
+
+ void InitializeFramebuffers()
+ {
+ framebuffers.resize(instance.GetMaxFramesInFlight());
+
+ for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i)
+ {
+ std::vector attachments{image->GetImageView(i), depthImage->GetImageView()};
+
+ VkFramebufferCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ createInfo.renderPass = renderPass;
+ createInfo.attachmentCount = attachments.size();
+ createInfo.pAttachments = attachments.data();
+ createInfo.width = width;
+ createInfo.height = height;
+ createInfo.layers = 1;
+
+ CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "InitializeFramebuffers : Failed to initialize swap chain framebuffer");
+ }
+ }
+};
\ No newline at end of file
diff --git a/Vulkan/src/Image.h b/Vulkan/src/Image.h
index 024071b..a4a9963 100644
--- a/Vulkan/src/Image.h
+++ b/Vulkan/src/Image.h
@@ -28,7 +28,7 @@ public:
createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
createInfo.flags = 0;
- CP_VK_ASSERT(vkCreateImage(instance.GetDevice(), &createInfo, nullptr, image), "Failed to initialize image");
+ CP_VK_ASSERT(vkCreateImage(instance.GetDevice(), &createInfo, nullptr, image), "InitializeImage : Failed to initialize image");
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(instance.GetDevice(), *image, &memoryRequirements);
@@ -38,7 +38,7 @@ public:
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");
+ CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, imageMemory), "InitializeImage : Failed to initiallizse image memory");
vkBindImageMemory(instance.GetDevice(), *image, *imageMemory, 0);
}
@@ -60,7 +60,7 @@ public:
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");
+ CP_VK_ASSERT(vkCreateImageView(instance.GetDevice(), &createInfo, nullptr, &imageView), "InitializeImageView : Failed to initialize image view");
return imageView;
}
@@ -115,12 +115,19 @@ public:
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
+ else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ }
else
{
- throw std::invalid_argument("Unsupported layout transition");
+ CP_ABORT("TransitioinImageLayout : Unsupported layout transition");
}
- vkCmdPipelineBarrier(commandBuffer.GetHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
+ vkCmdPipelineBarrier(commandBuffer, 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)
@@ -140,7 +147,13 @@ public:
region.imageOffset = {0, 0, 0};
region.imageExtent = {width, height, 1};
- vkCmdCopyBufferToImage(commandBuffer.GetHandle(), buffer.GetHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+ vkCmdCopyBufferToImage(commandBuffer, buffer.GetHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+ }
+
+
+ static VkFormat SelectDepthFormat(Instance& instance)
+ {
+ return SelectSupportedFormat(instance, {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
private:
@@ -148,4 +161,22 @@ private:
{
return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
}
+
+ static VkFormat SelectSupportedFormat(Instance& instance, const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
+ {
+ for (VkFormat format : candidates)
+ {
+ VkFormatProperties properties;
+ vkGetPhysicalDeviceFormatProperties(instance.GetPhysicalDevice(), format, &properties);
+ if(tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features)
+ {
+ return format;
+ }
+ else if (tiling == VK_IMAGE_TILING_OPTIMAL && (properties.optimalTilingFeatures & features) == features)
+ {
+ return format;
+ }
+ }
+ CP_ABORT("SelectSupportedFormat : Failed to select supported format");
+ }
};
\ No newline at end of file
diff --git a/Vulkan/src/IndexBuffer.h b/Vulkan/src/IndexBuffer.h
index 590e883..b626cb4 100644
--- a/Vulkan/src/IndexBuffer.h
+++ b/Vulkan/src/IndexBuffer.h
@@ -12,12 +12,12 @@ public:
: Buffer{instance, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexCount * sizeof(uint16_t), 1}, indexCount{indexCount}
{}
- void Bind(VkCommandBuffer commandBuffer) override
+ void Bind(const CommandBuffer& commandBuffer) override
{
vkCmdBindIndexBuffer(commandBuffer, handle, 0, VK_INDEX_TYPE_UINT16);
}
- void Draw(VkCommandBuffer commandBuffer)
+ void Draw(const CommandBuffer& commandBuffer)
{
vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
}
diff --git a/Vulkan/src/Pipeline.h b/Vulkan/src/Pipeline.h
index ac66894..8d0a25c 100644
--- a/Vulkan/src/Pipeline.h
+++ b/Vulkan/src/Pipeline.h
@@ -1,6 +1,7 @@
#pragma once
#include "Common.h"
+#include "CommandBuffer.h"
#include "Instance.h"
#include "FileSystem.h"
#include "DescriptorSet.h"
@@ -40,7 +41,7 @@ public:
}
}
- void Bind(VkCommandBuffer commandBuffer)
+ void Bind(const CommandBuffer& commandBuffer)
{
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
@@ -231,7 +232,7 @@ private:
graphicsPipelineCreateInfo.pColorBlendState = &colorBlendCreateInfo;
graphicsPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
graphicsPipelineCreateInfo.layout = pipelineLayout;
- graphicsPipelineCreateInfo.renderPass = instance.GetSwapChain().GetRenderPass();
+ graphicsPipelineCreateInfo.renderPass = creator.renderPass;
graphicsPipelineCreateInfo.subpass = 0;
graphicsPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
graphicsPipelineCreateInfo.basePipelineIndex = -1;
diff --git a/Vulkan/src/PipelineCreator.h b/Vulkan/src/PipelineCreator.h
index a57d343..e5b584c 100644
--- a/Vulkan/src/PipelineCreator.h
+++ b/Vulkan/src/PipelineCreator.h
@@ -25,10 +25,11 @@ private:
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
+ VkRenderPass renderPass = VK_NULL_HANDLE;
public:
- PipelineCreator(const std::string& vertexShader, const std::string& fragmentShader)
- : vertexShader{vertexShader}, fragmentShader{fragmentShader}
+ PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader)
+ : vertexShader{vertexShader}, fragmentShader{fragmentShader}, renderPass{renderPass}
{}
void SetVertexDescriptor(const VertexDescriptor& descriptor)
@@ -38,7 +39,7 @@ public:
void AddDescriptorSetLayoutBinding(uint32_t set, uint32_t binding, VkDescriptorType type, uint32_t count, VkShaderStageFlags stageFlags)
{
- CP_ASSERT(set <= descriptorSetLayouts.size(), "Cannot add descriptor set with set number greater than the current set count");
+ CP_ASSERT(set <= descriptorSetLayouts.size(), "AddDescriptorSetLayoutBinding : Cannot add descriptor set with set number greater than the current set count");
descriptorSetLayouts[set].emplace_back(DescriptorSetBinding{binding, type, count, stageFlags});
}
diff --git a/Vulkan/src/Shader.h b/Vulkan/src/Shader.h
index c5a4726..836618d 100644
--- a/Vulkan/src/Shader.h
+++ b/Vulkan/src/Shader.h
@@ -89,7 +89,7 @@ private:
VkShaderModule InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind shaderType)
{
- std::string spvFilename = filename + ".spv";
+ std::string spvFilename = ".cache/" + filename + ".spv";
try
{
if (FileSystem::FileExists(spvFilename))
diff --git a/Vulkan/src/SwapChain.cpp b/Vulkan/src/SwapChain.cpp
index c54699f..0392d22 100644
--- a/Vulkan/src/SwapChain.cpp
+++ b/Vulkan/src/SwapChain.cpp
@@ -1,8 +1,10 @@
#include "SwapChain.h"
+#include "CommandBuffer.h"
#include "Image.h"
#include "Instance.h"
#include "QueueFamilies.h"
+#include "Texture2D.h"
#include
#include
@@ -50,6 +52,28 @@ SwapChain::~SwapChain()
vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr);
}
+void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const
+{
+ std::vector clearValues{2};
+ clearValues[0].color = {{0.02f, 0.02f, 0.02f, 1.0f}};
+ clearValues[1].depthStencil = {1.0f, 0};
+
+ VkRenderPassBeginInfo renderPassBeginInfo{};
+ renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ renderPassBeginInfo.renderPass = renderPass;
+ renderPassBeginInfo.framebuffer = framebuffers[imageIndex];
+ renderPassBeginInfo.renderArea.offset = {0, 0};
+ renderPassBeginInfo.renderArea.extent = extent;
+ renderPassBeginInfo.clearValueCount = clearValues.size();
+ renderPassBeginInfo.pClearValues = clearValues.data();
+ vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+}
+
+void SwapChain::EndFrameBuffer(const CommandBuffer& commandBuffer) const
+{
+ vkCmdEndRenderPass(commandBuffer);
+}
+
VkSwapchainKHR SwapChain::GetHandle() const
{
return handle;
@@ -182,11 +206,7 @@ void SwapChain::InitializeImageViews()
void SwapChain::InitializeDepthBuffer()
{
- VkFormat depthFormat = SelectDepthFormat();
- Image::InitializeImage(instance, extent.width, extent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &depthImage, &depthImageMemory);
- Image::TransitionImageLayout(instance, depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
-
- depthImageView = Image::InitializeImageView(instance, depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
+ depthImage = std::make_unique(instance, extent.width, extent.height, Texture2D::Type::Static, Texture2D::Format::Depth);
}
void SwapChain::InitializeRenderPass()
@@ -202,7 +222,7 @@ void SwapChain::InitializeRenderPass()
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentDescription depthAttachment{};
- depthAttachment.format = SelectDepthFormat();
+ depthAttachment.format = Image::SelectDepthFormat(instance);
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@@ -252,7 +272,7 @@ void SwapChain::InitializeFramebuffers()
for (size_t i = 0; i < imageViews.size(); ++i)
{
- std::vector attachments{imageViews[i], depthImageView};
+ std::vector attachments{imageViews[i], depthImage->GetImageView()};
VkFramebufferCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
@@ -269,9 +289,6 @@ void SwapChain::InitializeFramebuffers()
void SwapChain::Destroy()
{
- vkDestroyImage(instance.GetDevice(), depthImage, nullptr);
- vkFreeMemory(instance.GetDevice(), depthImageMemory, nullptr);
- vkDestroyImageView(instance.GetDevice(), depthImageView, nullptr);
for (auto&& framebuffer : framebuffers)
{
vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr);
@@ -295,29 +312,6 @@ VkSurfaceFormatKHR SwapChain::SelectSwapSurfaceFormat(const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
-{
- for (VkFormat format : candidates)
- {
- VkFormatProperties properties;
- vkGetPhysicalDeviceFormatProperties(instance.GetPhysicalDevice(), format, &properties);
- if(tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features)
- {
- return format;
- }
- else if (tiling == VK_IMAGE_TILING_OPTIMAL && (properties.optimalTilingFeatures & features) == features)
- {
- return format;
- }
- }
- throw std::runtime_error("Failed to select supported format");
-}
-
VkPresentModeKHR SwapChain::SelectSwapPresentMode(const std::vector& availablePresentModes)
{
return VK_PRESENT_MODE_FIFO_KHR;
diff --git a/Vulkan/src/SwapChain.h b/Vulkan/src/SwapChain.h
index a150ef5..7b4364c 100644
--- a/Vulkan/src/SwapChain.h
+++ b/Vulkan/src/SwapChain.h
@@ -7,6 +7,8 @@
#include
class Instance;
+class CommandBuffer;
+class Texture2D;
struct SwapChainSupportDetails
{
@@ -24,24 +26,22 @@ class SwapChain final
private:
Instance& instance;
- // Created by the class
VkSwapchainKHR handle;
VkRenderPass renderPass;
VkFormat imageFormat;
VkExtent2D extent;
- VkImage depthImage;
- VkImageView depthImageView;
- VkDeviceMemory depthImageMemory;
+ std::unique_ptr depthImage;
std::vector imageViews;
std::vector images;
std::vector framebuffers;
-
uint32_t imageIndex;
public:
SwapChain(Instance& instance);
~SwapChain();
+ void BeginFrameBuffer(const CommandBuffer& commandBuffer) const;
+ void EndFrameBuffer(const CommandBuffer& commandBuffer) const;
VkSwapchainKHR GetHandle() const;
VkRenderPass GetRenderPass() const;
VkExtent2D GetExtent() const;
@@ -60,8 +60,6 @@ private:
void Destroy();
VkSurfaceFormatKHR SelectSwapSurfaceFormat(const std::vector& availableFormats);
- VkFormat SelectDepthFormat();
- VkFormat SelectSupportedFormat(const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
VkPresentModeKHR SelectSwapPresentMode(const std::vector& availablePresentModes);
VkExtent2D SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities);
};
diff --git a/Vulkan/src/Texture2D.cpp b/Vulkan/src/Texture2D.cpp
new file mode 100644
index 0000000..5b89074
--- /dev/null
+++ b/Vulkan/src/Texture2D.cpp
@@ -0,0 +1,150 @@
+#include "Texture2D.h"
+
+#define STB_IMAGE_IMPLEMENTATION
+#include
+
+Texture2D::Texture2D(Instance& instance, const std::string& filename)
+ : instance{instance}, type{Type::Static}, format{Format::Image}
+{
+ InitializeTextureImage(filename);
+ InitializeSampler();
+}
+
+Texture2D::Texture2D(Instance& instance, int width, int height, Type type, Format format)
+ : instance{instance}, type{type}, format{format}
+{
+ InitializeTexture(width, height);
+ InitializeSampler();
+}
+
+Texture2D::~Texture2D()
+{
+ for(auto&& image : images)
+ vkDestroyImage(instance.GetDevice(), image, nullptr);
+ for(auto&& imageMemory : imageMemories)
+ vkFreeMemory(instance.GetDevice(), imageMemory, nullptr);
+ for(auto&& imageView : imageViews)
+ vkDestroyImageView(instance.GetDevice(), imageView, nullptr);
+ vkDestroySampler(instance.GetDevice(), sampler, nullptr);
+}
+
+VkDescriptorImageInfo Texture2D::GetDescriptorImageInfo(int index) const
+{
+ VkDescriptorImageInfo imageInfo{};
+ imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ imageInfo.sampler = sampler;
+
+ switch (type) {
+ case Type::Static:
+ imageInfo.imageView = imageViews.front();
+ break;
+ case Type::Dynamic:
+ CP_ASSERT(index >= 0 && index < imageViews.size(), "GetDescriptorImageInfo : index out of bound for dynamic texture");
+ imageInfo.imageView = imageViews[index];
+ break;
+ default:
+ CP_ABORT("GetDescriptorImageInfo : Unreachable switch case");
+ }
+
+ return imageInfo;
+}
+
+VkImageView Texture2D::GetImageView() const
+{
+ CP_ASSERT(type == Type::Static, "GetImageView : Texture2D is not static");
+ return imageViews.front();
+}
+
+VkImageView Texture2D::GetImageView(int index)
+{
+ CP_ASSERT(type == Type::Dynamic && index >= 0 && index < imageViews.size(), "GetImageView : Texture2D is not dynamic or index out of bound for SystemTexture");
+ return imageViews[index];
+}
+
+void Texture2D::InitializeTextureImage(const std::string& filename)
+{
+ int texWidth;
+ int texHeight;
+ int texChannels;
+ stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
+
+ CP_ASSERT(pixels, "InitializeTextureImage : Failed to load texture image");
+
+ VkDeviceSize bufferSize = texWidth * texHeight * 4;
+ Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
+ void* data = stagingBuffer.Map();
+ memcpy(data, pixels, bufferSize);
+ stagingBuffer.Unmap();
+ stbi_image_free(pixels);
+
+ images.resize(1);
+ imageMemories.resize(1);
+ imageViews.resize(1);
+ Image::InitializeImage(instance, texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images.front(), &imageMemories.front());
+ Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ Image::CopyBufferToImage(instance, stagingBuffer, images.front(), texWidth, texHeight);
+ Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ imageViews[0] = Image::InitializeImageView(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
+}
+
+void Texture2D::InitializeTexture(int width, int height)
+{
+ int count = 1;
+ if (type == Type::Dynamic)
+ count = instance.GetMaxFramesInFlight();
+ images.resize(count);
+ imageMemories.resize(count);
+ imageViews.resize(count);
+ for (size_t i = 0; i < images.size(); i++)
+ {
+ switch (format)
+ {
+ case Format::Color:
+ {
+ Image::InitializeImage(instance, width, height, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]);
+ // Image::TransitionImageLayout(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ imageViews[i] = Image::InitializeImageView(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
+ break;
+ }
+ case Format::Depth:
+ {
+ VkFormat depthFormat = Image::SelectDepthFormat(instance);
+ Image::InitializeImage(instance, width, height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]);
+ // Image::TransitionImageLayout(instance, images[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ imageViews[i] = Image::InitializeImageView(instance, images[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
+ break;
+ }
+ case Format::Image:
+ {
+ CP_ABORT("InitializeTexture : Image format currently not supported");
+ }
+ default:
+ CP_ABORT("InitializeTexture : Unreachable switch case");
+ }
+ }
+}
+
+void Texture2D::InitializeSampler()
+{
+ VkPhysicalDeviceProperties properties{};
+ vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties);
+
+ VkSamplerCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ createInfo.magFilter = VK_FILTER_LINEAR;
+ createInfo.minFilter = VK_FILTER_LINEAR;
+ createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ createInfo.anisotropyEnable = VK_TRUE;
+ createInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
+ createInfo.unnormalizedCoordinates = VK_FALSE;
+ createInfo.compareEnable = VK_FALSE;
+ createInfo.compareOp = VK_COMPARE_OP_ALWAYS;
+ createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ createInfo.mipLodBias = 0.0f;
+ createInfo.minLod = 0.0f;
+ createInfo.maxLod = 0.0f;
+
+ CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &sampler), "InitializeSampler : Failed to initialize texture sampler");
+}
diff --git a/Vulkan/src/Texture2D.h b/Vulkan/src/Texture2D.h
index caa8b66..b512619 100644
--- a/Vulkan/src/Texture2D.h
+++ b/Vulkan/src/Texture2D.h
@@ -6,110 +6,40 @@
#include "Image.h"
#include "Instance.h"
-#define STB_IMAGE_IMPLEMENTATION
-#include
-
+// TODO: Separate Texture2D and Framebuffer Attachments
class Texture2D
{
CP_DELETE_COPY_AND_MOVE_CTOR(Texture2D);
+public:
+ enum class Type
+ {
+ Static, Dynamic
+ };
+
+ enum class Format
+ {
+ Image, Color, Depth
+ };
private:
Instance& instance;
- VkImage image;
- VkDeviceMemory imageMemory;
- VkImageView imageView;
+ std::vector images;
+ std::vector imageMemories;
+ std::vector imageViews;
VkSampler sampler;
+ Type type;
+ Format format;
public:
- Texture2D(Instance& instance, const std::string& filename)
- : instance{instance}
- {
- InitializeTextureImage(filename);
- InitializeSampler();
- }
+ Texture2D(Instance& instance, const std::string& filename);
+ Texture2D(Instance& instance, int width, int height, Type type, Format format);
+ ~Texture2D();
- ~Texture2D()
- {
- vkDestroyImage(instance.GetDevice(), image, nullptr);
- vkFreeMemory(instance.GetDevice(), imageMemory, nullptr);
- vkDestroyImageView(instance.GetDevice(), imageView, nullptr);
- vkDestroySampler(instance.GetDevice(), sampler, nullptr);
- }
-
- VkDescriptorImageInfo GetDescriptorImageInfo() const
- {
- VkDescriptorImageInfo imageInfo{};
- imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- imageInfo.imageView = imageView;
- imageInfo.sampler = sampler;
-
- return imageInfo;
- }
+ VkDescriptorImageInfo GetDescriptorImageInfo(int index) const;
+ VkImageView GetImageView() const;
+ VkImageView GetImageView(int index);
private:
- void InitializeTextureImage(const std::string& filename)
- {
- int texWidth;
- int texHeight;
- int texChannels;
- stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
-
- CP_ASSERT(pixels, "Failed to load texture image");
-
- VkDeviceSize bufferSize = texWidth * texHeight * 4;
- Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
- void* data = stagingBuffer.Map();
- memcpy(data, pixels, bufferSize);
- stagingBuffer.Unmap();
- stbi_image_free(pixels);
-
- Image::InitializeImage(instance, texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &image, &imageMemory);
- Image::TransitionImageLayout(instance, image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- Image::CopyBufferToImage(instance, stagingBuffer, image, texWidth, texHeight);
- Image::TransitionImageLayout(instance, image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- imageView = Image::InitializeImageView(instance, image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
- }
-
- void InitializeSampler()
- {
- VkPhysicalDeviceProperties properties{};
- vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties);
-
- VkSamplerCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
- createInfo.magFilter = VK_FILTER_LINEAR;
- createInfo.minFilter = VK_FILTER_LINEAR;
- createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- createInfo.anisotropyEnable = VK_TRUE;
- createInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
- createInfo.unnormalizedCoordinates = VK_FALSE;
- createInfo.compareEnable = VK_FALSE;
- createInfo.compareOp = VK_COMPARE_OP_ALWAYS;
- createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
- createInfo.mipLodBias = 0.0f;
- createInfo.minLod = 0.0f;
- createInfo.maxLod = 0.0f;
-
- CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &sampler), "Failed to initialize texture sampler");
- }
-
- VkImageView CreateImageView(VkImage image)
- {
- 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 = VK_FORMAT_R8G8B8A8_SRGB;
- createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- 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 ImageView");
-
- return imageView;
- }
-
+ void InitializeTextureImage(const std::string& filename);
+ void InitializeTexture(int width, int height);
+ void InitializeSampler();
};
diff --git a/Vulkan/src/VertexBuffer.h b/Vulkan/src/VertexBuffer.h
index 00530c8..902170e 100644
--- a/Vulkan/src/VertexBuffer.h
+++ b/Vulkan/src/VertexBuffer.h
@@ -22,7 +22,7 @@ public:
}
}
- void Bind(VkCommandBuffer commandBuffer) override
+ void Bind(const CommandBuffer& commandBuffer) override
{
std::vector buffers{bindingOffsets.size(), handle};
vkCmdBindVertexBuffers(commandBuffer, 0, bindingOffsets.size(), buffers.data(), bindingOffsets.data());
diff --git a/Vulkan/src/VertexPassthrough.h b/Vulkan/src/VertexPassthrough.h
new file mode 100644
index 0000000..e47c549
--- /dev/null
+++ b/Vulkan/src/VertexPassthrough.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include
+#include
+#include "VertexDescriptor.h"
+
+struct VertexPassthrough {
+ glm::vec2 texCoord;
+
+ static VertexDescriptor GetDescriptor()
+ {
+ VertexDescriptor descriptor{};
+ descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexPassthrough , texCoord));
+ return descriptor;
+ }
+};
diff --git a/Vulkan/src/main.cpp b/Vulkan/src/main.cpp
index 0f03519..1685def 100644
--- a/Vulkan/src/main.cpp
+++ b/Vulkan/src/main.cpp
@@ -1,6 +1,7 @@
#include "Buffer.h"
#include "DescriptorPool.h"
#include "DescriptorSet.h"
+#include "Framebuffer.h"
#include "IndexBuffer.h"
#include "Instance.h"
#include "Pipeline.h"
@@ -9,6 +10,7 @@
#include "UniformBuffer.h"
#include "Vertex.h"
#include "VertexBuffer.h"
+#include "VertexPassthrough.h"
#include
#include
@@ -20,13 +22,13 @@
#include
const std::vector vertices = {
- Vertex{{-0.5f, 0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
- Vertex{{ 0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
- Vertex{{ 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
+ Vertex{{-0.5f, 0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
+ Vertex{{ 0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
+ Vertex{{ 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
Vertex{{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
- Vertex{{-0.5f, 0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
- Vertex{{ 0.5f, 0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
- Vertex{{ 0.5f, 0.0f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
+ Vertex{{-0.5f, 0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
+ Vertex{{ 0.5f, 0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
+ Vertex{{ 0.5f, 0.0f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
Vertex{{-0.5f, 0.0f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
};
@@ -35,6 +37,17 @@ const std::vector indices = {
4, 5, 6, 6, 7, 4
};
+const std::vector verticesPassthrough = {
+ VertexPassthrough{{-1.0f, -1.0f}},
+ VertexPassthrough{{ 1.0f, -1.0f}},
+ VertexPassthrough{{ 1.0f, 1.0f}},
+ VertexPassthrough{{-1.0f, 1.0f}},
+};
+
+const std::vector indicesPassthrough = {
+ 0, 1, 2, 2, 3, 0,
+};
+
struct alignas(64) ShaderUniform
{
alignas(16) glm::mat4 projection;
@@ -56,10 +69,17 @@ private:
std::unique_ptr indexBuffer;
std::unique_ptr commandBuffer;
+ std::unique_ptr framebuffer;
+ std::unique_ptr graphicsPipelinePassthrough;
+ std::unique_ptr vertexBufferPassthrough;
+ std::unique_ptr indexBufferPassthrough;
+ std::unique_ptr descriptorSetPassthrough;
+
public:
Application()
{
InitializeInstance();
+ InitializeFrameBuffer();
InitializeGraphicsPipeline();
InitializeTextureSampler();
InitializeUniformBuffer();
@@ -94,7 +114,12 @@ private:
void InitializeInstance()
{
- instance = std::make_unique("Vulkan Tutorial");
+ instance = std::make_unique("Copium Engine");
+ }
+
+ void InitializeFrameBuffer()
+ {
+ framebuffer = std::make_unique(*instance, instance->GetSwapChain().GetExtent().width, instance->GetSwapChain().GetExtent().height);
}
void InitializeTextureSampler()
@@ -114,30 +139,44 @@ private:
descriptorSet = std::make_unique(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
descriptorSet->AddUniform(*shaderUniformBuffer, 0);
descriptorSet->AddTexture2D(*texture2D, 1);
+
+ descriptorSetPassthrough = std::make_unique(*instance, *descriptorPool, graphicsPipelinePassthrough->GetDescriptorSetLayout(0));
+ descriptorSetPassthrough->AddTexture2D(framebuffer->GetTexture2D(), 0);
}
void InitializeGraphicsPipeline()
{
- PipelineCreator creator{"res/shaders/shader.vert", "res/shaders/shader.frag"};
+ PipelineCreator creator{framebuffer->GetRenderPass(), "res/shaders/shader.vert", "res/shaders/shader.frag"};
creator.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
creator.AddDescriptorSetLayoutBinding(0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
creator.SetVertexDescriptor(Vertex::GetDescriptor());
creator.SetCullMode(VK_CULL_MODE_NONE);
graphicsPipeline = std::make_unique(*instance, creator);
+
+ PipelineCreator creatorPassthrough{instance->GetSwapChain().GetRenderPass(), "res/shaders/passthrough.vert", "res/shaders/passthrough.frag"};
+ creatorPassthrough.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
+ creatorPassthrough.SetVertexDescriptor(VertexPassthrough::GetDescriptor());
+ creatorPassthrough.SetCullMode(VK_CULL_MODE_NONE);
+ graphicsPipelinePassthrough = std::make_unique(*instance, creatorPassthrough);
}
void InitializeVertexBuffer()
{
vertexBuffer = std::make_unique(*instance, Vertex::GetDescriptor(), vertices.size());
vertexBuffer->Update(0, (void*)vertices.data());
- }
+
+ vertexBufferPassthrough = std::make_unique(*instance, VertexPassthrough::GetDescriptor(), verticesPassthrough.size());
+ vertexBufferPassthrough->Update(0, (void*)verticesPassthrough.data());
+ }
void InitializeIndexBuffer()
{
- VkDeviceSize bufferSize = sizeof(uint16_t) * indices.size();
indexBuffer = std::make_unique(*instance, indices.size());
indexBuffer->UpdateStaging((void*)indices.data());
- }
+
+ indexBufferPassthrough = std::make_unique(*instance, indicesPassthrough.size());
+ indexBufferPassthrough->UpdateStaging((void*)indicesPassthrough.data());
+ }
void InitializeCommandBuffer()
{
@@ -151,30 +190,32 @@ private:
clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
clearValues[1].depthStencil = {1.0f, 0};
- // TODO: framebuffer->Bind();
- VkRenderPassBeginInfo renderPassBeginInfo{};
- renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- renderPassBeginInfo.renderPass = instance->GetSwapChain().GetRenderPass();
- renderPassBeginInfo.framebuffer = instance->GetSwapChain().GetFramebuffer();
- renderPassBeginInfo.renderArea.offset = {0, 0};
- renderPassBeginInfo.renderArea.extent = instance->GetSwapChain().GetExtent();
- renderPassBeginInfo.clearValueCount = clearValues.size();
- renderPassBeginInfo.pClearValues = clearValues.data();
- vkCmdBeginRenderPass(commandBuffer->GetHandle(), &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
- graphicsPipeline->Bind(commandBuffer->GetHandle());
+
+ framebuffer->Bind(*commandBuffer);
+ graphicsPipeline->Bind(*commandBuffer);
UpdateUniformBuffer();
- vertexBuffer->Bind(commandBuffer->GetHandle());
- indexBuffer->Bind(commandBuffer->GetHandle());
+ vertexBuffer->Bind(*commandBuffer);
+ indexBuffer->Bind(*commandBuffer);
graphicsPipeline->SetDescriptorSet(0, *descriptorSet);
graphicsPipeline->BindDescriptorSets(commandBuffer->GetHandle());
- indexBuffer->Draw(commandBuffer->GetHandle());
+ indexBuffer->Draw(*commandBuffer);
+ framebuffer->Unbind(*commandBuffer);
- vkCmdEndRenderPass(commandBuffer->GetHandle());
+ instance->GetSwapChain().BeginFrameBuffer(*commandBuffer);
+
+ graphicsPipelinePassthrough->Bind(*commandBuffer);
+ graphicsPipelinePassthrough->SetDescriptorSet(0, *descriptorSetPassthrough);
+ graphicsPipelinePassthrough->BindDescriptorSets(commandBuffer->GetHandle());
+ vertexBufferPassthrough->Bind(*commandBuffer);
+ indexBufferPassthrough->Bind(*commandBuffer);
+ indexBufferPassthrough->Draw(*commandBuffer);
+
+ instance->GetSwapChain().EndFrameBuffer(*commandBuffer);
commandBuffer->End();
}
@@ -192,24 +233,15 @@ private:
shaderUniformBuffer->Update(shaderUniform);
}
-
- VkShaderModule InitializeShaderModule(const std::vector& code)
- {
- VkShaderModuleCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- createInfo.codeSize = code.size();
- createInfo.pCode = reinterpret_cast(code.data());
-
- VkShaderModule shaderModule;
- CP_VK_ASSERT(vkCreateShaderModule(instance->GetDevice(), &createInfo, nullptr, &shaderModule), "Failed to initialize shader module");
-
- return shaderModule;
- }
};
+void func(const int* ptr) {
+ *const_cast(ptr) = 20;
+}
+
int main()
{
- CP_ASSERT(glfwInit() == GLFW_TRUE, "Failed to initialize the glfw context");
+ CP_ASSERT(glfwInit() == GLFW_TRUE, "main : Failed to initialize the glfw context");
{
Application application;
Timer timer;