Compare commits

...

2 Commits

Author SHA1 Message Date
ba01d3716c stencil outline 2026-04-07 18:10:02 -05:00
1a365ca5d7 enable stencil buffer 2026-04-07 18:04:46 -05:00
5 changed files with 148 additions and 55 deletions

View File

@ -63,15 +63,14 @@ all: main
main: $(OBJS) $(LIBS) $(BINS) $(SHADERS) main: $(OBJS) $(LIBS) $(BINS) $(SHADERS)
$(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@ $(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@
%.vs.spv: %.hlsl %.spv: %.hlsl
../dxc/bin/dxc -spirv -T vs_6_1 -E VSMain -fspv-target-env=vulkan1.3 $< -Fo $@ ../dxc/bin/dxc -spirv -T lib_6_3 -fspv-target-env=vulkan1.3 $< -Fo $@
%.ps.spv: %.hlsl
../dxc/bin/dxc -spirv -T ps_6_1 -E PSMain -fspv-target-env=vulkan1.3 $< -Fo $@
tool/pack_file: tool/pack_file.cpp tool/pack_file: tool/pack_file.cpp
make -C tool pack_file make -C tool pack_file
src/pack.o: files.pack
PACK_FILENAMES = $(shell cat filenames.txt) PACK_FILENAMES = $(shell cat filenames.txt)
files.pack: tool/pack_file $(PACK_FILENAMES) filenames.txt files.pack: tool/pack_file $(PACK_FILENAMES) filenames.txt
./tool/pack_file $@ $(PACK_FILENAMES) ./tool/pack_file $@ $(PACK_FILENAMES)

View File

@ -1,5 +1,4 @@
shader/triangle.vs.spv shader/triangle.spv
shader/triangle.ps.spv
index.idx index.idx
position_normal_texture.vtx position_normal_texture.vtx
sprite.data sprite.data

View File

@ -49,3 +49,25 @@ float4 PSMain(VSOutput input) : SV_TARGET
return float4(color, 1.0); return float4(color, 1.0);
} }
struct VSOutlineOutput
{
float4 Position : SV_POSITION;
float3 Normal : NORMAL0;
};
[shader("vertex")]
VSOutlineOutput VSOutlineMain(VSInput input)
{
VSOutlineOutput output = (VSOutlineOutput)0;
float3 position = input.Position.xyz + input.Normal.xyz * 0.01;
output.Position = mul(constants.data.Get().Projection, mul(constants.data.Get().View, mul(constants.data.Get().Model, float4(position, 1.0))));
output.Normal = input.Normal;
return output;
}
[shader("pixel")]
float4 PSOutlineMain(VSOutlineOutput input) : SV_TARGET
{
return float4(1.0, 1.0, 1.0, 1.0);
}

View File

@ -109,7 +109,12 @@ VkSemaphore * renderSemaphores{ nullptr };
VkCommandPool commandPool{ VK_NULL_HANDLE }; VkCommandPool commandPool{ VK_NULL_HANDLE };
VkCommandBuffer commandBuffers[maxFramesInFlight]; VkCommandBuffer commandBuffers[maxFramesInFlight];
VkPipeline pipeline{ VK_NULL_HANDLE }; enum {
MAIN_PIPELINE = 0,
OUTLINE_PIPELINE = 1,
};
VkPipeline pipelines[2]{ VK_NULL_HANDLE, VK_NULL_HANDLE };
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
VkImage textureImage{ VK_NULL_HANDLE }; VkImage textureImage{ VK_NULL_HANDLE };
@ -349,7 +354,7 @@ void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, V
.viewType = VK_IMAGE_VIEW_TYPE_2D, .viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = depthFormat, .format = depthFormat,
.subresourceRange{ .subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
.levelCount = 1, .levelCount = 1,
.layerCount = 1 .layerCount = 1
} }
@ -959,26 +964,16 @@ int main()
// shaders // shaders
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
uint32_t triangleVSSize; uint32_t triangleSize;
void const * triangleVSStart = file::open("shader/triangle.vs.spv", &triangleVSSize); void const * triangleStart = file::open("shader/triangle.spv", &triangleSize);
uint32_t trianglePSSize;
void const * trianglePSStart = file::open("shader/triangle.ps.spv", &trianglePSSize);
VkShaderModuleCreateInfo vertexShaderModuleCreateInfo{ VkShaderModuleCreateInfo shaderModuleCreateInfo{
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = triangleVSSize, .codeSize = triangleSize,
.pCode = (uint32_t *)triangleVSStart .pCode = (uint32_t *)triangleStart
}; };
VkShaderModule vertexShaderModule{}; VkShaderModule shaderModule{};
VK_CHECK(vkCreateShaderModule(device, &vertexShaderModuleCreateInfo, nullptr, &vertexShaderModule)); VK_CHECK(vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &shaderModule));
VkShaderModuleCreateInfo pixelShaderModuleCreateInfo{
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = trianglePSSize,
.pCode = (uint32_t *)trianglePSStart
};
VkShaderModule pixelShaderModule{};
VK_CHECK(vkCreateShaderModule(device, &pixelShaderModuleCreateInfo, nullptr, &pixelShaderModule));
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// pipeline // pipeline
@ -1026,12 +1021,29 @@ int main()
{ {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT, .stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = vertexShaderModule, .pName = "VSMain" .module = shaderModule,
.pName = "VSMain"
}, },
{ {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT, .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = pixelShaderModule, .pName = "PSMain" .module = shaderModule,
.pName = "PSMain"
}
};
VkPipelineShaderStageCreateInfo outlineShaderStages[2]{
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = shaderModule,
.pName = "VSOutlineMain"
},
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = shaderModule,
.pName = "PSOutlineMain"
} }
}; };
@ -1041,13 +1053,14 @@ int main()
.scissorCount = 1 .scissorCount = 1
}; };
VkDynamicState dynamicStates[2]{ constexpr uint32_t dynamicStateCount = 2;
VkDynamicState dynamicStates[dynamicStateCount]{
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR VK_DYNAMIC_STATE_SCISSOR,
}; };
VkPipelineDynamicStateCreateInfo dynamicState{ VkPipelineDynamicStateCreateInfo dynamicState{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = 2, .dynamicStateCount = dynamicStateCount,
.pDynamicStates = dynamicStates .pDynamicStates = dynamicStates
}; };
@ -1055,14 +1068,42 @@ int main()
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = VK_TRUE, .depthTestEnable = VK_TRUE,
.depthWriteEnable = VK_TRUE, .depthWriteEnable = VK_TRUE,
.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL .depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL,
.stencilTestEnable = VK_TRUE,
.front = {
.failOp = VK_STENCIL_OP_REPLACE,
.passOp = VK_STENCIL_OP_REPLACE,
.depthFailOp = VK_STENCIL_OP_REPLACE,
.compareOp = VK_COMPARE_OP_ALWAYS,
.compareMask = 0x01,
.writeMask = 0x01,
.reference = 1,
},
};
VkPipelineDepthStencilStateCreateInfo outlineDepthStencilState{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = VK_TRUE,
.depthWriteEnable = VK_TRUE,
.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL,
.stencilTestEnable = VK_TRUE,
.front = {
.failOp = VK_STENCIL_OP_KEEP,
.passOp = VK_STENCIL_OP_REPLACE,
.depthFailOp = VK_STENCIL_OP_KEEP,
.compareOp = VK_COMPARE_OP_NOT_EQUAL,
.compareMask = 0x01,
.writeMask = 0x00,
.reference = 1,
},
}; };
VkPipelineRenderingCreateInfo renderingCreateInfo{ VkPipelineRenderingCreateInfo renderingCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.colorAttachmentCount = 1, .colorAttachmentCount = 1,
.pColorAttachmentFormats = &surfaceFormat.format, .pColorAttachmentFormats = &surfaceFormat.format,
.depthAttachmentFormat = depthFormat .depthAttachmentFormat = depthFormat,
.stencilAttachmentFormat = depthFormat
}; };
VkPipelineColorBlendAttachmentState blendAttachment{ VkPipelineColorBlendAttachmentState blendAttachment{
@ -1075,6 +1116,8 @@ int main()
}; };
VkPipelineRasterizationStateCreateInfo rasterizationState{ VkPipelineRasterizationStateCreateInfo rasterizationState{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.cullMode = VK_CULL_MODE_BACK_BIT,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
.lineWidth = 1.0f .lineWidth = 1.0f
}; };
VkPipelineMultisampleStateCreateInfo multisampleState{ VkPipelineMultisampleStateCreateInfo multisampleState{
@ -1082,22 +1125,39 @@ int main()
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
}; };
VkGraphicsPipelineCreateInfo pipelineCreateInfo{ VkGraphicsPipelineCreateInfo pipelineCreateInfos[2]{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, {
.pNext = &renderingCreateInfo, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.stageCount = 2, .pNext = &renderingCreateInfo,
.pStages = shaderStages, .stageCount = 2,
.pVertexInputState = &vertexInputState, .pStages = shaderStages,
.pInputAssemblyState = &inputAssemblyState, .pVertexInputState = &vertexInputState,
.pViewportState = &viewportState, .pInputAssemblyState = &inputAssemblyState,
.pRasterizationState = &rasterizationState, .pViewportState = &viewportState,
.pMultisampleState = &multisampleState, .pRasterizationState = &rasterizationState,
.pDepthStencilState = &depthStencilState, .pMultisampleState = &multisampleState,
.pColorBlendState = &colorBlendState, .pDepthStencilState = &depthStencilState,
.pDynamicState = &dynamicState, .pColorBlendState = &colorBlendState,
.layout = pipelineLayout .pDynamicState = &dynamicState,
.layout = pipelineLayout
},
{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &renderingCreateInfo,
.stageCount = 2,
.pStages = outlineShaderStages,
.pVertexInputState = &vertexInputState,
.pInputAssemblyState = &inputAssemblyState,
.pViewportState = &viewportState,
.pRasterizationState = &rasterizationState,
.pMultisampleState = &multisampleState,
.pDepthStencilState = &outlineDepthStencilState,
.pColorBlendState = &colorBlendState,
.pDynamicState = &dynamicState,
.layout = pipelineLayout
}
}; };
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &pipeline)); VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 2, pipelineCreateInfos, nullptr, pipelines));
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// loop // loop
@ -1113,6 +1173,11 @@ int main()
if (event.type == SDL_EVENT_QUIT) { if (event.type == SDL_EVENT_QUIT) {
quit = true; quit = true;
} }
if (event.type == SDL_EVENT_KEY_DOWN) {
if (event.key.key == SDLK_ESCAPE) {
quit = true;
}
}
if (event.type == SDL_EVENT_WINDOW_RESIZED) { if (event.type == SDL_EVENT_WINDOW_RESIZED) {
SDL_CHECK(SDL_GetWindowSize(window, &windowSize.x, &windowSize.y)); SDL_CHECK(SDL_GetWindowSize(window, &windowSize.x, &windowSize.y));
} }
@ -1169,9 +1234,9 @@ int main()
}, },
VkImageMemoryBarrier2{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.srcStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
@ -1213,7 +1278,8 @@ int main()
.layerCount = 1, .layerCount = 1,
.colorAttachmentCount = 1, .colorAttachmentCount = 1,
.pColorAttachments = &colorRenderingAttachmentInfo, .pColorAttachments = &colorRenderingAttachmentInfo,
.pDepthAttachment = &depthRenderingAttachmentInfo .pDepthAttachment = &depthRenderingAttachmentInfo,
.pStencilAttachment = &depthRenderingAttachmentInfo,
}; };
vkCmdBeginRendering(commandBuffer, &renderingInfo); vkCmdBeginRendering(commandBuffer, &renderingInfo);
@ -1227,7 +1293,6 @@ int main()
VkRect2D scissor{ .extent{ .width = (uint32_t)windowSize.x, .height = (uint32_t)windowSize.y } }; VkRect2D scissor{ .extent{ .width = (uint32_t)windowSize.x, .height = (uint32_t)windowSize.y } };
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
VkDeviceSize vertexOffset{ 0 }; VkDeviceSize vertexOffset{ 0 };
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &textureDescriptorSet, 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &textureDescriptorSet, 0, nullptr);
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset); vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset);
@ -1235,7 +1300,13 @@ int main()
vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32);
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, (sizeof (VkDeviceAddress)), &shaderDataDevice.frame[frameIndex].deviceAddress); vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, (sizeof (VkDeviceAddress)), &shaderDataDevice.frame[frameIndex].deviceAddress);
VkDeviceSize indexCount{ 9216 }; VkDeviceSize indexCount{ 9216 };
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[MAIN_PIPELINE]);
vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0); vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[OUTLINE_PIPELINE]);
vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0);
vkCmdEndRendering(commandBuffer); vkCmdEndRendering(commandBuffer);
VkImageMemoryBarrier2 barrierPresent{ VkImageMemoryBarrier2 barrierPresent{
@ -1326,12 +1397,12 @@ int main()
vkDestroyDescriptorSetLayout(device, textureDescriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, textureDescriptorSetLayout, nullptr);
vkDestroyDescriptorPool(device, descriptorPool, nullptr); vkDestroyDescriptorPool(device, descriptorPool, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyPipeline(device, pipeline, nullptr); vkDestroyPipeline(device, pipelines[0], nullptr);
vkDestroyPipeline(device, pipelines[1], nullptr);
vkDestroySwapchainKHR(device, swapchain, nullptr); vkDestroySwapchainKHR(device, swapchain, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr); vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyCommandPool(device, commandPool, nullptr); vkDestroyCommandPool(device, commandPool, nullptr);
vkDestroyShaderModule(device, vertexShaderModule, nullptr); vkDestroyShaderModule(device, shaderModule, nullptr);
vkDestroyShaderModule(device, pixelShaderModule, nullptr);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_QuitSubSystem(SDL_INIT_VIDEO);

2
validation.sh Normal file
View File

@ -0,0 +1,2 @@
export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
export VK_VALIDATION_VALIDATE_SYNC=1