fix: enable imageCubeArray feature + transition all 24 shadow layers

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
This commit is contained in:
emil28092005
2026-06-19 08:59:22 +03:00
parent d7b6851217
commit ab1a2d05c3
5 changed files with 21 additions and 4 deletions
Binary file not shown.
+8 -1
View File
@@ -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,
};
@@ -78,6 +78,7 @@ public enum VkStructureType : int
BufferMemoryBarrier2 = 1000314001,
DependencyInfo = 1000314003,
PhysicalDeviceDynamicRenderingFeatures = 1000044003,
PhysicalDeviceImageCubeArrayFeatures = 1000056000,
PhysicalDeviceSynchronization2Features = 1000314007,
}
+4 -3
View File
@@ -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],
@@ -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
{