mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Refactor] (MG_Backend/DirectVulkan): Move renderpass/framebuffer vk management out of VulkanRenderer.
This commit is contained in:
@@ -240,16 +240,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool VkFramebufferManager::GetOffscreenRenderTarget(Uint glFboExternalIndex, VkRenderPass& outRenderPass,
|
Bool VkFramebufferManager::GetOffscreenRenderSurface(Uint glFboExternalIndex, VkImageView& outColorView,
|
||||||
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
VkFormat& outColorFormat, VkImageView& outDepthStencilView,
|
||||||
VkFormat& outDepthStencilFormat) const {
|
VkFormat& outDepthStencilFormat, VkExtent2D& outExtent) const {
|
||||||
auto it = m_offscreenColorTargets.find(glFboExternalIndex);
|
auto it = m_offscreenColorTargets.find(glFboExternalIndex);
|
||||||
if (it == m_offscreenColorTargets.end() || it->second.framebuffer == VK_NULL_HANDLE ||
|
if (it == m_offscreenColorTargets.end() || it->second.imageView == VK_NULL_HANDLE) {
|
||||||
it->second.renderPassLoad == VK_NULL_HANDLE) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
outRenderPass = it->second.renderPassLoad;
|
outColorView = it->second.imageView;
|
||||||
outFramebuffer = it->second.framebuffer;
|
outColorFormat = it->second.format;
|
||||||
|
outDepthStencilView = it->second.depthStencilImageView;
|
||||||
outExtent = it->second.extent;
|
outExtent = it->second.extent;
|
||||||
outDepthStencilFormat = it->second.depthStencilFormat;
|
outDepthStencilFormat = it->second.depthStencilFormat;
|
||||||
return true;
|
return true;
|
||||||
@@ -378,76 +378,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
"vkCreateImageView(offscreen depth/stencil)");
|
"vkCreateImageView(offscreen depth/stencil)");
|
||||||
}
|
}
|
||||||
|
|
||||||
VkAttachmentDescription colorAttachmentDesc{};
|
|
||||||
colorAttachmentDesc.format = format;
|
|
||||||
colorAttachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
colorAttachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
||||||
colorAttachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
||||||
colorAttachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
||||||
colorAttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
||||||
colorAttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
colorAttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
VkAttachmentReference colorAttachmentRef{};
|
|
||||||
colorAttachmentRef.attachment = 0;
|
|
||||||
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
VkSubpassDescription subpass{};
|
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
||||||
subpass.colorAttachmentCount = 1;
|
|
||||||
subpass.pColorAttachments = &colorAttachmentRef;
|
|
||||||
|
|
||||||
VkAttachmentDescription depthAttachmentDesc{};
|
|
||||||
VkAttachmentReference depthAttachmentRef{};
|
|
||||||
Array<VkAttachmentDescription, 2> attachments{};
|
|
||||||
attachments[0] = colorAttachmentDesc;
|
|
||||||
Uint32 attachmentCount = 1;
|
|
||||||
if (hasDepthStencil) {
|
|
||||||
depthAttachmentDesc.format = depthStencilFormat;
|
|
||||||
depthAttachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
depthAttachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
||||||
depthAttachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
||||||
depthAttachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
||||||
depthAttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
||||||
depthAttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
||||||
depthAttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
depthAttachmentRef.attachment = 1;
|
|
||||||
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
||||||
subpass.pDepthStencilAttachment = &depthAttachmentRef;
|
|
||||||
|
|
||||||
attachments[1] = depthAttachmentDesc;
|
|
||||||
attachmentCount = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo renderPassInfo{};
|
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
||||||
renderPassInfo.attachmentCount = attachmentCount;
|
|
||||||
renderPassInfo.pAttachments = attachments.data();
|
|
||||||
renderPassInfo.subpassCount = 1;
|
|
||||||
renderPassInfo.pSubpasses = &subpass;
|
|
||||||
VK_VERIFY(vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &target.renderPassLoad),
|
|
||||||
"vkCreateRenderPass(offscreen)");
|
|
||||||
|
|
||||||
Array<VkImageView, 2> framebufferAttachments{};
|
|
||||||
framebufferAttachments[0] = target.imageView;
|
|
||||||
Uint32 framebufferAttachmentCount = 1;
|
|
||||||
if (hasDepthStencil) {
|
|
||||||
framebufferAttachments[1] = target.depthStencilImageView;
|
|
||||||
framebufferAttachmentCount = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkFramebufferCreateInfo framebufferInfo{};
|
|
||||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
||||||
framebufferInfo.renderPass = target.renderPassLoad;
|
|
||||||
framebufferInfo.attachmentCount = framebufferAttachmentCount;
|
|
||||||
framebufferInfo.pAttachments = framebufferAttachments.data();
|
|
||||||
framebufferInfo.width = static_cast<Uint32>(size.x());
|
|
||||||
framebufferInfo.height = static_cast<Uint32>(size.y());
|
|
||||||
framebufferInfo.layers = 1;
|
|
||||||
VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &target.framebuffer),
|
|
||||||
"vkCreateFramebuffer(offscreen)");
|
|
||||||
|
|
||||||
target.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
target.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
target.extent = {static_cast<Uint32>(size.x()), static_cast<Uint32>(size.y())};
|
target.extent = {static_cast<Uint32>(size.x()), static_cast<Uint32>(size.y())};
|
||||||
target.format = format;
|
target.format = format;
|
||||||
@@ -461,14 +391,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VkFramebufferManager::DestroyOffscreenColorTarget(OffscreenColorTarget& target) {
|
void VkFramebufferManager::DestroyOffscreenColorTarget(OffscreenColorTarget& target) {
|
||||||
if (target.framebuffer != VK_NULL_HANDLE) {
|
|
||||||
vkDestroyFramebuffer(m_device, target.framebuffer, nullptr);
|
|
||||||
target.framebuffer = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
if (target.renderPassLoad != VK_NULL_HANDLE) {
|
|
||||||
vkDestroyRenderPass(m_device, target.renderPassLoad, nullptr);
|
|
||||||
target.renderPassLoad = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
if (target.imageView != VK_NULL_HANDLE) {
|
if (target.imageView != VK_NULL_HANDLE) {
|
||||||
vkDestroyImageView(m_device, target.imageView, nullptr);
|
vkDestroyImageView(m_device, target.imageView, nullptr);
|
||||||
target.imageView = VK_NULL_HANDLE;
|
target.imageView = VK_NULL_HANDLE;
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Bool GetOffscreenDepthStencilImage(Uint glFboExternalIndex, VkImage& outImage, VkExtent2D& outExtent,
|
Bool GetOffscreenDepthStencilImage(Uint glFboExternalIndex, VkImage& outImage, VkExtent2D& outExtent,
|
||||||
VkFormat& outFormat) const;
|
VkFormat& outFormat) const;
|
||||||
Bool GetOffscreenColorViewByTexture(Uint textureExternalIndex, VkImageView& outImageView) const;
|
Bool GetOffscreenColorViewByTexture(Uint textureExternalIndex, VkImageView& outImageView) const;
|
||||||
Bool GetOffscreenRenderTarget(Uint glFboExternalIndex, VkRenderPass& outRenderPass,
|
Bool GetOffscreenRenderSurface(Uint glFboExternalIndex, VkImageView& outColorView, VkFormat& outColorFormat,
|
||||||
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
VkImageView& outDepthStencilView, VkFormat& outDepthStencilFormat,
|
||||||
VkFormat& outDepthStencilFormat) const;
|
VkExtent2D& outExtent) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct OffscreenColorTarget {
|
struct OffscreenColorTarget {
|
||||||
@@ -56,8 +56,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkImageView depthStencilImageView = VK_NULL_HANDLE;
|
VkImageView depthStencilImageView = VK_NULL_HANDLE;
|
||||||
VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
VkRenderPass renderPassLoad = VK_NULL_HANDLE;
|
|
||||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
|
||||||
Uint16 glObjectVersion = 0;
|
Uint16 glObjectVersion = 0;
|
||||||
Uint colorTextureExternalIndex = 0;
|
Uint colorTextureExternalIndex = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VkRenderPassManager::Shutdown() {
|
void VkRenderPassManager::Shutdown() {
|
||||||
|
DestroyDefaultFramebuffers();
|
||||||
|
for (auto& [_, target] : m_offscreenRenderTargets) {
|
||||||
|
DestroyOffscreenRenderTarget(target);
|
||||||
|
}
|
||||||
|
m_offscreenRenderTargets.clear();
|
||||||
|
|
||||||
if (m_device != VK_NULL_HANDLE) {
|
if (m_device != VK_NULL_HANDLE) {
|
||||||
if (m_renderPassClear != VK_NULL_HANDLE) {
|
if (m_renderPassClear != VK_NULL_HANDLE) {
|
||||||
vkDestroyRenderPass(m_device, m_renderPassClear, nullptr);
|
vkDestroyRenderPass(m_device, m_renderPassClear, nullptr);
|
||||||
@@ -40,9 +46,202 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_renderPassLoad = VK_NULL_HANDLE;
|
m_renderPassLoad = VK_NULL_HANDLE;
|
||||||
m_colorFormat = VK_FORMAT_UNDEFINED;
|
m_colorFormat = VK_FORMAT_UNDEFINED;
|
||||||
m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
m_defaultExtent = {0, 0};
|
||||||
m_device = VK_NULL_HANDLE;
|
m_device = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool VkRenderPassManager::RecreateDefaultFramebuffers(const Vector<VkImageView>& colorViews,
|
||||||
|
const Vector<VkImageView>& depthStencilViews,
|
||||||
|
VkExtent2D extent) {
|
||||||
|
DestroyDefaultFramebuffers();
|
||||||
|
|
||||||
|
if (m_device == VK_NULL_HANDLE || m_renderPassLoad == VK_NULL_HANDLE || extent.width == 0 ||
|
||||||
|
extent.height == 0 || colorViews.empty() || colorViews.size() != depthStencilViews.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_defaultFramebuffers.reserve(colorViews.size());
|
||||||
|
for (SizeT i = 0; i < colorViews.size(); ++i) {
|
||||||
|
if (colorViews[i] == VK_NULL_HANDLE || depthStencilViews[i] == VK_NULL_HANDLE) {
|
||||||
|
DestroyDefaultFramebuffers();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
VkImageView attachments[] = {colorViews[i], depthStencilViews[i]};
|
||||||
|
VkFramebufferCreateInfo createInfo{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||||
|
createInfo.renderPass = m_renderPassLoad;
|
||||||
|
createInfo.attachmentCount = static_cast<Uint32>(std::size(attachments));
|
||||||
|
createInfo.pAttachments = attachments;
|
||||||
|
createInfo.width = extent.width;
|
||||||
|
createInfo.height = extent.height;
|
||||||
|
createInfo.layers = 1;
|
||||||
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
|
if (vkCreateFramebuffer(m_device, &createInfo, nullptr, &framebuffer) != VK_SUCCESS) {
|
||||||
|
DestroyDefaultFramebuffers();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_defaultFramebuffers.push_back(framebuffer);
|
||||||
|
}
|
||||||
|
m_defaultExtent = extent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool VkRenderPassManager::GetDefaultRenderTarget(Uint32 imageIndex, VkRenderPass& outRenderPass,
|
||||||
|
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
||||||
|
VkFormat& outDepthStencilFormat) const {
|
||||||
|
if (imageIndex >= m_defaultFramebuffers.size() || m_renderPassLoad == VK_NULL_HANDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
outRenderPass = m_renderPassLoad;
|
||||||
|
outFramebuffer = m_defaultFramebuffers[imageIndex];
|
||||||
|
outExtent = m_defaultExtent;
|
||||||
|
outDepthStencilFormat = m_depthStencilFormat;
|
||||||
|
return outFramebuffer != VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool VkRenderPassManager::EnsureOffscreenRenderTarget(const OffscreenRenderTargetInfo& targetInfo) {
|
||||||
|
if (m_device == VK_NULL_HANDLE || targetInfo.colorView == VK_NULL_HANDLE ||
|
||||||
|
targetInfo.colorFormat == VK_FORMAT_UNDEFINED || targetInfo.extent.width == 0 ||
|
||||||
|
targetInfo.extent.height == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Bool hasDepthStencil =
|
||||||
|
targetInfo.depthStencilView != VK_NULL_HANDLE && targetInfo.depthStencilFormat != VK_FORMAT_UNDEFINED;
|
||||||
|
|
||||||
|
auto& target = m_offscreenRenderTargets[targetInfo.targetExternalIndex];
|
||||||
|
if (target.framebuffer != VK_NULL_HANDLE && target.renderPassLoad != VK_NULL_HANDLE &&
|
||||||
|
target.targetVersion == targetInfo.targetVersion && target.colorView == targetInfo.colorView &&
|
||||||
|
target.colorFormat == targetInfo.colorFormat && target.depthStencilView == targetInfo.depthStencilView &&
|
||||||
|
target.depthStencilFormat == targetInfo.depthStencilFormat &&
|
||||||
|
target.extent.width == targetInfo.extent.width && target.extent.height == targetInfo.extent.height) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyOffscreenRenderTarget(target);
|
||||||
|
|
||||||
|
const VkFormat depthStencilFormat = hasDepthStencil ? targetInfo.depthStencilFormat : VK_FORMAT_UNDEFINED;
|
||||||
|
target.renderPassLoad = CreateRenderPass(targetInfo.colorFormat, depthStencilFormat, VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
if (target.renderPassLoad == VK_NULL_HANDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<VkImageView, 2> attachments{};
|
||||||
|
attachments[0] = targetInfo.colorView;
|
||||||
|
Uint32 attachmentCount = 1;
|
||||||
|
if (hasDepthStencil) {
|
||||||
|
attachments[1] = targetInfo.depthStencilView;
|
||||||
|
attachmentCount = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFramebufferCreateInfo framebufferInfo{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||||
|
framebufferInfo.renderPass = target.renderPassLoad;
|
||||||
|
framebufferInfo.attachmentCount = attachmentCount;
|
||||||
|
framebufferInfo.pAttachments = attachments.data();
|
||||||
|
framebufferInfo.width = targetInfo.extent.width;
|
||||||
|
framebufferInfo.height = targetInfo.extent.height;
|
||||||
|
framebufferInfo.layers = 1;
|
||||||
|
VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &target.framebuffer),
|
||||||
|
"vkCreateFramebuffer(offscreen)");
|
||||||
|
|
||||||
|
target.targetVersion = targetInfo.targetVersion;
|
||||||
|
target.colorView = targetInfo.colorView;
|
||||||
|
target.colorFormat = targetInfo.colorFormat;
|
||||||
|
target.depthStencilView = targetInfo.depthStencilView;
|
||||||
|
target.depthStencilFormat = targetInfo.depthStencilFormat;
|
||||||
|
target.extent = targetInfo.extent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool VkRenderPassManager::GetOffscreenRenderTarget(Uint targetExternalIndex, VkRenderPass& outRenderPass,
|
||||||
|
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
||||||
|
VkFormat& outDepthStencilFormat) const {
|
||||||
|
auto it = m_offscreenRenderTargets.find(targetExternalIndex);
|
||||||
|
if (it == m_offscreenRenderTargets.end() || it->second.renderPassLoad == VK_NULL_HANDLE ||
|
||||||
|
it->second.framebuffer == VK_NULL_HANDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outRenderPass = it->second.renderPassLoad;
|
||||||
|
outFramebuffer = it->second.framebuffer;
|
||||||
|
outExtent = it->second.extent;
|
||||||
|
outDepthStencilFormat = it->second.depthStencilFormat;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::RemoveOffscreenRenderTarget(Uint targetExternalIndex) {
|
||||||
|
auto it = m_offscreenRenderTargets.find(targetExternalIndex);
|
||||||
|
if (it == m_offscreenRenderTargets.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DestroyOffscreenRenderTarget(it->second);
|
||||||
|
m_offscreenRenderTargets.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::BeginRenderPass(VkCommandBuffer commandBuffer, VkRenderPass renderPass,
|
||||||
|
VkFramebuffer framebuffer, VkExtent2D extent) const {
|
||||||
|
VkRenderPassBeginInfo beginInfo{};
|
||||||
|
beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
|
beginInfo.renderPass = renderPass;
|
||||||
|
beginInfo.framebuffer = framebuffer;
|
||||||
|
beginInfo.renderArea.offset = {0, 0};
|
||||||
|
beginInfo.renderArea.extent = extent;
|
||||||
|
beginInfo.clearValueCount = 0;
|
||||||
|
beginInfo.pClearValues = nullptr;
|
||||||
|
vkCmdBeginRenderPass(commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::EndRenderPass(VkCommandBuffer commandBuffer) const {
|
||||||
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::RecordColorClear(VkCommandBuffer commandBuffer, VkExtent2D extent,
|
||||||
|
const VkClearColorValue& clearColor) const {
|
||||||
|
VkClearAttachment clearAttachment{};
|
||||||
|
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
clearAttachment.colorAttachment = 0;
|
||||||
|
clearAttachment.clearValue.color = clearColor;
|
||||||
|
|
||||||
|
VkClearRect clearRect{};
|
||||||
|
clearRect.rect.offset = {0, 0};
|
||||||
|
clearRect.rect.extent = extent;
|
||||||
|
clearRect.baseArrayLayer = 0;
|
||||||
|
clearRect.layerCount = 1;
|
||||||
|
|
||||||
|
vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::RecordDepthStencilClear(VkCommandBuffer commandBuffer, VkExtent2D extent, GLbitfield mask,
|
||||||
|
Float depth, Uint32 stencil, VkFormat depthStencilFormat) const {
|
||||||
|
if (depthStencilFormat == VK_FORMAT_UNDEFINED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageAspectFlags aspectMask = 0;
|
||||||
|
if ((mask & GL_DEPTH_BUFFER_BIT) != 0) {
|
||||||
|
aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
}
|
||||||
|
if ((mask & GL_STENCIL_BUFFER_BIT) != 0 && HasStencilComponent(depthStencilFormat)) {
|
||||||
|
aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
}
|
||||||
|
if (aspectMask == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkClearAttachment clearAttachment{};
|
||||||
|
clearAttachment.aspectMask = aspectMask;
|
||||||
|
clearAttachment.clearValue.depthStencil.depth = depth;
|
||||||
|
clearAttachment.clearValue.depthStencil.stencil = stencil;
|
||||||
|
|
||||||
|
VkClearRect clearRect{};
|
||||||
|
clearRect.rect.offset = {0, 0};
|
||||||
|
clearRect.rect.extent = extent;
|
||||||
|
clearRect.baseArrayLayer = 0;
|
||||||
|
clearRect.layerCount = 1;
|
||||||
|
|
||||||
|
vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect);
|
||||||
|
}
|
||||||
|
|
||||||
VkRenderPass VkRenderPassManager::GetLoadRenderPass() const {
|
VkRenderPass VkRenderPassManager::GetLoadRenderPass() const {
|
||||||
return m_renderPassLoad;
|
return m_renderPassLoad;
|
||||||
}
|
}
|
||||||
@@ -56,17 +255,26 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MOBILEGL_ASSERT(m_colorFormat != VK_FORMAT_UNDEFINED, "VkRenderPassManager: color format is undefined");
|
MOBILEGL_ASSERT(m_colorFormat != VK_FORMAT_UNDEFINED, "VkRenderPassManager: color format is undefined");
|
||||||
MOBILEGL_ASSERT(m_depthStencilFormat != VK_FORMAT_UNDEFINED,
|
MOBILEGL_ASSERT(m_depthStencilFormat != VK_FORMAT_UNDEFINED,
|
||||||
"VkRenderPassManager: depth/stencil format is undefined");
|
"VkRenderPassManager: depth/stencil format is undefined");
|
||||||
|
return CreateRenderPass(m_colorFormat, m_depthStencilFormat, colorLoadOp, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkRenderPass VkRenderPassManager::CreateRenderPass(VkFormat colorFormat, VkFormat depthStencilFormat,
|
||||||
|
VkAttachmentLoadOp colorLoadOp,
|
||||||
|
VkImageLayout colorFinalLayout) const {
|
||||||
VkAttachmentDescription color{};
|
VkAttachmentDescription color{};
|
||||||
color.format = m_colorFormat;
|
color.format = colorFormat;
|
||||||
color.samples = VK_SAMPLE_COUNT_1_BIT;
|
color.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
color.loadOp = colorLoadOp;
|
color.loadOp = colorLoadOp;
|
||||||
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
color.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
color.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
color.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
color.finalLayout = colorFinalLayout;
|
||||||
|
color.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
color.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
|
||||||
|
const Bool hasDepthStencil = depthStencilFormat != VK_FORMAT_UNDEFINED;
|
||||||
VkAttachmentDescription depthStencil{};
|
VkAttachmentDescription depthStencil{};
|
||||||
depthStencil.format = m_depthStencilFormat;
|
if (hasDepthStencil) {
|
||||||
|
depthStencil.format = depthStencilFormat;
|
||||||
depthStencil.samples = VK_SAMPLE_COUNT_1_BIT;
|
depthStencil.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
depthStencil.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
depthStencil.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
depthStencil.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
depthStencil.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
@@ -74,6 +282,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
depthStencil.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
depthStencil.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
depthStencil.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
depthStencil.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
depthStencil.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
depthStencil.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
VkAttachmentReference colorRef{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
VkAttachmentReference colorRef{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||||
VkAttachmentReference depthStencilRef{1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
|
VkAttachmentReference depthStencilRef{1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
|
||||||
@@ -82,18 +291,57 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
subpass.colorAttachmentCount = 1;
|
subpass.colorAttachmentCount = 1;
|
||||||
subpass.pColorAttachments = &colorRef;
|
subpass.pColorAttachments = &colorRef;
|
||||||
|
if (hasDepthStencil) {
|
||||||
subpass.pDepthStencilAttachment = &depthStencilRef;
|
subpass.pDepthStencilAttachment = &depthStencilRef;
|
||||||
|
}
|
||||||
|
|
||||||
VkAttachmentDescription attachments[2] = {color, depthStencil};
|
Array<VkAttachmentDescription, 2> attachments{};
|
||||||
|
attachments[0] = color;
|
||||||
|
Uint32 attachmentCount = 1;
|
||||||
|
if (hasDepthStencil) {
|
||||||
|
attachments[1] = depthStencil;
|
||||||
|
attachmentCount = 2;
|
||||||
|
}
|
||||||
|
|
||||||
VkRenderPassCreateInfo createInfo{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
VkRenderPassCreateInfo createInfo{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||||
createInfo.attachmentCount = 2;
|
createInfo.attachmentCount = attachmentCount;
|
||||||
createInfo.pAttachments = attachments;
|
createInfo.pAttachments = attachments.data();
|
||||||
createInfo.subpassCount = 1;
|
createInfo.subpassCount = 1;
|
||||||
createInfo.pSubpasses = &subpass;
|
createInfo.pSubpasses = &subpass;
|
||||||
|
|
||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
VK_VERIFY(vkCreateRenderPass(m_device, &createInfo, nullptr, &renderPass), "vkCreateRenderPass(default)");
|
VK_VERIFY(vkCreateRenderPass(m_device, &createInfo, nullptr, &renderPass), "vkCreateRenderPass");
|
||||||
return renderPass;
|
return renderPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::DestroyDefaultFramebuffers() {
|
||||||
|
for (auto framebuffer : m_defaultFramebuffers) {
|
||||||
|
if (framebuffer != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyFramebuffer(m_device, framebuffer, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_defaultFramebuffers.clear();
|
||||||
|
m_defaultExtent = {0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::DestroyOffscreenRenderTarget(OffscreenRenderTarget& target) {
|
||||||
|
if (target.framebuffer != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyFramebuffer(m_device, target.framebuffer, nullptr);
|
||||||
|
target.framebuffer = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (target.renderPassLoad != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyRenderPass(m_device, target.renderPassLoad, nullptr);
|
||||||
|
target.renderPassLoad = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
target.targetVersion = 0;
|
||||||
|
target.colorView = VK_NULL_HANDLE;
|
||||||
|
target.colorFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
target.depthStencilView = VK_NULL_HANDLE;
|
||||||
|
target.depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
target.extent = {0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool VkRenderPassManager::HasStencilComponent(VkFormat format) {
|
||||||
|
return format == VK_FORMAT_D24_UNORM_S8_UINT || format == VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||||
|
}
|
||||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
|
|||||||
@@ -20,19 +20,67 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OffscreenRenderTargetInfo {
|
||||||
|
Uint targetExternalIndex = 0;
|
||||||
|
Uint16 targetVersion = 0;
|
||||||
|
VkImageView colorView = VK_NULL_HANDLE;
|
||||||
|
VkFormat colorFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkImageView depthStencilView = VK_NULL_HANDLE;
|
||||||
|
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkExtent2D extent = {0, 0};
|
||||||
|
};
|
||||||
|
|
||||||
Bool Initialize(const InitInfo& initInfo);
|
Bool Initialize(const InitInfo& initInfo);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
Bool RecreateDefaultFramebuffers(const Vector<VkImageView>& colorViews,
|
||||||
|
const Vector<VkImageView>& depthStencilViews, VkExtent2D extent);
|
||||||
|
Bool GetDefaultRenderTarget(Uint32 imageIndex, VkRenderPass& outRenderPass, VkFramebuffer& outFramebuffer,
|
||||||
|
VkExtent2D& outExtent, VkFormat& outDepthStencilFormat) const;
|
||||||
|
|
||||||
|
Bool EnsureOffscreenRenderTarget(const OffscreenRenderTargetInfo& targetInfo);
|
||||||
|
Bool GetOffscreenRenderTarget(Uint targetExternalIndex, VkRenderPass& outRenderPass,
|
||||||
|
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
||||||
|
VkFormat& outDepthStencilFormat) const;
|
||||||
|
void RemoveOffscreenRenderTarget(Uint targetExternalIndex);
|
||||||
|
|
||||||
|
void BeginRenderPass(VkCommandBuffer commandBuffer, VkRenderPass renderPass, VkFramebuffer framebuffer,
|
||||||
|
VkExtent2D extent) const;
|
||||||
|
void EndRenderPass(VkCommandBuffer commandBuffer) const;
|
||||||
|
void RecordColorClear(VkCommandBuffer commandBuffer, VkExtent2D extent,
|
||||||
|
const VkClearColorValue& clearColor) const;
|
||||||
|
void RecordDepthStencilClear(VkCommandBuffer commandBuffer, VkExtent2D extent, GLbitfield mask, Float depth,
|
||||||
|
Uint32 stencil, VkFormat depthStencilFormat) const;
|
||||||
|
|
||||||
VkRenderPass GetLoadRenderPass() const;
|
VkRenderPass GetLoadRenderPass() const;
|
||||||
VkRenderPass GetClearRenderPass() const;
|
VkRenderPass GetClearRenderPass() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct OffscreenRenderTarget {
|
||||||
|
Uint16 targetVersion = 0;
|
||||||
|
VkImageView colorView = VK_NULL_HANDLE;
|
||||||
|
VkFormat colorFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkImageView depthStencilView = VK_NULL_HANDLE;
|
||||||
|
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkExtent2D extent = {0, 0};
|
||||||
|
VkRenderPass renderPassLoad = VK_NULL_HANDLE;
|
||||||
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
|
||||||
VkRenderPass CreateDefaultRenderPass(VkAttachmentLoadOp colorLoadOp) const;
|
VkRenderPass CreateDefaultRenderPass(VkAttachmentLoadOp colorLoadOp) const;
|
||||||
|
VkRenderPass CreateRenderPass(VkFormat colorFormat, VkFormat depthStencilFormat, VkAttachmentLoadOp colorLoadOp,
|
||||||
|
VkImageLayout colorFinalLayout) const;
|
||||||
|
void DestroyDefaultFramebuffers();
|
||||||
|
void DestroyOffscreenRenderTarget(OffscreenRenderTarget& target);
|
||||||
|
static Bool HasStencilComponent(VkFormat format);
|
||||||
|
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
VkFormat m_colorFormat = VK_FORMAT_UNDEFINED;
|
VkFormat m_colorFormat = VK_FORMAT_UNDEFINED;
|
||||||
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
VkRenderPass m_renderPassLoad = VK_NULL_HANDLE;
|
VkRenderPass m_renderPassLoad = VK_NULL_HANDLE;
|
||||||
VkRenderPass m_renderPassClear = VK_NULL_HANDLE;
|
VkRenderPass m_renderPassClear = VK_NULL_HANDLE;
|
||||||
|
Vector<VkFramebuffer> m_defaultFramebuffers;
|
||||||
|
VkExtent2D m_defaultExtent = {0, 0};
|
||||||
|
UnorderedMap<Uint, OffscreenRenderTarget> m_offscreenRenderTargets;
|
||||||
};
|
};
|
||||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
|
|||||||
@@ -254,10 +254,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_textureSamplerManager.reset();
|
m_textureSamplerManager.reset();
|
||||||
}
|
}
|
||||||
m_vertexInputStateFactory.reset();
|
m_vertexInputStateFactory.reset();
|
||||||
if (m_framebufferManager) {
|
|
||||||
m_framebufferManager->Shutdown();
|
|
||||||
m_framebufferManager.reset();
|
|
||||||
}
|
|
||||||
for (auto& buffer : m_frameVertexUploadBuffers) {
|
for (auto& buffer : m_frameVertexUploadBuffers) {
|
||||||
buffer.Destroy();
|
buffer.Destroy();
|
||||||
}
|
}
|
||||||
@@ -283,6 +279,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
ShutdownSwapchain();
|
ShutdownSwapchain();
|
||||||
m_renderPassManager.reset();
|
m_renderPassManager.reset();
|
||||||
|
if (m_framebufferManager) {
|
||||||
|
m_framebufferManager->Shutdown();
|
||||||
|
m_framebufferManager.reset();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_commandPool != VK_NULL_HANDLE) {
|
if (m_commandPool != VK_NULL_HANDLE) {
|
||||||
vkDestroyCommandPool(m_device, m_commandPool, nullptr);
|
vkDestroyCommandPool(m_device, m_commandPool, nullptr);
|
||||||
@@ -383,52 +383,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_swapchainObject.SetImageLayout(imageIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
m_swapchainObject.SetImageLayout(imageIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::RecordColorClear(VkCommandBuffer commandBuffer, const VkClearColorValue& clearColor) {
|
|
||||||
VkClearAttachment clearAttachment{};
|
|
||||||
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
clearAttachment.colorAttachment = 0;
|
|
||||||
clearAttachment.clearValue.color = clearColor;
|
|
||||||
|
|
||||||
VkClearRect clearRect{};
|
|
||||||
clearRect.rect.offset = {0, 0};
|
|
||||||
clearRect.rect.extent = m_activeRenderExtent;
|
|
||||||
clearRect.baseArrayLayer = 0;
|
|
||||||
clearRect.layerCount = 1;
|
|
||||||
|
|
||||||
vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::RecordDepthStencilClear(VkCommandBuffer commandBuffer, GLbitfield mask, Float depth,
|
|
||||||
Uint32 stencil) {
|
|
||||||
if (m_activeDepthStencilFormat == VK_FORMAT_UNDEFINED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageAspectFlags aspectMask = 0;
|
|
||||||
if ((mask & GL_DEPTH_BUFFER_BIT) != 0) {
|
|
||||||
aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
||||||
}
|
|
||||||
if ((mask & GL_STENCIL_BUFFER_BIT) != 0 && HasStencilComponent(m_activeDepthStencilFormat)) {
|
|
||||||
aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
||||||
}
|
|
||||||
if (aspectMask == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkClearAttachment clearAttachment{};
|
|
||||||
clearAttachment.aspectMask = aspectMask;
|
|
||||||
clearAttachment.clearValue.depthStencil.depth = depth;
|
|
||||||
clearAttachment.clearValue.depthStencil.stencil = stencil;
|
|
||||||
|
|
||||||
VkClearRect clearRect{};
|
|
||||||
clearRect.rect.offset = {0, 0};
|
|
||||||
clearRect.rect.extent = m_activeRenderExtent;
|
|
||||||
clearRect.baseArrayLayer = 0;
|
|
||||||
clearRect.layerCount = 1;
|
|
||||||
|
|
||||||
vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex) {
|
void VulkanRenderer::TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex) {
|
||||||
if (m_depthStencilImageLayouts.empty()) {
|
if (m_depthStencilImageLayouts.empty()) {
|
||||||
return;
|
return;
|
||||||
@@ -487,7 +441,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
(drawTargetsDefault != m_activeRenderTargetIsDefault) ||
|
(drawTargetsDefault != m_activeRenderTargetIsDefault) ||
|
||||||
(!drawTargetsDefault && m_activeDrawFboExternalIndex != drawFboExternalIndex);
|
(!drawTargetsDefault && m_activeDrawFboExternalIndex != drawFboExternalIndex);
|
||||||
if (activeTargetMismatch) {
|
if (activeTargetMismatch) {
|
||||||
vkCmdEndRenderPass(frame.commandBuffer);
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "EnsureFrameRecordingStarted: manager is null");
|
||||||
|
m_renderPassManager->EndRenderPass(frame.commandBuffer);
|
||||||
if (m_activeRenderTargetIsDefault) {
|
if (m_activeRenderTargetIsDefault) {
|
||||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
}
|
}
|
||||||
@@ -514,15 +469,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkCommandBuffer& commandBuffer = *commandBufferPtr;
|
VkCommandBuffer& commandBuffer = *commandBufferPtr;
|
||||||
|
|
||||||
if (!drawTargetsDefault) {
|
if (!drawTargetsDefault) {
|
||||||
if (!m_framebufferManager || !drawFbo) {
|
if (!m_framebufferManager || !m_renderPassManager || !drawFbo) {
|
||||||
MGLOG_D("EnsureFrameRecordingStarted skipped: offscreen draw target is unavailable");
|
MGLOG_D("EnsureFrameRecordingStarted skipped: offscreen draw target is unavailable");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_framebufferManager->EnsureOffscreenColorTarget(drawFboExternalIndex, *drawFbo)) {
|
|
||||||
MGLOG_D("EnsureFrameRecordingStarted skipped: failed to materialize offscreen target for FBO %u",
|
|
||||||
drawFboExternalIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This frame touched only offscreen resources. Present still requires
|
// This frame touched only offscreen resources. Present still requires
|
||||||
// the acquired swapchain image to be in PRESENT layout.
|
// the acquired swapchain image to be in PRESENT layout.
|
||||||
@@ -549,33 +499,24 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer, drawFboExternalIndex)) {
|
|
||||||
MGLOG_D("EnsureFrameRecordingStarted skipped: failed to transition offscreen FBO %u for attachment",
|
|
||||||
drawFboExternalIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
||||||
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
||||||
VkExtent2D offscreenExtent{};
|
VkExtent2D offscreenExtent{};
|
||||||
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
if (!m_framebufferManager->GetOffscreenRenderTarget(drawFboExternalIndex, offscreenRenderPass,
|
if (!EnsureOffscreenRenderTarget(drawFboExternalIndex, *drawFbo, offscreenRenderPass, offscreenFramebuffer,
|
||||||
offscreenFramebuffer, offscreenExtent,
|
offscreenExtent, offscreenDepthStencilFormat)) {
|
||||||
offscreenDepthStencilFormat)) {
|
|
||||||
MGLOG_D("EnsureFrameRecordingStarted skipped: offscreen render target for FBO %u is unavailable",
|
MGLOG_D("EnsureFrameRecordingStarted skipped: offscreen render target for FBO %u is unavailable",
|
||||||
drawFboExternalIndex);
|
drawFboExternalIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassInfo{};
|
if (!m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer, drawFboExternalIndex)) {
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
MGLOG_D("EnsureFrameRecordingStarted skipped: failed to transition offscreen FBO %u for attachment",
|
||||||
renderPassInfo.renderPass = offscreenRenderPass;
|
drawFboExternalIndex);
|
||||||
renderPassInfo.framebuffer = offscreenFramebuffer;
|
return;
|
||||||
renderPassInfo.renderArea.offset = {0, 0};
|
}
|
||||||
renderPassInfo.renderArea.extent = offscreenExtent;
|
m_renderPassManager->BeginRenderPass(commandBuffer, offscreenRenderPass, offscreenFramebuffer,
|
||||||
renderPassInfo.clearValueCount = 0;
|
offscreenExtent);
|
||||||
renderPassInfo.pClearValues = nullptr;
|
|
||||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
m_isMainRenderPassActive = true;
|
m_isMainRenderPassActive = true;
|
||||||
m_activeRenderPass = offscreenRenderPass;
|
m_activeRenderPass = offscreenRenderPass;
|
||||||
m_activeRenderExtent = offscreenExtent;
|
m_activeRenderExtent = offscreenExtent;
|
||||||
@@ -585,12 +526,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
auto pendingIt = m_pendingClears.find(drawTargetKey);
|
auto pendingIt = m_pendingClears.find(drawTargetKey);
|
||||||
if (pendingIt != m_pendingClears.end()) {
|
if (pendingIt != m_pendingClears.end()) {
|
||||||
if ((pendingIt->second.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
if ((pendingIt->second.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||||
RecordColorClear(commandBuffer, pendingIt->second.color);
|
m_renderPassManager->RecordColorClear(commandBuffer, m_activeRenderExtent, pendingIt->second.color);
|
||||||
pendingIt->second.mask &= ~GL_COLOR_BUFFER_BIT;
|
pendingIt->second.mask &= ~GL_COLOR_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
if ((pendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
if ((pendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||||
RecordDepthStencilClear(commandBuffer, pendingIt->second.mask, pendingIt->second.depth,
|
m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent,
|
||||||
pendingIt->second.stencil);
|
pendingIt->second.mask, pendingIt->second.depth,
|
||||||
|
pendingIt->second.stencil, m_activeDepthStencilFormat);
|
||||||
pendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
pendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
if (pendingIt->second.mask == 0) {
|
if (pendingIt->second.mask == 0) {
|
||||||
@@ -603,30 +545,33 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
||||||
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassInfo{};
|
VkRenderPass defaultRenderPass = VK_NULL_HANDLE;
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
VkFramebuffer defaultFramebuffer = VK_NULL_HANDLE;
|
||||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
VkExtent2D defaultExtent{};
|
||||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
VkFormat defaultDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
renderPassInfo.renderArea.offset = {0, 0};
|
if (!GetDefaultRenderTargetForCurrentImage(defaultRenderPass, defaultFramebuffer, defaultExtent,
|
||||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
defaultDepthStencilFormat)) {
|
||||||
renderPassInfo.clearValueCount = 0;
|
MGLOG_D("EnsureFrameRecordingStarted skipped: default render target unavailable");
|
||||||
renderPassInfo.pClearValues = nullptr;
|
return;
|
||||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
}
|
||||||
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "EnsureFrameRecordingStarted: manager is null");
|
||||||
|
m_renderPassManager->BeginRenderPass(commandBuffer, defaultRenderPass, defaultFramebuffer, defaultExtent);
|
||||||
m_isMainRenderPassActive = true;
|
m_isMainRenderPassActive = true;
|
||||||
m_activeRenderPass = renderPassInfo.renderPass;
|
m_activeRenderPass = defaultRenderPass;
|
||||||
m_activeRenderExtent = renderPassInfo.renderArea.extent;
|
m_activeRenderExtent = defaultExtent;
|
||||||
m_activeDepthStencilFormat = m_depthStencilFormat;
|
m_activeDepthStencilFormat = defaultDepthStencilFormat;
|
||||||
m_activeRenderTargetIsDefault = true;
|
m_activeRenderTargetIsDefault = true;
|
||||||
m_activeDrawFboExternalIndex = drawFboExternalIndex;
|
m_activeDrawFboExternalIndex = drawFboExternalIndex;
|
||||||
auto pendingIt = m_pendingClears.find(drawTargetKey);
|
auto pendingIt = m_pendingClears.find(drawTargetKey);
|
||||||
if (pendingIt != m_pendingClears.end()) {
|
if (pendingIt != m_pendingClears.end()) {
|
||||||
if ((pendingIt->second.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
if ((pendingIt->second.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||||
RecordColorClear(commandBuffer, pendingIt->second.color);
|
m_renderPassManager->RecordColorClear(commandBuffer, m_activeRenderExtent, pendingIt->second.color);
|
||||||
pendingIt->second.mask &= ~GL_COLOR_BUFFER_BIT;
|
pendingIt->second.mask &= ~GL_COLOR_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
if ((pendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
if ((pendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||||
RecordDepthStencilClear(commandBuffer, pendingIt->second.mask, pendingIt->second.depth,
|
m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent,
|
||||||
pendingIt->second.stencil);
|
pendingIt->second.mask, pendingIt->second.depth,
|
||||||
|
pendingIt->second.stencil, m_activeDepthStencilFormat);
|
||||||
pendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
pendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
if (pendingIt->second.mask == 0) {
|
if (pendingIt->second.mask == 0) {
|
||||||
@@ -642,7 +587,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_isMainRenderPassActive) {
|
if (m_isMainRenderPassActive) {
|
||||||
vkCmdEndRenderPass(frame.commandBuffer);
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "EndFrameRecordingIfNeeded: manager is null");
|
||||||
|
m_renderPassManager->EndRenderPass(frame.commandBuffer);
|
||||||
if (m_activeRenderTargetIsDefault) {
|
if (m_activeRenderTargetIsDefault) {
|
||||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
}
|
}
|
||||||
@@ -1270,7 +1216,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkCommandBuffer commandBuffer = frame.commandBuffer;
|
VkCommandBuffer commandBuffer = frame.commandBuffer;
|
||||||
if (m_isMainRenderPassActive) {
|
if (m_isMainRenderPassActive) {
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "BlitFramebuffer: render pass manager is null");
|
||||||
|
m_renderPassManager->EndRenderPass(commandBuffer);
|
||||||
if (m_activeRenderTargetIsDefault) {
|
if (m_activeRenderTargetIsDefault) {
|
||||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
}
|
}
|
||||||
@@ -1286,6 +1233,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MGLOG_W("BlitFramebuffer skipped: offscreen framebuffer manager not available");
|
MGLOG_W("BlitFramebuffer skipped: offscreen framebuffer manager not available");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!m_renderPassManager) {
|
||||||
|
MGLOG_W("BlitFramebuffer skipped: render pass manager not available");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto consumePendingClearForTarget = [&](Bool targetIsDefault, Uint targetFboExternalIndex) {
|
auto consumePendingClearForTarget = [&](Bool targetIsDefault, Uint targetFboExternalIndex) {
|
||||||
const Uint64 pendingKey = BuildPendingClearKey(targetFboExternalIndex, targetIsDefault);
|
const Uint64 pendingKey = BuildPendingClearKey(targetFboExternalIndex, targetIsDefault);
|
||||||
@@ -1304,60 +1255,55 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
||||||
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassInfo{};
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
VkExtent2D extent{};
|
||||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
renderPassInfo.renderArea.offset = {0, 0};
|
if (!GetDefaultRenderTargetForCurrentImage(renderPass, framebuffer, extent, depthStencilFormat)) {
|
||||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
return;
|
||||||
renderPassInfo.clearValueCount = 0;
|
}
|
||||||
renderPassInfo.pClearValues = nullptr;
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "BlitFramebuffer: manager is null");
|
||||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
m_renderPassManager->BeginRenderPass(commandBuffer, renderPass, framebuffer, extent);
|
||||||
|
|
||||||
m_activeRenderExtent = renderPassInfo.renderArea.extent;
|
m_activeRenderExtent = extent;
|
||||||
m_activeDepthStencilFormat = m_depthStencilFormat;
|
m_activeDepthStencilFormat = depthStencilFormat;
|
||||||
|
|
||||||
if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||||
RecordColorClear(commandBuffer, pending.color);
|
m_renderPassManager->RecordColorClear(commandBuffer, m_activeRenderExtent, pending.color);
|
||||||
}
|
}
|
||||||
if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||||
RecordDepthStencilClear(commandBuffer, pending.mask, pending.depth, pending.stencil);
|
m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent, pending.mask,
|
||||||
|
pending.depth, pending.stencil,
|
||||||
|
m_activeDepthStencilFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
m_renderPassManager->EndRenderPass(commandBuffer);
|
||||||
} else if (m_framebufferManager && MG_State::pGLContext) {
|
} else if (m_framebufferManager && MG_State::pGLContext) {
|
||||||
const auto targetFbo = MG_State::pGLContext->GetFramebufferObject(targetFboExternalIndex);
|
const auto targetFbo = MG_State::pGLContext->GetFramebufferObject(targetFboExternalIndex);
|
||||||
if (targetFbo && m_framebufferManager->EnsureOffscreenColorTarget(targetFboExternalIndex, *targetFbo) &&
|
|
||||||
m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer, targetFboExternalIndex)) {
|
|
||||||
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
||||||
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
||||||
VkExtent2D offscreenExtent{};
|
VkExtent2D offscreenExtent{};
|
||||||
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
if (m_framebufferManager->GetOffscreenRenderTarget(targetFboExternalIndex, offscreenRenderPass,
|
if (targetFbo &&
|
||||||
offscreenFramebuffer, offscreenExtent,
|
EnsureOffscreenRenderTarget(targetFboExternalIndex, *targetFbo, offscreenRenderPass,
|
||||||
offscreenDepthStencilFormat)) {
|
offscreenFramebuffer, offscreenExtent, offscreenDepthStencilFormat) &&
|
||||||
VkRenderPassBeginInfo offscreenPassInfo{};
|
m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer, targetFboExternalIndex)) {
|
||||||
offscreenPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
m_renderPassManager->BeginRenderPass(commandBuffer, offscreenRenderPass, offscreenFramebuffer,
|
||||||
offscreenPassInfo.renderPass = offscreenRenderPass;
|
offscreenExtent);
|
||||||
offscreenPassInfo.framebuffer = offscreenFramebuffer;
|
|
||||||
offscreenPassInfo.renderArea.offset = {0, 0};
|
|
||||||
offscreenPassInfo.renderArea.extent = offscreenExtent;
|
|
||||||
offscreenPassInfo.clearValueCount = 0;
|
|
||||||
offscreenPassInfo.pClearValues = nullptr;
|
|
||||||
vkCmdBeginRenderPass(commandBuffer, &offscreenPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
|
|
||||||
m_activeRenderExtent = offscreenPassInfo.renderArea.extent;
|
m_activeRenderExtent = offscreenExtent;
|
||||||
m_activeDepthStencilFormat = offscreenDepthStencilFormat;
|
m_activeDepthStencilFormat = offscreenDepthStencilFormat;
|
||||||
|
|
||||||
if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||||
RecordColorClear(commandBuffer, pending.color);
|
m_renderPassManager->RecordColorClear(commandBuffer, m_activeRenderExtent, pending.color);
|
||||||
}
|
}
|
||||||
if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||||
RecordDepthStencilClear(commandBuffer, pending.mask, pending.depth, pending.stencil);
|
m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent, pending.mask,
|
||||||
|
pending.depth, pending.stencil,
|
||||||
|
m_activeDepthStencilFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
m_renderPassManager->EndRenderPass(commandBuffer);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1858,6 +1804,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (frame.hasCommandBufferRecorded) {
|
if (frame.hasCommandBufferRecorded) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!m_renderPassManager) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!frame.isCommandRecording) {
|
if (!frame.isCommandRecording) {
|
||||||
m_frameContext.BeginCommandRecording();
|
m_frameContext.BeginCommandRecording();
|
||||||
if (m_uniformDescriptorBinder) {
|
if (m_uniformDescriptorBinder) {
|
||||||
@@ -1867,7 +1816,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkCommandBuffer commandBuffer = frame.commandBuffer;
|
VkCommandBuffer commandBuffer = frame.commandBuffer;
|
||||||
|
|
||||||
if (m_isMainRenderPassActive) {
|
if (m_isMainRenderPassActive) {
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "Present: render pass manager is null");
|
||||||
|
m_renderPassManager->EndRenderPass(commandBuffer);
|
||||||
if (m_activeRenderTargetIsDefault) {
|
if (m_activeRenderTargetIsDefault) {
|
||||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
}
|
}
|
||||||
@@ -1883,19 +1833,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
||||||
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassInfo{};
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
VkExtent2D extent{};
|
||||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
renderPassInfo.renderArea.offset = {0, 0};
|
if (!GetDefaultRenderTargetForCurrentImage(renderPass, framebuffer, extent, depthStencilFormat)) {
|
||||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
return false;
|
||||||
renderPassInfo.clearValueCount = 0;
|
}
|
||||||
renderPassInfo.pClearValues = nullptr;
|
m_renderPassManager->BeginRenderPass(commandBuffer, renderPass, framebuffer, extent);
|
||||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
m_isMainRenderPassActive = true;
|
m_isMainRenderPassActive = true;
|
||||||
m_activeRenderPass = renderPassInfo.renderPass;
|
m_activeRenderPass = renderPass;
|
||||||
m_activeRenderExtent = renderPassInfo.renderArea.extent;
|
m_activeRenderExtent = extent;
|
||||||
m_activeDepthStencilFormat = m_depthStencilFormat;
|
m_activeDepthStencilFormat = depthStencilFormat;
|
||||||
m_activeRenderTargetIsDefault = true;
|
m_activeRenderTargetIsDefault = true;
|
||||||
m_activeDrawFboExternalIndex = 0;
|
m_activeDrawFboExternalIndex = 0;
|
||||||
return true;
|
return true;
|
||||||
@@ -1908,21 +1857,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (!pendingFbo) {
|
if (!pendingFbo) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_framebufferManager->EnsureOffscreenColorTarget(targetFboExternalIndex, *pendingFbo)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer,
|
|
||||||
targetFboExternalIndex)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
||||||
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
||||||
VkExtent2D offscreenExtent{};
|
VkExtent2D offscreenExtent{};
|
||||||
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
if (!m_framebufferManager->GetOffscreenRenderTarget(targetFboExternalIndex, offscreenRenderPass,
|
if (!EnsureOffscreenRenderTarget(targetFboExternalIndex, *pendingFbo, offscreenRenderPass,
|
||||||
offscreenFramebuffer, offscreenExtent,
|
offscreenFramebuffer, offscreenExtent, offscreenDepthStencilFormat)) {
|
||||||
offscreenDepthStencilFormat)) {
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer,
|
||||||
|
targetFboExternalIndex)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1949,15 +1893,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPassBeginInfo offscreenPassInfo{};
|
m_renderPassManager->BeginRenderPass(commandBuffer, offscreenRenderPass, offscreenFramebuffer,
|
||||||
offscreenPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
offscreenExtent);
|
||||||
offscreenPassInfo.renderPass = offscreenRenderPass;
|
|
||||||
offscreenPassInfo.framebuffer = offscreenFramebuffer;
|
|
||||||
offscreenPassInfo.renderArea.offset = {0, 0};
|
|
||||||
offscreenPassInfo.renderArea.extent = offscreenExtent;
|
|
||||||
offscreenPassInfo.clearValueCount = 0;
|
|
||||||
offscreenPassInfo.pClearValues = nullptr;
|
|
||||||
vkCmdBeginRenderPass(commandBuffer, &offscreenPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
m_isMainRenderPassActive = true;
|
m_isMainRenderPassActive = true;
|
||||||
m_activeRenderPass = offscreenRenderPass;
|
m_activeRenderPass = offscreenRenderPass;
|
||||||
m_activeRenderExtent = offscreenExtent;
|
m_activeRenderExtent = offscreenExtent;
|
||||||
@@ -1994,12 +1931,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((activePendingIt->second.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
if ((activePendingIt->second.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||||
RecordColorClear(frame.commandBuffer, activePendingIt->second.color);
|
m_renderPassManager->RecordColorClear(frame.commandBuffer, m_activeRenderExtent,
|
||||||
|
activePendingIt->second.color);
|
||||||
activePendingIt->second.mask &= ~GL_COLOR_BUFFER_BIT;
|
activePendingIt->second.mask &= ~GL_COLOR_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
if ((activePendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
if ((activePendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||||
RecordDepthStencilClear(frame.commandBuffer, activePendingIt->second.mask,
|
m_renderPassManager->RecordDepthStencilClear(
|
||||||
activePendingIt->second.depth, activePendingIt->second.stencil);
|
frame.commandBuffer, m_activeRenderExtent, activePendingIt->second.mask,
|
||||||
|
activePendingIt->second.depth, activePendingIt->second.stencil, m_activeDepthStencilFormat);
|
||||||
activePendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
activePendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
if (activePendingIt->second.mask == 0) {
|
if (activePendingIt->second.mask == 0) {
|
||||||
@@ -2541,26 +2480,49 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return renderPass;
|
return renderPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateDefaultFramebuffers() {
|
Bool VulkanRenderer::GetDefaultRenderTargetForCurrentImage(VkRenderPass& outRenderPass,
|
||||||
// Create framebuffers now (use swapchain imageviews)
|
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
||||||
const auto& imageViews = m_swapchainObject.GetImageViews();
|
VkFormat& outDepthStencilFormat) const {
|
||||||
const auto swapchainExtent = m_swapchainObject.GetExtent();
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "GetDefaultRenderTargetForCurrentImage: manager is null");
|
||||||
Vector<VkFramebuffer>& fbs = m_framebuffers;
|
return m_renderPassManager->GetDefaultRenderTarget(m_imageIndexAcquired, outRenderPass, outFramebuffer,
|
||||||
fbs.reserve(imageViews.size());
|
outExtent, outDepthStencilFormat);
|
||||||
for (SizeT i = 0; i < imageViews.size(); ++i) {
|
|
||||||
VkImageView attachments[] = {imageViews[i], m_depthStencilImageViews[i]};
|
|
||||||
VkFramebufferCreateInfo fbci{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
|
||||||
fbci.renderPass = GetDefaultLoadRenderPass();
|
|
||||||
fbci.attachmentCount = static_cast<Uint32>(std::size(attachments));
|
|
||||||
fbci.pAttachments = attachments;
|
|
||||||
fbci.width = swapchainExtent.width;
|
|
||||||
fbci.height = swapchainExtent.height;
|
|
||||||
fbci.layers = 1;
|
|
||||||
VkFramebuffer fb;
|
|
||||||
VK_VERIFY(vkCreateFramebuffer(m_device, &fbci, nullptr, &fb), "vkCreateFramebuffer");
|
|
||||||
fbs.push_back(fb);
|
|
||||||
}
|
}
|
||||||
MGLOG_D("Default framebuffer created.");
|
|
||||||
|
Bool VulkanRenderer::EnsureOffscreenRenderTarget(Uint glFboExternalIndex,
|
||||||
|
const MG_State::GLState::FramebufferObject& glFbo,
|
||||||
|
VkRenderPass& outRenderPass, VkFramebuffer& outFramebuffer,
|
||||||
|
VkExtent2D& outExtent, VkFormat& outDepthStencilFormat) {
|
||||||
|
MOBILEGL_ASSERT(m_framebufferManager != nullptr, "EnsureOffscreenRenderTarget: framebuffer manager is null");
|
||||||
|
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "EnsureOffscreenRenderTarget: render pass manager is null");
|
||||||
|
|
||||||
|
if (!m_framebufferManager->EnsureOffscreenColorTarget(glFboExternalIndex, glFbo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageView colorView = VK_NULL_HANDLE;
|
||||||
|
VkFormat colorFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkImageView depthStencilView = VK_NULL_HANDLE;
|
||||||
|
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkExtent2D extent{};
|
||||||
|
if (!m_framebufferManager->GetOffscreenRenderSurface(glFboExternalIndex, colorView, colorFormat,
|
||||||
|
depthStencilView, depthStencilFormat, extent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkRenderPassManager::OffscreenRenderTargetInfo targetInfo{};
|
||||||
|
targetInfo.targetExternalIndex = glFboExternalIndex;
|
||||||
|
targetInfo.targetVersion = glFbo.GetObjectVersion();
|
||||||
|
targetInfo.colorView = colorView;
|
||||||
|
targetInfo.colorFormat = colorFormat;
|
||||||
|
targetInfo.depthStencilView = depthStencilView;
|
||||||
|
targetInfo.depthStencilFormat = depthStencilFormat;
|
||||||
|
targetInfo.extent = extent;
|
||||||
|
if (!m_renderPassManager->EnsureOffscreenRenderTarget(targetInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_renderPassManager->GetOffscreenRenderTarget(glFboExternalIndex, outRenderPass, outFramebuffer,
|
||||||
|
outExtent, outDepthStencilFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateSurface() {
|
void VulkanRenderer::CreateSurface() {
|
||||||
@@ -2707,11 +2669,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::ShutdownSwapchain() {
|
void VulkanRenderer::ShutdownSwapchain() {
|
||||||
for (auto fb : m_framebuffers) {
|
|
||||||
vkDestroyFramebuffer(m_device, fb, nullptr);
|
|
||||||
}
|
|
||||||
m_framebuffers.clear();
|
|
||||||
|
|
||||||
DestroyDepthStencilResources();
|
DestroyDepthStencilResources();
|
||||||
|
|
||||||
if (m_renderPassManager) {
|
if (m_renderPassManager) {
|
||||||
@@ -2746,7 +2703,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
renderPassInitInfo.depthStencilFormat = m_depthStencilFormat;
|
renderPassInitInfo.depthStencilFormat = m_depthStencilFormat;
|
||||||
MOBILEGL_ASSERT(m_renderPassManager->Initialize(renderPassInitInfo),
|
MOBILEGL_ASSERT(m_renderPassManager->Initialize(renderPassInitInfo),
|
||||||
"RecreateSwapchain: render pass manager initialization failed");
|
"RecreateSwapchain: render pass manager initialization failed");
|
||||||
CreateDefaultFramebuffers();
|
MOBILEGL_ASSERT(m_renderPassManager->RecreateDefaultFramebuffers(
|
||||||
|
m_swapchainObject.GetImageViews(), m_depthStencilImageViews, m_swapchainObject.GetExtent()),
|
||||||
|
"RecreateSwapchain: default framebuffers initialization failed");
|
||||||
if (m_pipelineFactory) {
|
if (m_pipelineFactory) {
|
||||||
m_pipelineFactory->DestroyAll();
|
m_pipelineFactory->DestroyAll();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "../VkIncludes.h"
|
#include "../VkIncludes.h"
|
||||||
|
|
||||||
namespace MobileGL::MG_State::GLState {
|
namespace MobileGL::MG_State::GLState {
|
||||||
|
class FramebufferObject;
|
||||||
class ProgramObject;
|
class ProgramObject;
|
||||||
class VertexArrayObject;
|
class VertexArrayObject;
|
||||||
} // namespace MobileGL::MG_State::GLState
|
} // namespace MobileGL::MG_State::GLState
|
||||||
@@ -125,7 +126,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
||||||
|
|
||||||
Vector<VkFramebuffer> m_framebuffers;
|
|
||||||
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||||
Vector<VkImage> m_depthStencilImages;
|
Vector<VkImage> m_depthStencilImages;
|
||||||
Vector<VkDeviceMemory> m_depthStencilImageMemories;
|
Vector<VkDeviceMemory> m_depthStencilImageMemories;
|
||||||
@@ -172,15 +172,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void CreateDepthStencilResources();
|
void CreateDepthStencilResources();
|
||||||
void DestroyDepthStencilResources();
|
void DestroyDepthStencilResources();
|
||||||
VkRenderPass GetDefaultLoadRenderPass() const;
|
VkRenderPass GetDefaultLoadRenderPass() const;
|
||||||
void CreateDefaultFramebuffers();
|
Bool GetDefaultRenderTargetForCurrentImage(VkRenderPass& outRenderPass, VkFramebuffer& outFramebuffer,
|
||||||
|
VkExtent2D& outExtent, VkFormat& outDepthStencilFormat) const;
|
||||||
|
Bool EnsureOffscreenRenderTarget(Uint glFboExternalIndex, const MG_State::GLState::FramebufferObject& glFbo,
|
||||||
|
VkRenderPass& outRenderPass, VkFramebuffer& outFramebuffer,
|
||||||
|
VkExtent2D& outExtent, VkFormat& outDepthStencilFormat);
|
||||||
void PrepareDemoPipeline();
|
void PrepareDemoPipeline();
|
||||||
VkPipeline GetOrCreatePipeline(const MG_State::GLState::ProgramObject& program, VkPipelineLayout pipelineLayout,
|
VkPipeline GetOrCreatePipeline(const MG_State::GLState::ProgramObject& program, VkPipelineLayout pipelineLayout,
|
||||||
Uint64 vertexInputHash,
|
Uint64 vertexInputHash,
|
||||||
const VkPipelineVertexInputStateCreateInfo& vertexInputState);
|
const VkPipelineVertexInputStateCreateInfo& vertexInputState);
|
||||||
void TransitionSwapchainImageToColorAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
void TransitionSwapchainImageToColorAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
||||||
void TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
void TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
||||||
void RecordColorClear(VkCommandBuffer commandBuffer, const VkClearColorValue& clearColor);
|
|
||||||
void RecordDepthStencilClear(VkCommandBuffer commandBuffer, GLbitfield mask, Float depth, Uint32 stencil);
|
|
||||||
void EndFrameRecordingIfNeeded();
|
void EndFrameRecordingIfNeeded();
|
||||||
void DeferDestroyBuffer(VkBufferObject& buffer);
|
void DeferDestroyBuffer(VkBufferObject& buffer);
|
||||||
void CollectDeferredBufferReleases(Uint32 frameIndex);
|
void CollectDeferredBufferReleases(Uint32 frameIndex);
|
||||||
|
|||||||
Reference in New Issue
Block a user