From a9de176d12bc794959aba94ce4752a7c06f444e7 Mon Sep 17 00:00:00 2001 From: saschawillems Date: Thu, 23 Jun 2016 22:01:48 +0200 Subject: [PATCH] Added tessellation evaluation shader frustum culling and pipeline stats for dynamic terrain tessellation example --- base/frustum.hpp | 4 +- data/shaders/terraintessellation/terrain.frag | 4 +- data/shaders/terraintessellation/terrain.tesc | 67 +++++++++---- .../terraintessellation/terrain.tesc.spv | Bin 6464 -> 7788 bytes data/shaders/terraintessellation/terrain.tese | 5 +- .../terraintessellation/terrain.tese.spv | Bin 4696 -> 4916 bytes terraintessellation/terraintessellation.cpp | 94 ++++++++++++++++-- 7 files changed, 147 insertions(+), 27 deletions(-) diff --git a/base/frustum.hpp b/base/frustum.hpp index 968b31da..7461aa15 100644 --- a/base/frustum.hpp +++ b/base/frustum.hpp @@ -14,10 +14,10 @@ namespace vkTools { class Frustum { - private: + public: enum side { LEFT = 0, RIGHT = 1, TOP = 2, BOTTOM = 3, BACK = 4, FRONT = 5 }; std::array planes; - public: + void update(glm::mat4 matrix) { planes[LEFT].x = matrix[0].w + matrix[0].x; diff --git a/data/shaders/terraintessellation/terrain.frag b/data/shaders/terraintessellation/terrain.frag index 61354832..c5634c9d 100644 --- a/data/shaders/terraintessellation/terrain.frag +++ b/data/shaders/terraintessellation/terrain.frag @@ -54,4 +54,6 @@ void main() outFragColor = vec4((IAmbient + IDiffuse) * vec4(texture(terrainLayers, vec3(inUV, 0.0)).rgb, 1.0)); */ outFragColor = sampleTerrainLayer(); -} \ No newline at end of file + + //outFragColor.rgb = normalize(inNormal); +} diff --git a/data/shaders/terraintessellation/terrain.tesc b/data/shaders/terraintessellation/terrain.tesc index 02cc0f15..3b0d81d3 100644 --- a/data/shaders/terraintessellation/terrain.tesc +++ b/data/shaders/terraintessellation/terrain.tesc @@ -8,13 +8,14 @@ layout(set = 0, binding = 0) uniform UBO mat4 projection; mat4 modelview; vec4 lightPos; + vec4 frustumPlanes[6]; float displacementFactor; float tessellationFactor; vec2 viewportDim; float tessellatedEdgeSize; } ubo; -layout(set = 0, binding = 2) uniform sampler2D samplerHeight; +layout(set = 0, binding = 1) uniform sampler2D samplerHeight; layout (vertices = 4) out; @@ -31,7 +32,7 @@ float screenSpaceTessFactor(vec4 p0, vec4 p1) // Calculate edge mid point vec4 midPoint = 0.5 * (p0 + p1); // Sphere radius as distance between the control points - float radius = distance(p0, p1) / 2; + float radius = distance(p0, p1) / 2.0; // View space vec4 v0 = ubo.modelview * midPoint; @@ -54,30 +55,62 @@ float screenSpaceTessFactor(vec4 p0, vec4 p1) return clamp(distance(clip0, clip1) / ubo.tessellatedEdgeSize * ubo.tessellationFactor, 1.0, 64.0); } +// Checks the current's patch visibility against the frustum using a sphere check +// Sphere radius is given by the patch size +bool frustumCheck() +{ + // Fixed radius (increase if patch size is increased in example) + const float radius = 8.0f; + vec4 pos = gl_in[gl_InvocationID].gl_Position; + pos.y -= textureLod(samplerHeight, inUV[0], 0.0).r * ubo.displacementFactor; + + // Check sphere against frustum planes + for (int i = 0; i < 6; i++) { + if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) + { + return false; + } + } + return true; +} + void main() { if (gl_InvocationID == 0) { - if (ubo.tessellationFactor > 0.0) + if (!frustumCheck()) { - gl_TessLevelOuter[0] = screenSpaceTessFactor(gl_in[3].gl_Position, gl_in[0].gl_Position); - gl_TessLevelOuter[1] = screenSpaceTessFactor(gl_in[0].gl_Position, gl_in[1].gl_Position); - gl_TessLevelOuter[2] = screenSpaceTessFactor(gl_in[1].gl_Position, gl_in[2].gl_Position); - gl_TessLevelOuter[3] = screenSpaceTessFactor(gl_in[2].gl_Position, gl_in[3].gl_Position); - gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5); - gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5); + gl_TessLevelInner[0] = 0.0; + gl_TessLevelInner[1] = 0.0; + gl_TessLevelOuter[0] = 0.0; + gl_TessLevelOuter[1] = 0.0; + gl_TessLevelOuter[2] = 0.0; + gl_TessLevelOuter[3] = 0.0; } else { - // Tessellation factor can be set to zero by example - // to demonstrate a simple passthrough - gl_TessLevelInner[0] = 1.0; - gl_TessLevelInner[1] = 1.0; - gl_TessLevelOuter[0] = 1.0; - gl_TessLevelOuter[1] = 1.0; - gl_TessLevelOuter[2] = 1.0; - gl_TessLevelOuter[3] = 1.0; + if (ubo.tessellationFactor > 0.0) + { + gl_TessLevelOuter[0] = screenSpaceTessFactor(gl_in[3].gl_Position, gl_in[0].gl_Position); + gl_TessLevelOuter[1] = screenSpaceTessFactor(gl_in[0].gl_Position, gl_in[1].gl_Position); + gl_TessLevelOuter[2] = screenSpaceTessFactor(gl_in[1].gl_Position, gl_in[2].gl_Position); + gl_TessLevelOuter[3] = screenSpaceTessFactor(gl_in[2].gl_Position, gl_in[3].gl_Position); + gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5); + gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5); + } + else + { + // Tessellation factor can be set to zero by example + // to demonstrate a simple passthrough + gl_TessLevelInner[0] = 1.0; + gl_TessLevelInner[1] = 1.0; + gl_TessLevelOuter[0] = 1.0; + gl_TessLevelOuter[1] = 1.0; + gl_TessLevelOuter[2] = 1.0; + gl_TessLevelOuter[3] = 1.0; + } } + } gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; diff --git a/data/shaders/terraintessellation/terrain.tesc.spv b/data/shaders/terraintessellation/terrain.tesc.spv index da911f5f6dd1da07f485b59d4f760d7760112ffc..e5349df5c3d48f9679f8a268f4a92f6525cd8e32 100644 GIT binary patch literal 7788 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 literal 6464 zcmZ{miJw(v8OIOIFo2L~f`}m9ffhTv5!xFsGl${AoqMO5J5yO1WQb*% zwrXXOMT_lw*^1d>Wo4F?6zdqX|1HSmvvg!gMXH-+qiY(;?dT?;-wcX0cIx`QD)1s86ekg zWT;weuw=u?wa9+tlgK^DeaQXDL&y>26e5f{6LIb0-$d5CN!FcBrDor%D_8f8=EK#I zYAf#>-BlgPNBWvOcIW-A(Z~8=sx=1t>ea^JSamS(TYCPI;cEY$Y*MNbeND~Vm@$ESiZd`+@7vHAZ}t}rY*-6Fxi}Z_ z&V6G(p4T^zwepb^vyTB^gDgG(_6QEKif`<|w{+mQci?w-;M+U!9Ub`4 zWANnS{?O0Sd2MJkj?U{azS#b6Uh+QL%JY&x(Y&;sXkOY*G%xQqb(&+`2JeUW9I&Z5 zGE}Xj%X#l>jiVGyckvy-Z`=05r@Qzj)EWiE-jh8FKUy6cuID4`bI(6`J#le|JiqJl z47?ERQ|9>K@trvq=ibY4V&hgK5hr&nuASex=(iUMKj$HLbBXiL$$19C&w6sVmN@U2 z+(Bd=lXVZ)SjYYkr}^4_b`|F`>iUh>&u^>w4zv2m`2^QlSHI4>a-DU<&v|&h;+=~Vc1@SRXyatIp z_OS`^-q^=xR{L;o(MJ{C+S+%pY8QunC%UtXzILN$+1?d__q6e9D#X0=`2W?c)|4~PYgpZbym`deCNAP%3pTIuds&T_n~%1SHO|CdbS2_m zhh9O9yN*@gHrJiK9^IVs))nthobkQr*CY03pEo3%wZv~pHhT&G+t8h9)W0)f>wg?w zUpeDH!D?=K>x=y!$hoh>teyKZ&)x9aVt(I2H%8t(;(HQjoqLmRF5`d1>KTjpA1AxK z@nXLf=G6bEtop~?euh2)k=I}Bw?xi*4}XlWvUlA7M3@cn;ryzp(lq^e;bw=i>cW4Eh=Wx8x*eJ@KQ7 zyO7&95xqNM>--bOJE*VUu>**+4}4<>_V1vw-QU16_V1uFzP$tA(SZ*odfWpm^Xv98RM+Q z7gNW6Z$hRc=F;ZgyvH{qesj!YoLJwe^;Y!b)p{GeHe-B`;)r<%x-kooa)0jxYcs}o zEsp-)g>HZ5(iZ*Qif(`AGES^-)Orv4@oK#nUYjwVBXPvM58asCkaBb%!kp9={yr3fzxKpAy#qp_fd5F zGncmL?_=opXD;K!`iA{e=-OirJ?NiCL5xsR`c?IX^U*qDED zFTJzgPw#2e{2F?>Z?S(Hg#GKu9{I#&`!~QbU-vC8+rOFY5ic&=zm@E9zQkqwx05~I zuULC|KkiFB#_IlDonJ5Ocah-|{$9dy7QYYnEXv0jnT-AeM4Nv1vi=b9x7U2}j^*@= zT0cQA*ZO(F&hi2DUm*7*^2T_Ueu>EI^C0W5koypGIZv@ZQRBDhgXmo>!t{D+fu5#n#3XWskfGZk5e-xSu9O8PW(=lwX=_zgT6 z-T8@Uvd$`DSQxIzgJ{8@%`{+^o;}L!2Z%W*0iT7T(KYNmk9H*m~ zbIt~vb2=H__Zf(HYz?BX_8Zbn&P3Nf2Qjz%lXJEUS)Yhh5YM~y=CM8rk&pUMMz^P1 zQom0@*GJx*&PXnDJ`KHs#Q8Mm*@%4PJO|x4v3qzrVsBTZzRyEng7^e?KDwNH4el9< zo5;F_c{t;xi22N6j6T<;-Y-D6wmz|+3(@UQoBQz{%f)^!La!j@{ag%|kNrFoy}Y00 z;PQT+1@7F>C5bEV=hDQL_p<`deC9AlpEyq|(XFjd>}M6a{jEgYk7rcQ{dmULBJR=i z67#<-@v)!FlTXZa9ax{Tc*dOfdPIMHVt#T_Zv(nLlJJ7xrkyCtpC;Q2#?J7jOIU;@=dOLn< zF@x=3Ieoj4Nr>;T3yGQN6Foi;y@Hf`d_Gt{YP_Ps^ThQk3#Qy-ge{nnj diff --git a/data/shaders/terraintessellation/terrain.tese b/data/shaders/terraintessellation/terrain.tese index 7f6397bd..1f90b024 100644 --- a/data/shaders/terraintessellation/terrain.tese +++ b/data/shaders/terraintessellation/terrain.tese @@ -8,8 +8,11 @@ layout (set = 0, binding = 0) uniform UBO mat4 projection; mat4 modelview; vec4 lightPos; + vec4 frustumPlanes[6]; float displacementFactor; - float tessellationFalloff; + float tessellationFactor; + vec2 viewportDim; + float tessellatedEdgeSize; } ubo; layout (set = 0, binding = 1) uniform sampler2D displacementMap; diff --git a/data/shaders/terraintessellation/terrain.tese.spv b/data/shaders/terraintessellation/terrain.tese.spv index 4c5fa6f9b66e65f1fb45e463099340949450828b..a3976020982ec0149c458bbf4df9d06e055d1024 100644 GIT binary patch delta 1456 zcmY+E%WD%+7{%{olGv)jLX{wuVr+5a!mTJ3D#jK!Eftq8q8TNSb~F!*&uOjonX2jd zs+#)#1Eg+UxODAC5dVaNf}k70^P9}Ial)BeX6( za=cua@~TlxSL92E-x7TuQ7NJ3RjXdPT&R`&sY8VmHNO&9i!zL%!D+uzJ6M`jmv#l| zUCZ-|`Qj<>Na?(%dajw3uYTOuK5ZJ|2Pf+^!XcOUs?(?U8JG8h+n3{{I5tB5R#iWHEVN^ESdC)(qx3vc%_J0nooq0^|Utahl*&C1zyB685 zm=H(B8Nqg8u5kA{xMa+I@8IY_+|Le<6TtoM;M8+(M516s<3kLMIX0u*A@Eo`*ESf&d-DzPvEb;lN$V8>dBo452&XM@U3*)wUu+}Hb!Q6; zVmTS7p)59^6C7pkYNZMiu^(y0hg9MZYvuHC)^5c%@yjbq-7D!}PSjNa#i$&T3t{sD z{Je&YeNDI!*~ScuL-Y-yEbJC+-p!bwi}P;Dh9lqR-PS(N3(S5ggdmUr&c&yPAUnc&hM${-L2#Tn#dfng&6f!M^^ zB2ToZ$e8{uvRa=CaDc}VxST*u@jnxYp%#~dO|NA>n&$#185C@T7uv(y1~0XT13b0? l@icfPPgul)TuX6wZ delta 1234 zcmYk5O=}ZT7=`c5Bx$1t3Q>XtgRw<$A>yteiWO>$AeDj(ml3B>7@b8Di)fp~S~Y6a z>G+xYQT+!Jw=Vn*ZUk5U0N3K8;CYgJp);Jh?>X=1y*K%K^ygF|@F&NN@$`CuAme zX})aY+D=Q8Y;nfz7tae}PJ2WndQP*k-y;H#E`07&N)>C*S$aJ<$n0JiZ;VgcPtjQ<}3~?ZA~^Q#GJC6!O`%ytxXR6o>qIe*2 z6;8{=Aa@1y4V@i)UAQfv&q!nF4IvUv2rlow)z@v_193F+UEV|4Hm_yQXhH-631DA6 zfr0qJP?$YF70_MGGug!K7hKG9+31_9Lrx-)hfWM(Z*|w;gE$)C oaSe#4!AF6@9TkOd3*?~h(*>e^63CkswgrZn;3t7&N3Ln%KT0T%kN^Mx diff --git a/terraintessellation/terraintessellation.cpp b/terraintessellation/terraintessellation.cpp index c99ffb77..f1f10eab 100644 --- a/terraintessellation/terraintessellation.cpp +++ b/terraintessellation/terraintessellation.cpp @@ -20,7 +20,7 @@ #include #include "vulkanexamplebase.h" -#include "vulkanMeshLoader.hpp" +#include "frustum.hpp" #define VERTEX_BUFFER_BIND_ID 0 #define ENABLE_VALIDATION false @@ -66,8 +66,9 @@ public: glm::mat4 projection; glm::mat4 modelview; glm::vec4 lightPos = glm::vec4(0.0f, -2.0f, 0.0f, 0.0f); - float displacementFactor = 16.0f * 2.0f; - float tessellationFactor = 0.75f; + glm::vec4 frustumPlanes[6]; + float displacementFactor = 32.0f; + float tessellationFactor = 1.0f; glm::vec2 viewportDim; // Desired size of tessellated quad patch edge float tessellatedEdgeSize = 20.0f; @@ -99,6 +100,17 @@ public: VkDescriptorSet skysphere; } descriptorSets; + // Pipeline statistics + struct { + VkBuffer buffer; + VkDeviceMemory memory; + } queryResult; + VkQueryPool queryPool; + uint64_t pipelineStats[2] = { 0 }; + + // View frustum passed to tessellation control shader for culling + vkTools::Frustum frustum; + VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) { enableTextOverlay = true; @@ -140,6 +152,58 @@ public: textureLoader->destroyTexture(textures.heightMap); textureLoader->destroyTexture(textures.skySphere); textureLoader->destroyTexture(textures.terrainArray); + + vkDestroyQueryPool(device, queryPool, nullptr); + + vkDestroyBuffer(device, queryResult.buffer, nullptr); + vkFreeMemory(device, queryResult.memory, nullptr); + } + + // Setup pool and buffer for storing pipeline statistics results + void setupQueryResultBuffer() + { + uint32_t bufSize = 2 * sizeof(uint64_t); + + VkMemoryRequirements memReqs; + VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); + VkBufferCreateInfo bufferCreateInfo = + vkTools::initializers::bufferCreateInfo( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + bufSize); + + // Results are saved in a host visible buffer for easy access by the application + VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &queryResult.buffer)); + vkGetBufferMemoryRequirements(device, queryResult.buffer, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &queryResult.memory)); + VK_CHECK_RESULT(vkBindBufferMemory(device, queryResult.buffer, queryResult.memory, 0)); + + // Create query pool + VkQueryPoolCreateInfo queryPoolInfo = {}; + queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + queryPoolInfo.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS; + queryPoolInfo.pipelineStatistics = + VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT; + queryPoolInfo.queryCount = 2; + + VK_CHECK_RESULT(vkCreateQueryPool(device, &queryPoolInfo, NULL, &queryPool)); + } + + // Retrieves the results of the pipeline statistics query submitted to the command buffer + void getQueryResults() + { + // We use vkGetQueryResults to copy the results into a host visible buffer + vkGetQueryPoolResults( + device, + queryPool, + 0, + 1, + sizeof(pipelineStats), + pipelineStats, + sizeof(uint64_t), + VK_QUERY_RESULT_64_BIT); } void loadTextures() @@ -223,6 +287,8 @@ public: VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); + vkCmdResetQueryPool(drawCmdBuffers[i], queryPool, 0, 2); + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); VkViewport viewport = vkTools::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); @@ -243,11 +309,16 @@ public: vkCmdDrawIndexed(drawCmdBuffers[i], meshes.skysphere.indexCount, 1, 0, 0, 0); // Terrrain + // Begin pipeline statistics query + vkCmdBeginQuery(drawCmdBuffers[i], queryPool, 0, VK_QUERY_CONTROL_PRECISE_BIT); + // Render vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.terrain); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.terrain, 0, 1, &descriptorSets.terrain, 0, NULL); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.object.vertices.buf, offsets); vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.object.indices.buf, 0, VK_INDEX_TYPE_UINT32); vkCmdDrawIndexed(drawCmdBuffers[i], meshes.object.indexCount, 1, 0, 0, 0); + // End pipeline statistics query + vkCmdEndQuery(drawCmdBuffers[i], queryPool, 0); vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -285,7 +356,7 @@ public: vertices[index].pos[0] = x * wx + wx / 2.0f - (float)PATCH_SIZE * wx / 2.0f; vertices[index].pos[1] = 0.0f; vertices[index].pos[2] = y * wy + wy / 2.0f - (float)PATCH_SIZE * wy / 2.0f; - vertices[index].normal = glm::vec3(0.0f, -1.0f, 0.0f); + vertices[index].normal = glm::vec3(0.0f, 1.0f, 0.0f); vertices[index].uv = glm::vec2((float)x / PATCH_SIZE, (float)y / PATCH_SIZE) * UV_SCALE; } } @@ -459,7 +530,7 @@ public: // Binding 1 : Height map vkTools::initializers::descriptorSetLayoutBinding( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 1), // Binding 3 : Terrain texture array layers vkTools::initializers::descriptorSetLayoutBinding( @@ -685,6 +756,9 @@ public: uboTess.lightPos.y = -0.5f - uboTess.displacementFactor; // todo: Not uesed yet uboTess.viewportDim = glm::vec2((float)width, (float)height); + frustum.update(uboTess.projection * uboTess.modelview); + memcpy(uboTess.frustumPlanes, frustum.planes.data(), sizeof(glm::vec4) * 6); + float savedFactor = uboTess.tessellationFactor; if (!tessellation) { @@ -721,6 +795,9 @@ public: // Submit to queue VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + // Read query results for displaying in next frame + getQueryResults(); + VulkanExampleBase::submitFrame(); } @@ -728,8 +805,9 @@ public: { VulkanExampleBase::prepare(); loadMeshes(); - generateTerrain(); loadTextures(); + generateTerrain(); + setupQueryResultBuffer(); setupVertexDescriptions(); prepareUniformBuffers(); setupDescriptorSetLayouts(); @@ -810,6 +888,10 @@ public: textOverlay->addText("Press \"f\" to toggle wireframe", 5.0f, 100.0f, VulkanTextOverlay::alignLeft); textOverlay->addText("Press \"t\" to toggle tessellation", 5.0f, 115.0f, VulkanTextOverlay::alignLeft); #endif + + textOverlay->addText("pipeline stats:", width - 5.0f, 5.0f, VulkanTextOverlay::alignRight); + textOverlay->addText("VS:" + std::to_string(pipelineStats[0]), width - 5.0f, 20.0f, VulkanTextOverlay::alignRight); + textOverlay->addText("TE:" + std::to_string(pipelineStats[1]), width - 5.0f, 35.0f, VulkanTextOverlay::alignRight); } };