From ab1a2d05c347ebb33bdfeb90b14a9e6be8231a6a Mon Sep 17 00:00:00 2001 From: emil28092005 Date: Fri, 19 Jun 2026 08:59:22 +0300 Subject: [PATCH] fix: enable imageCubeArray feature + transition all 24 shadow layers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two validation errors fixed: 1. imageCubeArray feature not enabled → added VkPhysicalDeviceImageCubeArrayFeatures to device creation chain (pNext: cubeArray → sync2 → dynamicRendering) 2. Shadow layers 18-23 in UNDEFINED layout → transition ALL 24 layers (MaxShadowLights * 6) instead of only numShadowLights * 6 Descriptor references all 24 layers via CubeArray view --- Videos/cortex_20260619_085721.mp4 | Bin 0 -> 261 bytes src/Engine.Graphics.Vulkan/VulkanContext.cs | 9 ++++++++- src/Engine.Graphics.Vulkan/VulkanEnums.cs | 1 + src/Engine.Graphics.Vulkan/VulkanRenderer.cs | 7 ++++--- src/Engine.Graphics.Vulkan/VulkanStructs.cs | 8 ++++++++ 5 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 Videos/cortex_20260619_085721.mp4 diff --git a/Videos/cortex_20260619_085721.mp4 b/Videos/cortex_20260619_085721.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..862f49648777ee248bc8b232c07d0600e621c1fa GIT binary patch literal 261 zcmZQzU{FXasVvAW&d+6FU}6B#Kx~v)mTZ_?U}DI?z`&7Kl$r{nb5jyafb`Ye{QNQ? zos(OZkpiTV0P_nlhmnB+h!6mU0~AK%J0MhIV=(~*6H8M{5`lDNZYr1tsZ-2I$teOc yKp;0Ivna8kAP2&OkUE(;#UKZ(tSrgT2huV?_k#=pTkn%tmS$$8XRK#vU;qH;LL|HZ literal 0 HcmV?d00001 diff --git a/src/Engine.Graphics.Vulkan/VulkanContext.cs b/src/Engine.Graphics.Vulkan/VulkanContext.cs index 59ecd41..4cc2bf6 100644 --- a/src/Engine.Graphics.Vulkan/VulkanContext.cs +++ b/src/Engine.Graphics.Vulkan/VulkanContext.cs @@ -305,10 +305,17 @@ internal sealed unsafe class VulkanContext : IDisposable synchronization2 = VkBool32.True, }; + var cubeArrayFeatures = new VkPhysicalDeviceImageCubeArrayFeatures + { + sType = VkStructureType.PhysicalDeviceImageCubeArrayFeatures, + pNext = (nint)(&sync2Features), + imageCubeArray = VkBool32.True, + }; + var renderingFeatures = new VkPhysicalDeviceDynamicRenderingFeatures { sType = VkStructureType.PhysicalDeviceDynamicRenderingFeatures, - pNext = (nint)(&sync2Features), + pNext = (nint)(&cubeArrayFeatures), dynamicRendering = VkBool32.True, }; diff --git a/src/Engine.Graphics.Vulkan/VulkanEnums.cs b/src/Engine.Graphics.Vulkan/VulkanEnums.cs index 028b6b0..03bc1ed 100644 --- a/src/Engine.Graphics.Vulkan/VulkanEnums.cs +++ b/src/Engine.Graphics.Vulkan/VulkanEnums.cs @@ -78,6 +78,7 @@ public enum VkStructureType : int BufferMemoryBarrier2 = 1000314001, DependencyInfo = 1000314003, PhysicalDeviceDynamicRenderingFeatures = 1000044003, + PhysicalDeviceImageCubeArrayFeatures = 1000056000, PhysicalDeviceSynchronization2Features = 1000314007, } diff --git a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs index b2b666e..8ca22cb 100644 --- a/src/Engine.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Engine.Graphics.Vulkan/VulkanRenderer.cs @@ -308,12 +308,13 @@ public sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreensh // === SHADOW CUBEMAP ARRAY PASSES (numShadowLights × 6 faces) === int totalLayers = numShadowLights * 6; + // Always transition ALL layers (24) to avoid UNDEFINED layout errors for unused layers TransitionImageLayout(cmd, _shadowMap.ColorImage, VkImageLayout.Undefined, VkImageLayout.ColorAttachmentOptimal, - 0, 0, 0x400, 0x100, (uint)totalLayers); + 0, 0, 0x400, 0x100, (uint)(VulkanShadowMap.MaxShadowLights * 6)); TransitionImageLayoutDepth(cmd, _shadowMap.DepthImage, VkImageLayout.Undefined, VkImageLayout.DepthStencilAttachmentOptimal, - 0, 0, 0x100, 0x200, (uint)totalLayers); + 0, 0, 0x100, 0x200, (uint)(VulkanShadowMap.MaxShadowLights * 6)); for (int lightIdx = 0; lightIdx < numShadowLights; lightIdx++) { @@ -422,7 +423,7 @@ public sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreensh // Transition shadow color array: ColorAttachmentOptimal → ShaderReadOnlyOptimal TransitionImageLayout(cmd, _shadowMap.ColorImage, VkImageLayout.ColorAttachmentOptimal, VkImageLayout.ShaderReadOnlyOptimal, - 0x400, 0x100, 0x8, 0x20, (uint)totalLayers); + 0x400, 0x100, 0x8, 0x20, (uint)(VulkanShadowMap.MaxShadowLights * 6)); // === MAIN PASS === TransitionImageLayout(cmd, _swapchain.Images[imageIndex], diff --git a/src/Engine.Graphics.Vulkan/VulkanStructs.cs b/src/Engine.Graphics.Vulkan/VulkanStructs.cs index 446cbed..e6209f6 100644 --- a/src/Engine.Graphics.Vulkan/VulkanStructs.cs +++ b/src/Engine.Graphics.Vulkan/VulkanStructs.cs @@ -208,6 +208,14 @@ public unsafe struct VkPhysicalDeviceDynamicRenderingFeatures public VkBool32 dynamicRendering; } +[StructLayout(LayoutKind.Sequential)] +public unsafe struct VkPhysicalDeviceImageCubeArrayFeatures +{ + public VkStructureType sType; + public nint pNext; + public VkBool32 imageCubeArray; +} + [StructLayout(LayoutKind.Sequential)] public unsafe struct VkPhysicalDeviceSynchronization2Features {