From d85734c7497cbd421aae16ea13f75c3fb14f504f Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Sun, 6 Jun 2021 20:23:14 +0200 Subject: [PATCH] [#66] Added barrier/transition function for sampled images and implemented shadow mapping as a test --- include/vkcv/Core.hpp | 1 + include/vkcv/PipelineConfig.hpp | 2 +- include/vkcv/ShaderProgram.hpp | 2 + .../resources/shaders/compile.bat | 2 + .../cmd_sync_test/resources/shaders/frag.spv | Bin 920 -> 3844 bytes .../resources/shaders/shader.frag | 32 ++++- .../resources/shaders/shader.vert | 3 + .../resources/shaders/shadow.frag | 6 + .../resources/shaders/shadow.vert | 12 ++ .../resources/shaders/shadow_frag.spv | Bin 0 -> 288 bytes .../resources/shaders/shadow_vert.spv | Bin 0 -> 1184 bytes .../cmd_sync_test/resources/shaders/vert.spv | Bin 1520 -> 1872 bytes projects/cmd_sync_test/src/main.cpp | 120 ++++++++++++++++-- src/vkcv/Core.cpp | 10 +- src/vkcv/PipelineConfig.cpp | 14 +- src/vkcv/PipelineManager.cpp | 2 +- src/vkcv/ShaderProgram.cpp | 11 ++ 17 files changed, 193 insertions(+), 24 deletions(-) create mode 100644 projects/cmd_sync_test/resources/shaders/shadow.frag create mode 100644 projects/cmd_sync_test/resources/shaders/shadow.vert create mode 100644 projects/cmd_sync_test/resources/shaders/shadow_frag.spv create mode 100644 projects/cmd_sync_test/resources/shaders/shadow_vert.spv diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 01e59191..8a165adf 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -258,5 +258,6 @@ namespace vkcv void submitCommandStream(const CommandStreamHandle handle); void prepareSwapchainImageForPresent(const CommandStreamHandle handle); + void prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image); }; } diff --git a/include/vkcv/PipelineConfig.hpp b/include/vkcv/PipelineConfig.hpp index f464997b..7dc6f220 100644 --- a/include/vkcv/PipelineConfig.hpp +++ b/include/vkcv/PipelineConfig.hpp @@ -27,7 +27,7 @@ namespace vkcv { const ShaderProgram& shaderProgram, uint32_t width, uint32_t height, - PassHandle &passHandle, + const PassHandle &passHandle, const std::vector<VertexAttribute> &vertexAttributes, const std::vector<vk::DescriptorSetLayout> &descriptorLayouts, bool useDynamicViewport); diff --git a/include/vkcv/ShaderProgram.hpp b/include/vkcv/ShaderProgram.hpp index ef5d1f00..459125bb 100644 --- a/include/vkcv/ShaderProgram.hpp +++ b/include/vkcv/ShaderProgram.hpp @@ -58,10 +58,12 @@ namespace vkcv { void reflectShader(ShaderStage shaderStage); const VertexLayout &getVertexLayout() const; + size_t getPushConstantSize() const; private: std::unordered_map<ShaderStage, Shader> m_Shaders; VertexLayout m_VertexLayout; + size_t m_pushConstantSize = 0; }; } diff --git a/projects/cmd_sync_test/resources/shaders/compile.bat b/projects/cmd_sync_test/resources/shaders/compile.bat index b4521235..516c2f2f 100644 --- a/projects/cmd_sync_test/resources/shaders/compile.bat +++ b/projects/cmd_sync_test/resources/shaders/compile.bat @@ -1,3 +1,5 @@ %VULKAN_SDK%\Bin32\glslc.exe shader.vert -o vert.spv %VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv +%VULKAN_SDK%\Bin32\glslc.exe shadow.vert -o shadow_vert.spv +%VULKAN_SDK%\Bin32\glslc.exe shadow.frag -o shadow_frag.spv pause \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/frag.spv b/projects/cmd_sync_test/resources/shaders/frag.spv index 087e4e22fb2fcec27d99b3ff2aa1a705fe755796..ff3110571871d65ce119dc6c5006e7e67aa53546 100644 GIT binary patch literal 3844 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 JL2OWY2mp}OH~s(s literal 920 zcmZQ(Qf6mhU}WH8;AN0yfB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!N<T1qQG+e z3>*wB3=CkLo0ypglHg=uU=U+qV31*8U=Uzn2FtNCFfcGPFf%YQFfbfq1gYm_aQBIK z404JuPAy0*N-Rl@FV09zNiB-cPs&P7E-417;R2~~_xE@Aag9$dD2OjEsmw`@&&kY7 zjZeueN=+`wEK3Ec<3LiEnU|bXnu4r=m4OB92AKO;8CV%WZp<$&an8@lF9Nw4B*w$Q zz>u3-oDq^*QBqoz%D~FN#vs7Jz)%9=2Pfth<fIlcFo4Vh`L7_cxHvQn#AgNj6~y<; zFUn2KVPJ4)U;*192Qr)i!UvhJgvM7y;)Co$mIv`c@}Rf?nFq2HWFCwU3SST(WP~sS z6F6)Y!J*6mW{WW}Gq5o*FeorEFo-j-Fo5C!#0SNm0s{*J2RKd`z~a_WJ}6v3@{$ak z3|tHhVErKbKz6_|j1Mw{8!8A=3o--52l*2uEXBaYzz4RUg@GR=z`y|JgVcfeApe1c zr5TtRgcumW_JQ0f0<{;ERzP-$GJsMj0|Q7Lq!+{og$2kRAoUVZ^`LYJQZEfv5ArWa zJ%|qqE0B6K23By`fYgHQ2Kn^|0}}%)0|SFC0}I#<ybKHsAU}ZkAomM`(=h`>7y~QV zox%(Z3?MZiagZ92yTqYsKAeG-0puP@1_lO@I*_<O0|z*ar5G3(K;j?_vK!<ckRR<B Sn89fUB>$Izk->t2kpTei7*62; diff --git a/projects/cmd_sync_test/resources/shaders/shader.frag b/projects/cmd_sync_test/resources/shaders/shader.frag index 71a1de69..95f1b331 100644 --- a/projects/cmd_sync_test/resources/shaders/shader.frag +++ b/projects/cmd_sync_test/resources/shaders/shader.frag @@ -3,12 +3,42 @@ layout(location = 0) in vec3 passNormal; layout(location = 1) in vec2 passUV; +layout(location = 2) in vec3 passPos; layout(location = 0) out vec3 outColor; layout(set=0, binding=0) uniform texture2D meshTexture; layout(set=0, binding=1) uniform sampler textureSampler; +layout(set=0, binding=2) uniform sunBuffer { + vec3 L; float padding; + mat4 lightMatrix; +}; +layout(set=0, binding=3) uniform texture2D shadowMap; +layout(set=0, binding=4) uniform sampler shadowMapSampler; + +float shadowTest(vec3 worldPos){ + vec4 lightPos = lightMatrix * vec4(worldPos, 1); + lightPos /= lightPos.w; + lightPos.xy = lightPos.xy * 0.5 + 0.5; + + if(any(lessThan(lightPos.xy, vec2(0))) || any(greaterThan(lightPos.xy, vec2(1)))){ + return 1; + } + + lightPos.z = clamp(lightPos.z, 0, 1); + + float shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy).r; + float bias = 0.01f; + shadowMapSample += bias; + return shadowMapSample < lightPos.z ? 0 : 1; +} void main() { - outColor = texture(sampler2D(meshTexture, textureSampler), passUV).rgb; + vec3 N = normalize(passNormal); + vec3 sunColor = vec3(1); + vec3 sun = sunColor * clamp(dot(N, L), 0, 1); + sun *= shadowTest(passPos); + vec3 ambient = vec3(0.1); + vec3 albedo = texture(sampler2D(meshTexture, textureSampler), passUV).rgb; + outColor = albedo * (sun + ambient); } \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/shader.vert b/projects/cmd_sync_test/resources/shaders/shader.vert index 76855152..0ab82c20 100644 --- a/projects/cmd_sync_test/resources/shaders/shader.vert +++ b/projects/cmd_sync_test/resources/shaders/shader.vert @@ -7,13 +7,16 @@ layout(location = 2) in vec2 inUV; layout(location = 0) out vec3 passNormal; layout(location = 1) out vec2 passUV; +layout(location = 2) out vec3 passPos; layout( push_constant ) uniform constants{ mat4 mvp; + mat4 model; }; void main() { gl_Position = mvp * vec4(inPosition, 1.0); passNormal = inNormal; passUV = inUV; + passPos = (model * vec4(inPosition, 1)).xyz; } \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/shadow.frag b/projects/cmd_sync_test/resources/shaders/shadow.frag new file mode 100644 index 00000000..848f853f --- /dev/null +++ b/projects/cmd_sync_test/resources/shaders/shadow.frag @@ -0,0 +1,6 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +void main() { + +} \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/shadow.vert b/projects/cmd_sync_test/resources/shaders/shadow.vert new file mode 100644 index 00000000..e0f41d42 --- /dev/null +++ b/projects/cmd_sync_test/resources/shaders/shadow.vert @@ -0,0 +1,12 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 inPosition; + +layout( push_constant ) uniform constants{ + mat4 mvp; +}; + +void main() { + gl_Position = mvp * vec4(inPosition, 1.0); +} \ No newline at end of file diff --git a/projects/cmd_sync_test/resources/shaders/shadow_frag.spv b/projects/cmd_sync_test/resources/shaders/shadow_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..6be3bd2518a3b1f234e39aea2503ba86cfb3314b GIT binary patch literal 288 zcmZQ(Qf6mhU}WH8;ALQAfB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!N<T1qQG+e z46F<+3=CkLo0ypgk`Q2E2J_h&7#Nrtm>HND7#I#Qg4A#_xckIA206tSrxqj@C6=Vd z7iT1<q!z{JCuOB3mlT84aDmjg`}@25xW*?J6vP*oROY0{=Va!k#;0T!r6!kTmZgH! zaUiM7%uCKGO+i)wauvv3FgFP^FoE5n2zC(zm~F<u3Z_BoK<)<l>IVZ811kdq!(RqQ J1`7s81^|-UE#&|J literal 0 HcmV?d00001 diff --git a/projects/cmd_sync_test/resources/shaders/shadow_vert.spv b/projects/cmd_sync_test/resources/shaders/shadow_vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..afaa0824ee9be2c22209d611943c6512587dce24 GIT binary patch literal 1184 zcmZQ(Qf6mhU}WH8;AK!|fB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!N<T1qQG+e z4D4Vw3j+f~ZenI0h{Makz#z%Mz`)GF%)rFJz;K9>fq{jAlfm65-Z982zBsiYu_&=5 zHNH3_F(tJqK0hfdHMyi1q=pNm#@*lF-N!XPxu77vxTG>CH9jXZFEu_TvnVyWB(p3P zq>ckgU1nZ#PH76V0#*hV24wfJGO#glGcYiu=fnr37KNo2m84dH+{p$N2eCnN`Nf$f znfZAPYz*vR^`I~Si)ZGQ1ZP&Ig4Ds}K>kY4iFeM)EO5yzE=kNwPKE0Og$_urG$#ix z$I8IW016k78LSMf41x>{49WR<Ae|tuGq5qRfW<)axn%_mAoao^4g&)NNIfV#GxGvq zPGs<4U<JDoqy*$Q5DgOpxf>(~qG4hn_kzSgZi9(|*dQ@bSh+JWgUth}^FVS7D+2@A zE|7accEHjI$PAbmC<O>GFff430EvOjaA#lvrvW*TCI$uuVFo5}T2KV13I;G+jDeYf zje&tdfq{WRoPh<Ll0bZrdqf#n7&xGEAS1M)d`<>XYGq)MVPIk4VqgI42Z_l+;}YZ+ zkQpF35LRGdVc-F$MNoQXV6cYrL2&`{Kgb?Fs6C+Y0@(xN^Mfp9U|^77U||6H4P-9J zU2+V};CKRwfy@?SU|;~*5Arw2Y!Dw5Zy+&{ya-etq#oo)aj2U?c7x<4p#A}ggY<*= zpty#)1>_fLuv;4JLFyHuegV11jDZy#jv#k|lz`0q!N9}-iZe$BRtAvWqTsM+U;z2Y z7U~x<1_lO@IEW9jR|=Y60~tU$1r)Xn3?MO(nJ_U~28bBQT`)0F+=A4B;yZwW9UOo1 z3=sVw^&okW+b1%xg5^N*46+-f2IM}FUz8Xa!1)5?K05|x1`r>l?k@u)g9QU40|0-Z BV|)Mr literal 0 HcmV?d00001 diff --git a/projects/cmd_sync_test/resources/shaders/vert.spv b/projects/cmd_sync_test/resources/shaders/vert.spv index 374c023e14b351eb43cbcda5951cbb8b3d6f96a1..5e514eef5983927316465679af5461f507497130 100644 GIT binary patch delta 394 zcmeyseSwdcnMs+Qfq{{Mi-DKHVj{08BhN%<O-9{~nf8prYz(Xnf(#&828P`Hl++vs zhRMqrGx=E=SQvB}7#Io?i;DyDizo9lP1W^aV1cV;Wnf_NK+>zsz`)>uEH-&2Q#z|V z$dt)nnXa-!bP8-f%goLwY0bdG0MY=mfSG}TL7RbvfscWKL2vU}7HP(MM+Q~~5e5bZ zeFg>wVUREb1A{FC3xfay1A_rn9K;uAU|=w0U|^7BU|<MjU}a!qU|=wUiZLLG8AHVw zk;F`(VoVGS3;_)64D1XH45kqMp$s4mAO+G43=9()SizEJP|HDz{24eHK$e>`Fff3` cK^SBq$O4dob_~qmzyrzuWng5mU|?hb08{8ANB{r; delta 69 zcmcb>_ko+2nMs+Qfq{{Mi-DIxcOtJTBlkpS&5Z>%jFS&AW=ytVnlhP%Ic9PJ^C@O# a2EomaEbNS%Ggw6!IsP&*GFUJ$G5`P-)(-;! diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp index c3455be6..d28adb37 100644 --- a/projects/cmd_sync_test/src/main.cpp +++ b/projects/cmd_sync_test/src/main.cpp @@ -20,6 +20,7 @@ int main(int argc, const char** argv) { vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); cameraManager.getCamera().setPosition(glm::vec3(0.f, 0.f, 3.f)); + cameraManager.getCamera().setNearFar(0.1, 30); window.initEvents(); @@ -103,8 +104,11 @@ int main(int argc, const char** argv) { triangleShaderProgram.reflectShader(vkcv::ShaderStage::FRAGMENT); std::vector<vkcv::DescriptorBinding> descriptorBindings = { - vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT), - vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT)}; + vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT), + vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT), + vkcv::DescriptorBinding(vkcv::DescriptorType::UNIFORM_BUFFER, 1, vkcv::ShaderStage::FRAGMENT), + vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT) , + vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT) }; vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings); const vkcv::PipelineConfig trianglePipelineDefinition( @@ -132,10 +136,12 @@ int main(int argc, const char** argv) { vkcv::SamplerAddressMode::REPEAT ); - vkcv::DescriptorWrites setWrites; - setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) }; - setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) }; - core.writeResourceDescription(descriptorSet, 0, setWrites); + vkcv::SamplerHandle shadowSampler = core.createSampler( + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerFilterType::NEAREST, + vkcv::SamplerMipmapMode::NEAREST, + vkcv::SamplerAddressMode::CLAMP_TO_EDGE + ); vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle(); @@ -147,19 +153,69 @@ int main(int argc, const char** argv) { glm::vec3( 0.f, -2.f, 0.f), glm::vec3( 3.f, 0.f, 0.f), glm::vec3(-3.f, 0.f, 0.f), - glm::vec3( 0.f, 2.f, 0.f) + glm::vec3( 0.f, 2.f, 0.f), + glm::vec3( 0.f, -5.f, 0.f) }; std::vector<glm::mat4> modelMatrices; std::vector<vkcv::DrawcallInfo> drawcalls; + std::vector<vkcv::DrawcallInfo> shadowDrawcalls; for (const auto& position : instancePositions) { modelMatrices.push_back(glm::translate(glm::mat4(1.f), position)); drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage })); + shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {})); } - std::vector<glm::mat4> mvpMatrices; + modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f)); + + std::vector<std::array<glm::mat4, 2>> mainPassMatrices; + std::vector<glm::mat4> mvpLight; + + vkcv::ShaderProgram shadowShader; + shadowShader.addShader(vkcv::ShaderStage::VERTEX, "resources/shaders/shadow_vert.spv"); + shadowShader.addShader(vkcv::ShaderStage::FRAGMENT, "resources/shaders/shadow_frag.spv"); + shadowShader.reflectShader(vkcv::ShaderStage::VERTEX); + shadowShader.reflectShader(vkcv::ShaderStage::FRAGMENT); + + const vk::Format shadowMapFormat = vk::Format::eD16Unorm; + const std::vector<vkcv::AttachmentDescription> shadowAttachments = { + vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat) + }; + const vkcv::PassConfig shadowPassConfig(shadowAttachments); + const vkcv::PassHandle shadowPass = core.createPass(shadowPassConfig); + + const uint32_t shadowMapResolution = 1024; + const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1); + const vkcv::PipelineConfig shadowPipeConfig( + shadowShader, + shadowMapResolution, + shadowMapResolution, + shadowPass, + attributes, + {}, + false); + const vkcv::PipelineHandle shadowPipe = core.createGraphicsPipeline(shadowPipeConfig); + + struct LightInfo { + glm::vec3 direction; + float padding; + glm::mat4 lightMatrix; + }; + LightInfo lightInfo; + vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3)); + + vkcv::DescriptorWrites setWrites; + setWrites.sampledImageWrites = { + vkcv::SampledImageDescriptorWrite(0, texture.getHandle()), + vkcv::SampledImageDescriptorWrite(3, shadowMap.getHandle()) }; + setWrites.samplerWrites = { + vkcv::SamplerDescriptorWrite(1, sampler), + vkcv::SamplerDescriptorWrite(4, shadowSampler) }; + setWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) }; + core.writeResourceDescription(descriptorSet, 0, setWrites); auto start = std::chrono::system_clock::now(); + const auto appStartTime = start; while (window.isWindowOpen()) { vkcv::Window::pollEvents(); @@ -180,16 +236,54 @@ int main(int argc, const char** argv) { start = end; cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); - const glm::mat4 viewProjection = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); - mvpMatrices.clear(); + const float sunTheta = (end - appStartTime).count() * 0.0000001; + lightInfo.direction = glm::normalize(glm::vec3(cos(sunTheta), 1, sin(sunTheta))); + + const float shadowProjectionSize = 5.f; + glm::mat4 projectionLight = glm::ortho( + -shadowProjectionSize, + shadowProjectionSize, + -shadowProjectionSize, + shadowProjectionSize, + -shadowProjectionSize, + shadowProjectionSize); + + glm::mat4 vulkanCorrectionMatrix(1.f); + vulkanCorrectionMatrix[2][2] = 0.5; + vulkanCorrectionMatrix[3][2] = 0.5; + projectionLight = vulkanCorrectionMatrix * projectionLight; + + const glm::mat4 viewLight = glm::lookAt(glm::vec3(0), -lightInfo.direction, glm::vec3(0, -1, 0)); + + lightInfo.lightMatrix = projectionLight * viewLight; + lightBuffer.fill({ lightInfo }); + + const glm::mat4 viewProjectionCamera = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); + + mainPassMatrices.clear(); + mvpLight.clear(); for (const auto& m : modelMatrices) { - mvpMatrices.push_back(viewProjection * m); + mainPassMatrices.push_back({ viewProjectionCamera * m, m }); + mvpLight.push_back(lightInfo.lightMatrix* m); } - vkcv::PushConstantData pushConstantData((void*)mvpMatrices.data(), sizeof(glm::mat4)); - const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; + + vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4)); + const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; + + vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4)); auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); + core.recordDrawcallsToCmdStream( + cmdStream, + shadowPass, + shadowPipe, + shadowPushConstantData, + shadowDrawcalls, + { shadowMap.getHandle() }); + + core.prepareImageForSampling(cmdStream, shadowMap.getHandle()); + core.recordDrawcallsToCmdStream( cmdStream, trianglePass, diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 908cb617..9ed83d2a 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -375,7 +375,9 @@ namespace vkcv const FinishCommandFunction &finish) { m_CommandStreamManager->recordCommandsToStream(cmdStreamHandle, record); - m_CommandStreamManager->addFinishCallbackToStream(cmdStreamHandle, finish); + if (finish) { + m_CommandStreamManager->addFinishCallbackToStream(cmdStreamHandle, finish); + } } void Core::submitCommandStream(const CommandStreamHandle handle) { @@ -457,4 +459,10 @@ namespace vkcv recordSwapchainImageLayoutTransition(cmdBuffer, vk::ImageLayout::ePresentSrcKHR); }); } + + void Core::prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image) { + recordCommandsToStream(cmdStream, [image, this](const vk::CommandBuffer cmdBuffer) { + m_ImageManager->recordImageLayoutTransition(image, vk::ImageLayout::eShaderReadOnlyOptimal, cmdBuffer); + }, nullptr); + } } diff --git a/src/vkcv/PipelineConfig.cpp b/src/vkcv/PipelineConfig.cpp index 14259245..ad8437ca 100644 --- a/src/vkcv/PipelineConfig.cpp +++ b/src/vkcv/PipelineConfig.cpp @@ -9,13 +9,13 @@ namespace vkcv { PipelineConfig::PipelineConfig( - const ShaderProgram& shaderProgram, - uint32_t width, - uint32_t height, - PassHandle &passHandle, - const std::vector<VertexAttribute> &vertexAttributes, - const std::vector<vk::DescriptorSetLayout> &descriptorLayouts, - bool useDynamicViewport) + const ShaderProgram& shaderProgram, + uint32_t width, + uint32_t height, + const PassHandle &passHandle, + const std::vector<VertexAttribute> &vertexAttributes, + const std::vector<vk::DescriptorSetLayout> &descriptorLayouts, + bool useDynamicViewport) : m_ShaderProgram(shaderProgram), m_Height(height), diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp index 9afa2bc9..28a64a24 100644 --- a/src/vkcv/PipelineManager.cpp +++ b/src/vkcv/PipelineManager.cpp @@ -174,7 +174,7 @@ namespace vkcv { 1.f,1.f,1.f,1.f } ); - const size_t matrixPushConstantSize = 4 * 4 * sizeof(float); + const size_t matrixPushConstantSize = config.m_ShaderProgram.getPushConstantSize(); const vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eAll, 0, matrixPushConstantSize); // pipeline layout diff --git a/src/vkcv/ShaderProgram.cpp b/src/vkcv/ShaderProgram.cpp index 5185b8b4..3eea7ed2 100644 --- a/src/vkcv/ShaderProgram.cpp +++ b/src/vkcv/ShaderProgram.cpp @@ -5,6 +5,7 @@ */ #include "vkcv/ShaderProgram.hpp" +#include <algorithm> namespace vkcv { /** @@ -128,9 +129,19 @@ namespace vkcv { m_VertexLayout = VertexLayout(inputVec); } + for (const auto &pushConstantBuffer : resources.push_constant_buffers) { + for (const auto &range : comp.get_active_buffer_ranges(pushConstantBuffer.id)) { + const size_t size = range.range + range.offset; + m_pushConstantSize = std::max(m_pushConstantSize, size); + } + } } const VertexLayout& ShaderProgram::getVertexLayout() const{ return m_VertexLayout; } + + size_t ShaderProgram::getPushConstantSize() const { + return m_pushConstantSize; + } } -- GitLab