add msaa
This commit is contained in:
parent
fd9c1c89e6
commit
2f16c0b5e4
|
|
@ -53,6 +53,10 @@ VulkanRenderer::VulkanRenderer()
|
||||||
, m_fontTextureMemory(VK_NULL_HANDLE)
|
, m_fontTextureMemory(VK_NULL_HANDLE)
|
||||||
, m_fontTextureView(VK_NULL_HANDLE)
|
, m_fontTextureView(VK_NULL_HANDLE)
|
||||||
, m_fontSampler(VK_NULL_HANDLE)
|
, m_fontSampler(VK_NULL_HANDLE)
|
||||||
|
, m_msaaImage(VK_NULL_HANDLE)
|
||||||
|
, m_msaaImageMemory(VK_NULL_HANDLE)
|
||||||
|
, m_msaaImageView(VK_NULL_HANDLE)
|
||||||
|
, m_msaaSamples(VK_SAMPLE_COUNT_1_BIT)
|
||||||
, m_width(0)
|
, m_width(0)
|
||||||
, m_height(0)
|
, m_height(0)
|
||||||
, m_swapchainFormat(0)
|
, m_swapchainFormat(0)
|
||||||
|
|
@ -80,6 +84,18 @@ bool VulkanRenderer::initialize(VkDevice device, VkPhysicalDevice physicalDevice
|
||||||
m_height = height;
|
m_height = height;
|
||||||
m_transferCommandPool = VK_NULL_HANDLE;
|
m_transferCommandPool = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
// Determine best MSAA sample count
|
||||||
|
m_msaaSamples = getMaxUsableSampleCount();
|
||||||
|
std::cout << "Using MSAA with " << m_msaaSamples << " samples" << std::endl;
|
||||||
|
|
||||||
|
// Create MSAA resources if MSAA is enabled
|
||||||
|
if (m_msaaSamples > VK_SAMPLE_COUNT_1_BIT) {
|
||||||
|
if (!createMSAAResources()) {
|
||||||
|
logError("Failed to create MSAA resources, falling back to no MSAA");
|
||||||
|
m_msaaSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!createRenderPass()) {
|
if (!createRenderPass()) {
|
||||||
logError("Failed to create render pass");
|
logError("Failed to create render pass");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -201,8 +217,131 @@ bool VulkanRenderer::initialize(VkDevice device, VkPhysicalDevice physicalDevice
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t VulkanRenderer::getMaxUsableSampleCount()
|
||||||
|
{
|
||||||
|
VkPhysicalDeviceProperties physicalDeviceProperties;
|
||||||
|
vkGetPhysicalDeviceProperties(m_physicalDevice, &physicalDeviceProperties);
|
||||||
|
|
||||||
|
VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts &
|
||||||
|
physicalDeviceProperties.limits.framebufferDepthSampleCounts;
|
||||||
|
|
||||||
|
// Try to use 4x MSAA as a good balance between quality and performance
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanRenderer::createMSAAResources()
|
||||||
|
{
|
||||||
|
std::cout << "Creating MSAA resources: " << m_width << "x" << m_height
|
||||||
|
<< " with " << m_msaaSamples << " samples" << std::endl;
|
||||||
|
|
||||||
|
VkImageCreateInfo imageInfo = {};
|
||||||
|
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
|
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||||
|
imageInfo.extent.width = m_width;
|
||||||
|
imageInfo.extent.height = m_height;
|
||||||
|
imageInfo.extent.depth = 1;
|
||||||
|
imageInfo.mipLevels = 1;
|
||||||
|
imageInfo.arrayLayers = 1;
|
||||||
|
imageInfo.format = static_cast<VkFormat>(m_swapchainFormat);
|
||||||
|
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
imageInfo.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
imageInfo.samples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||||
|
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
|
VkResult result = vkCreateImage(m_device, &imageInfo, nullptr, &m_msaaImage);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
std::cout << "Failed to create MSAA image, error: " << result << std::endl;
|
||||||
|
logError("Failed to create MSAA image");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::cout << "MSAA image created successfully" << std::endl;
|
||||||
|
|
||||||
|
VkMemoryRequirements memRequirements;
|
||||||
|
vkGetImageMemoryRequirements(m_device, m_msaaImage, &memRequirements);
|
||||||
|
std::cout << "MSAA memory requirements: size=" << memRequirements.size
|
||||||
|
<< " alignment=" << memRequirements.alignment << std::endl;
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo allocInfo = {};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
allocInfo.allocationSize = memRequirements.size;
|
||||||
|
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
result = vkAllocateMemory(m_device, &allocInfo, nullptr, &m_msaaImageMemory);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
std::cout << "Failed to allocate MSAA image memory, error: " << result << std::endl;
|
||||||
|
logError("Failed to allocate MSAA image memory");
|
||||||
|
vkDestroyImage(m_device, m_msaaImage, nullptr);
|
||||||
|
m_msaaImage = VK_NULL_HANDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::cout << "MSAA memory allocated successfully" << std::endl;
|
||||||
|
|
||||||
|
result = vkBindImageMemory(m_device, m_msaaImage, m_msaaImageMemory, 0);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
std::cout << "Failed to bind MSAA image memory, error: " << result << std::endl;
|
||||||
|
logError("Failed to bind MSAA image memory");
|
||||||
|
vkFreeMemory(m_device, m_msaaImageMemory, nullptr);
|
||||||
|
vkDestroyImage(m_device, m_msaaImage, nullptr);
|
||||||
|
m_msaaImage = VK_NULL_HANDLE;
|
||||||
|
m_msaaImageMemory = VK_NULL_HANDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::cout << "MSAA memory bound successfully" << std::endl;
|
||||||
|
|
||||||
|
// Create image view
|
||||||
|
VkImageViewCreateInfo viewInfo = {};
|
||||||
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
viewInfo.image = m_msaaImage;
|
||||||
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
viewInfo.format = static_cast<VkFormat>(m_swapchainFormat);
|
||||||
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||||
|
viewInfo.subresourceRange.levelCount = 1;
|
||||||
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
result = vkCreateImageView(m_device, &viewInfo, nullptr, &m_msaaImageView);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
std::cout << "Failed to create MSAA image view, error: " << result << std::endl;
|
||||||
|
logError("Failed to create MSAA image view");
|
||||||
|
vkFreeMemory(m_device, m_msaaImageMemory, nullptr);
|
||||||
|
vkDestroyImage(m_device, m_msaaImage, nullptr);
|
||||||
|
m_msaaImage = VK_NULL_HANDLE;
|
||||||
|
m_msaaImageMemory = VK_NULL_HANDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::cout << "MSAA image view created successfully" << std::endl;
|
||||||
|
std::cout << "MSAA resources created: image=" << m_msaaImage
|
||||||
|
<< " view=" << m_msaaImageView << std::endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderer::cleanupMSAAResources()
|
||||||
|
{
|
||||||
|
if (m_msaaImageView != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyImageView(m_device, m_msaaImageView, nullptr);
|
||||||
|
m_msaaImageView = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (m_msaaImage != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyImage(m_device, m_msaaImage, nullptr);
|
||||||
|
m_msaaImage = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (m_msaaImageMemory != VK_NULL_HANDLE) {
|
||||||
|
vkFreeMemory(m_device, m_msaaImageMemory, nullptr);
|
||||||
|
m_msaaImageMemory = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanRenderer::cleanup()
|
void VulkanRenderer::cleanup()
|
||||||
{
|
{
|
||||||
|
cleanupMSAAResources();
|
||||||
if (!m_device) return;
|
if (!m_device) return;
|
||||||
|
|
||||||
// Clean up buffers
|
// Clean up buffers
|
||||||
|
|
@ -295,6 +434,15 @@ bool VulkanRenderer::resize(uint32_t width, uint32_t height)
|
||||||
}
|
}
|
||||||
m_framebuffers.clear();
|
m_framebuffers.clear();
|
||||||
|
|
||||||
|
// Recreate MSAA resources if MSAA is enabled
|
||||||
|
if (m_msaaSamples > VK_SAMPLE_COUNT_1_BIT) {
|
||||||
|
cleanupMSAAResources();
|
||||||
|
if (!createMSAAResources()) {
|
||||||
|
logError("Failed to recreate MSAA resources during resize");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return createFramebuffers();
|
return createFramebuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,52 +544,64 @@ void VulkanRenderer::recordCommandBuffer(VkCommandBuffer commandBuffer,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create or get framebuffer for this image view
|
|
||||||
if (m_framebuffers.empty() || imageIndex >= m_framebuffers.size()) {
|
|
||||||
// We need to create framebuffers on-the-fly
|
|
||||||
m_imageViews.clear();
|
|
||||||
m_imageViews.push_back(imageView);
|
|
||||||
createFramebuffers();
|
|
||||||
} else if (imageIndex < m_imageViews.size() && m_imageViews[imageIndex] != imageView) {
|
|
||||||
// Update image view if changed
|
|
||||||
if (m_framebuffers[imageIndex]) {
|
|
||||||
vkDestroyFramebuffer(m_device, m_framebuffers[imageIndex], nullptr);
|
|
||||||
}
|
|
||||||
m_imageViews[imageIndex] = imageView;
|
|
||||||
|
|
||||||
VkFramebufferCreateInfo fbInfo = {};
|
|
||||||
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
||||||
fbInfo.renderPass = m_renderPass;
|
|
||||||
fbInfo.attachmentCount = 1;
|
|
||||||
fbInfo.pAttachments = &imageView;
|
|
||||||
fbInfo.width = m_width;
|
|
||||||
fbInfo.height = m_height;
|
|
||||||
fbInfo.layers = 1;
|
|
||||||
vkCreateFramebuffer(m_device, &fbInfo, nullptr, &m_framebuffers[imageIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we have enough image views
|
// Make sure we have enough image views
|
||||||
while (m_imageViews.size() <= imageIndex) {
|
while (m_imageViews.size() <= imageIndex) {
|
||||||
m_imageViews.push_back(VK_NULL_HANDLE);
|
m_imageViews.push_back(VK_NULL_HANDLE);
|
||||||
}
|
}
|
||||||
m_imageViews[imageIndex] = imageView;
|
|
||||||
|
|
||||||
// Make sure we have enough framebuffers
|
// Make sure we have enough framebuffers
|
||||||
while (m_framebuffers.size() <= imageIndex) {
|
while (m_framebuffers.size() <= imageIndex) {
|
||||||
m_framebuffers.push_back(VK_NULL_HANDLE);
|
m_framebuffers.push_back(VK_NULL_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create framebuffer if needed
|
// Check if we need to create or recreate framebuffer
|
||||||
|
bool needsRecreate = false;
|
||||||
if (m_framebuffers[imageIndex] == VK_NULL_HANDLE) {
|
if (m_framebuffers[imageIndex] == VK_NULL_HANDLE) {
|
||||||
|
needsRecreate = true;
|
||||||
|
} else if (m_imageViews[imageIndex] != imageView) {
|
||||||
|
// Image view changed - destroy old framebuffer
|
||||||
|
vkDestroyFramebuffer(m_device, m_framebuffers[imageIndex], nullptr);
|
||||||
|
m_framebuffers[imageIndex] = VK_NULL_HANDLE;
|
||||||
|
needsRecreate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update image view
|
||||||
|
m_imageViews[imageIndex] = imageView;
|
||||||
|
|
||||||
|
// Create framebuffer if needed
|
||||||
|
if (needsRecreate) {
|
||||||
VkFramebufferCreateInfo fbInfo = {};
|
VkFramebufferCreateInfo fbInfo = {};
|
||||||
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
fbInfo.renderPass = m_renderPass;
|
fbInfo.renderPass = m_renderPass;
|
||||||
fbInfo.attachmentCount = 1;
|
|
||||||
fbInfo.pAttachments = &imageView;
|
|
||||||
fbInfo.width = m_width;
|
fbInfo.width = m_width;
|
||||||
fbInfo.height = m_height;
|
fbInfo.height = m_height;
|
||||||
fbInfo.layers = 1;
|
fbInfo.layers = 1;
|
||||||
vkCreateFramebuffer(m_device, &fbInfo, nullptr, &m_framebuffers[imageIndex]);
|
|
||||||
|
if (m_msaaSamples > VK_SAMPLE_COUNT_1_BIT) {
|
||||||
|
// MSAA enabled: attach MSAA image and resolve image
|
||||||
|
VkImageView attachments[2] = {
|
||||||
|
m_msaaImageView,
|
||||||
|
imageView
|
||||||
|
};
|
||||||
|
fbInfo.attachmentCount = 2;
|
||||||
|
fbInfo.pAttachments = attachments;
|
||||||
|
|
||||||
|
static int fbCreateCount = 0;
|
||||||
|
std::cout << "Creating framebuffer " << imageIndex << " (#" << fbCreateCount++
|
||||||
|
<< ") with MSAA (msaa_view=" << m_msaaImageView
|
||||||
|
<< ", resolve=" << imageView << ")" << std::endl;
|
||||||
|
} else {
|
||||||
|
// No MSAA: single attachment
|
||||||
|
fbInfo.attachmentCount = 1;
|
||||||
|
fbInfo.pAttachments = &imageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult result = vkCreateFramebuffer(m_device, &fbInfo, nullptr, &m_framebuffers[imageIndex]);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
std::cout << "ERROR: Failed to create framebuffer " << imageIndex
|
||||||
|
<< ", error code: " << result << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin render pass
|
// Begin render pass
|
||||||
|
|
@ -507,6 +667,67 @@ VkFramebuffer VulkanRenderer::getFramebuffer(uint32_t index) const
|
||||||
|
|
||||||
bool VulkanRenderer::createRenderPass()
|
bool VulkanRenderer::createRenderPass()
|
||||||
{
|
{
|
||||||
|
std::vector<VkAttachmentDescription> attachments;
|
||||||
|
|
||||||
|
if (m_msaaSamples > VK_SAMPLE_COUNT_1_BIT) {
|
||||||
|
// MSAA color attachment
|
||||||
|
VkAttachmentDescription colorAttachment = {};
|
||||||
|
colorAttachment.format = static_cast<VkFormat>(m_swapchainFormat);
|
||||||
|
colorAttachment.samples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||||
|
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_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
attachments.push_back(colorAttachment);
|
||||||
|
|
||||||
|
// Resolve attachment (for presenting)
|
||||||
|
VkAttachmentDescription resolveAttachment = {};
|
||||||
|
resolveAttachment.format = static_cast<VkFormat>(m_swapchainFormat);
|
||||||
|
resolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
resolveAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
resolveAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
resolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
resolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
resolveAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
resolveAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
attachments.push_back(resolveAttachment);
|
||||||
|
|
||||||
|
VkAttachmentReference colorAttachmentRef = {};
|
||||||
|
colorAttachmentRef.attachment = 0;
|
||||||
|
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
VkAttachmentReference resolveAttachmentRef = {};
|
||||||
|
resolveAttachmentRef.attachment = 1;
|
||||||
|
resolveAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
VkSubpassDescription subpass = {};
|
||||||
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
|
subpass.colorAttachmentCount = 1;
|
||||||
|
subpass.pColorAttachments = &colorAttachmentRef;
|
||||||
|
subpass.pResolveAttachments = &resolveAttachmentRef;
|
||||||
|
|
||||||
|
VkSubpassDependency dependency = {};
|
||||||
|
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
|
dependency.dstSubpass = 0;
|
||||||
|
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.srcAccessMask = 0;
|
||||||
|
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
|
||||||
|
VkRenderPassCreateInfo renderPassInfo = {};
|
||||||
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
|
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||||
|
renderPassInfo.pAttachments = attachments.data();
|
||||||
|
renderPassInfo.subpassCount = 1;
|
||||||
|
renderPassInfo.pSubpasses = &subpass;
|
||||||
|
renderPassInfo.dependencyCount = 1;
|
||||||
|
renderPassInfo.pDependencies = &dependency;
|
||||||
|
|
||||||
|
return vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &m_renderPass) == VK_SUCCESS;
|
||||||
|
} else {
|
||||||
|
// No MSAA - single color attachment
|
||||||
VkAttachmentDescription colorAttachment = {};
|
VkAttachmentDescription colorAttachment = {};
|
||||||
colorAttachment.format = static_cast<VkFormat>(m_swapchainFormat);
|
colorAttachment.format = static_cast<VkFormat>(m_swapchainFormat);
|
||||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
@ -545,6 +766,7 @@ bool VulkanRenderer::createRenderPass()
|
||||||
|
|
||||||
return vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &m_renderPass) == VK_SUCCESS;
|
return vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &m_renderPass) == VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool VulkanRenderer::createFramebuffers()
|
bool VulkanRenderer::createFramebuffers()
|
||||||
{
|
{
|
||||||
|
|
@ -554,13 +776,33 @@ bool VulkanRenderer::createFramebuffers()
|
||||||
VkFramebufferCreateInfo framebufferInfo = {};
|
VkFramebufferCreateInfo framebufferInfo = {};
|
||||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
framebufferInfo.renderPass = m_renderPass;
|
framebufferInfo.renderPass = m_renderPass;
|
||||||
framebufferInfo.attachmentCount = 1;
|
|
||||||
framebufferInfo.pAttachments = &m_imageViews[i];
|
|
||||||
framebufferInfo.width = m_width;
|
framebufferInfo.width = m_width;
|
||||||
framebufferInfo.height = m_height;
|
framebufferInfo.height = m_height;
|
||||||
framebufferInfo.layers = 1;
|
framebufferInfo.layers = 1;
|
||||||
|
|
||||||
if (vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &m_framebuffers[i]) != VK_SUCCESS) {
|
if (m_msaaSamples > VK_SAMPLE_COUNT_1_BIT) {
|
||||||
|
// MSAA enabled: attach MSAA image and resolve image
|
||||||
|
if (m_msaaImageView == VK_NULL_HANDLE) {
|
||||||
|
std::cout << "ERROR: MSAA image view is null when creating framebuffer " << i << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
VkImageView attachments[2] = {
|
||||||
|
m_msaaImageView,
|
||||||
|
m_imageViews[i]
|
||||||
|
};
|
||||||
|
framebufferInfo.attachmentCount = 2;
|
||||||
|
framebufferInfo.pAttachments = attachments;
|
||||||
|
std::cout << "Creating framebuffer " << i << " with MSAA (view=" << m_msaaImageView
|
||||||
|
<< ", resolve=" << m_imageViews[i] << ")" << std::endl;
|
||||||
|
} else {
|
||||||
|
// No MSAA: single attachment
|
||||||
|
framebufferInfo.attachmentCount = 1;
|
||||||
|
framebufferInfo.pAttachments = &m_imageViews[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult result = vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &m_framebuffers[i]);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
std::cout << "Failed to create framebuffer " << i << ", error: " << result << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -694,7 +936,7 @@ bool VulkanRenderer::createBackgroundPipeline()
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
multisampling.sampleShadingEnable = VK_FALSE;
|
multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||||
|
|
||||||
// Color blending
|
// Color blending
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||||
|
|
@ -860,7 +1102,7 @@ bool VulkanRenderer::createGeometryPipeline()
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
multisampling.sampleShadingEnable = VK_FALSE;
|
multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||||
|
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||||
|
|
@ -1021,7 +1263,7 @@ bool VulkanRenderer::createLinePipeline()
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
multisampling.sampleShadingEnable = VK_FALSE;
|
multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||||
|
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||||
|
|
@ -1200,7 +1442,7 @@ bool VulkanRenderer::createTextPipeline()
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
multisampling.sampleShadingEnable = VK_FALSE;
|
multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||||
|
|
||||||
// Enable alpha blending for text
|
// Enable alpha blending for text
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||||
|
|
@ -2382,7 +2624,7 @@ void VulkanRenderer::drawText(VkCommandBuffer commandBuffer, int frameCount,
|
||||||
// Lock info (if available)
|
// Lock info (if available)
|
||||||
if (!lockInfo.empty()) {
|
if (!lockInfo.empty()) {
|
||||||
std::string lockTitle = "Last Lock Info:";
|
std::string lockTitle = "Last Lock Info:";
|
||||||
generateTextQuads(lockTitle, 20.0f * scaleX, 210.0f * scaleY, 0.3f, magenta, vertices, indices);
|
generateTextQuads(lockTitle, 20.0f * scaleX, 220.0f * scaleY, 0.4f, magenta, vertices, indices);
|
||||||
|
|
||||||
// Parse lock info (assuming format from lockInfo string)
|
// Parse lock info (assuming format from lockInfo string)
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
|
@ -2391,13 +2633,13 @@ void VulkanRenderer::drawText(VkCommandBuffer commandBuffer, int frameCount,
|
||||||
while ((pos = info.find('\n')) != std::string::npos) {
|
while ((pos = info.find('\n')) != std::string::npos) {
|
||||||
std::string token = info.substr(0, pos);
|
std::string token = info.substr(0, pos);
|
||||||
if (!token.empty()) {
|
if (!token.empty()) {
|
||||||
generateTextQuads(token, 20.0f * scaleX, (230.0f + line * 20.0f) * scaleY, 0.2f, magenta, vertices, indices);
|
generateTextQuads(token, 20.0f * scaleX, (240.0f + line * 20.0f) * scaleY, 0.3f, magenta, vertices, indices);
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
info.erase(0, pos + 1);
|
info.erase(0, pos + 1);
|
||||||
}
|
}
|
||||||
if (!info.empty()) {
|
if (!info.empty()) {
|
||||||
generateTextQuads(info, 20.0f * scaleX, (230.0f + line * 20.0f) * scaleY, 0.2f, magenta, vertices, indices);
|
generateTextQuads(info, 20.0f * scaleX, (240.0f + line * 20.0f) * scaleY, 0.3f, magenta, vertices, indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,21 @@ private:
|
||||||
*/
|
*/
|
||||||
uint32_t findMemoryType(uint32_t typeFilter, uint32_t properties);
|
uint32_t findMemoryType(uint32_t typeFilter, uint32_t properties);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取最大可用的采样数
|
||||||
|
*/
|
||||||
|
uint32_t getMaxUsableSampleCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建多重采样图像资源
|
||||||
|
*/
|
||||||
|
bool createMSAAResources();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清理多重采样资源
|
||||||
|
*/
|
||||||
|
void cleanupMSAAResources();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化文本渲染系统
|
* @brief 初始化文本渲染系统
|
||||||
*/
|
*/
|
||||||
|
|
@ -354,6 +369,12 @@ private:
|
||||||
VkSampler m_fontSampler;
|
VkSampler m_fontSampler;
|
||||||
std::map<char, CharInfo> m_charInfoMap;
|
std::map<char, CharInfo> m_charInfoMap;
|
||||||
|
|
||||||
|
// MSAA 资源
|
||||||
|
VkImage m_msaaImage;
|
||||||
|
VkDeviceMemory m_msaaImageMemory;
|
||||||
|
VkImageView m_msaaImageView;
|
||||||
|
uint32_t m_msaaSamples; // VkSampleCountFlagBits
|
||||||
|
|
||||||
// 渲染目标尺寸
|
// 渲染目标尺寸
|
||||||
uint32_t m_width;
|
uint32_t m_width;
|
||||||
uint32_t m_height;
|
uint32_t m_height;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue