mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_Backend/DirectVulkan): Transition texture for sampling
This commit is contained in:
@@ -461,25 +461,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
(void)commandBuffer;
|
(void)commandBuffer;
|
||||||
MOBILEGL_ASSERT(m_textureManager != nullptr, "ResolveSamplerDescriptor: texture manager is null");
|
MOBILEGL_ASSERT(m_textureManager != nullptr, "ResolveSamplerDescriptor: texture manager is null");
|
||||||
MOBILEGL_ASSERT(m_samplerManager != nullptr, "ResolveSamplerDescriptor: sampler manager is null");
|
MOBILEGL_ASSERT(m_samplerManager != nullptr, "ResolveSamplerDescriptor: sampler manager is null");
|
||||||
if (!MG_State::pGLContext || binding >= layout.samplerUniformLocationByBinding.size()) {
|
SharedPtr<MG_State::GLState::ITextureObject> texture;
|
||||||
|
if (!ResolveSamplerTexture(program, layout, binding, texture)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Int location = layout.samplerUniformLocationByBinding[binding];
|
const Int location = layout.samplerUniformLocationByBinding[binding];
|
||||||
if (location < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Int unit = program.GetUniformSamplerOrImageUnitIndex(static_cast<Uint>(location));
|
const Int unit = program.GetUniformSamplerOrImageUnitIndex(static_cast<Uint>(location));
|
||||||
if (unit < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit);
|
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit);
|
||||||
const auto samplerOverride = textureUnit.GetSamplerObject();
|
const auto samplerOverride = textureUnit.GetSamplerObject();
|
||||||
|
|
||||||
const TextureTarget preferredTarget = layout.samplerTextureTargetByBinding[binding];
|
|
||||||
auto texture = textureUnit.GetBindingSlot(preferredTarget).GetBoundObject();
|
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -504,6 +494,56 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return outImageInfo.sampler != VK_NULL_HANDLE;
|
return outImageInfo.sampler != VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool UniformDescriptorBinder::ResolveSamplerTexture(const MG_State::GLState::ProgramObject& program,
|
||||||
|
const ProgramLayout& layout, Uint32 binding,
|
||||||
|
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) const {
|
||||||
|
outTexture.reset();
|
||||||
|
if (!MG_State::pGLContext || binding >= layout.samplerUniformLocationByBinding.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Int location = layout.samplerUniformLocationByBinding[binding];
|
||||||
|
if (location < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Int unit = program.GetUniformSamplerOrImageUnitIndex(static_cast<Uint>(location));
|
||||||
|
if (unit < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit);
|
||||||
|
const TextureTarget preferredTarget = layout.samplerTextureTargetByBinding[binding];
|
||||||
|
outTexture = textureUnit.GetBindingSlot(preferredTarget).GetBoundObject();
|
||||||
|
return outTexture != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool UniformDescriptorBinder::CollectSampledTextures(const MG_State::GLState::ProgramObject& program,
|
||||||
|
Vector<MG_State::GLState::ITextureObject*>& outTextures) {
|
||||||
|
outTextures.clear();
|
||||||
|
ProgramLayout* layout = GetOrCreateProgramLayout(program);
|
||||||
|
if (layout == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Uint32 binding = 0; binding < m_maxBindings; ++binding) {
|
||||||
|
if (layout->bindingKinds[binding] != BindingKind::CombinedImageSampler) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPtr<MG_State::GLState::ITextureObject> texture;
|
||||||
|
if (!ResolveSamplerTexture(program, *layout, binding, texture) || !texture) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto found = std::find(outTextures.begin(), outTextures.end(), texture.get());
|
||||||
|
if (found == outTextures.end()) {
|
||||||
|
outTextures.push_back(texture.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
UniformDescriptorBinder::ProgramLayout* UniformDescriptorBinder::GetOrCreateProgramLayout(
|
UniformDescriptorBinder::ProgramLayout* UniformDescriptorBinder::GetOrCreateProgramLayout(
|
||||||
const MG_State::GLState::ProgramObject& program) {
|
const MG_State::GLState::ProgramObject& program) {
|
||||||
const Uint64 hash = ComputeProgramHash(program);
|
const Uint64 hash = ComputeProgramHash(program);
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
void BeginFrame(Uint32 frameIndex);
|
void BeginFrame(Uint32 frameIndex);
|
||||||
VkPipelineLayout GetOrCreatePipelineLayout(const MG_State::GLState::ProgramObject& program);
|
VkPipelineLayout GetOrCreatePipelineLayout(const MG_State::GLState::ProgramObject& program);
|
||||||
|
Bool CollectSampledTextures(const MG_State::GLState::ProgramObject& program,
|
||||||
|
Vector<MG_State::GLState::ITextureObject*>& outTextures);
|
||||||
Bool BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
Bool BindProgramUniformBuffers(VkCommandBuffer commandBuffer,
|
||||||
const MG_State::GLState::ProgramObject& program, Uint32 frameIndex);
|
const MG_State::GLState::ProgramObject& program, Uint32 frameIndex);
|
||||||
|
|
||||||
@@ -72,6 +74,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
static TextureTarget UniformTypeToTextureTarget(GLenum glType);
|
static TextureTarget UniformTypeToTextureTarget(GLenum glType);
|
||||||
Bool ReflectSamplerBindings(const MG_State::GLState::ProgramObject& program, ProgramLayout& layout) const;
|
Bool ReflectSamplerBindings(const MG_State::GLState::ProgramObject& program, ProgramLayout& layout) const;
|
||||||
Bool ReflectGlobalUboBinding(const MG_State::GLState::ProgramObject& program, ProgramLayout& layout) const;
|
Bool ReflectGlobalUboBinding(const MG_State::GLState::ProgramObject& program, ProgramLayout& layout) const;
|
||||||
|
Bool ResolveSamplerTexture(const MG_State::GLState::ProgramObject& program, const ProgramLayout& layout,
|
||||||
|
Uint32 binding, SharedPtr<MG_State::GLState::ITextureObject>& outTexture) const;
|
||||||
Bool ResolveSamplerDescriptor(VkCommandBuffer commandBuffer, const MG_State::GLState::ProgramObject& program,
|
Bool ResolveSamplerDescriptor(VkCommandBuffer commandBuffer, const MG_State::GLState::ProgramObject& program,
|
||||||
const ProgramLayout& layout, Uint32 binding,
|
const ProgramLayout& layout, Uint32 binding,
|
||||||
VkDescriptorImageInfo& outImageInfo) const;
|
VkDescriptorImageInfo& outImageInfo) const;
|
||||||
|
|||||||
@@ -12,6 +12,19 @@
|
|||||||
#include "MG_Util/Converters/MGToVk/TextureEnumConverter.h"
|
#include "MG_Util/Converters/MGToVk/TextureEnumConverter.h"
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
static Bool IsValidSampledImageLayout(VkImageLayout layout) {
|
||||||
|
switch (layout) {
|
||||||
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||||
|
case VK_IMAGE_LAYOUT_GENERAL:
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bool VkTextureManager::Initialize(const InitInfo& initInfo) {
|
Bool VkTextureManager::Initialize(const InitInfo& initInfo) {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
@@ -69,6 +82,44 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
it->second.layout = newLayout;
|
it->second.layout = newLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool VkTextureManager::TransitionTextureForSampling(VkCommandBuffer commandBuffer, MG_State::GLState::ITextureObject& texture) {
|
||||||
|
TextureResource* resource = SyncTextureAndGetDescriptor(texture);
|
||||||
|
if (resource == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (IsValidSampledImageLayout(resource->layout)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageLayout targetLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
VkAccessFlags srcAccessMask = 0;
|
||||||
|
if ((resource->aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||||
|
MOBILEGL_ASSERT(resource->layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
"TransitionTextureForSampling: unsupported color layout=%d for textureId=%d",
|
||||||
|
static_cast<Int>(resource->layout), texture.GetExternalIndex());
|
||||||
|
srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
targetLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
} else if ((resource->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) {
|
||||||
|
MOBILEGL_ASSERT(resource->layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||||
|
"TransitionTextureForSampling: unsupported depth/stencil layout=%d for textureId=%d",
|
||||||
|
static_cast<Int>(resource->layout), texture.GetExternalIndex());
|
||||||
|
srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
targetLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||||
|
} else {
|
||||||
|
MOBILEGL_ASSERT(false, "TransitionTextureForSampling: unsupported aspect mask=0x%x for textureId=%d",
|
||||||
|
static_cast<Uint32>(resource->aspect), texture.GetExternalIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Bool ok = TransitionImageLayout(commandBuffer, resource->image, resource->layout, targetLayout, srcStageMask,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, srcAccessMask,
|
||||||
|
VK_ACCESS_SHADER_READ_BIT, resource->aspect);
|
||||||
|
MOBILEGL_ASSERT(ok, "TransitionTextureForSampling: transition failed for textureId=%d", texture.GetExternalIndex());
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
Bool VkTextureManager::TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image,
|
Bool VkTextureManager::TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image,
|
||||||
VkImageLayout& trackedLayout, VkImageLayout newLayout,
|
VkImageLayout& trackedLayout, VkImageLayout newLayout,
|
||||||
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
|
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public:
|
|||||||
TextureResource* SyncTextureAndGetDescriptor(
|
TextureResource* SyncTextureAndGetDescriptor(
|
||||||
MG_State::GLState::ITextureObject& texture);
|
MG_State::GLState::ITextureObject& texture);
|
||||||
void UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout);
|
void UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout);
|
||||||
|
Bool TransitionTextureForSampling(VkCommandBuffer commandBuffer, MG_State::GLState::ITextureObject& texture);
|
||||||
|
|
||||||
static Bool TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout& trackedLayout,
|
static Bool TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout& trackedLayout,
|
||||||
VkImageLayout newLayout, VkPipelineStageFlags srcStageMask,
|
VkImageLayout newLayout, VkPipelineStageFlags srcStageMask,
|
||||||
|
|||||||
@@ -405,8 +405,25 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_uniformDescriptorBinder->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
m_uniformDescriptorBinder->BeginFrame(m_frameContext.GetCurrentFrameIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin render pass, and handle clear
|
|
||||||
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
||||||
|
Vector<MG_State::GLState::ITextureObject*> sampledTextures;
|
||||||
|
Bool hasSampledTextures = m_uniformDescriptorBinder->CollectSampledTextures(program, sampledTextures);
|
||||||
|
MOBILEGL_ASSERT(hasSampledTextures, "%s: CollectSampledTextures failed", __func__);
|
||||||
|
if (activeRenderPass && !sampledTextures.empty()) {
|
||||||
|
VkRenderPassManager::EndRenderPass(frame.commandBuffer);
|
||||||
|
activeRenderPass = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* sampledTexture : sampledTextures) {
|
||||||
|
if (!sampledTexture) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const Bool ready = m_textureManager->TransitionTextureForSampling(frame.commandBuffer, *sampledTexture);
|
||||||
|
MOBILEGL_ASSERT(ready, "%s: TransitionTextureForSampling failed for textureId=%d",
|
||||||
|
__func__, sampledTexture->GetExternalIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin render pass, and handle clear
|
||||||
|
|
||||||
if (activeRenderPass && (activeRenderPass == &renderPassEntry || activeRenderPass->CompatibleWith(renderPassEntry))) {
|
if (activeRenderPass && (activeRenderPass == &renderPassEntry || activeRenderPass->CompatibleWith(renderPassEntry))) {
|
||||||
ClearAttachmentsOnActiveRenderPass(frame.commandBuffer, renderPassEntry);
|
ClearAttachmentsOnActiveRenderPass(frame.commandBuffer, renderPassEntry);
|
||||||
|
|||||||
Reference in New Issue
Block a user