From 367fce5b462032fb4f12b8c61a23caeda8aab9fe Mon Sep 17 00:00:00 2001 From: saschawillems Date: Sun, 7 Oct 2018 10:27:28 +0200 Subject: [PATCH] Reworked inline uniform block example --- data/shaders/inlineuniformblocks/cube.frag | 23 - .../shaders/inlineuniformblocks/cube.frag.spv | Bin 1616 -> 0 bytes data/shaders/inlineuniformblocks/cube.vert | 40 -- .../shaders/inlineuniformblocks/cube.vert.spv | Bin 3220 -> 0 bytes data/shaders/inlineuniformblocks/pbr.frag | 116 +++++ data/shaders/inlineuniformblocks/pbr.frag.spv | Bin 0 -> 7240 bytes data/shaders/inlineuniformblocks/pbr.vert | 32 ++ data/shaders/inlineuniformblocks/pbr.vert.spv | Bin 0 -> 2196 bytes .../inlineuniformblocks.cpp | 440 ++++++++---------- 9 files changed, 349 insertions(+), 302 deletions(-) delete mode 100644 data/shaders/inlineuniformblocks/cube.frag delete mode 100644 data/shaders/inlineuniformblocks/cube.frag.spv delete mode 100644 data/shaders/inlineuniformblocks/cube.vert delete mode 100644 data/shaders/inlineuniformblocks/cube.vert.spv create mode 100644 data/shaders/inlineuniformblocks/pbr.frag create mode 100644 data/shaders/inlineuniformblocks/pbr.frag.spv create mode 100644 data/shaders/inlineuniformblocks/pbr.vert create mode 100644 data/shaders/inlineuniformblocks/pbr.vert.spv diff --git a/data/shaders/inlineuniformblocks/cube.frag b/data/shaders/inlineuniformblocks/cube.frag deleted file mode 100644 index f00d3d99..00000000 --- a/data/shaders/inlineuniformblocks/cube.frag +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout (set = 0, binding = 2) uniform sampler2D samplerColorMap; - -layout (location = 0) in vec3 inNormal; -layout (location = 1) in vec3 inColor; -layout (location = 2) in vec2 inUV; -layout (location = 3) in vec3 inViewVec; -layout (location = 4) in vec3 inLightVec; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - vec3 color = texture(samplerColorMap, inUV).rgb * inColor; - - vec3 N = normalize(inNormal); - vec3 L = normalize(inLightVec); - vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); - float diffuse = max(dot(N, L), 0.1); - outFragColor = vec4(color * diffuse, 1.0); -} \ No newline at end of file diff --git a/data/shaders/inlineuniformblocks/cube.frag.spv b/data/shaders/inlineuniformblocks/cube.frag.spv deleted file mode 100644 index 2acb5f85035bf5481a526bcb4b74cf7cf20a5f3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1616 zcmZ9KNl#Q!5Js;w4JgPU3L*|PC=O^l0iuX5jIwEQin#7TgD-(@(hYH`8@I0fMXvGx zxH0jZ+wUeXzL!eX_tkK#>fTb%Tz?2BLVp+tPeb<`3q3F)42Hg_*J~eY)z0B|b#dvQ z5yPPr1C1FWsu!*7*R!UMF=P^%My?=p$U|h5JmWYJtHdcG{Gv!1wwNzIiEpd5*J`87 z^l=*9sqY``HQFzvU)K*}o@ZsvkDI87JvVE{5O6760B=NJIrft^H(Kre`W{sDUq;t* zzrAM7TDJT7aI>-1_0Pgtyv*+$S#vXMe2MOuKM(gl`g_A|^mewhbJS_z>x(nDjt*b7 z>$}~C@UJtQvsl+J;R?3<5Id87CG1RM_pRT(iv7g)Ep~@u`xKXQ?Cw+iI907%i8s(a zV*%PCXb%qg^f`zd}2Pm?)_!#MMY@*ug@9J>QQ&l^Eo&%TTw zMO#bWc(FT?GkzRxyz?4Af!1e##*5vVT*B_Gh}~HcyEC!%7SL%23t-Rk;r~89Ueo^o z+uhiQ^~LU3F2z5>4&mGLWnO}F*{h#1e_+aJbKR|PJ@qd3%@(nDSH!db;rRl#ci*A$ zYt(n=!-)G9yVEm>`}{-~&TtknM*a;QnR^bASNz;uWknKoo%%sx4Y*5nAs;Nkcf8CY>}@zsZc_572+4 zpZrOFamMF4XRmrD?#!CK-gjO0+H0?z+QjtUEZdXq&GuzmS-B2n6EIn}KbtJ}g{7NI zGuxw$nbT+9(&J!OD;)KCoS&gFgPX;=c0UVTyhA^76Iy z(J*g!wu?A9*Vb_GpwlkG;7eb7`a|CNQG0OqXmha9v1jHy!M<~Mu$$AG?Qh2Ke;-*tMl9yxr6yuV8oe%`;AckhqNG;sCoYq?$ADBg}-OS-Lf+C`i>;npZy zDqA4Vx3h2FN9?MqZ9ng2g~ zeK&UloBnZD)Klg7gB0~FQkQ<#P>mBCH;Y7^+<2U|R^!CRJwzf-F5;|t3M^+2e0Q-c zaI1s`b_U|!+I{yb_RYoCrrrOcxSp`@D6S!gIn{GpAhG&Uv`O|Ra*QbJ6l-sS_a$Ba ze8SE_*dImr?68Y{A35_q#%@0AIZl-GAZKpBGS(nxZm}~WcLaQhy@{CXWWrCPyNo}~ zuCMt#>uGk+lGFYSyLHN&U+j!U?a!f`JM3a-PR?5GTh#g@x^Z&m5;u`Df1RF|zU4j3 z*^>*go@ubPO(EtGpGchcmy&Kw-1k-VJr#T^`514nosY14_jiyidw9uw=g_P#?(hM+ z?<6+fx1C4g4p-5&izC1DWq$LmvTIkY&+|SrJE5sQ6v_&0V z^f=eLoLli({$2LWzPjZ8hVegVtatLeXl}7J`pv6izjxvb*xe5x&gdLjoS~->=g!&E z$Nn5a^(#5FA4ANm-$knQKO$#7=j#Q;+0y0=iap;qe;IKO;`|o+ zD~S)E*OHI(U`~BrN92DekN6~FoP5N+fo^W+CgNt$#yAz{f)fZ-a|ZJA8U4I-$$B={jgtR{o+m^qL1I{ z0-Su*e-XV}|0S@TD{7rZm#fx4m$+*Em*I?`MYLDzzXJAbeXP}4l#5zFLLaa7V>tN( zbhgF5fLOy6qU~0C-$it7)@!dmLF8O9m!G1`D=za)AQ7{KZj5}yTtk;vT;nm<;fyg) z#4MxBE3SxH;SPQ`RuF43x4!WXpP~B=@vhF*O~hF5ugy7-zlE4XyM3HbocbEN-;L<$ zH|XO%{T5C>?)@FQoGb2d8(m&;#T_E%4xBOa5wnhdCkfmCV(!8jQ|(n7EU&oYoaogC zoVA!+-{@5b-MdCl?xE`|Zy)@Q$%X%YbUCr}kt5Du)czoG@~)`km(=s`;mo0*`Md0L gk#7^dny(L*Q(Ten=k(1O!0BVI9=rG-yv`y20^mN%uK)l5 diff --git a/data/shaders/inlineuniformblocks/pbr.frag b/data/shaders/inlineuniformblocks/pbr.frag new file mode 100644 index 00000000..6c237e76 --- /dev/null +++ b/data/shaders/inlineuniformblocks/pbr.frag @@ -0,0 +1,116 @@ +#version 450 + +layout (location = 0) in vec3 inWorldPos; +layout (location = 1) in vec3 inNormal; + +layout (set = 0, binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; + mat4 view; + vec3 camPos; +} ubo; + +// Inline uniform block +layout (set = 1, binding = 0) uniform UniformInline { + float roughness; + float metallic; + float r; + float g; + float b; + float ambient; +} material; + +layout (location = 0) out vec4 outColor; + +const float PI = 3.14159265359; + +vec3 materialcolor() +{ + return vec3(material.r, material.g, material.b); +} + +// Normal Distribution function -------------------------------------- +float D_GGX(float dotNH, float roughness) +{ + float alpha = roughness * roughness; + float alpha2 = alpha * alpha; + float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; + return (alpha2)/(PI * denom*denom); +} + +// Geometric Shadowing function -------------------------------------- +float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + float GL = dotNL / (dotNL * (1.0 - k) + k); + float GV = dotNV / (dotNV * (1.0 - k) + k); + return GL * GV; +} + +// Fresnel function ---------------------------------------------------- +vec3 F_Schlick(float cosTheta, float metallic) +{ + vec3 F0 = mix(vec3(0.04), materialcolor(), metallic); // * material.specular + vec3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); + return F; +} + +// Specular BRDF composition -------------------------------------------- + +vec3 BRDF(vec3 L, vec3 V, vec3 N, float metallic, float roughness) +{ + // Precalculate vectors and dot products + vec3 H = normalize (V + L); + float dotNV = clamp(dot(N, V), 0.0, 1.0); + float dotNL = clamp(dot(N, L), 0.0, 1.0); + float dotLH = clamp(dot(L, H), 0.0, 1.0); + float dotNH = clamp(dot(N, H), 0.0, 1.0); + + // Light color fixed + vec3 lightColor = vec3(1.0); + + vec3 color = vec3(0.0); + + if (dotNL > 0.0) + { + float rroughness = max(0.05, roughness); + // D = Normal distribution (Distribution of the microfacets) + float D = D_GGX(dotNH, rroughness); + // G = Geometric shadowing term (Microfacets shadowing) + float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); + // F = Fresnel factor (Reflectance depending on angle of incidence) + vec3 F = F_Schlick(dotNV, metallic); + + vec3 spec = D * F * G / (4.0 * dotNL * dotNV); + + color += spec * dotNL * lightColor; + } + + return color; +} + +// ---------------------------------------------------------------------------- +void main() +{ + vec3 N = normalize(inNormal); + vec3 V = normalize(ubo.camPos - inWorldPos); + + float roughness = material.roughness; + + // Specular contribution + vec3 lightPos = vec3(0.0f, 0.0f, 10.0f); + vec3 Lo = vec3(0.0); + vec3 L = normalize(lightPos.xyz - inWorldPos); + Lo += BRDF(L, V, N, material.metallic, roughness); + + // Combine with ambient + vec3 color = materialcolor() * material.ambient; + color += Lo; + + // Gamma correct + color = pow(color, vec3(0.4545)); + + outColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/data/shaders/inlineuniformblocks/pbr.frag.spv b/data/shaders/inlineuniformblocks/pbr.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..f4200da8e7cfa6d3c5b9a7bf87faa058b536df89 GIT binary patch literal 7240 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 ZpW36G>8oiy+qTjFhhSs;Zi)SF{SVl9o}d5# literal 0 HcmV?d00001 diff --git a/data/shaders/inlineuniformblocks/pbr.vert b/data/shaders/inlineuniformblocks/pbr.vert new file mode 100644 index 00000000..a1b542a5 --- /dev/null +++ b/data/shaders/inlineuniformblocks/pbr.vert @@ -0,0 +1,32 @@ +#version 450 + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inNormal; + +layout (set = 0, binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; + mat4 view; + vec3 camPos; +} ubo; + +layout (location = 0) out vec3 outWorldPos; +layout (location = 1) out vec3 outNormal; + +layout(push_constant) uniform PushConsts { + vec3 objPos; +} pushConsts; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +void main() +{ + vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0)); + outWorldPos = locPos + pushConsts.objPos; + outNormal = mat3(ubo.model) * inNormal; + gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); +} diff --git a/data/shaders/inlineuniformblocks/pbr.vert.spv b/data/shaders/inlineuniformblocks/pbr.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..84274aa1f5c141cdc66603b3de6c66e5ee5af6d5 GIT binary patch literal 2196 zcmZ9NSyNL%5QT??1QZ1kS==xL#RbI;5Jh%1K`Du4sgG7jQW`4BrIMgN;!n_DWcjOn zvC8w^JDpsa)X7YrIo;FKJ%MCmy3e^D*XR1(D;JGnmk{IJfJ=vSZs+aJT&rE4n_swx zV$dZ+A(|m~GFE2VZd&?#xD(2zqtC|7EljpLjz)yh{*9gd7k#d;_HpzOoFAk2k) ztBr6=b}Gz0IBb6inzb@4+*N4`hpo?BL8H}Hj+_O@2=?}U+?1P(OC1#NbPIaYDIu?Kv!_G$ ze@+c|XF^@%M-AhC*!Zmr77OmUA9arVVdHlsm>*o%FUpHvp!+4{e6P{vbPxKH6&Pku zMP_KztI3#+)@;tSo)Diwd^n3wFVJ%z;?oDS@uvrjfoKZ-;qV{PH}jNYatGF9TBS8- zgmJ~=uGs8nWcO=^1MKr_VZT?H&^PD6VNYs@zQGyrBhG2foX7sMx2YA}sO%xl8KFm* z^)@}m#(!8dTH<1#)65?6iHA*X;qWKNalyHxHS|+jaVOJbXFWHm9cpa3UelW2GaRw8 zXFO-QU6;)u_6^PG)#wKX_thJ!dt&Bl~zw=fuHtFYd}eA~?pb zIz!z10z6=FKkj2b546Sy-h3Wv4G$Q{edfjCLmcy2&>9{v%%`C4@>UlGav?TatHYAk zyj%K3zK;d8@YI1f4`+2)(Rxs@TJpA51$fh}YmJ6C%{gc`gmvMk&cWUk@PoHpwzSR) z_D-H@4aYFbl6!G)Y;=Eh(vt8G DtN3}< literal 0 HcmV?d00001 diff --git a/examples/inlineuniformblocks/inlineuniformblocks.cpp b/examples/inlineuniformblocks/inlineuniformblocks.cpp index bdb7114f..5ec5161a 100644 --- a/examples/inlineuniformblocks/inlineuniformblocks.cpp +++ b/examples/inlineuniformblocks/inlineuniformblocks.cpp @@ -1,5 +1,5 @@ /* -* Vulkan Example - Using inline uniform blocks for passing data to shader stages +* Vulkan Example - Using inline uniform blocks for passing data to shader stages at descriptor setup * Note: Requires a device that supports the VK_EXT_inline_uniform_block extension * @@ -20,81 +20,93 @@ #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include -#include + +#include #include #include "vulkanexamplebase.h" -#include "VulkanTexture.hpp" +#include "VulkanBuffer.hpp" #include "VulkanModel.hpp" #define ENABLE_VALIDATION false +#define OBJ_DIM 0.025f + +float rnd() { + return ((float)rand() / (RAND_MAX)); +} class VulkanExample : public VulkanExampleBase { public: - bool animate = true; - vks::VertexLayout vertexLayout = vks::VertexLayout({ vks::VERTEX_COMPONENT_POSITION, vks::VERTEX_COMPONENT_NORMAL, vks::VERTEX_COMPONENT_UV, - vks::VERTEX_COMPONENT_COLOR, - }); + }); - /* - [POI] This is the data structure that'll be passed using inline uniform blocks - */ - struct InlineBlockData { - glm::vec4 color; - }; + vks::Model model; - struct Cube { - struct Matrices { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - } matrices; - InlineBlockData inlineBlockData; + struct Object { + struct Material { + float roughness; + float metallic; + float r, g, b; + float ambient; + } material; VkDescriptorSet descriptorSet; - vks::Texture2D texture; - vks::Buffer uniformBuffer; - glm::vec3 rotation; }; - std::array cubes; + std::array objects; + + struct { + vks::Buffer scene; + } uniformBuffers; + + struct UBOMatrices { + glm::mat4 projection; + glm::mat4 model; + glm::mat4 view; + glm::vec3 camPos; + } uboMatrices; - struct Models { - vks::Model cube; - } models; - - VkPipeline pipeline; VkPipelineLayout pipelineLayout; + VkPipeline pipeline; + VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; + struct DescriptorSetLaysts { + VkDescriptorSetLayout scene; + VkDescriptorSetLayout object; + } descriptorSetLayouts; VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) { title = "Inline uniform blocks"; + camera.type = Camera::CameraType::firstperson; + camera.setPosition(glm::vec3(0.0f, 0.0f, -10.0f)); + camera.setRotation(glm::vec3(0.0, 0.0f, 0.0f)); + camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); + camera.movementSpeed = 4.0f; + camera.rotationSpeed = 0.25f; settings.overlay = true; - camera.type = Camera::CameraType::lookat; - camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f); - camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - camera.setTranslation(glm::vec3(0.0f, 0.0f, -5.0f)); + + srand((unsigned int)time(0)); + /* - [POI] Enable extension required for conditional rendering - */ + [POI] Enable extensions required for inline uniform blocks + */ enabledDeviceExtensions.push_back(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME); } ~VulkanExample() { vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - models.cube.destroy(); - for (auto cube : cubes) { - cube.uniformBuffer.destroy(); - cube.texture.destroy(); - } + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.object, nullptr); + + model.destroy(); + + uniformBuffers.scene.destroy(); } void buildCommandBuffers() @@ -102,7 +114,7 @@ public: VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); VkClearValue clearValues[2]; - clearValues[0].color = defaultClearColor; + clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; clearValues[1].depthStencil = { 1.0f, 0 }; VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); @@ -114,15 +126,14 @@ public: renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.pClearValues = clearValues; - for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { + for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) + { renderPassBeginInfo.framebuffer = frameBuffers[i]; VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); @@ -130,14 +141,30 @@ public: vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); VkDeviceSize offsets[1] = { 0 }; - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.cube.vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], models.cube.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - for (auto cube : cubes) { - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &cube.descriptorSet, 0, nullptr); - vkCmdDrawIndexed(drawCmdBuffers[i], models.cube.indexCount, 1, 0, 0, 0); + // Render objects + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &model.vertices.buffer, offsets); + vkCmdBindIndexBuffer(drawCmdBuffers[i], model.indices.buffer, 0, VK_INDEX_TYPE_UINT32); + + uint32_t objcount = static_cast(objects.size()); + for (uint32_t x = 0; x < objcount; x++) { + /* + [POI] Bind descriptor sets + Set 0 = Scene matrices: + Set 1 = Object inline uniform block (In shader pbr.frag: layout (set = 1, binding = 0) uniform UniformInline ... ) + */ + std::vector descriptorSets = { + descriptorSet, + objects[x].descriptorSet + }; + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, descriptorSets.data(), 0, nullptr); + + glm::vec3 pos = glm::vec3(sin(glm::radians(x * (360.0f / objcount))), cos(glm::radians(x * (360.0f / objcount))), 0.0f) * 3.5f; + + vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos); + vkCmdDrawIndexed(drawCmdBuffers[i], model.indexCount, 1, 0, 0, 0); } - drawUI(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -148,184 +175,135 @@ public: void loadAssets() { - models.cube.loadFromFile(getAssetPath() + "models/cube.dae", vertexLayout, 1.0f, vulkanDevice, queue); - cubes[0].texture.loadFromFile(getAssetPath() + "textures/crate01_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - cubes[1].texture.loadFromFile(getAssetPath() + "textures/crate02_color_height_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); - cubes[0].inlineBlockData.color = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f); - cubes[1].inlineBlockData.color = glm::vec4(0.0f, 0.0f, 1.0f, 1.0f); + model.loadFromFile(getAssetPath() + "models/geosphere.obj", vertexLayout, OBJ_DIM, vulkanDevice, queue); + + // Setup random materials for every object in the scene + for (uint32_t i = 0; i < objects.size(); i++) { + objects[i].material.r = rnd(); + objects[i].material.g = rnd(); + objects[i].material.b = rnd(); + objects[i].material.ambient = 0.05f; + objects[i].material.roughness = glm::clamp(rnd(), 0.005f, 1.0f); + objects[i].material.metallic = glm::clamp(rnd(), 0.005f, 1.0f); + } } - /* - [POI] Set up descriptor sets and set layout - */ - void setupDescriptors() + void setupDescriptorSetLayout() { - const uint32_t cubeCount = static_cast(cubes.size()); + // Scene + { + std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), + }; + VkDescriptorSetLayoutCreateInfo descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.scene)); + } + + // Objects + { + std::vector setLayoutBindings = { + /* + [POI] Setup inline uniform block for set 0 at binding 2 (see vertex shader) + Descriptor count for an inline uniform block contains data sizes of the block (last parameter) + */ + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Object::Material)), + }; + VkDescriptorSetLayoutCreateInfo descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.object)); + } /* - Descriptor pool + [POI] Pipeline layout */ + std::vector setLayouts = { + descriptorSetLayouts.scene, // Set 0 = Scene matrices + descriptorSetLayouts.object // Set 1 = Object inline uniform block + }; + VkPipelineLayoutCreateInfo pipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); - std::array descriptorPoolSizes{}; + std::vector pushConstantRanges = { + vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0), + }; + pipelineLayoutCI.pushConstantRangeCount = 1; + pipelineLayoutCI.pPushConstantRanges = pushConstantRanges.data(); - // One uniform buffer descriptor per cube - descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorPoolSizes[0].descriptorCount = cubeCount; + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); + } + + void setupDescriptorSets() + { + // Pool + std::vector poolSizes = { + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, (static_cast(objects.size()) + 1)), + /* [POI] TODO */ + // TODO: split scene and object + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, (static_cast(objects.size()) + 1) * sizeof(Object::Material)), + }; + VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, static_cast(objects.size()) + 1); /* - [POI] One inline uniform block descriptor per cube - */ - descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - // Descriptor count for inline uniform blocks contains the combined data sizes of all inline uniform blocks used from this pool - descriptorPoolSizes[1].descriptorCount = cubeCount * sizeof(InlineBlockData); - - // One combined image samples per cube - descriptorPoolSizes[2].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorPoolSizes[2].descriptorCount = static_cast(cubes.size()); - - // Create the global descriptor pool - - VkDescriptorPoolCreateInfo descriptorPoolCI = {}; - descriptorPoolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptorPoolCI.poolSizeCount = static_cast(descriptorPoolSizes.size()); - descriptorPoolCI.pPoolSizes = descriptorPoolSizes.data(); - descriptorPoolCI.maxSets = static_cast(descriptorPoolSizes.size()); -# - /* - [POI] New structure that has to be chained into the descriptor pool create info if you want to allocate inline uniform blocks + [POI] New structure that has to be chained into the descriptor pool's createinfo if you want to allocate inline uniform blocks */ VkDescriptorPoolInlineUniformBlockCreateInfoEXT descriptorPoolInlineUniformBlockCreateInfo{}; descriptorPoolInlineUniformBlockCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT; descriptorPoolInlineUniformBlockCreateInfo.maxInlineUniformBlockBindings = 1; - // Chain into descriptor pool create info descriptorPoolCI.pNext = &descriptorPoolInlineUniformBlockCreateInfo; - + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool)); - /* - Descriptor set layout - */ + // Sets - std::array setLayoutBindings{}; + // Scene + VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &descriptorSet)); - // Binding 0: Uniform buffers (used to pass matrices) - setLayoutBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - setLayoutBindings[0].binding = 0; - setLayoutBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - setLayoutBindings[0].descriptorCount = 1; + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), + }; + vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); - /* - [POI] Binding 1: Inline uniform block - */ - setLayoutBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - setLayoutBindings[1].binding = 1; - setLayoutBindings[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - // Descriptor count for an inline uniform block contains data sizes of the block - setLayoutBindings[1].descriptorCount = sizeof(InlineBlockData); - - // Binding 2: Combined image sampler (used to pass per object texture information) - setLayoutBindings[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - setLayoutBindings[2].binding = 2; - setLayoutBindings[2].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - setLayoutBindings[2].descriptorCount = 1; - - // Create the descriptor set layout - VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{}; - descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorLayoutCI.bindingCount = static_cast(setLayoutBindings.size()); - descriptorLayoutCI.pBindings = setLayoutBindings.data(); - - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout)); - - /* - Descriptor sets - */ - - for (auto &cube: cubes) { - - // Allocates an empty descriptor set without actual descriptors from the pool using the set layout - VkDescriptorSetAllocateInfo allocateInfo{}; - allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocateInfo.descriptorPool = descriptorPool; - allocateInfo.descriptorSetCount = 1; - allocateInfo.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocateInfo, &cube.descriptorSet)); - - // Update the descriptor set with the actual descriptors matching shader bindings set in the layout - - std::array writeDescriptorSets{}; - - // Binding 0: Object matrices Uniform buffer - writeDescriptorSets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[0].dstSet = cube.descriptorSet; - writeDescriptorSets[0].dstBinding = 0; - writeDescriptorSets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeDescriptorSets[0].pBufferInfo = &cube.uniformBuffer.descriptor; - writeDescriptorSets[0].descriptorCount = 1; - - /* - [POI] Binding 1: Inline uniform block - */ - writeDescriptorSets[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[1].dstSet = cube.descriptorSet; - writeDescriptorSets[1].dstBinding = 1; - writeDescriptorSets[1].descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; - // The dstArrayElement member can be used to define an offset for inline uniform blocks - writeDescriptorSets[1].dstArrayElement = 0; - // TODO: API-Design from hell - writeDescriptorSets[1].descriptorCount = sizeof(glm::vec4); + // Objects + for (auto &object : objects) { + VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.object, 1); + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &object.descriptorSet)); /* - [POI] New structure that defines size and data of the inline uniform block + [POI] New structure that defines size and data of the inline uniform block needs to be chained into the write descriptor set + We will be using this inline uniform block to pass per-object material information to the fragment shader */ VkWriteDescriptorSetInlineUniformBlockEXT writeDescriptorSetInlineUniformBlock{}; writeDescriptorSetInlineUniformBlock.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT; - writeDescriptorSetInlineUniformBlock.dataSize = sizeof(InlineBlockData); - writeDescriptorSetInlineUniformBlock.pData = &cube.inlineBlockData; - // Needs to be chained to an existing write descriptor set structure - writeDescriptorSets[1].pNext = &writeDescriptorSetInlineUniformBlock; + writeDescriptorSetInlineUniformBlock.dataSize = sizeof(Object::Material); + // Uniform data for the inline block + writeDescriptorSetInlineUniformBlock.pData = &object.material; - // Binding 2: Object texture - writeDescriptorSets[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[2].dstSet = cube.descriptorSet; - writeDescriptorSets[2].dstBinding = 2; - writeDescriptorSets[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSets[2].pImageInfo = &cube.texture.descriptor; - writeDescriptorSets[2].descriptorCount = 1; + /* + [POI] Setup the inline uniform block + */ + VkWriteDescriptorSet writeDescriptorSet{}; + writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; + writeDescriptorSet.dstSet = object.descriptorSet; + writeDescriptorSet.dstBinding = 0; + // Descriptor count for an inline uniform block contains data sizes of the block(last parameter) + writeDescriptorSet.descriptorCount = sizeof(Object::Material); + // Chain inline uniform block structure + writeDescriptorSet.pNext = &writeDescriptorSetInlineUniformBlock; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); } - } void preparePipelines() { - VkPipelineLayoutCreateInfo pipelineLayoutCI{}; - pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutCI.setLayoutCount = 1; - pipelineLayoutCI.pSetLayouts = &descriptorSetLayout; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout)); - - const std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0); - VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); - VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); - VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); - VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); - VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); - VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast(dynamicStateEnables.size()),0); - - // Vertex bindings and attributes - const std::vector vertexInputBindings = { + // Vertex bindings an attributes + std::vector vertexInputBindings = { vks::initializers::vertexInputBindingDescription(0, vertexLayout.stride(), VK_VERTEX_INPUT_RATE_VERTEX), }; - const std::vector vertexInputAttributes = { - vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 0: Position - vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 1: Normal - vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 6), // Location 2: UV - vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 8), // Location 3: Color + std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), + vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), }; VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); @@ -333,8 +311,18 @@ public: vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); - VkGraphicsPipelineCreateInfo pipelineCreateInfoCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0); - pipelineCreateInfoCI.pVertexInputState = &vertexInputState; + VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); + VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); + VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1); + VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); + std::array shaderStages; + + VkGraphicsPipelineCreateInfo pipelineCreateInfoCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); pipelineCreateInfoCI.pInputAssemblyState = &inputAssemblyStateCI; pipelineCreateInfoCI.pRasterizationState = &rasterizationStateCI; pipelineCreateInfoCI.pColorBlendState = &colorBlendStateCI; @@ -342,54 +330,39 @@ public: pipelineCreateInfoCI.pViewportState = &viewportStateCI; pipelineCreateInfoCI.pDepthStencilState = &depthStencilStateCI; pipelineCreateInfoCI.pDynamicState = &dynamicStateCI; - - const std::array shaderStages = { - loadShader(getAssetPath() + "shaders/inlineuniformblocks/cube.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), - loadShader(getAssetPath() + "shaders/inlineuniformblocks/cube.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - }; - pipelineCreateInfoCI.stageCount = static_cast(shaderStages.size()); pipelineCreateInfoCI.pStages = shaderStages.data(); + pipelineCreateInfoCI.pVertexInputState = &vertexInputState; + shaderStages[0] = loadShader(getAssetPath() + "shaders/inlineuniformblocks/pbr.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getAssetPath() + "shaders/inlineuniformblocks/pbr.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfoCI, nullptr, &pipeline)); } void prepareUniformBuffers() { - // Vertex shader matrix uniform buffer block - for (auto& cube : cubes) { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &cube.uniformBuffer, - sizeof(Cube::Matrices))); - VK_CHECK_RESULT(cube.uniformBuffer.map()); - } - + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.scene, sizeof(uboMatrices))); + VK_CHECK_RESULT(uniformBuffers.scene.map()); updateUniformBuffers(); } void updateUniformBuffers() { - cubes[0].matrices.model = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 0.0f, 0.0f)); - cubes[1].matrices.model = glm::translate(glm::mat4(1.0f), glm::vec3( 1.5f, 0.5f, 0.0f)); - - for (auto& cube : cubes) { - cube.matrices.projection = camera.matrices.perspective; - cube.matrices.view = camera.matrices.view; - cube.matrices.model = glm::rotate(cube.matrices.model, glm::radians(cube.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - cube.matrices.model = glm::rotate(cube.matrices.model, glm::radians(cube.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - cube.matrices.model = glm::rotate(cube.matrices.model, glm::radians(cube.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); - memcpy(cube.uniformBuffer.mapped, &cube.matrices, sizeof(cube.matrices)); - } + uboMatrices.projection = camera.matrices.perspective; + uboMatrices.view = camera.matrices.view; + uboMatrices.model = glm::mat4(1.0f); + uboMatrices.camPos = camera.position * -1.0f; + memcpy(uniformBuffers.scene.mapped, &uboMatrices, sizeof(uboMatrices)); } void draw() { VulkanExampleBase::prepareFrame(); + submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + VulkanExampleBase::submitFrame(); } @@ -398,8 +371,9 @@ public: VulkanExampleBase::prepare(); loadAssets(); prepareUniformBuffers(); - setupDescriptors(); + setupDescriptorSetLayout(); preparePipelines(); + setupDescriptorSets(); buildCommandBuffers(); prepared = true; } @@ -409,24 +383,12 @@ public: if (!prepared) return; draw(); - if (animate) { - cubes[0].rotation.x += 2.5f * frameTimer; - if (cubes[0].rotation.x > 360.0f) - cubes[0].rotation.x -= 360.0f; - cubes[1].rotation.y += 2.0f * frameTimer; - if (cubes[1].rotation.x > 360.0f) - cubes[1].rotation.x -= 360.0f; - } - if ((camera.updated) || (animate)) { + if (camera.updated) updateUniformBuffers(); - } } virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { - if (overlay->header("Settings")) { - overlay->checkBox("Animate", &animate); - } } };