mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Fix] (MG_Backend/DirectVulkan): query clear color/state inside of RenderPassManager
This commit is contained in:
@@ -47,7 +47,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
QueueClear({
|
QueueClear({
|
||||||
.stencil = clearPayload.stencil,
|
.stencil = clearPayload.stencil,
|
||||||
.attachmentType = FramebufferAttachmentType::Stencil,
|
.attachmentType = FramebufferAttachmentType::Stencil,
|
||||||
}, drawFbo.GetAttachment(FramebufferAttachmentType::Depth).GetTexture());
|
}, drawFbo.GetAttachment(FramebufferAttachmentType::Stencil).GetTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_device(device), m_config(config), m_clearManager(clearManager), m_textureManager(textureManager),
|
m_device(device), m_config(config), m_clearManager(clearManager), m_textureManager(textureManager),
|
||||||
m_swapchainObject(swapchainObject) {
|
m_swapchainObject(swapchainObject) {
|
||||||
RenderPassEntry::s_device = m_device;
|
RenderPassEntry::s_device = m_device;
|
||||||
|
s_clearManager = &m_clearManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPassManager::~VkRenderPassManager() {}
|
VkRenderPassManager::~VkRenderPassManager() {}
|
||||||
@@ -65,8 +66,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &contentPtr, sizeof(contentPtr)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &contentPtr, sizeof(contentPtr)));
|
||||||
|
|
||||||
if (att.IsTexture()) {
|
if (att.IsTexture()) {
|
||||||
auto hasClear = m_clearManager.HasPendingClear(att.GetTexture().get());
|
auto* texture = att.GetTexture().get();
|
||||||
|
auto hasClear = m_clearManager.HasPendingClear(texture);
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &hasClear, sizeof(hasClear)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &hasClear, sizeof(hasClear)));
|
||||||
|
if (hasClear) {
|
||||||
|
ClearAttachmentPayload clearPayload{};
|
||||||
|
Bool hasPayload = m_clearManager.GetPendingClear(texture, clearPayload);
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &hasPayload, sizeof(hasPayload)));
|
||||||
|
if (hasPayload) {
|
||||||
|
XXHASH_VERIFY(XXH64_update(
|
||||||
|
m_hashState, &clearPayload.attachmentType, sizeof(clearPayload.attachmentType)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -103,6 +114,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Int height = 0;
|
Int height = 0;
|
||||||
Vector<VkAttachmentDescription> attachmentDescriptions(validDrawBufCount);
|
Vector<VkAttachmentDescription> attachmentDescriptions(validDrawBufCount);
|
||||||
Vector<VkAttachmentReference> colorAttachmentRefs(validDrawBufCount);
|
Vector<VkAttachmentReference> colorAttachmentRefs(validDrawBufCount);
|
||||||
|
Vector<PendingClearAttachmentInfo> pendingClearAttachments;
|
||||||
Vector<VkTextureManager::TextureResource*> textureResources(validDrawBufCount, nullptr);
|
Vector<VkTextureManager::TextureResource*> textureResources(validDrawBufCount, nullptr);
|
||||||
Vector<VkImageView> attachmentViews(validDrawBufCount, VK_NULL_HANDLE);
|
Vector<VkImageView> attachmentViews(validDrawBufCount, VK_NULL_HANDLE);
|
||||||
// This should automatically work on default & offscreen FBO
|
// This should automatically work on default & offscreen FBO
|
||||||
@@ -128,17 +140,26 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MG_Util::ConvertTextureInternalFormatToVkEnum(
|
MG_Util::ConvertTextureInternalFormatToVkEnum(
|
||||||
texture2d->GetFormat());
|
texture2d->GetFormat());
|
||||||
desc.samples = VK_SAMPLE_COUNT_1_BIT;
|
desc.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
Bool hasClear = m_clearManager.HasPendingClear(texture);
|
ClearAttachmentPayload clearPayload{};
|
||||||
|
Bool hasClear = m_clearManager.GetPendingClear(texture, clearPayload);
|
||||||
desc.loadOp = hasClear ?
|
desc.loadOp = hasClear ?
|
||||||
VK_ATTACHMENT_LOAD_OP_CLEAR :
|
VK_ATTACHMENT_LOAD_OP_CLEAR :
|
||||||
VK_ATTACHMENT_LOAD_OP_LOAD;
|
VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
desc.initialLayout = hasClear ?
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED :
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
desc.finalLayout = isDefaultFbo ?
|
desc.finalLayout = isDefaultFbo ?
|
||||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR :
|
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR :
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
if (hasClear) {
|
||||||
|
pendingClearAttachments.emplace_back(PendingClearAttachmentInfo {
|
||||||
|
.attachmentIndex = static_cast<Uint32>(i),
|
||||||
|
.texture = texture
|
||||||
|
});
|
||||||
|
}
|
||||||
if (width == 0)
|
if (width == 0)
|
||||||
width = texture2d->GetBaseSize().x();
|
width = texture2d->GetBaseSize().x();
|
||||||
if (height == 0)
|
if (height == 0)
|
||||||
@@ -171,19 +192,39 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// Depth attachment description
|
// Depth attachment description
|
||||||
auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth);
|
auto& depthAtt = fbo.GetAttachment(FramebufferAttachmentType::Depth);
|
||||||
VkAttachmentDescription depthAttachmentDescription;
|
VkAttachmentDescription depthAttachmentDescription;
|
||||||
|
VkAttachmentReference depthAttachmentRef;
|
||||||
|
depthAttachmentRef.attachment = VK_ATTACHMENT_UNUSED;
|
||||||
|
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
VkTextureManager::TextureResource* depthTextureResource = nullptr;
|
VkTextureManager::TextureResource* depthTextureResource = nullptr;
|
||||||
if (depthAtt.IsComplete() && depthAtt.IsTexture()) {
|
if (depthAtt.IsComplete() && depthAtt.IsTexture()) {
|
||||||
auto& texture = *depthAtt.GetTexture();
|
auto& texture = *depthAtt.GetTexture();
|
||||||
|
const Uint32 depthAttachmentIndex = static_cast<Uint32>(attachmentDescriptions.size());
|
||||||
|
ClearAttachmentPayload clearPayload{};
|
||||||
|
Bool hasClear = m_clearManager.GetPendingClear(&texture, clearPayload);
|
||||||
|
Bool clearDepth = hasClear && clearPayload.attachmentType == FramebufferAttachmentType::Depth;
|
||||||
|
Bool clearStencil = hasClear && clearPayload.attachmentType == FramebufferAttachmentType::Stencil;
|
||||||
depthAttachmentDescription.flags = 0;
|
depthAttachmentDescription.flags = 0;
|
||||||
depthAttachmentDescription.format =
|
depthAttachmentDescription.format =
|
||||||
MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat());
|
MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat());
|
||||||
depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
|
depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
depthAttachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
depthAttachmentDescription.loadOp = clearDepth ?
|
||||||
|
VK_ATTACHMENT_LOAD_OP_CLEAR :
|
||||||
|
VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
depthAttachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
depthAttachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
depthAttachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
depthAttachmentDescription.stencilLoadOp = clearStencil ?
|
||||||
depthAttachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
VK_ATTACHMENT_LOAD_OP_CLEAR :
|
||||||
depthAttachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
depthAttachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
depthAttachmentDescription.initialLayout = hasClear ?
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED :
|
||||||
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
depthAttachmentDescription.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
depthAttachmentDescription.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
if (hasClear) {
|
||||||
|
pendingClearAttachments.emplace_back(PendingClearAttachmentInfo {
|
||||||
|
.attachmentIndex = depthAttachmentIndex,
|
||||||
|
.texture = &texture
|
||||||
|
});
|
||||||
|
}
|
||||||
if (isDefaultFbo) {
|
if (isDefaultFbo) {
|
||||||
attachmentViews.emplace_back(m_swapchainObject.GetDepthStencilImageView(swapchainImageIndex));
|
attachmentViews.emplace_back(m_swapchainObject.GetDepthStencilImageView(swapchainImageIndex));
|
||||||
} else {
|
} else {
|
||||||
@@ -192,15 +233,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
"GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at depth attachment");
|
"GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at depth attachment");
|
||||||
textureResources.emplace_back(depthTextureResource);
|
textureResources.emplace_back(depthTextureResource);
|
||||||
attachmentViews.emplace_back(depthTextureResource->view);
|
attachmentViews.emplace_back(depthTextureResource->view);
|
||||||
|
if (width == 0 || height == 0) {
|
||||||
|
auto texture2d = static_cast<MG_State::GLState::TextureObject2D*>(&texture);
|
||||||
|
width = texture2d->GetBaseSize().x();
|
||||||
|
height = texture2d->GetBaseSize().y();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
attachmentDescriptions.emplace_back(depthAttachmentDescription);
|
attachmentDescriptions.emplace_back(depthAttachmentDescription);
|
||||||
|
depthAttachmentRef.attachment = depthAttachmentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth attachment ref
|
|
||||||
VkAttachmentReference depthAttachmentRef;
|
|
||||||
depthAttachmentRef.attachment = 1;
|
|
||||||
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
// Subpass
|
// Subpass
|
||||||
VkSubpassDescription subpassDesc;
|
VkSubpassDescription subpassDesc;
|
||||||
subpassDesc.flags = 0;
|
subpassDesc.flags = 0;
|
||||||
@@ -244,7 +286,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferCreateInfo, nullptr, &framebuffer));
|
VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferCreateInfo, nullptr, &framebuffer));
|
||||||
IntVec2 extent = {width, height};
|
IntVec2 extent = {width, height};
|
||||||
RenderPassEntry renderPassEntry {
|
RenderPassEntry renderPassEntry {
|
||||||
renderPass, framebuffer, Move(textureResources), static_cast<Uint32>(attachmentViews.size()), extent, 1 };
|
renderPass,
|
||||||
|
framebuffer,
|
||||||
|
Move(textureResources),
|
||||||
|
Move(pendingClearAttachments),
|
||||||
|
static_cast<Uint32>(attachmentViews.size()),
|
||||||
|
extent,
|
||||||
|
1 };
|
||||||
auto [insertedIt, _] = m_renderPasses.emplace(hash, Move(renderPassEntry));
|
auto [insertedIt, _] = m_renderPasses.emplace(hash, Move(renderPassEntry));
|
||||||
return insertedIt->second;
|
return insertedIt->second;
|
||||||
}
|
}
|
||||||
@@ -260,16 +308,45 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
renderPassBeginInfo.renderArea.extent = {
|
renderPassBeginInfo.renderArea.extent = {
|
||||||
(Uint32)renderPassEntry.extent.x(), (Uint32)renderPassEntry.extent.y() };
|
(Uint32)renderPassEntry.extent.x(), (Uint32)renderPassEntry.extent.y() };
|
||||||
|
|
||||||
// TODO: should query proper clear color
|
Vector<VkClearValue> clearValues(renderPassEntry.attachmentCount);
|
||||||
VkClearValue defaultClearValue;
|
for (auto& clearValue: clearValues) {
|
||||||
defaultClearValue.color = { 0.0f, 0.0f, 0.0f, 1.0f };
|
clearValue.color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
defaultClearValue.depthStencil = { 1.0f, 0 };
|
clearValue.depthStencil = {1.0f, 0};
|
||||||
Vector<VkClearValue> clearValue(renderPassEntry.attachmentCount, defaultClearValue);
|
}
|
||||||
|
if (s_clearManager) {
|
||||||
|
for (const auto& pending: renderPassEntry.pendingClearAttachments) {
|
||||||
|
if (!pending.texture || pending.attachmentIndex >= clearValues.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ClearAttachmentPayload clearPayload{};
|
||||||
|
if (!s_clearManager->GetPendingClear(pending.texture, clearPayload)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (clearPayload.attachmentType >= FramebufferAttachmentType::Color0 &&
|
||||||
|
clearPayload.attachmentType <= FramebufferAttachmentType::Color31) {
|
||||||
|
clearValues[pending.attachmentIndex].color = {
|
||||||
|
clearPayload.color.x(),
|
||||||
|
clearPayload.color.y(),
|
||||||
|
clearPayload.color.z(),
|
||||||
|
clearPayload.color.w()
|
||||||
|
};
|
||||||
|
} else if (clearPayload.attachmentType == FramebufferAttachmentType::Depth) {
|
||||||
|
clearValues[pending.attachmentIndex].depthStencil.depth = clearPayload.depth;
|
||||||
|
} else if (clearPayload.attachmentType == FramebufferAttachmentType::Stencil) {
|
||||||
|
clearValues[pending.attachmentIndex].depthStencil.stencil = clearPayload.stencil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderPassBeginInfo.clearValueCount = clearValue.size();
|
renderPassBeginInfo.clearValueCount = static_cast<Uint32>(clearValues.size());
|
||||||
renderPassBeginInfo.pClearValues = clearValue.data();
|
renderPassBeginInfo.pClearValues = clearValues.data();
|
||||||
|
|
||||||
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
if (s_clearManager) {
|
||||||
|
for (const auto& pending: renderPassEntry.pendingClearAttachments) {
|
||||||
|
s_clearManager->PopPendingClear(pending.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
s_activeRenderPass = &renderPassEntry;
|
s_activeRenderPass = &renderPassEntry;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -18,12 +18,18 @@
|
|||||||
#include <Includes.h>
|
#include <Includes.h>
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
struct PendingClearAttachmentInfo {
|
||||||
|
Uint32 attachmentIndex = 0;
|
||||||
|
MG_State::GLState::ITextureObject* texture = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct RenderPassEntry {
|
struct RenderPassEntry {
|
||||||
static inline VkDevice s_device;
|
static inline VkDevice s_device;
|
||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
// Should we hold pointer-to-resource here?
|
// Should we hold pointer-to-resource here?
|
||||||
Vector<VkTextureManager::TextureResource*> textureResources;
|
Vector<VkTextureManager::TextureResource*> textureResources;
|
||||||
|
Vector<PendingClearAttachmentInfo> pendingClearAttachments;
|
||||||
Uint32 attachmentCount = 0;
|
Uint32 attachmentCount = 0;
|
||||||
IntVec2 extent = {0, 0};
|
IntVec2 extent = {0, 0};
|
||||||
Uint32 subpass = 0;
|
Uint32 subpass = 0;
|
||||||
@@ -34,6 +40,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
std::swap(renderPass, that.renderPass);
|
std::swap(renderPass, that.renderPass);
|
||||||
std::swap(framebuffer, that.framebuffer);
|
std::swap(framebuffer, that.framebuffer);
|
||||||
std::swap(textureResources, that.textureResources);
|
std::swap(textureResources, that.textureResources);
|
||||||
|
std::swap(pendingClearAttachments, that.pendingClearAttachments);
|
||||||
std::swap(attachmentCount, that.attachmentCount);
|
std::swap(attachmentCount, that.attachmentCount);
|
||||||
std::swap(extent, that.extent);
|
std::swap(extent, that.extent);
|
||||||
std::swap(subpass, that.subpass);
|
std::swap(subpass, that.subpass);
|
||||||
@@ -42,11 +49,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkRenderPass renderpass,
|
VkRenderPass renderpass,
|
||||||
VkFramebuffer framebuffer,
|
VkFramebuffer framebuffer,
|
||||||
const std::vector<VkTextureManager::TextureResource*>& textureResources,
|
const std::vector<VkTextureManager::TextureResource*>& textureResources,
|
||||||
|
const Vector<PendingClearAttachmentInfo>& pendingClearAttachments,
|
||||||
Uint32 attachmentCount,
|
Uint32 attachmentCount,
|
||||||
IntVec2 extent, int subpass):
|
IntVec2 extent, int subpass):
|
||||||
renderPass(renderpass),
|
renderPass(renderpass),
|
||||||
framebuffer(framebuffer),
|
framebuffer(framebuffer),
|
||||||
textureResources(Move(textureResources)),
|
textureResources(Move(textureResources)),
|
||||||
|
pendingClearAttachments(Move(pendingClearAttachments)),
|
||||||
attachmentCount(attachmentCount),
|
attachmentCount(attachmentCount),
|
||||||
extent(extent),
|
extent(extent),
|
||||||
subpass(subpass)
|
subpass(subpass)
|
||||||
@@ -87,5 +96,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
UnorderedMap<Uint64, RenderPassEntry> m_renderPasses;
|
UnorderedMap<Uint64, RenderPassEntry> m_renderPasses;
|
||||||
static inline XXH64_state_t* m_hashState = XXH64_createState();
|
static inline XXH64_state_t* m_hashState = XXH64_createState();
|
||||||
static inline RenderPassEntry* s_activeRenderPass = nullptr;
|
static inline RenderPassEntry* s_activeRenderPass = nullptr;
|
||||||
|
static inline VkClearManager* s_clearManager = nullptr;
|
||||||
};
|
};
|
||||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
|
|||||||
Reference in New Issue
Block a user