diff --git a/include/collada/scene/vulkan.h b/include/collada/scene/vulkan.h index 33e4930..0a51612 100644 --- a/include/collada/scene/vulkan.h +++ b/include/collada/scene/vulkan.h @@ -46,6 +46,7 @@ namespace collada::scene { static constexpr uint32_t uniformBufferDescriptorCount = maxFrames * perFrameDescriptorCount + constantDescriptorCount; // +3: linear sampler, shadow sampled image, scene sampled image (array) static constexpr uint32_t bindingCount = uniformBufferDescriptorCount + 3; + static constexpr int shaderVariantCount = 3; // externally initialized, opaque handle VkInstance instance; diff --git a/shader/collada.hlsl b/shader/collada.hlsl index 0aaad50..16e8a19 100644 --- a/shader/collada.hlsl +++ b/shader/collada.hlsl @@ -169,6 +169,57 @@ float4 PSMain(VSOutput input) : SV_TARGET return float4(diffuseSpecular * shadowIntensity + emissionColor.xyz, 1.0); } +struct VSGeometryOutput +{ + float4 Position : SV_POSITION; + float3 Normal : Normal; +}; + +[shader("vertex")] +VSGeometryOutput VSGeometryMain(VSInput input) +{ + VSGeometryOutput output = (VSGeometryOutput)0; + output.Position = float4(input.Position, 1.0); + output.Normal = input.Normal; + return output; +} + +struct GSGeometryOutput +{ + float4 Position : SV_POSITION; + float3 Color : Color; +}; + +[shader("geometry")] +[maxvertexcount(6)] +void GSGeometryMain(triangle VSGeometryOutput input[3], inout LineStream outputStream) +{ + float normalLength = 2.0; + + for (int i = 0; i < 3; i++) { + float3 position = input[i].Position.xyz; + float3 normal = input[i].Normal; + float3 positionNormal = position + normal * normalLength; + + GSGeometryOutput output = (GSGeometryOutput)0; + output.Position = getProjection(Scene.Projection, getView(Scene.View, position)); + output.Color = float3(1, 0, 0); + outputStream.Append(output); + + output.Position = getProjection(Scene.Projection, getView(Scene.View, positionNormal)); + output.Color = float3(0, 1, 0); + outputStream.Append(output); + + outputStream.RestartStrip(); + } +} + +[shader("pixel")] +float4 PSGeometryMain(GSGeometryOutput input) : SV_TARGET +{ + return float4(input.Color, 1.0); +} + [shader("vertex")] VSShadowOutput VSShadowMain(VSInput input) { diff --git a/src/collada/scene/vulkan.cpp b/src/collada/scene/vulkan.cpp index c595a4f..1bf94ad 100644 --- a/src/collada/scene/vulkan.cpp +++ b/src/collada/scene/vulkan.cpp @@ -327,13 +327,13 @@ namespace collada::scene { .binding = 0, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT }, { .binding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT } }; @@ -655,7 +655,7 @@ namespace collada::scene { { VkPushConstantRange pushConstantRanges[1]{ { - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, .offset = 0, .size = (sizeof (PushConstant)) } @@ -690,6 +690,27 @@ namespace collada::scene { } }; + VkPipelineShaderStageCreateInfo geometryShaderStages[3]{ + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = shaderModule, + .pName = "VSGeometryMain" + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_GEOMETRY_BIT, + .module = shaderModule, + .pName = "GSGeometryMain" + }, + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = shaderModule, + .pName = "PSGeometryMain" + } + }; + VkPipelineShaderStageCreateInfo shadowShaderStages[2]{ { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, @@ -788,13 +809,12 @@ namespace collada::scene { vertexInputStates, vertexBindingDescriptions); - // piplineCount must match destroy_all - int pipelineCount = descriptor->inputs_list_count * 2; + int pipelineCount = descriptor->inputs_list_count * shaderVariantCount; VkGraphicsPipelineCreateInfo * pipelineCreateInfos = NewM(pipelineCount); for (int i = 0; i < descriptor->inputs_list_count; i++) { // shadow - pipelineCreateInfos[i * 2 + 0] = { + pipelineCreateInfos[i * shaderVariantCount + 0] = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &shadowRenderingCreateInfo, .stageCount = 2, @@ -811,7 +831,7 @@ namespace collada::scene { }; // non-shadow - pipelineCreateInfos[i * 2 + 1] = { + pipelineCreateInfos[i * shaderVariantCount + 1] = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &renderingCreateInfo, .stageCount = 2, @@ -826,6 +846,23 @@ namespace collada::scene { .pDynamicState = &dynamicState, .layout = pipelineLayout }; + + // geometry + pipelineCreateInfos[i * shaderVariantCount + 2] = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = &renderingCreateInfo, + .stageCount = 3, + .pStages = geometryShaderStages, + .pVertexInputState = &vertexInputStates[i], + .pInputAssemblyState = &inputAssemblyState, + .pViewportState = &viewportState, + .pRasterizationState = &rasterizationState, + .pMultisampleState = &multisampleState, + .pDepthStencilState = &depthStencilState, + .pColorBlendState = &colorBlendState, + .pDynamicState = &dynamicState, + .layout = pipelineLayout + }; }; pipelines = NewM(pipelineCount); @@ -860,13 +897,13 @@ namespace collada::scene { } types::triangles const& triangles = mesh.triangles[instance_material.element_index]; - VkShaderStageFlags stageFlags{ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT }; + VkShaderStageFlags stageFlags{ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_GEOMETRY_BIT }; constexpr uint32_t offset{ (offsetof (PushConstant, materialIndex)) }; vkCmdPushConstants(commandBuffer, pipelineLayout, stageFlags, offset, (sizeof (uint32_t)), &materialIndex); VkDeviceSize vertexOffset{ (VkDeviceSize)mesh.vertex_buffer_offset }; vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndex.buffer, &vertexOffset); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[triangles.inputs_index * 2 + pipelineIndex]); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[triangles.inputs_index * shaderVariantCount + pipelineIndex]); uint32_t indexCount = triangles.count * 3; vkCmdDrawIndexed(commandBuffer, indexCount, 1, triangles.index_offset, 0, 0); @@ -935,7 +972,7 @@ namespace collada::scene { types::node const & node, instance_types::node const & node_instance) { - VkShaderStageFlags stageFlags{ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT }; + VkShaderStageFlags stageFlags{ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_GEOMETRY_BIT }; constexpr uint32_t offset{ (offsetof (PushConstant, nodeIndex)) }; vkCmdPushConstants(commandBuffer, pipelineLayout, stageFlags, offset, (sizeof (uint32_t)), &node_index); @@ -983,8 +1020,7 @@ namespace collada::scene { vkDestroyDescriptorSetLayout(device, descriptorSetLayouts[1], nullptr); vkDestroyDescriptorPool(device, descriptorPool, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - // pipelineCount must match create_pipelines - int pipelineCount = descriptor->inputs_list_count * 2; + int pipelineCount = descriptor->inputs_list_count * shaderVariantCount; for (int i = 0; i < pipelineCount; i++) { vkDestroyPipeline(device, pipelines[i], nullptr); } diff --git a/src/main.cpp b/src/main.cpp index 6db276c..7cb46b3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -154,6 +154,19 @@ void createDepth(VkDeviceSize nonCoherentAtomSize, VK_CHECK(vkCreateImageView(device, &imageViewCreateInfo, nullptr, imageView)); } +void createCubeDepth(VkDeviceSize nonCoherentAtomSize, + VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties, + uint32_t width, + uint32_t height, + VkFormat format, + VkImageUsageFlags usage, + VkImage * image, + VkDeviceMemory * memory, + VkImageView * imageView) +{ + +} + void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, VkDeviceSize nonCoherentAtomSize, @@ -402,7 +415,8 @@ int main() .dynamicRendering = true, }; VkPhysicalDeviceFeatures enabledFeatures{ - .samplerAnisotropy = VK_TRUE + .geometryShader = true, + .samplerAnisotropy = true, }; constexpr uint32_t enabledExtensionCount = 1; char const * enabledExtensionNames[enabledExtensionCount]{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }; @@ -867,7 +881,7 @@ int main() VkViewport viewport{ .x = 0, - .y = 0,//static_cast(windowSize.y), + .y = 0, .width = static_cast(windowSize.x), .height = static_cast(windowSize.y), .minDepth = 0.0f, @@ -882,6 +896,8 @@ int main() collada_state.vulkan.excludeMaterialIndex = -1; collada_state.vulkan.pipelineIndex = 1; // non-shadow pipeline collada_state.draw(); + collada_state.vulkan.pipelineIndex = 2; // geometry shader pipeline + collada_state.draw(); vkCmdEndRendering(commandBuffer);