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:
@@ -34,7 +34,7 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
||||
var vertSpv = LoadShader("Shaders/triangle.vert.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,
|
||||
swapchain.ImageCount, ctx, _pipeline.DescriptorSetLayout);
|
||||
@@ -109,11 +109,21 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
||||
0, 0,
|
||||
0x400, 0x100);
|
||||
|
||||
TransitionImageLayoutDepth(cmd, _swapchain.DepthImage,
|
||||
VkImageLayout.Undefined, VkImageLayout.DepthStencilAttachmentOptimal,
|
||||
0, 0,
|
||||
0x100, 0x200);
|
||||
|
||||
var clearValue = new VkClearValue
|
||||
{
|
||||
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
|
||||
{
|
||||
sType = VkStructureType.RenderingAttachmentInfo,
|
||||
@@ -124,6 +134,16 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
||||
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
|
||||
{
|
||||
sType = VkStructureType.RenderingInfo,
|
||||
@@ -135,6 +155,7 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
||||
layerCount = 1,
|
||||
colorAttachmentCount = 1,
|
||||
pColorAttachments = &colorAttachment,
|
||||
pDepthAttachment = &depthAttachment,
|
||||
};
|
||||
|
||||
Vk.vkCmdBeginRendering(cmd, &renderingInfo);
|
||||
@@ -168,7 +189,8 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
||||
Vk.vkCmdBindIndexBuffer(cmd, _indexBuffer.Buffer, 0, 0);
|
||||
|
||||
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);
|
||||
|
||||
@@ -282,6 +304,39 @@ internal sealed unsafe class VulkanRenderer : IRenderer, Engine.Graphics.IScreen
|
||||
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)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
|
||||
Reference in New Issue
Block a user