feat: depth buffer + 3D model matrix — rotating cube now looks correct
- Depth image (D32_SFLOAT) + image view created in VulkanSwapchain - VkPipelineDepthStencilStateCreateInfo: depth test + write enabled, CompareOp=Less - Push constant changed from float angle (4B) to mat4 model (64B) - 3D rotation: RotateY * RotateX in renderer, applied via push constant - Vertex shader: gl_Position = vp * model * vec4(pos, 1.0) - Depth attachment in VkRenderingInfo + depth clear (1.0) - Depth image layout transition (Undefined → DepthStencilAttachmentOptimal) - New Vulkan functions: vkCreateImage, vkDestroyImage, vkGetImageMemoryRequirements, vkBindImageMemory - New structs: VkPipelineDepthStencilStateCreateInfo, VkStencilOpState, VkImageCreateInfo - New enums: VkCompareOp, VkImageType, VkImageTiling - 0 validation errors
This commit is contained in:
@@ -10,18 +10,11 @@ layout(row_major, set = 0, binding = 0) uniform CameraUBO {
|
|||||||
mat4 vp;
|
mat4 vp;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(push_constant) uniform PC {
|
layout(row_major, push_constant) uniform PC {
|
||||||
float angle;
|
mat4 model;
|
||||||
} pc;
|
} pc;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float c = cos(pc.angle);
|
gl_Position = vp * pc.model * vec4(inPosition, 1.0);
|
||||||
float s = sin(pc.angle);
|
|
||||||
vec3 rotated = vec3(
|
|
||||||
inPosition.x * c - inPosition.y * s,
|
|
||||||
inPosition.x * s + inPosition.y * c,
|
|
||||||
inPosition.z
|
|
||||||
);
|
|
||||||
gl_Position = vp * vec4(rotated, 1.0);
|
|
||||||
fragColor = inColor;
|
fragColor = inColor;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -47,6 +47,10 @@ internal static unsafe class Vk
|
|||||||
public delegate VkResult VkGetFenceStatus(VkDevice device, VkFence fence);
|
public delegate VkResult VkGetFenceStatus(VkDevice device, VkFence fence);
|
||||||
public delegate VkResult VkCreateBuffer(VkDevice device, VkBufferCreateInfo* pCreateInfo, nint pAllocator, VkBuffer* pBuffer);
|
public delegate VkResult VkCreateBuffer(VkDevice device, VkBufferCreateInfo* pCreateInfo, nint pAllocator, VkBuffer* pBuffer);
|
||||||
public delegate void VkDestroyBuffer(VkDevice device, VkBuffer buffer, nint pAllocator);
|
public delegate void VkDestroyBuffer(VkDevice device, VkBuffer buffer, nint pAllocator);
|
||||||
|
public delegate VkResult VkCreateImage(VkDevice device, VkImageCreateInfo* pCreateInfo, nint pAllocator, VkImage* pImage);
|
||||||
|
public delegate void VkDestroyImage(VkDevice device, VkImage image, nint pAllocator);
|
||||||
|
public delegate void VkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
|
||||||
|
public delegate VkResult VkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, ulong memoryOffset);
|
||||||
public delegate VkResult VkAllocateMemory(VkDevice device, VkMemoryAllocateInfo* pAllocateInfo, nint pAllocator, VkDeviceMemory* pMemory);
|
public delegate VkResult VkAllocateMemory(VkDevice device, VkMemoryAllocateInfo* pAllocateInfo, nint pAllocator, VkDeviceMemory* pMemory);
|
||||||
public delegate void VkFreeMemory(VkDevice device, VkDeviceMemory memory, nint pAllocator);
|
public delegate void VkFreeMemory(VkDevice device, VkDeviceMemory memory, nint pAllocator);
|
||||||
public delegate VkResult VkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, ulong memoryOffset);
|
public delegate VkResult VkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, ulong memoryOffset);
|
||||||
@@ -124,6 +128,10 @@ internal static unsafe class Vk
|
|||||||
public static VkGetFenceStatus vkGetFenceStatus;
|
public static VkGetFenceStatus vkGetFenceStatus;
|
||||||
public static VkCreateBuffer vkCreateBuffer;
|
public static VkCreateBuffer vkCreateBuffer;
|
||||||
public static VkDestroyBuffer vkDestroyBuffer;
|
public static VkDestroyBuffer vkDestroyBuffer;
|
||||||
|
public static VkCreateImage vkCreateImage;
|
||||||
|
public static VkDestroyImage vkDestroyImage;
|
||||||
|
public static VkGetImageMemoryRequirements vkGetImageMemoryRequirements;
|
||||||
|
public static VkBindImageMemory vkBindImageMemory;
|
||||||
public static VkAllocateMemory vkAllocateMemory;
|
public static VkAllocateMemory vkAllocateMemory;
|
||||||
public static VkFreeMemory vkFreeMemory;
|
public static VkFreeMemory vkFreeMemory;
|
||||||
public static VkBindBufferMemory vkBindBufferMemory;
|
public static VkBindBufferMemory vkBindBufferMemory;
|
||||||
@@ -208,6 +216,10 @@ internal static unsafe class Vk
|
|||||||
vkGetFenceStatus = LoadDev<VkGetFenceStatus>(p, "vkGetFenceStatus");
|
vkGetFenceStatus = LoadDev<VkGetFenceStatus>(p, "vkGetFenceStatus");
|
||||||
vkCreateBuffer = LoadDev<VkCreateBuffer>(p, "vkCreateBuffer");
|
vkCreateBuffer = LoadDev<VkCreateBuffer>(p, "vkCreateBuffer");
|
||||||
vkDestroyBuffer = LoadDev<VkDestroyBuffer>(p, "vkDestroyBuffer");
|
vkDestroyBuffer = LoadDev<VkDestroyBuffer>(p, "vkDestroyBuffer");
|
||||||
|
vkCreateImage = LoadDev<VkCreateImage>(p, "vkCreateImage");
|
||||||
|
vkDestroyImage = LoadDev<VkDestroyImage>(p, "vkDestroyImage");
|
||||||
|
vkGetImageMemoryRequirements = LoadDev<VkGetImageMemoryRequirements>(p, "vkGetImageMemoryRequirements");
|
||||||
|
vkBindImageMemory = LoadDev<VkBindImageMemory>(p, "vkBindImageMemory");
|
||||||
vkAllocateMemory = LoadDev<VkAllocateMemory>(p, "vkAllocateMemory");
|
vkAllocateMemory = LoadDev<VkAllocateMemory>(p, "vkAllocateMemory");
|
||||||
vkFreeMemory = LoadDev<VkFreeMemory>(p, "vkFreeMemory");
|
vkFreeMemory = LoadDev<VkFreeMemory>(p, "vkFreeMemory");
|
||||||
vkBindBufferMemory = LoadDev<VkBindBufferMemory>(p, "vkBindBufferMemory");
|
vkBindBufferMemory = LoadDev<VkBindBufferMemory>(p, "vkBindBufferMemory");
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public enum VkStructureType : int
|
|||||||
CommandBufferBeginInfo = 42,
|
CommandBufferBeginInfo = 42,
|
||||||
RenderPassBeginInfo = 43,
|
RenderPassBeginInfo = 43,
|
||||||
ImageViewCreateInfo = 15,
|
ImageViewCreateInfo = 15,
|
||||||
|
ImageCreateInfo = 14,
|
||||||
SemaphoreCreateInfo = 9,
|
SemaphoreCreateInfo = 9,
|
||||||
FenceCreateInfo = 8,
|
FenceCreateInfo = 8,
|
||||||
SwapchainCreateInfoKHR = 1000001000,
|
SwapchainCreateInfoKHR = 1000001000,
|
||||||
@@ -207,6 +208,31 @@ public enum VkFrontFace : int
|
|||||||
Clockwise = 1,
|
Clockwise = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum VkCompareOp : int
|
||||||
|
{
|
||||||
|
Never = 0,
|
||||||
|
Less = 1,
|
||||||
|
Equal = 2,
|
||||||
|
LessOrEqual = 3,
|
||||||
|
Greater = 4,
|
||||||
|
NotEqual = 5,
|
||||||
|
GreaterOrEqual = 6,
|
||||||
|
Always = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VkImageType : int
|
||||||
|
{
|
||||||
|
Type1D = 0,
|
||||||
|
Type2D = 1,
|
||||||
|
Type3D = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VkImageTiling : int
|
||||||
|
{
|
||||||
|
Optimal = 0,
|
||||||
|
Linear = 1,
|
||||||
|
}
|
||||||
|
|
||||||
public enum VkBlendFactor : int
|
public enum VkBlendFactor : int
|
||||||
{
|
{
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
@@ -283,6 +309,8 @@ public enum VkPipelineStageFlags2 : ulong
|
|||||||
public enum VkAccessFlags2 : ulong
|
public enum VkAccessFlags2 : ulong
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
DepthStencilAttachmentWrite = 0x00000400,
|
||||||
|
DepthStencilAttachmentRead = 0x00000200,
|
||||||
ColorAttachmentRead = 0x00000080,
|
ColorAttachmentRead = 0x00000080,
|
||||||
ColorAttachmentWrite = 0x00000100,
|
ColorAttachmentWrite = 0x00000100,
|
||||||
TransferRead = 0x00000800,
|
TransferRead = 0x00000800,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ internal sealed unsafe class VulkanPipeline : IDisposable
|
|||||||
private readonly VkDevice _device;
|
private readonly VkDevice _device;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public VulkanPipeline(VkDevice device, VkFormat colorFormat, byte[] vertSpv, byte[] fragSpv)
|
public VulkanPipeline(VkDevice device, VkFormat colorFormat, VkFormat depthFormat, byte[] vertSpv, byte[] fragSpv)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
VertModule = CreateShaderModule(vertSpv);
|
VertModule = CreateShaderModule(vertSpv);
|
||||||
@@ -115,6 +115,16 @@ internal sealed unsafe class VulkanPipeline : IDisposable
|
|||||||
sampleShadingEnable = VkBool32.False,
|
sampleShadingEnable = VkBool32.False,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var depthStencilState = new VkPipelineDepthStencilStateCreateInfo
|
||||||
|
{
|
||||||
|
sType = VkStructureType.PipelineDepthStencilStateCreateInfo,
|
||||||
|
depthTestEnable = VkBool32.True,
|
||||||
|
depthWriteEnable = VkBool32.True,
|
||||||
|
depthCompareOp = VkCompareOp.Less,
|
||||||
|
depthBoundsTestEnable = VkBool32.False,
|
||||||
|
stencilTestEnable = VkBool32.False,
|
||||||
|
};
|
||||||
|
|
||||||
var blendAttachment = new VkPipelineColorBlendAttachmentState
|
var blendAttachment = new VkPipelineColorBlendAttachmentState
|
||||||
{
|
{
|
||||||
blendEnable = VkBool32.False,
|
blendEnable = VkBool32.False,
|
||||||
@@ -144,7 +154,7 @@ internal sealed unsafe class VulkanPipeline : IDisposable
|
|||||||
{
|
{
|
||||||
stageFlags = VkShaderStageFlags.Vertex,
|
stageFlags = VkShaderStageFlags.Vertex,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
size = 4,
|
size = 64,
|
||||||
};
|
};
|
||||||
|
|
||||||
var descLayout = DescriptorSetLayout;
|
var descLayout = DescriptorSetLayout;
|
||||||
@@ -169,6 +179,7 @@ internal sealed unsafe class VulkanPipeline : IDisposable
|
|||||||
sType = VkStructureType.PipelineRenderingCreateInfo,
|
sType = VkStructureType.PipelineRenderingCreateInfo,
|
||||||
colorAttachmentCount = 1,
|
colorAttachmentCount = 1,
|
||||||
pColorAttachmentFormats = &colorFormat,
|
pColorAttachmentFormats = &colorFormat,
|
||||||
|
depthAttachmentFormat = depthFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
var pipelineInfo = new VkGraphicsPipelineCreateInfo
|
var pipelineInfo = new VkGraphicsPipelineCreateInfo
|
||||||
@@ -182,6 +193,7 @@ internal sealed unsafe class VulkanPipeline : IDisposable
|
|||||||
pViewportState = &viewportState,
|
pViewportState = &viewportState,
|
||||||
pRasterizationState = &rasterizationState,
|
pRasterizationState = &rasterizationState,
|
||||||
pMultisampleState = &multisampleState,
|
pMultisampleState = &multisampleState,
|
||||||
|
pDepthStencilState = &depthStencilState,
|
||||||
pColorBlendState = &colorBlendState,
|
pColorBlendState = &colorBlendState,
|
||||||
pDynamicState = &dynamicState,
|
pDynamicState = &dynamicState,
|
||||||
layout = PipelineLayout,
|
layout = PipelineLayout,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ internal sealed class VulkanRenderContext : IRenderContext
|
|||||||
};
|
};
|
||||||
|
|
||||||
_swapchain = new VulkanSwapchain(_ctx.Device, _ctx.PhysicalDevice, _ctx.Surface,
|
_swapchain = new VulkanSwapchain(_ctx.Device, _ctx.PhysicalDevice, _ctx.Surface,
|
||||||
surfaceFormat, window.Width, window.Height);
|
surfaceFormat, window.Width, window.Height, _ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRenderer CreateRenderer()
|
public IRenderer CreateRenderer()
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
|||||||
var vertSpv = LoadShader("Shaders/triangle.vert.spv");
|
var vertSpv = LoadShader("Shaders/triangle.vert.spv");
|
||||||
var fragSpv = LoadShader("Shaders/triangle.frag.spv");
|
var fragSpv = LoadShader("Shaders/triangle.frag.spv");
|
||||||
|
|
||||||
_pipeline = new VulkanPipeline(ctx.Device, swapchain.Format, vertSpv, fragSpv);
|
_pipeline = new VulkanPipeline(ctx.Device, swapchain.Format, swapchain.DepthFormat, vertSpv, fragSpv);
|
||||||
|
|
||||||
_frameResources = new VulkanFrameResources(ctx.Device, ctx.GraphicsQueueFamilyIndex,
|
_frameResources = new VulkanFrameResources(ctx.Device, ctx.GraphicsQueueFamilyIndex,
|
||||||
swapchain.ImageCount, ctx, _pipeline.DescriptorSetLayout);
|
swapchain.ImageCount, ctx, _pipeline.DescriptorSetLayout);
|
||||||
@@ -109,11 +109,21 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
|||||||
0, 0,
|
0, 0,
|
||||||
0x400, 0x100);
|
0x400, 0x100);
|
||||||
|
|
||||||
|
TransitionImageLayoutDepth(cmd, _swapchain.DepthImage,
|
||||||
|
VkImageLayout.Undefined, VkImageLayout.DepthStencilAttachmentOptimal,
|
||||||
|
0, 0,
|
||||||
|
0x100, 0x200);
|
||||||
|
|
||||||
var clearValue = new VkClearValue
|
var clearValue = new VkClearValue
|
||||||
{
|
{
|
||||||
Color = new VkClearColorValue { Float0 = 0.02f, Float1 = 0.02f, Float2 = 0.02f, Float3 = 1.0f },
|
Color = new VkClearColorValue { Float0 = 0.02f, Float1 = 0.02f, Float2 = 0.02f, Float3 = 1.0f },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var depthClearValue = new VkClearValue
|
||||||
|
{
|
||||||
|
DepthStencil = new VkClearDepthStencilValue { Depth = 1.0f, Stencil = 0 },
|
||||||
|
};
|
||||||
|
|
||||||
var colorAttachment = new VkRenderingAttachmentInfo
|
var colorAttachment = new VkRenderingAttachmentInfo
|
||||||
{
|
{
|
||||||
sType = VkStructureType.RenderingAttachmentInfo,
|
sType = VkStructureType.RenderingAttachmentInfo,
|
||||||
@@ -124,6 +134,16 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
|||||||
clearValue = clearValue,
|
clearValue = clearValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var depthAttachment = new VkRenderingAttachmentInfo
|
||||||
|
{
|
||||||
|
sType = VkStructureType.RenderingAttachmentInfo,
|
||||||
|
imageView = _swapchain.DepthImageView,
|
||||||
|
imageLayout = VkImageLayout.DepthStencilAttachmentOptimal,
|
||||||
|
loadOp = VkAttachmentLoadOp.Clear,
|
||||||
|
storeOp = VkAttachmentStoreOp.Store,
|
||||||
|
clearValue = depthClearValue,
|
||||||
|
};
|
||||||
|
|
||||||
var renderingInfo = new VkRenderingInfo
|
var renderingInfo = new VkRenderingInfo
|
||||||
{
|
{
|
||||||
sType = VkStructureType.RenderingInfo,
|
sType = VkStructureType.RenderingInfo,
|
||||||
@@ -135,6 +155,7 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
|||||||
layerCount = 1,
|
layerCount = 1,
|
||||||
colorAttachmentCount = 1,
|
colorAttachmentCount = 1,
|
||||||
pColorAttachments = &colorAttachment,
|
pColorAttachments = &colorAttachment,
|
||||||
|
pDepthAttachment = &depthAttachment,
|
||||||
};
|
};
|
||||||
|
|
||||||
Vk.vkCmdBeginRendering(cmd, &renderingInfo);
|
Vk.vkCmdBeginRendering(cmd, &renderingInfo);
|
||||||
@@ -168,7 +189,8 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
|||||||
Vk.vkCmdBindIndexBuffer(cmd, _indexBuffer.Buffer, 0, 0);
|
Vk.vkCmdBindIndexBuffer(cmd, _indexBuffer.Buffer, 0, 0);
|
||||||
|
|
||||||
var angle = _totalTime;
|
var angle = _totalTime;
|
||||||
Vk.vkCmdPushConstants(cmd, _pipeline.PipelineLayout, VkShaderStageFlags.Vertex, 0, 4, &angle);
|
var model = Matrix4x4.CreateRotationY(angle) * Matrix4x4.CreateRotationX(angle * 0.5f);
|
||||||
|
Vk.vkCmdPushConstants(cmd, _pipeline.PipelineLayout, VkShaderStageFlags.Vertex, 0, 64, &model);
|
||||||
|
|
||||||
Vk.vkCmdDrawIndexed(cmd, _indexCount, 1, 0, 0, 0);
|
Vk.vkCmdDrawIndexed(cmd, _indexCount, 1, 0, 0, 0);
|
||||||
|
|
||||||
@@ -282,6 +304,39 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
|||||||
Vk.vkCmdPipelineBarrier2(cmd, &depInfo);
|
Vk.vkCmdPipelineBarrier2(cmd, &depInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void TransitionImageLayoutDepth(VkCommandBuffer cmd, VkImage image,
|
||||||
|
VkImageLayout oldLayout, VkImageLayout newLayout,
|
||||||
|
ulong srcStage, ulong srcAccess,
|
||||||
|
ulong dstStage, ulong dstAccess)
|
||||||
|
{
|
||||||
|
var barrier = new VkImageMemoryBarrier2
|
||||||
|
{
|
||||||
|
sType = VkStructureType.ImageMemoryBarrier2,
|
||||||
|
srcStageMask = srcStage,
|
||||||
|
srcAccessMask = srcAccess,
|
||||||
|
dstStageMask = dstStage,
|
||||||
|
dstAccessMask = dstAccess,
|
||||||
|
oldLayout = oldLayout,
|
||||||
|
newLayout = newLayout,
|
||||||
|
image = image,
|
||||||
|
subresourceRange = new VkImageSubresourceRange
|
||||||
|
{
|
||||||
|
AspectMask = VkImageAspectFlags.Depth,
|
||||||
|
LevelCount = 1,
|
||||||
|
LayerCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var depInfo = new VkDependencyInfo
|
||||||
|
{
|
||||||
|
sType = VkStructureType.DependencyInfo,
|
||||||
|
imageMemoryBarrierCount = 1,
|
||||||
|
pImageMemoryBarriers = &barrier,
|
||||||
|
};
|
||||||
|
|
||||||
|
Vk.vkCmdPipelineBarrier2(cmd, &depInfo);
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] LoadShader(string path)
|
private static byte[] LoadShader(string path)
|
||||||
{
|
{
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
|
|||||||
@@ -671,7 +671,7 @@ public unsafe struct VkGraphicsPipelineCreateInfo
|
|||||||
public VkPipelineViewportStateCreateInfo* pViewportState;
|
public VkPipelineViewportStateCreateInfo* pViewportState;
|
||||||
public VkPipelineRasterizationStateCreateInfo* pRasterizationState;
|
public VkPipelineRasterizationStateCreateInfo* pRasterizationState;
|
||||||
public VkPipelineMultisampleStateCreateInfo* pMultisampleState;
|
public VkPipelineMultisampleStateCreateInfo* pMultisampleState;
|
||||||
public nint pDepthStencilState;
|
public VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
|
||||||
public VkPipelineColorBlendStateCreateInfo* pColorBlendState;
|
public VkPipelineColorBlendStateCreateInfo* pColorBlendState;
|
||||||
public VkPipelineDynamicStateCreateInfo* pDynamicState;
|
public VkPipelineDynamicStateCreateInfo* pDynamicState;
|
||||||
public VkPipelineLayout layout;
|
public VkPipelineLayout layout;
|
||||||
@@ -792,7 +792,7 @@ public unsafe struct VkRenderingInfo
|
|||||||
public uint viewMask;
|
public uint viewMask;
|
||||||
public uint colorAttachmentCount;
|
public uint colorAttachmentCount;
|
||||||
public VkRenderingAttachmentInfo* pColorAttachments;
|
public VkRenderingAttachmentInfo* pColorAttachments;
|
||||||
public nint pDepthAttachment;
|
public VkRenderingAttachmentInfo* pDepthAttachment;
|
||||||
public nint pStencilAttachment;
|
public nint pStencilAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,6 +908,55 @@ public unsafe struct VkDebugUtilsMessengerCallbackDataEXT
|
|||||||
public nint pObjects;
|
public nint pObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public unsafe struct VkStencilOpState
|
||||||
|
{
|
||||||
|
public int failOp;
|
||||||
|
public int passOp;
|
||||||
|
public int depthFailOp;
|
||||||
|
public int compareOp;
|
||||||
|
public uint compareMask;
|
||||||
|
public uint writeMask;
|
||||||
|
public uint reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public unsafe struct VkPipelineDepthStencilStateCreateInfo
|
||||||
|
{
|
||||||
|
public VkStructureType sType;
|
||||||
|
public nint pNext;
|
||||||
|
public uint flags;
|
||||||
|
public VkBool32 depthTestEnable;
|
||||||
|
public VkBool32 depthWriteEnable;
|
||||||
|
public VkCompareOp depthCompareOp;
|
||||||
|
public VkBool32 depthBoundsTestEnable;
|
||||||
|
public VkBool32 stencilTestEnable;
|
||||||
|
public VkStencilOpState front;
|
||||||
|
public VkStencilOpState back;
|
||||||
|
public float minDepthBounds;
|
||||||
|
public float maxDepthBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public unsafe struct VkImageCreateInfo
|
||||||
|
{
|
||||||
|
public VkStructureType sType;
|
||||||
|
public nint pNext;
|
||||||
|
public uint flags;
|
||||||
|
public VkImageType imageType;
|
||||||
|
public VkFormat format;
|
||||||
|
public VkExtent3D extent;
|
||||||
|
public uint mipLevels;
|
||||||
|
public uint arrayLayers;
|
||||||
|
public VkSampleCountFlags samples;
|
||||||
|
public VkImageTiling tiling;
|
||||||
|
public VkImageUsageFlags usage;
|
||||||
|
public VkSharingMode sharingMode;
|
||||||
|
public uint queueFamilyIndexCount;
|
||||||
|
public uint* pQueueFamilyIndices;
|
||||||
|
public VkImageLayout initialLayout;
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public unsafe struct VkPushConstantRange
|
public unsafe struct VkPushConstantRange
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,19 +11,26 @@ internal sealed unsafe class VulkanSwapchain : IDisposable
|
|||||||
public VkExtent2D Extent;
|
public VkExtent2D Extent;
|
||||||
public uint ImageCount;
|
public uint ImageCount;
|
||||||
|
|
||||||
|
public VkImage DepthImage;
|
||||||
|
public VkDeviceMemory DepthImageMemory;
|
||||||
|
public VkImageView DepthImageView;
|
||||||
|
public VkFormat DepthFormat = VkFormat.D32Sfloat;
|
||||||
|
|
||||||
private readonly VkDevice _device;
|
private readonly VkDevice _device;
|
||||||
private readonly VkPhysicalDevice _physicalDevice;
|
private readonly VkPhysicalDevice _physicalDevice;
|
||||||
private readonly VkSurfaceKHR _surface;
|
private readonly VkSurfaceKHR _surface;
|
||||||
private readonly VkSurfaceFormatKHR _surfaceFormat;
|
private readonly VkSurfaceFormatKHR _surfaceFormat;
|
||||||
|
private readonly VulkanContext _ctx;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public VulkanSwapchain(VkDevice device, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
|
public VulkanSwapchain(VkDevice device, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
|
||||||
VkSurfaceFormatKHR surfaceFormat, int width, int height)
|
VkSurfaceFormatKHR surfaceFormat, int width, int height, VulkanContext ctx)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_physicalDevice = physicalDevice;
|
_physicalDevice = physicalDevice;
|
||||||
_surface = surface;
|
_surface = surface;
|
||||||
_surfaceFormat = surfaceFormat;
|
_surfaceFormat = surfaceFormat;
|
||||||
|
_ctx = ctx;
|
||||||
Create(width, height);
|
Create(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +139,81 @@ internal sealed unsafe class VulkanSwapchain : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"[Vulkan] Swapchain: {actualCount} images, {Extent.Width}x{Extent.Height}, format={Format}");
|
Console.WriteLine($"[Vulkan] Swapchain: {actualCount} images, {Extent.Width}x{Extent.Height}, format={Format}");
|
||||||
|
|
||||||
|
CreateDepthResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateDepthResources()
|
||||||
|
{
|
||||||
|
var imageInfo = new VkImageCreateInfo
|
||||||
|
{
|
||||||
|
sType = VkStructureType.ImageCreateInfo,
|
||||||
|
imageType = VkImageType.Type2D,
|
||||||
|
format = DepthFormat,
|
||||||
|
extent = new VkExtent3D { Width = Extent.Width, Height = Extent.Height, Depth = 1 },
|
||||||
|
mipLevels = 1,
|
||||||
|
arrayLayers = 1,
|
||||||
|
samples = VkSampleCountFlags.Count1,
|
||||||
|
tiling = VkImageTiling.Optimal,
|
||||||
|
usage = VkImageUsageFlags.DepthStencilAttachment,
|
||||||
|
sharingMode = VkSharingMode.Exclusive,
|
||||||
|
initialLayout = VkImageLayout.Undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
var depthImg = VkImage.Null;
|
||||||
|
var result = Vk.vkCreateImage(_device, &imageInfo, 0, &depthImg);
|
||||||
|
if (result != VkResult.Success)
|
||||||
|
throw new InvalidOperationException($"vkCreateImage (depth) failed: {result}");
|
||||||
|
DepthImage = depthImg;
|
||||||
|
|
||||||
|
var reqs = new VkMemoryRequirements();
|
||||||
|
Vk.vkGetImageMemoryRequirements(_device, DepthImage, &reqs);
|
||||||
|
|
||||||
|
var memTypeIndex = _ctx.FindMemoryType(reqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);
|
||||||
|
|
||||||
|
var allocInfo = new VkMemoryAllocateInfo
|
||||||
|
{
|
||||||
|
sType = VkStructureType.MemoryAllocateInfo,
|
||||||
|
allocationSize = reqs.size,
|
||||||
|
memoryTypeIndex = memTypeIndex,
|
||||||
|
};
|
||||||
|
|
||||||
|
var depthMem = VkDeviceMemory.Null;
|
||||||
|
result = Vk.vkAllocateMemory(_device, &allocInfo, 0, &depthMem);
|
||||||
|
if (result != VkResult.Success)
|
||||||
|
throw new InvalidOperationException($"vkAllocateMemory (depth) failed: {result}");
|
||||||
|
DepthImageMemory = depthMem;
|
||||||
|
|
||||||
|
Vk.vkBindImageMemory(_device, DepthImage, DepthImageMemory, 0);
|
||||||
|
|
||||||
|
var viewInfo = new VkImageViewCreateInfo
|
||||||
|
{
|
||||||
|
sType = VkStructureType.ImageViewCreateInfo,
|
||||||
|
image = DepthImage,
|
||||||
|
viewType = VkImageViewType.Type2D,
|
||||||
|
format = DepthFormat,
|
||||||
|
components = new VkComponentMapping
|
||||||
|
{
|
||||||
|
R = VkComponentSwizzle.Identity,
|
||||||
|
G = VkComponentSwizzle.Identity,
|
||||||
|
B = VkComponentSwizzle.Identity,
|
||||||
|
A = VkComponentSwizzle.Identity,
|
||||||
|
},
|
||||||
|
subresourceRange = new VkImageSubresourceRange
|
||||||
|
{
|
||||||
|
AspectMask = VkImageAspectFlags.Depth,
|
||||||
|
BaseMipLevel = 0,
|
||||||
|
LevelCount = 1,
|
||||||
|
BaseArrayLayer = 0,
|
||||||
|
LayerCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var depthView = VkImageView.Null;
|
||||||
|
result = Vk.vkCreateImageView(_device, &viewInfo, 0, &depthView);
|
||||||
|
if (result != VkResult.Success)
|
||||||
|
throw new InvalidOperationException($"vkCreateImageView (depth) failed: {result}");
|
||||||
|
DepthImageView = depthView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Recreate(int width, int height)
|
public void Recreate(int width, int height)
|
||||||
@@ -143,6 +225,22 @@ internal sealed unsafe class VulkanSwapchain : IDisposable
|
|||||||
|
|
||||||
private void Cleanup()
|
private void Cleanup()
|
||||||
{
|
{
|
||||||
|
if (DepthImageView.Handle != 0)
|
||||||
|
{
|
||||||
|
Vk.vkDestroyImageView(_device, DepthImageView, 0);
|
||||||
|
DepthImageView = VkImageView.Null;
|
||||||
|
}
|
||||||
|
if (DepthImage.Handle != 0)
|
||||||
|
{
|
||||||
|
Vk.vkDestroyImage(_device, DepthImage, 0);
|
||||||
|
DepthImage = VkImage.Null;
|
||||||
|
}
|
||||||
|
if (DepthImageMemory.Handle != 0)
|
||||||
|
{
|
||||||
|
Vk.vkFreeMemory(_device, DepthImageMemory, 0);
|
||||||
|
DepthImageMemory = VkDeviceMemory.Null;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ImageViews.Length; i++)
|
for (int i = 0; i < ImageViews.Length; i++)
|
||||||
{
|
{
|
||||||
if (ImageViews[i].Handle != 0)
|
if (ImageViews[i].Handle != 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user