Skip to content

Commit

Permalink
adds msaa
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerboa-app committed Sep 7, 2023
1 parent ba54c37 commit e52b575
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 34 deletions.
106 changes: 106 additions & 0 deletions include/Renderer/vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ namespace Renderer
std::vector<VkSemaphore> imageAvailableSemaphores, renderFinsihedSemaphores;
std::vector<VkFence> framesFinished;

VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
VkImage colourImage;
VkDeviceMemory colourImageMemory;
VkImageView colourImageView;

unsigned currentFrame = 0;

VkSwapchainKHR swapChain;
Expand All @@ -206,6 +211,7 @@ namespace Renderer

void createSurface(GLFWwindow * window);

VkSampleCountFlagBits getMaxUsableSampleCount();
void pickPhysicalDevice();
bool isSuitableDevice(VkPhysicalDevice physicalDevice);
void createLogicalDevice();
Expand Down Expand Up @@ -327,6 +333,106 @@ namespace Renderer
);

void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);

void createColorResources()
{
VkFormat colorFormat = swapChainImageFormat;

createImage
(
swapChainExtent.width,
swapChainExtent.height,
1,
msaaSamples,
colorFormat,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
colourImage,
colourImageMemory
);

colourImageView = createImageView(colourImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}

void createImage
(
uint32_t width,
uint32_t height,
uint32_t mipLevels,
VkSampleCountFlagBits numSamples,
VkFormat format,
VkImageTiling tiling,
VkImageUsageFlags usage,
VkMemoryPropertyFlags properties,
VkImage & image,
VkDeviceMemory & imageMemory
)
{
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = mipLevels;
imageInfo.arrayLayers = 1;
imageInfo.format = format;
imageInfo.tiling = tiling;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = usage;
imageInfo.samples = numSamples;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS)
{
throw std::runtime_error("failed to create image");
}

VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(device, image, &memRequirements);

VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);

if (vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS)
{
throw std::runtime_error("failed to allocate image memory");
}

vkBindImageMemory(device, image, imageMemory, 0);
}

VkImageView createImageView
(
VkImage image,
VkFormat format,
VkImageAspectFlags aspectFlags,
uint32_t mipLevels
)
{
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = format;
viewInfo.subresourceRange.aspectMask = aspectFlags;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = mipLevels;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;

VkImageView imageView;
if (vkCreateImageView(device, &viewInfo, nullptr, &imageView) != VK_SUCCESS)
{
throw std::runtime_error("failed to create texture image view");
}

return imageView;
}

};

}
Expand Down
116 changes: 82 additions & 34 deletions src/Renderer/vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ namespace Renderer

createGraphicsPipeline();

createColorResources();

createFramebuffers();

createCommandPool();
Expand All @@ -96,6 +98,11 @@ namespace Renderer

VulkanRenderer::~VulkanRenderer()
{

vkDestroyImageView(device, colourImageView, nullptr);
vkDestroyImage(device, colourImage, nullptr);
vkFreeMemory(device, colourImageMemory, nullptr);

cleanupSwapChain();

for (size_t i = 0; i < MAX_CONCURRENT_FRAMES; i++)
Expand Down Expand Up @@ -149,6 +156,23 @@ namespace Renderer
}
}

VkSampleCountFlagBits VulkanRenderer::getMaxUsableSampleCount()
{
VkPhysicalDeviceProperties physicalDeviceProperties;

vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);

VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts;

if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }

return VK_SAMPLE_COUNT_1_BIT;
}

void VulkanRenderer::pickPhysicalDevice()
{
Expand All @@ -175,6 +199,8 @@ namespace Renderer
if (isSuitableDevice(physicalDevice))
{
this->physicalDevice = physicalDevice;
msaaSamples = getMaxUsableSampleCount();
std::cout << "Device supports " << msaaSamples << " msaa samples\n";
break;
}
}
Expand Down Expand Up @@ -462,6 +488,7 @@ namespace Renderer

createSwapChain();
createImageViews();
createColorResources();
createFramebuffers();
}

Expand Down Expand Up @@ -626,7 +653,7 @@ namespace Renderer
{
VkAttachmentDescription colourAttachment{};
colourAttachment.format = swapChainImageFormat;
colourAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colourAttachment.samples = msaaSamples;
// do before rendering; clear
colourAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
// do after rendering, store
Expand All @@ -637,20 +664,39 @@ namespace Renderer
// we clear image so don't need to worry about intial layout
colourAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
// image is auto converted to presentation layout
colourAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

// one subpass
// since msaa is enabled optimal is needed as they
// cannot be presented as is
colourAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

// e.g. layout(location = 0) out vec4 outColour
VkAttachmentReference colourAttachmentRef{};
colourAttachmentRef.attachment = 0;
colourAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

// resolve attachment for msaa
VkAttachmentDescription colourAttachmentResolve{};
colourAttachmentResolve.format = swapChainImageFormat;
colourAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT;
colourAttachmentResolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colourAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colourAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colourAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colourAttachmentResolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colourAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

// resolve ref
VkAttachmentReference colourResolveAttachmentRef{};
colourResolveAttachmentRef.attachment = 1;
colourResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

// one subpass

VkSubpassDescription subpass{};
// specify as a graphics subpass
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colourAttachmentRef;
subpass.pResolveAttachments = &colourResolveAttachmentRef;

VkSubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
Expand All @@ -661,10 +707,12 @@ namespace Renderer
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

std::array<VkAttachmentDescription, 2> attachments = {colourAttachment, colourAttachmentResolve};

VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colourAttachment;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;

Expand Down Expand Up @@ -746,9 +794,9 @@ namespace Renderer

VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampling.sampleShadingEnable = VK_TRUE;
multisampling.minSampleShading = 1.0f;
multisampling.rasterizationSamples = msaaSamples;
multisampling.pSampleMask = nullptr;
multisampling.alphaToCoverageEnable = VK_FALSE;
multisampling.alphaToOneEnable = VK_FALSE;
Expand Down Expand Up @@ -823,13 +871,13 @@ namespace Renderer

for (size_t i = 0; i < swapChainImageViews.size(); i++)
{
VkImageView attchaments[] = {swapChainImageViews[i]};
std::array<VkImageView,2> attachments = {colourImageView, swapChainImageViews[i]};

VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = renderPass;
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = attchaments;
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
framebufferInfo.pAttachments = attachments.data();
framebufferInfo.width = swapChainExtent.width;
framebufferInfo.height = swapChainExtent.height;
framebufferInfo.layers = 1;
Expand Down Expand Up @@ -1075,33 +1123,33 @@ namespace Renderer

vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

// dynamics viewport and scissor
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
// dynamics viewport and scissor
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);

// bind vertex buffers
VkBuffer vertexBuffers[] = {vertexBuffer};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
// bind vertex buffers
VkBuffer vertexBuffers[] = {vertexBuffer};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);

// use descriptor stes
vkCmdBindDescriptorSets
(
commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout,
0,
1,
&descriptorSets[currentFrame],
0,
nullptr
);
// use descriptor stes
vkCmdBindDescriptorSets
(
commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout,
0,
1,
&descriptorSets[currentFrame],
0,
nullptr
);

// the draw command is issues
// vertexCount, instanceCount, firstVertex, firstInstance
vkCmdDraw(commandBuffer, vertices.size(), 1, 0, 0);
// the draw command is issues
// vertexCount, instanceCount, firstVertex, firstInstance
vkCmdDraw(commandBuffer, vertices.size(), 1, 0, 0);

// end
vkCmdEndRenderPass(commandBuffer);
Expand Down

0 comments on commit e52b575

Please sign in to comment.