mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Fix] (MG_Backend): resolve a framebuffer attachment's layer in the Vulkan blit bindings
ResolveAttachmentBaseArrayLayer answered zero for everything but a cube map face, so every blit, copy and glReadPixels against a layered attachment read layer zero whatever was attached. It reads the attachment's layer now. A 3D texture needs the other half of the distinction: its image has arrayLayers == 1 and the GL layer is a z slice, which VkBufferImageCopy will not take as a base array layer. BlitImageBinding carries it separately as depthOffset, and the readback copy region uses it as the image offset's z. Takes textures_copy from failing to passing on DirectVulkan, which is what glCopyTextureSubImage3D needs to see the slice the CTS attached rather than slice zero.
This commit is contained in:
@@ -1235,10 +1235,20 @@ void main() {
|
|||||||
|
|
||||||
static Uint32 ResolveAttachmentBaseArrayLayer(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
|
static Uint32 ResolveAttachmentBaseArrayLayer(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
|
||||||
const TextureUploadTarget uploadTarget = attachment.GetTextureUploadTarget();
|
const TextureUploadTarget uploadTarget = attachment.GetTextureUploadTarget();
|
||||||
if (!IsCubeMapFaceUploadTarget(uploadTarget)) {
|
if (IsCubeMapFaceUploadTarget(uploadTarget)) {
|
||||||
return 0;
|
return static_cast<Uint32>(uploadTarget) - static_cast<Uint32>(TextureUploadTarget::CubeMapPositiveX);
|
||||||
}
|
}
|
||||||
return static_cast<Uint32>(uploadTarget) - static_cast<Uint32>(TextureUploadTarget::CubeMapPositiveX);
|
// Every other layered attachment names its layer directly. Returning 0 regardless made
|
||||||
|
// every blit, copy and ReadPixels against such an attachment read layer zero.
|
||||||
|
return static_cast<Uint32>(std::max(attachment.GetTextureLayer(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// A 3D image has arrayLayers == 1: its "layer" is a z slice, which has to travel as an
|
||||||
|
// image offset rather than a base array layer (VkBufferImageCopy requires baseArrayLayer 0
|
||||||
|
// for VK_IMAGE_TYPE_3D).
|
||||||
|
static Bool AttachmentIsDepthSlice(const MG_State::GLState::FramebufferAttachmentObject& attachment) {
|
||||||
|
return attachment.IsTexture() && attachment.GetTexture() &&
|
||||||
|
attachment.GetTexture()->GetTarget() == TextureTarget::Texture3D;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class BlitSurfaceTransform : Uint32 {
|
enum class BlitSurfaceTransform : Uint32 {
|
||||||
@@ -1259,6 +1269,8 @@ void main() {
|
|||||||
Uint32 mipLevelCount = 1;
|
Uint32 mipLevelCount = 1;
|
||||||
Uint32 baseArrayLayer = 0;
|
Uint32 baseArrayLayer = 0;
|
||||||
Uint32 layerCount = 1;
|
Uint32 layerCount = 1;
|
||||||
|
// z slice for a VK_IMAGE_TYPE_3D source; array attachments use baseArrayLayer instead.
|
||||||
|
Uint32 depthOffset = 0;
|
||||||
const char* label = nullptr;
|
const char* label = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1490,7 +1502,12 @@ void main() {
|
|||||||
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
||||||
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
||||||
outBinding.mipLevelCount = resource->mipLevels;
|
outBinding.mipLevelCount = resource->mipLevels;
|
||||||
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
if (AttachmentIsDepthSlice(attachment)) {
|
||||||
|
outBinding.depthOffset = static_cast<Uint32>(std::max(attachment.GetTextureLayer(), 0));
|
||||||
|
outBinding.baseArrayLayer = 0;
|
||||||
|
} else {
|
||||||
|
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
||||||
|
}
|
||||||
outBinding.layerCount = 1;
|
outBinding.layerCount = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1601,7 +1618,12 @@ void main() {
|
|||||||
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
||||||
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
||||||
outBinding.mipLevelCount = resource->mipLevels;
|
outBinding.mipLevelCount = resource->mipLevels;
|
||||||
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
if (AttachmentIsDepthSlice(attachment)) {
|
||||||
|
outBinding.depthOffset = static_cast<Uint32>(std::max(attachment.GetTextureLayer(), 0));
|
||||||
|
outBinding.baseArrayLayer = 0;
|
||||||
|
} else {
|
||||||
|
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
||||||
|
}
|
||||||
outBinding.layerCount = 1;
|
outBinding.layerCount = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1745,7 +1767,12 @@ void main() {
|
|||||||
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
outBinding.extent = {attachmentExtent.x(), attachmentExtent.y()};
|
||||||
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
outBinding.mipLevel = static_cast<Uint32>(std::max(attachment.GetTextureLevel(), 0));
|
||||||
outBinding.mipLevelCount = 1;
|
outBinding.mipLevelCount = 1;
|
||||||
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
if (AttachmentIsDepthSlice(attachment)) {
|
||||||
|
outBinding.depthOffset = static_cast<Uint32>(std::max(attachment.GetTextureLayer(), 0));
|
||||||
|
outBinding.baseArrayLayer = 0;
|
||||||
|
} else {
|
||||||
|
outBinding.baseArrayLayer = ResolveAttachmentBaseArrayLayer(attachment);
|
||||||
|
}
|
||||||
outBinding.layerCount = 1;
|
outBinding.layerCount = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -7176,7 +7203,7 @@ void main() {
|
|||||||
copyRegion.imageSubresource.mipLevel = srcBinding.mipLevel;
|
copyRegion.imageSubresource.mipLevel = srcBinding.mipLevel;
|
||||||
copyRegion.imageSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
|
copyRegion.imageSubresource.baseArrayLayer = srcBinding.baseArrayLayer;
|
||||||
copyRegion.imageSubresource.layerCount = 1;
|
copyRegion.imageSubresource.layerCount = 1;
|
||||||
copyRegion.imageOffset = {x, y, 0};
|
copyRegion.imageOffset = {x, y, static_cast<Int32>(srcBinding.depthOffset)};
|
||||||
copyRegion.imageExtent = {static_cast<Uint32>(width), static_cast<Uint32>(height), 1};
|
copyRegion.imageExtent = {static_cast<Uint32>(width), static_cast<Uint32>(height), 1};
|
||||||
vkCmdCopyImageToBuffer(frame.commandBuffer, srcBinding.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
vkCmdCopyImageToBuffer(frame.commandBuffer, srcBinding.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
readback.GetHandle(), 1, ©Region);
|
readback.GetHandle(), 1, ©Region);
|
||||||
|
|||||||
Reference in New Issue
Block a user