diff --git a/mesh/mesh.cpp b/mesh/mesh.cpp index f6cb0365..e085a48d 100644 --- a/mesh/mesh.cpp +++ b/mesh/mesh.cpp @@ -86,9 +86,9 @@ public: glm::vec4 lightPos = glm::vec4(25.0f, 5.0f, 5.0f, 1.0f); } uboVS; - struct { + struct Pipelines { VkPipeline solid; - VkPipeline wireframe; + VkPipeline wireframe = VK_NULL_HANDLE; } pipelines; VkPipelineLayout pipelineLayout; @@ -111,7 +111,9 @@ public: // Clean up used Vulkan resources // Note : Inherited destructor cleans up resources stored in base class vkDestroyPipeline(device, pipelines.solid, nullptr); - vkDestroyPipeline(device, pipelines.wireframe, nullptr); + if (pipelines.wireframe != VK_NULL_HANDLE) { + vkDestroyPipeline(device, pipelines.wireframe, nullptr); + } vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); diff --git a/tessellation/tessellation.cpp b/tessellation/tessellation.cpp index cf146ccb..f3978ecb 100644 --- a/tessellation/tessellation.cpp +++ b/tessellation/tessellation.cpp @@ -69,11 +69,11 @@ public: float tessAlpha = 1.0f; } uboTessEval; - struct { + struct Pipelines { VkPipeline solid; - VkPipeline wire; + VkPipeline wire = VK_NULL_HANDLE; VkPipeline solidPassThrough; - VkPipeline wirePassThrough; + VkPipeline wirePassThrough = VK_NULL_HANDLE; } pipelines; VkPipeline *pipelineLeft = &pipelines.wirePassThrough; VkPipeline *pipelineRight = &pipelines.wire; @@ -89,11 +89,6 @@ public: cameraPos = glm::vec3(-3.0f, 2.3f, 0.0f); title = "Vulkan Example - Tessellation shader (PN Triangles)"; enableTextOverlay = true; - // Enable physical device features required for this example - // Tell the driver that we are going to use geometry shaders - enabledFeatures.tessellationShader = VK_TRUE; - // Example also uses a wireframe pipeline, enable non-solid fill modes - enabledFeatures.fillModeNonSolid = VK_TRUE; } ~VulkanExample() @@ -101,9 +96,13 @@ public: // Clean up used Vulkan resources // Note : Inherited destructor cleans up resources stored in base class vkDestroyPipeline(device, pipelines.solid, nullptr); - vkDestroyPipeline(device, pipelines.wire, nullptr); + if (pipelines.wire != VK_NULL_HANDLE) { + vkDestroyPipeline(device, pipelines.wire, nullptr); + }; vkDestroyPipeline(device, pipelines.solidPassThrough, nullptr); - vkDestroyPipeline(device, pipelines.wirePassThrough, nullptr); + if (pipelines.wirePassThrough != VK_NULL_HANDLE) { + vkDestroyPipeline(device, pipelines.wirePassThrough, nullptr); + }; vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); @@ -114,6 +113,28 @@ public: textures.colorMap.destroy(); } + // Enable physical device features required for this example + virtual void getEnabledFeatures() + { + // Example uses tessellation shaders + if (deviceFeatures.tessellationShader) { + enabledFeatures.tessellationShader = VK_TRUE; + } + else { + vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported"); + } + // Fill mode non solid is required for wireframe display + if (deviceFeatures.fillModeNonSolid) { + enabledFeatures.fillModeNonSolid = VK_TRUE; + } + else { + // Wireframe not supported, switch to solid pipelines + pipelineLeft = &pipelines.solidPassThrough; + pipelineRight = &pipelines.solid; + } + } + + void reBuildCommandBuffers() { if (!checkCommandBuffers()) @@ -413,8 +434,10 @@ public: // Solid VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid)); // Wireframe - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wire)); + if (deviceFeatures.fillModeNonSolid) { + rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wire)); + } // Pass through pipelines // Load pass through tessellation shaders (Vert and frag are reused) @@ -425,8 +448,10 @@ public: rasterizationState.polygonMode = VK_POLYGON_MODE_FILL; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solidPassThrough)); // Wireframe - rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wirePassThrough)); + if (deviceFeatures.fillModeNonSolid) { + rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wirePassThrough)); + } } // Prepare and initialize uniform buffer containing shader uniforms @@ -486,12 +511,6 @@ public: void prepare() { - // Check if device supports tessellation shaders - if (!deviceFeatures.tessellationShader) - { - vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported"); - } - VulkanExampleBase::prepare(); loadAssets(); setupVertexDescriptions(); @@ -532,7 +551,9 @@ public: break; case KEY_W: case GAMEPAD_BUTTON_A: - togglePipelines(); + if (deviceFeatures.fillModeNonSolid) { + togglePipelines(); + } break; case KEY_S: case GAMEPAD_BUTTON_X: @@ -547,10 +568,14 @@ public: ss << std::setprecision(2) << std::fixed << uboTessControl.tessLevel; #if defined(__ANDROID__) textOverlay->addText("Tessellation level: " + ss.str() + " (Buttons L1/R1 to change)", 5.0f, 85.0f, VulkanTextOverlay::alignLeft); - textOverlay->addText("Press \"Button X\" to toggle splitscreen", 5.0f, 100.0f, VulkanTextOverlay::alignLeft); + if (deviceFeatures.fillModeNonSolid) { + textOverlay->addText("Press \"Button X\" to toggle splitscreen", 5.0f, 100.0f, VulkanTextOverlay::alignLeft); + } #else textOverlay->addText("Tessellation level: " + ss.str() + " (NUMPAD +/- to change)", 5.0f, 85.0f, VulkanTextOverlay::alignLeft); - textOverlay->addText("Press \"s\" to toggle splitscreen", 5.0f, 100.0f, VulkanTextOverlay::alignLeft); + if (deviceFeatures.fillModeNonSolid) { + textOverlay->addText("Press \"s\" to toggle splitscreen", 5.0f, 100.0f, VulkanTextOverlay::alignLeft); + } #endif }