add msaa
This commit is contained in:
parent
fd9c1c89e6
commit
2f16c0b5e4
|
|
@ -53,6 +53,10 @@ VulkanRenderer::VulkanRenderer()
|
|||
, m_fontTextureMemory(VK_NULL_HANDLE)
|
||||
, m_fontTextureView(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_height(0)
|
||||
, m_swapchainFormat(0)
|
||||
|
|
@ -80,6 +84,18 @@ bool VulkanRenderer::initialize(VkDevice device, VkPhysicalDevice physicalDevice
|
|||
m_height = height;
|
||||
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()) {
|
||||
logError("Failed to create render pass");
|
||||
return false;
|
||||
|
|
@ -201,8 +217,131 @@ bool VulkanRenderer::initialize(VkDevice device, VkPhysicalDevice physicalDevice
|
|||
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()
|
||||
{
|
||||
cleanupMSAAResources();
|
||||
if (!m_device) return;
|
||||
|
||||
// Clean up buffers
|
||||
|
|
@ -295,6 +434,15 @@ bool VulkanRenderer::resize(uint32_t width, uint32_t height)
|
|||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
@ -396,52 +544,64 @@ void VulkanRenderer::recordCommandBuffer(VkCommandBuffer commandBuffer,
|
|||
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
|
||||
while (m_imageViews.size() <= imageIndex) {
|
||||
m_imageViews.push_back(VK_NULL_HANDLE);
|
||||
}
|
||||
m_imageViews[imageIndex] = imageView;
|
||||
|
||||
// Make sure we have enough framebuffers
|
||||
while (m_framebuffers.size() <= imageIndex) {
|
||||
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) {
|
||||
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 = {};
|
||||
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]);
|
||||
|
||||
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
|
||||
|
|
@ -507,6 +667,67 @@ VkFramebuffer VulkanRenderer::getFramebuffer(uint32_t index) const
|
|||
|
||||
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 = {};
|
||||
colorAttachment.format = static_cast<VkFormat>(m_swapchainFormat);
|
||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
|
@ -544,6 +765,7 @@ bool VulkanRenderer::createRenderPass()
|
|||
renderPassInfo.pDependencies = &dependency;
|
||||
|
||||
return vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &m_renderPass) == VK_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanRenderer::createFramebuffers()
|
||||
|
|
@ -554,13 +776,33 @@ bool VulkanRenderer::createFramebuffers()
|
|||
VkFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.renderPass = m_renderPass;
|
||||
framebufferInfo.attachmentCount = 1;
|
||||
framebufferInfo.pAttachments = &m_imageViews[i];
|
||||
framebufferInfo.width = m_width;
|
||||
framebufferInfo.height = m_height;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -694,7 +936,7 @@ bool VulkanRenderer::createBackgroundPipeline()
|
|||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampling.sampleShadingEnable = VK_FALSE;
|
||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||
|
||||
// Color blending
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||
|
|
@ -860,7 +1102,7 @@ bool VulkanRenderer::createGeometryPipeline()
|
|||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampling.sampleShadingEnable = VK_FALSE;
|
||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||
|
||||
// Enable alpha blending
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||
|
|
@ -1021,7 +1263,7 @@ bool VulkanRenderer::createLinePipeline()
|
|||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampling.sampleShadingEnable = VK_FALSE;
|
||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||
|
||||
// Enable alpha blending
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||
|
|
@ -1200,7 +1442,7 @@ bool VulkanRenderer::createTextPipeline()
|
|||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampling.sampleShadingEnable = VK_FALSE;
|
||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
multisampling.rasterizationSamples = static_cast<VkSampleCountFlagBits>(m_msaaSamples);
|
||||
|
||||
// Enable alpha blending for text
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
|
||||
|
|
@ -2382,7 +2624,7 @@ void VulkanRenderer::drawText(VkCommandBuffer commandBuffer, int frameCount,
|
|||
// Lock info (if available)
|
||||
if (!lockInfo.empty()) {
|
||||
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)
|
||||
size_t pos = 0;
|
||||
|
|
@ -2391,13 +2633,13 @@ void VulkanRenderer::drawText(VkCommandBuffer commandBuffer, int frameCount,
|
|||
while ((pos = info.find('\n')) != std::string::npos) {
|
||||
std::string token = info.substr(0, pos);
|
||||
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++;
|
||||
}
|
||||
info.erase(0, pos + 1);
|
||||
}
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief 获取最大可用的采样数
|
||||
*/
|
||||
uint32_t getMaxUsableSampleCount();
|
||||
|
||||
/**
|
||||
* @brief 创建多重采样图像资源
|
||||
*/
|
||||
bool createMSAAResources();
|
||||
|
||||
/**
|
||||
* @brief 清理多重采样资源
|
||||
*/
|
||||
void cleanupMSAAResources();
|
||||
|
||||
/**
|
||||
* @brief 初始化文本渲染系统
|
||||
*/
|
||||
|
|
@ -354,6 +369,12 @@ private:
|
|||
VkSampler m_fontSampler;
|
||||
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_height;
|
||||
|
|
|
|||
Loading…
Reference in New Issue