Add Offscreen Framebuffer support

This commit is contained in:
Thraix
2023-02-05 01:04:07 +01:00
parent 9de2ff594b
commit 708b81c571
25 changed files with 597 additions and 219 deletions
+1
View File
@@ -5,3 +5,4 @@ Release/
*/Release/
bin/
.ycm_extra_conf.py
.cache
+9 -4
View File
@@ -130,7 +130,8 @@
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>glslc res/shaders/shader.vert -o res/shaders/vert.spv &amp;&amp; glslc res/shaders/shader.frag -o res/shaders/frag.spv</Command>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -157,12 +158,14 @@
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>glslc res/shaders/shader.vert -o res/shaders/vert.spv &amp;&amp; glslc res/shaders/shader.frag -o res/shaders/frag.spv</Command>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\SwapChain.cpp" />
<ClCompile Include="src\Texture2D.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Buffer.h" />
@@ -172,6 +175,7 @@
<ClInclude Include="src\DescriptorSet.h" />
<ClInclude Include="src\DescriptorPool.h" />
<ClInclude Include="src\FileSystem.h" />
<ClInclude Include="src\Framebuffer.h" />
<ClInclude Include="src\Image.h" />
<ClInclude Include="src\IndexBuffer.h" />
<ClInclude Include="src\Pipeline.h" />
@@ -189,13 +193,14 @@
<ClInclude Include="src\VertexDescriptor.h" />
<ClInclude Include="src\VulkanException.h" />
<ClInclude Include="src\Window.h" />
<ClInclude Include="src\VertexPassthrough.h" />
</ItemGroup>
<ItemGroup>
<None Include="compile.bat" />
<None Include="res\shaders\frag.spv" />
<None Include="res\shaders\passthrough.frag" />
<None Include="res\shaders\passthrough.vert" />
<None Include="res\shaders\shader.frag" />
<None Include="res\shaders\shader.vert" />
<None Include="res\shaders\vert.spv" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
+11 -2
View File
@@ -21,6 +21,9 @@
<ClCompile Include="src\SwapChain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Texture2D.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\DebugMessenger.h">
@@ -95,6 +98,12 @@
<ClInclude Include="src\Image.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Framebuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\VertexPassthrough.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="res\shaders\shader.frag" />
@@ -102,7 +111,7 @@
<None Include="compile.bat">
<Filter>Source Files</Filter>
</None>
<None Include="res\shaders\frag.spv" />
<None Include="res\shaders\vert.spv" />
<None Include="res\shaders\passthrough.frag" />
<None Include="res\shaders\passthrough.vert" />
</ItemGroup>
</Project>
+11
View File
@@ -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);
}
+11
View File
@@ -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;
}
+1 -1
View File
@@ -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)
{
+6 -1
View File
@@ -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;
}
+6
View File
@@ -21,6 +21,12 @@
#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 \
{ \
+3 -3
View File
@@ -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;
+3
View File
@@ -2,6 +2,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <filesystem>
#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");
+174
View File
@@ -0,0 +1,174 @@
#pragma once
#include "Common.h"
#include "Image.h"
#include "Instance.h"
#include "Texture2D.h"
#include <vulkan/vulkan.hpp>
// TODO: Add resizing (recreate image, depthImage, framebuffers)
class Framebuffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(Framebuffer);
private:
Instance& instance;
std::unique_ptr<Texture2D> image;
std::unique_ptr<Texture2D> depthImage;
std::vector<VkFramebuffer> 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<VkClearValue> 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<Texture2D>(instance, width, height, Texture2D::Type::Dynamic, Texture2D::Format::Color);
}
void InitializeDepthBuffer()
{
depthImage = std::make_unique<Texture2D>(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<VkSubpassDependency> 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<VkAttachmentDescription> 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<VkImageView> 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");
}
}
};
+37 -6
View File
@@ -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, &region);
vkCmdCopyBufferToImage(commandBuffer, buffer.GetHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
}
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<VkFormat>& 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");
}
};
+2 -2
View File
@@ -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);
}
+3 -2
View File
@@ -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;
+4 -3
View File
@@ -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});
}
+1 -1
View File
@@ -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))
+27 -33
View File
@@ -1,8 +1,10 @@
#include "SwapChain.h"
#include "CommandBuffer.h"
#include "Image.h"
#include "Instance.h"
#include "QueueFamilies.h"
#include "Texture2D.h"
#include <glfw/glfw3.h>
#include <vulkan/vulkan.h>
@@ -50,6 +52,28 @@ SwapChain::~SwapChain()
vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr);
}
void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const
{
std::vector<VkClearValue> 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<Texture2D>(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<VkImageView> attachments{imageViews[i], depthImageView};
std::vector<VkImageView> 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<VkSurfac
return availableFormats[0];
}
VkFormat SwapChain::SelectDepthFormat()
{
return SelectSupportedFormat({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);
}
VkFormat SwapChain::SelectSupportedFormat(const std::vector<VkFormat>& 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<VkPresentModeKHR>& availablePresentModes)
{
return VK_PRESENT_MODE_FIFO_KHR;
+5 -7
View File
@@ -7,6 +7,8 @@
#include <GLFW/glfw3.h>
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<Texture2D> depthImage;
std::vector<VkImageView> imageViews;
std::vector<VkImage> images;
std::vector<VkFramebuffer> 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<VkSurfaceFormatKHR>& availableFormats);
VkFormat SelectDepthFormat();
VkFormat SelectSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
VkPresentModeKHR SelectSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
VkExtent2D SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities);
};
+150
View File
@@ -0,0 +1,150 @@
#include "Texture2D.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
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");
}
+25 -95
View File
@@ -6,110 +6,40 @@
#include "Image.h"
#include "Instance.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
// 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<VkImage> images;
std::vector<VkDeviceMemory> imageMemories;
std::vector<VkImageView> 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();
};
+1 -1
View File
@@ -22,7 +22,7 @@ public:
}
}
void Bind(VkCommandBuffer commandBuffer) override
void Bind(const CommandBuffer& commandBuffer) override
{
std::vector<VkBuffer> buffers{bindingOffsets.size(), handle};
vkCmdBindVertexBuffers(commandBuffer, 0, bindingOffsets.size(), buffers.data(), bindingOffsets.data());
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <glm/glm.hpp>
#include <vulkan/vulkan.hpp>
#include "VertexDescriptor.h"
struct VertexPassthrough {
glm::vec2 texCoord;
static VertexDescriptor GetDescriptor()
{
VertexDescriptor descriptor{};
descriptor.AddAttribute<VertexPassthrough>(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexPassthrough , texCoord));
return descriptor;
}
};
+64 -32
View File
@@ -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 <GLFW/glfw3.h>
#include <chrono>
@@ -35,6 +37,17 @@ const std::vector<uint16_t> indices = {
4, 5, 6, 6, 7, 4
};
const std::vector<VertexPassthrough> verticesPassthrough = {
VertexPassthrough{{-1.0f, -1.0f}},
VertexPassthrough{{ 1.0f, -1.0f}},
VertexPassthrough{{ 1.0f, 1.0f}},
VertexPassthrough{{-1.0f, 1.0f}},
};
const std::vector<uint16_t> 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> indexBuffer;
std::unique_ptr<CommandBuffer> commandBuffer;
std::unique_ptr<Framebuffer> framebuffer;
std::unique_ptr<Pipeline> graphicsPipelinePassthrough;
std::unique_ptr<VertexBuffer> vertexBufferPassthrough;
std::unique_ptr<IndexBuffer> indexBufferPassthrough;
std::unique_ptr<DescriptorSet> descriptorSetPassthrough;
public:
Application()
{
InitializeInstance();
InitializeFrameBuffer();
InitializeGraphicsPipeline();
InitializeTextureSampler();
InitializeUniformBuffer();
@@ -94,7 +114,12 @@ private:
void InitializeInstance()
{
instance = std::make_unique<Instance>("Vulkan Tutorial");
instance = std::make_unique<Instance>("Copium Engine");
}
void InitializeFrameBuffer()
{
framebuffer = std::make_unique<Framebuffer>(*instance, instance->GetSwapChain().GetExtent().width, instance->GetSwapChain().GetExtent().height);
}
void InitializeTextureSampler()
@@ -114,29 +139,43 @@ private:
descriptorSet = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
descriptorSet->AddUniform(*shaderUniformBuffer, 0);
descriptorSet->AddTexture2D(*texture2D, 1);
descriptorSetPassthrough = std::make_unique<DescriptorSet>(*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<Pipeline>(*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<Pipeline>(*instance, creatorPassthrough);
}
void InitializeVertexBuffer()
{
vertexBuffer = std::make_unique<VertexBuffer>(*instance, Vertex::GetDescriptor(), vertices.size());
vertexBuffer->Update(0, (void*)vertices.data());
vertexBufferPassthrough = std::make_unique<VertexBuffer>(*instance, VertexPassthrough::GetDescriptor(), verticesPassthrough.size());
vertexBufferPassthrough->Update(0, (void*)verticesPassthrough.data());
}
void InitializeIndexBuffer()
{
VkDeviceSize bufferSize = sizeof(uint16_t) * indices.size();
indexBuffer = std::make_unique<IndexBuffer>(*instance, indices.size());
indexBuffer->UpdateStaging((void*)indices.data());
indexBufferPassthrough = std::make_unique<IndexBuffer>(*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<char>& code)
{
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = code.size();
createInfo.pCode = reinterpret_cast<const uint32_t*>(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<int*>(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;