diff --git a/Videos/cortex_20260619_085721.mp4 b/Videos/cortex_20260619_085721.mp4 new file mode 100644 index 0000000..862f496 Binary files /dev/null and b/Videos/cortex_20260619_085721.mp4 differ 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 {