mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 20:58: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;
|
||||
}
|
||||
|
||||
Bool VkFramebufferManager::GetOffscreenRenderTarget(Uint glFboExternalIndex, VkRenderPass& outRenderPass,
|
||||
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
||||
VkFormat& outDepthStencilFormat) const {
|
||||
Bool VkFramebufferManager::GetOffscreenRenderSurface(Uint glFboExternalIndex, VkImageView& outColorView,
|
||||
VkFormat& outColorFormat, VkImageView& outDepthStencilView,
|
||||
VkFormat& outDepthStencilFormat, VkExtent2D& outExtent) const {
|
||||
auto it = m_offscreenColorTargets.find(glFboExternalIndex);
|
||||
if (it == m_offscreenColorTargets.end() || it->second.framebuffer == VK_NULL_HANDLE ||
|
||||
it->second.renderPassLoad == VK_NULL_HANDLE) {
|
||||
if (it == m_offscreenColorTargets.end() || it->second.imageView == VK_NULL_HANDLE) {
|
||||
return false;
|
||||
}
|
||||
outRenderPass = it->second.renderPassLoad;
|
||||
outFramebuffer = it->second.framebuffer;
|
||||
outColorView = it->second.imageView;
|
||||
outColorFormat = it->second.format;
|
||||
outDepthStencilView = it->second.depthStencilImageView;
|
||||
outExtent = it->second.extent;
|
||||
outDepthStencilFormat = it->second.depthStencilFormat;
|
||||
return true;
|
||||
@@ -378,76 +378,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
"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.extent = {static_cast<Uint32>(size.x()), static_cast<Uint32>(size.y())};
|
||||
target.format = format;
|
||||
@@ -461,14 +391,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
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) {
|
||||
vkDestroyImageView(m_device, target.imageView, nullptr);
|
||||
target.imageView = VK_NULL_HANDLE;
|
||||
|
||||
@@ -39,9 +39,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Bool GetOffscreenDepthStencilImage(Uint glFboExternalIndex, VkImage& outImage, VkExtent2D& outExtent,
|
||||
VkFormat& outFormat) const;
|
||||
Bool GetOffscreenColorViewByTexture(Uint textureExternalIndex, VkImageView& outImageView) const;
|
||||
Bool GetOffscreenRenderTarget(Uint glFboExternalIndex, VkRenderPass& outRenderPass,
|
||||
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
||||
VkFormat& outDepthStencilFormat) const;
|
||||
Bool GetOffscreenRenderSurface(Uint glFboExternalIndex, VkImageView& outColorView, VkFormat& outColorFormat,
|
||||
VkImageView& outDepthStencilView, VkFormat& outDepthStencilFormat,
|
||||
VkExtent2D& outExtent) const;
|
||||
|
||||
private:
|
||||
struct OffscreenColorTarget {
|
||||
@@ -56,8 +56,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkImageView depthStencilImageView = VK_NULL_HANDLE;
|
||||
VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
VkRenderPass renderPassLoad = VK_NULL_HANDLE;
|
||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||
Uint16 glObjectVersion = 0;
|
||||
Uint colorTextureExternalIndex = 0;
|
||||
};
|
||||
|
||||
@@ -27,6 +27,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
void VkRenderPassManager::Shutdown() {
|
||||
DestroyDefaultFramebuffers();
|
||||
for (auto& [_, target] : m_offscreenRenderTargets) {
|
||||
DestroyOffscreenRenderTarget(target);
|
||||
}
|
||||
m_offscreenRenderTargets.clear();
|
||||
|
||||
if (m_device != VK_NULL_HANDLE) {
|
||||
if (m_renderPassClear != VK_NULL_HANDLE) {
|
||||
vkDestroyRenderPass(m_device, m_renderPassClear, nullptr);
|
||||
@@ -40,9 +46,202 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
m_renderPassLoad = VK_NULL_HANDLE;
|
||||
m_colorFormat = VK_FORMAT_UNDEFINED;
|
||||
m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
m_defaultExtent = {0, 0};
|
||||
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 {
|
||||
return m_renderPassLoad;
|
||||
}
|
||||
@@ -56,24 +255,34 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MOBILEGL_ASSERT(m_colorFormat != VK_FORMAT_UNDEFINED, "VkRenderPassManager: color format is undefined");
|
||||
MOBILEGL_ASSERT(m_depthStencilFormat != VK_FORMAT_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{};
|
||||
color.format = m_colorFormat;
|
||||
color.format = colorFormat;
|
||||
color.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
color.loadOp = colorLoadOp;
|
||||
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
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{};
|
||||
depthStencil.format = m_depthStencilFormat;
|
||||
depthStencil.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
depthStencil.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthStencil.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
if (hasDepthStencil) {
|
||||
depthStencil.format = depthStencilFormat;
|
||||
depthStencil.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
depthStencil.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.initialLayout = 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 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.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &colorRef;
|
||||
subpass.pDepthStencilAttachment = &depthStencilRef;
|
||||
if (hasDepthStencil) {
|
||||
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};
|
||||
createInfo.attachmentCount = 2;
|
||||
createInfo.pAttachments = attachments;
|
||||
createInfo.attachmentCount = attachmentCount;
|
||||
createInfo.pAttachments = attachments.data();
|
||||
createInfo.subpassCount = 1;
|
||||
createInfo.pSubpasses = &subpass;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -20,19 +20,67 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
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);
|
||||
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 GetClearRenderPass() const;
|
||||
|
||||
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 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;
|
||||
VkFormat m_colorFormat = VK_FORMAT_UNDEFINED;
|
||||
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
VkRenderPass m_renderPassLoad = 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
|
||||
|
||||
@@ -254,10 +254,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
m_textureSamplerManager.reset();
|
||||
}
|
||||
m_vertexInputStateFactory.reset();
|
||||
if (m_framebufferManager) {
|
||||
m_framebufferManager->Shutdown();
|
||||
m_framebufferManager.reset();
|
||||
}
|
||||
for (auto& buffer : m_frameVertexUploadBuffers) {
|
||||
buffer.Destroy();
|
||||
}
|
||||
@@ -283,6 +279,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
ShutdownSwapchain();
|
||||
m_renderPassManager.reset();
|
||||
if (m_framebufferManager) {
|
||||
m_framebufferManager->Shutdown();
|
||||
m_framebufferManager.reset();
|
||||
}
|
||||
|
||||
if (m_commandPool != VK_NULL_HANDLE) {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (m_depthStencilImageLayouts.empty()) {
|
||||
return;
|
||||
@@ -487,7 +441,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
(drawTargetsDefault != m_activeRenderTargetIsDefault) ||
|
||||
(!drawTargetsDefault && m_activeDrawFboExternalIndex != drawFboExternalIndex);
|
||||
if (activeTargetMismatch) {
|
||||
vkCmdEndRenderPass(frame.commandBuffer);
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "EnsureFrameRecordingStarted: manager is null");
|
||||
m_renderPassManager->EndRenderPass(frame.commandBuffer);
|
||||
if (m_activeRenderTargetIsDefault) {
|
||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
}
|
||||
@@ -514,15 +469,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkCommandBuffer& commandBuffer = *commandBufferPtr;
|
||||
|
||||
if (!drawTargetsDefault) {
|
||||
if (!m_framebufferManager || !drawFbo) {
|
||||
if (!m_framebufferManager || !m_renderPassManager || !drawFbo) {
|
||||
MGLOG_D("EnsureFrameRecordingStarted skipped: offscreen draw target is unavailable");
|
||||
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
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
||||
VkExtent2D offscreenExtent{};
|
||||
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
if (!m_framebufferManager->GetOffscreenRenderTarget(drawFboExternalIndex, offscreenRenderPass,
|
||||
offscreenFramebuffer, offscreenExtent,
|
||||
offscreenDepthStencilFormat)) {
|
||||
if (!EnsureOffscreenRenderTarget(drawFboExternalIndex, *drawFbo, offscreenRenderPass, offscreenFramebuffer,
|
||||
offscreenExtent, offscreenDepthStencilFormat)) {
|
||||
MGLOG_D("EnsureFrameRecordingStarted skipped: offscreen render target for FBO %u is unavailable",
|
||||
drawFboExternalIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = offscreenRenderPass;
|
||||
renderPassInfo.framebuffer = offscreenFramebuffer;
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = offscreenExtent;
|
||||
renderPassInfo.clearValueCount = 0;
|
||||
renderPassInfo.pClearValues = nullptr;
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
if (!m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer, drawFboExternalIndex)) {
|
||||
MGLOG_D("EnsureFrameRecordingStarted skipped: failed to transition offscreen FBO %u for attachment",
|
||||
drawFboExternalIndex);
|
||||
return;
|
||||
}
|
||||
m_renderPassManager->BeginRenderPass(commandBuffer, offscreenRenderPass, offscreenFramebuffer,
|
||||
offscreenExtent);
|
||||
m_isMainRenderPassActive = true;
|
||||
m_activeRenderPass = offscreenRenderPass;
|
||||
m_activeRenderExtent = offscreenExtent;
|
||||
@@ -585,12 +526,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
auto pendingIt = m_pendingClears.find(drawTargetKey);
|
||||
if (pendingIt != m_pendingClears.end()) {
|
||||
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;
|
||||
}
|
||||
if ((pendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||
RecordDepthStencilClear(commandBuffer, pendingIt->second.mask, pendingIt->second.depth,
|
||||
pendingIt->second.stencil);
|
||||
m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent,
|
||||
pendingIt->second.mask, pendingIt->second.depth,
|
||||
pendingIt->second.stencil, m_activeDepthStencilFormat);
|
||||
pendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
if (pendingIt->second.mask == 0) {
|
||||
@@ -603,30 +545,33 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
||||
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
||||
renderPassInfo.clearValueCount = 0;
|
||||
renderPassInfo.pClearValues = nullptr;
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
VkRenderPass defaultRenderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer defaultFramebuffer = VK_NULL_HANDLE;
|
||||
VkExtent2D defaultExtent{};
|
||||
VkFormat defaultDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
if (!GetDefaultRenderTargetForCurrentImage(defaultRenderPass, defaultFramebuffer, defaultExtent,
|
||||
defaultDepthStencilFormat)) {
|
||||
MGLOG_D("EnsureFrameRecordingStarted skipped: default render target unavailable");
|
||||
return;
|
||||
}
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "EnsureFrameRecordingStarted: manager is null");
|
||||
m_renderPassManager->BeginRenderPass(commandBuffer, defaultRenderPass, defaultFramebuffer, defaultExtent);
|
||||
m_isMainRenderPassActive = true;
|
||||
m_activeRenderPass = renderPassInfo.renderPass;
|
||||
m_activeRenderExtent = renderPassInfo.renderArea.extent;
|
||||
m_activeDepthStencilFormat = m_depthStencilFormat;
|
||||
m_activeRenderPass = defaultRenderPass;
|
||||
m_activeRenderExtent = defaultExtent;
|
||||
m_activeDepthStencilFormat = defaultDepthStencilFormat;
|
||||
m_activeRenderTargetIsDefault = true;
|
||||
m_activeDrawFboExternalIndex = drawFboExternalIndex;
|
||||
auto pendingIt = m_pendingClears.find(drawTargetKey);
|
||||
if (pendingIt != m_pendingClears.end()) {
|
||||
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;
|
||||
}
|
||||
if ((pendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||
RecordDepthStencilClear(commandBuffer, pendingIt->second.mask, pendingIt->second.depth,
|
||||
pendingIt->second.stencil);
|
||||
m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent,
|
||||
pendingIt->second.mask, pendingIt->second.depth,
|
||||
pendingIt->second.stencil, m_activeDepthStencilFormat);
|
||||
pendingIt->second.mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
if (pendingIt->second.mask == 0) {
|
||||
@@ -642,7 +587,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
if (m_isMainRenderPassActive) {
|
||||
vkCmdEndRenderPass(frame.commandBuffer);
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "EndFrameRecordingIfNeeded: manager is null");
|
||||
m_renderPassManager->EndRenderPass(frame.commandBuffer);
|
||||
if (m_activeRenderTargetIsDefault) {
|
||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
}
|
||||
@@ -1270,7 +1216,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkCommandBuffer commandBuffer = frame.commandBuffer;
|
||||
if (m_isMainRenderPassActive) {
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "BlitFramebuffer: render pass manager is null");
|
||||
m_renderPassManager->EndRenderPass(commandBuffer);
|
||||
if (m_activeRenderTargetIsDefault) {
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
if (!m_renderPassManager) {
|
||||
MGLOG_W("BlitFramebuffer skipped: render pass manager not available");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto consumePendingClearForTarget = [&](Bool targetIsDefault, Uint targetFboExternalIndex) {
|
||||
const Uint64 pendingKey = BuildPendingClearKey(targetFboExternalIndex, targetIsDefault);
|
||||
@@ -1304,60 +1255,55 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
||||
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
||||
renderPassInfo.clearValueCount = 0;
|
||||
renderPassInfo.pClearValues = nullptr;
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||
VkExtent2D extent{};
|
||||
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
if (!GetDefaultRenderTargetForCurrentImage(renderPass, framebuffer, extent, depthStencilFormat)) {
|
||||
return;
|
||||
}
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "BlitFramebuffer: manager is null");
|
||||
m_renderPassManager->BeginRenderPass(commandBuffer, renderPass, framebuffer, extent);
|
||||
|
||||
m_activeRenderExtent = renderPassInfo.renderArea.extent;
|
||||
m_activeDepthStencilFormat = m_depthStencilFormat;
|
||||
m_activeRenderExtent = extent;
|
||||
m_activeDepthStencilFormat = depthStencilFormat;
|
||||
|
||||
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) {
|
||||
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) {
|
||||
const auto targetFbo = MG_State::pGLContext->GetFramebufferObject(targetFboExternalIndex);
|
||||
if (targetFbo && m_framebufferManager->EnsureOffscreenColorTarget(targetFboExternalIndex, *targetFbo) &&
|
||||
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
||||
VkExtent2D offscreenExtent{};
|
||||
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
if (targetFbo &&
|
||||
EnsureOffscreenRenderTarget(targetFboExternalIndex, *targetFbo, offscreenRenderPass,
|
||||
offscreenFramebuffer, offscreenExtent, offscreenDepthStencilFormat) &&
|
||||
m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer, targetFboExternalIndex)) {
|
||||
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
||||
VkExtent2D offscreenExtent{};
|
||||
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
if (m_framebufferManager->GetOffscreenRenderTarget(targetFboExternalIndex, offscreenRenderPass,
|
||||
offscreenFramebuffer, offscreenExtent,
|
||||
offscreenDepthStencilFormat)) {
|
||||
VkRenderPassBeginInfo offscreenPassInfo{};
|
||||
offscreenPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
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_renderPassManager->BeginRenderPass(commandBuffer, offscreenRenderPass, offscreenFramebuffer,
|
||||
offscreenExtent);
|
||||
|
||||
m_activeRenderExtent = offscreenPassInfo.renderArea.extent;
|
||||
m_activeDepthStencilFormat = offscreenDepthStencilFormat;
|
||||
m_activeRenderExtent = offscreenExtent;
|
||||
m_activeDepthStencilFormat = offscreenDepthStencilFormat;
|
||||
|
||||
if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||
RecordColorClear(commandBuffer, pending.color);
|
||||
}
|
||||
if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||
RecordDepthStencilClear(commandBuffer, pending.mask, pending.depth, pending.stencil);
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) {
|
||||
m_renderPassManager->RecordColorClear(commandBuffer, m_activeRenderExtent, pending.color);
|
||||
}
|
||||
if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||
m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent, pending.mask,
|
||||
pending.depth, pending.stencil,
|
||||
m_activeDepthStencilFormat);
|
||||
}
|
||||
|
||||
m_renderPassManager->EndRenderPass(commandBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1858,6 +1804,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (frame.hasCommandBufferRecorded) {
|
||||
return false;
|
||||
}
|
||||
if (!m_renderPassManager) {
|
||||
return false;
|
||||
}
|
||||
if (!frame.isCommandRecording) {
|
||||
m_frameContext.BeginCommandRecording();
|
||||
if (m_uniformDescriptorBinder) {
|
||||
@@ -1867,7 +1816,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkCommandBuffer commandBuffer = frame.commandBuffer;
|
||||
|
||||
if (m_isMainRenderPassActive) {
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "Present: render pass manager is null");
|
||||
m_renderPassManager->EndRenderPass(commandBuffer);
|
||||
if (m_activeRenderTargetIsDefault) {
|
||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
}
|
||||
@@ -1883,19 +1833,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired);
|
||||
TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired);
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
||||
renderPassInfo.clearValueCount = 0;
|
||||
renderPassInfo.pClearValues = nullptr;
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||
VkExtent2D extent{};
|
||||
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
if (!GetDefaultRenderTargetForCurrentImage(renderPass, framebuffer, extent, depthStencilFormat)) {
|
||||
return false;
|
||||
}
|
||||
m_renderPassManager->BeginRenderPass(commandBuffer, renderPass, framebuffer, extent);
|
||||
m_isMainRenderPassActive = true;
|
||||
m_activeRenderPass = renderPassInfo.renderPass;
|
||||
m_activeRenderExtent = renderPassInfo.renderArea.extent;
|
||||
m_activeDepthStencilFormat = m_depthStencilFormat;
|
||||
m_activeRenderPass = renderPass;
|
||||
m_activeRenderExtent = extent;
|
||||
m_activeDepthStencilFormat = depthStencilFormat;
|
||||
m_activeRenderTargetIsDefault = true;
|
||||
m_activeDrawFboExternalIndex = 0;
|
||||
return true;
|
||||
@@ -1908,21 +1857,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (!pendingFbo) {
|
||||
return false;
|
||||
}
|
||||
if (!m_framebufferManager->EnsureOffscreenColorTarget(targetFboExternalIndex, *pendingFbo)) {
|
||||
return false;
|
||||
}
|
||||
if (!m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer,
|
||||
targetFboExternalIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VkRenderPass offscreenRenderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE;
|
||||
VkExtent2D offscreenExtent{};
|
||||
VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
if (!m_framebufferManager->GetOffscreenRenderTarget(targetFboExternalIndex, offscreenRenderPass,
|
||||
offscreenFramebuffer, offscreenExtent,
|
||||
offscreenDepthStencilFormat)) {
|
||||
if (!EnsureOffscreenRenderTarget(targetFboExternalIndex, *pendingFbo, offscreenRenderPass,
|
||||
offscreenFramebuffer, offscreenExtent, offscreenDepthStencilFormat)) {
|
||||
return false;
|
||||
}
|
||||
if (!m_framebufferManager->TransitionOffscreenColorToAttachment(commandBuffer,
|
||||
targetFboExternalIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1949,15 +1893,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
}
|
||||
|
||||
VkRenderPassBeginInfo offscreenPassInfo{};
|
||||
offscreenPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
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_renderPassManager->BeginRenderPass(commandBuffer, offscreenRenderPass, offscreenFramebuffer,
|
||||
offscreenExtent);
|
||||
m_isMainRenderPassActive = true;
|
||||
m_activeRenderPass = offscreenRenderPass;
|
||||
m_activeRenderExtent = offscreenExtent;
|
||||
@@ -1994,12 +1931,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if ((activePendingIt->second.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) {
|
||||
RecordDepthStencilClear(frame.commandBuffer, activePendingIt->second.mask,
|
||||
activePendingIt->second.depth, activePendingIt->second.stencil);
|
||||
m_renderPassManager->RecordDepthStencilClear(
|
||||
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);
|
||||
}
|
||||
if (activePendingIt->second.mask == 0) {
|
||||
@@ -2541,26 +2480,49 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return renderPass;
|
||||
}
|
||||
|
||||
void VulkanRenderer::CreateDefaultFramebuffers() {
|
||||
// Create framebuffers now (use swapchain imageviews)
|
||||
const auto& imageViews = m_swapchainObject.GetImageViews();
|
||||
const auto swapchainExtent = m_swapchainObject.GetExtent();
|
||||
Vector<VkFramebuffer>& fbs = m_framebuffers;
|
||||
fbs.reserve(imageViews.size());
|
||||
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);
|
||||
Bool VulkanRenderer::GetDefaultRenderTargetForCurrentImage(VkRenderPass& outRenderPass,
|
||||
VkFramebuffer& outFramebuffer, VkExtent2D& outExtent,
|
||||
VkFormat& outDepthStencilFormat) const {
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "GetDefaultRenderTargetForCurrentImage: manager is null");
|
||||
return m_renderPassManager->GetDefaultRenderTarget(m_imageIndexAcquired, outRenderPass, outFramebuffer,
|
||||
outExtent, outDepthStencilFormat);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
MGLOG_D("Default framebuffer created.");
|
||||
|
||||
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() {
|
||||
@@ -2707,11 +2669,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
void VulkanRenderer::ShutdownSwapchain() {
|
||||
for (auto fb : m_framebuffers) {
|
||||
vkDestroyFramebuffer(m_device, fb, nullptr);
|
||||
}
|
||||
m_framebuffers.clear();
|
||||
|
||||
DestroyDepthStencilResources();
|
||||
|
||||
if (m_renderPassManager) {
|
||||
@@ -2746,7 +2703,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
renderPassInitInfo.depthStencilFormat = m_depthStencilFormat;
|
||||
MOBILEGL_ASSERT(m_renderPassManager->Initialize(renderPassInitInfo),
|
||||
"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) {
|
||||
m_pipelineFactory->DestroyAll();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "../VkIncludes.h"
|
||||
|
||||
namespace MobileGL::MG_State::GLState {
|
||||
class FramebufferObject;
|
||||
class ProgramObject;
|
||||
class VertexArrayObject;
|
||||
} // namespace MobileGL::MG_State::GLState
|
||||
@@ -125,7 +126,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
||||
|
||||
Vector<VkFramebuffer> m_framebuffers;
|
||||
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
Vector<VkImage> m_depthStencilImages;
|
||||
Vector<VkDeviceMemory> m_depthStencilImageMemories;
|
||||
@@ -172,15 +172,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void CreateDepthStencilResources();
|
||||
void DestroyDepthStencilResources();
|
||||
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();
|
||||
VkPipeline GetOrCreatePipeline(const MG_State::GLState::ProgramObject& program, VkPipelineLayout pipelineLayout,
|
||||
Uint64 vertexInputHash,
|
||||
const VkPipelineVertexInputStateCreateInfo& vertexInputState);
|
||||
void TransitionSwapchainImageToColorAttachment(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 DeferDestroyBuffer(VkBufferObject& buffer);
|
||||
void CollectDeferredBufferReleases(Uint32 frameIndex);
|
||||
|
||||
Reference in New Issue
Block a user