From abdcd6305804b4668c85ee823818b8af125aebe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 5 Sep 2021 18:26:12 +0200 Subject: [PATCH] Graphics: Add support for draw call data (texture overlay) --- include/Nazara/Graphics/Graphics.hpp | 13 ++++- include/Nazara/Graphics/Graphics.inl | 5 ++ include/Nazara/Graphics/MaterialSettings.inl | 1 + include/Nazara/Graphics/RenderSpriteChain.hpp | 4 +- include/Nazara/Graphics/RenderSpriteChain.inl | 8 +++- .../Nazara/Graphics/SpriteChainRenderer.hpp | 3 ++ include/Nazara/Graphics/SubmeshRenderer.hpp | 6 ++- include/Nazara/Renderer/ShaderBinding.hpp | 4 +- src/Nazara/Graphics/Graphics.cpp | 31 ++++++++++++ .../Resources/Shaders/basic_material.nzsl | 13 +++-- .../Resources/Shaders/depth_material.nzsl | 12 +++-- src/Nazara/Graphics/Sprite.cpp | 4 +- src/Nazara/Graphics/SpriteChainRenderer.cpp | 47 +++++++++++++++++++ src/Nazara/Graphics/SubmeshRenderer.cpp | 19 ++++++++ .../OpenGLRenderer/OpenGLShaderBinding.cpp | 4 +- .../VulkanRenderer/VulkanShaderBinding.cpp | 4 +- 16 files changed, 160 insertions(+), 18 deletions(-) diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index d88031f19..dcce88373 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -29,12 +29,14 @@ namespace Nz using Dependencies = TypeList; struct Config; + struct DefaultTextures; Graphics(Config config); ~Graphics(); inline const std::shared_ptr& GetBlitPipeline() const; inline const std::shared_ptr& GetBlitPipelineLayout() const; + inline const DefaultTextures& GetDefaultTextures() const; inline const std::shared_ptr& GetFullscreenVertexBuffer() const; inline const std::shared_ptr& GetFullscreenVertexDeclaration() const; inline MaterialPassRegistry& GetMaterialPassRegistry(); @@ -51,15 +53,23 @@ namespace Nz bool useDedicatedRenderDevice = true; }; - static constexpr UInt32 MaterialBindingSet = 2; + struct DefaultTextures + { + std::shared_ptr whiteTexture2d; + }; + + static constexpr UInt32 DrawDataBindingSet = 2; + static constexpr UInt32 MaterialBindingSet = 3; static constexpr UInt32 ViewerBindingSet = 0; static constexpr UInt32 WorldBindingSet = 1; + static void FillDrawDataPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set = DrawDataBindingSet); static void FillViewerPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set = ViewerBindingSet); static void FillWorldPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set = WorldBindingSet); private: void BuildBlitPipeline(); + void BuildDefaultTextures(); void BuildFullscreenVertexBuffer(); void RegisterMaterialPasses(); void SelectDepthStencilFormats(); @@ -72,6 +82,7 @@ namespace Nz std::shared_ptr m_blitPipelineLayout; std::shared_ptr m_referencePipelineLayout; std::shared_ptr m_fullscreenVertexDeclaration; + DefaultTextures m_defaultTextures; MaterialPassRegistry m_materialPassRegistry; PixelFormat m_preferredDepthStencilFormat; diff --git a/include/Nazara/Graphics/Graphics.inl b/include/Nazara/Graphics/Graphics.inl index 7ed467446..855a8a91c 100644 --- a/include/Nazara/Graphics/Graphics.inl +++ b/include/Nazara/Graphics/Graphics.inl @@ -17,6 +17,11 @@ namespace Nz return m_blitPipelineLayout; } + inline auto Graphics::GetDefaultTextures() const -> const DefaultTextures& + { + return m_defaultTextures; + } + inline const std::shared_ptr& Graphics::GetFullscreenVertexBuffer() const { return m_fullscreenVertexBuffer; diff --git a/include/Nazara/Graphics/MaterialSettings.inl b/include/Nazara/Graphics/MaterialSettings.inl index b867baef6..2c63337dd 100644 --- a/include/Nazara/Graphics/MaterialSettings.inl +++ b/include/Nazara/Graphics/MaterialSettings.inl @@ -18,6 +18,7 @@ namespace Nz m_data(std::move(data)) { RenderPipelineLayoutInfo info; + Graphics::FillDrawDataPipelineLayout(info); Graphics::FillViewerPipelineLayout(info); Graphics::FillWorldPipelineLayout(info); diff --git a/include/Nazara/Graphics/RenderSpriteChain.hpp b/include/Nazara/Graphics/RenderSpriteChain.hpp index a60749377..59f18193e 100644 --- a/include/Nazara/Graphics/RenderSpriteChain.hpp +++ b/include/Nazara/Graphics/RenderSpriteChain.hpp @@ -23,7 +23,7 @@ namespace Nz class RenderSpriteChain : public RenderElement { public: - inline RenderSpriteChain(int renderLayer, std::shared_ptr renderPipeline, std::shared_ptr vertexDeclaration, std::size_t spriteCount, const void* spriteData, const ShaderBinding& materialBinding, const ShaderBinding& instanceBinding); + inline RenderSpriteChain(int renderLayer, std::shared_ptr renderPipeline, std::shared_ptr vertexDeclaration, std::shared_ptr textureOverlay, std::size_t spriteCount, const void* spriteData, const ShaderBinding& materialBinding, const ShaderBinding& instanceBinding); ~RenderSpriteChain() = default; inline UInt64 ComputeSortingScore(const RenderQueueRegistry& registry) const override; @@ -33,6 +33,7 @@ namespace Nz inline const RenderPipeline* GetRenderPipeline() const; inline std::size_t GetSpriteCount() const; inline const void* GetSpriteData() const; + inline const Texture* GetTextureOverlay() const; inline const VertexDeclaration* GetVertexDeclaration() const; inline void Register(RenderQueueRegistry& registry) const override; @@ -40,6 +41,7 @@ namespace Nz private: std::shared_ptr m_renderPipeline; std::shared_ptr m_vertexDeclaration; + std::shared_ptr m_textureOverlay; std::size_t m_spriteCount; const void* m_spriteData; const ShaderBinding& m_instanceBinding; diff --git a/include/Nazara/Graphics/RenderSpriteChain.inl b/include/Nazara/Graphics/RenderSpriteChain.inl index f94a758cd..71d0ef9a7 100644 --- a/include/Nazara/Graphics/RenderSpriteChain.inl +++ b/include/Nazara/Graphics/RenderSpriteChain.inl @@ -7,10 +7,11 @@ namespace Nz { - inline RenderSpriteChain::RenderSpriteChain(int renderLayer, std::shared_ptr renderPipeline, std::shared_ptr vertexDeclaration, std::size_t spriteCount, const void* spriteData, const ShaderBinding& materialBinding, const ShaderBinding& instanceBinding) : + inline RenderSpriteChain::RenderSpriteChain(int renderLayer, std::shared_ptr renderPipeline, std::shared_ptr vertexDeclaration, std::shared_ptr textureOverlay, std::size_t spriteCount, const void* spriteData, const ShaderBinding& materialBinding, const ShaderBinding& instanceBinding) : RenderElement(BasicRenderElement::SpriteChain), m_renderPipeline(std::move(renderPipeline)), m_vertexDeclaration(std::move(vertexDeclaration)), + m_textureOverlay(std::move(textureOverlay)), m_spriteCount(spriteCount), m_spriteData(spriteData), m_instanceBinding(instanceBinding), @@ -64,6 +65,11 @@ namespace Nz return m_spriteData; } + inline const Texture* RenderSpriteChain::GetTextureOverlay() const + { + return m_textureOverlay.get(); + } + inline const VertexDeclaration* RenderSpriteChain::GetVertexDeclaration() const { return m_vertexDeclaration.get(); diff --git a/include/Nazara/Graphics/SpriteChainRenderer.hpp b/include/Nazara/Graphics/SpriteChainRenderer.hpp index 73d354f4a..9dab88f00 100644 --- a/include/Nazara/Graphics/SpriteChainRenderer.hpp +++ b/include/Nazara/Graphics/SpriteChainRenderer.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -53,6 +54,7 @@ namespace Nz { const AbstractBuffer* vertexBuffer; const RenderPipeline* renderPipeline; + const ShaderBinding* drawDataBinding; const ShaderBinding* instanceBinding; const ShaderBinding* materialBinding; std::size_t firstIndex; @@ -68,6 +70,7 @@ namespace Nz std::unordered_map drawCallPerElement; std::vector drawCalls; std::vector> vertexBuffers; + std::vector shaderBindings; }; } diff --git a/include/Nazara/Graphics/SubmeshRenderer.hpp b/include/Nazara/Graphics/SubmeshRenderer.hpp index 16464f94e..156bc8731 100644 --- a/include/Nazara/Graphics/SubmeshRenderer.hpp +++ b/include/Nazara/Graphics/SubmeshRenderer.hpp @@ -9,17 +9,21 @@ #include #include +#include namespace Nz { class NAZARA_GRAPHICS_API SubmeshRenderer : public ElementRenderer { public: - SubmeshRenderer() = default; + SubmeshRenderer(); ~SubmeshRenderer() = default; std::unique_ptr InstanciateData(); void Render(ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer* elements, std::size_t elementCount) override; + + private: + ShaderBindingPtr m_renderDataBinding; }; } diff --git a/include/Nazara/Renderer/ShaderBinding.hpp b/include/Nazara/Renderer/ShaderBinding.hpp index 53f38b128..d2d77f01f 100644 --- a/include/Nazara/Renderer/ShaderBinding.hpp +++ b/include/Nazara/Renderer/ShaderBinding.hpp @@ -42,8 +42,8 @@ namespace Nz struct TextureBinding { - Texture* texture; - TextureSampler* sampler; + const Texture* texture; + const TextureSampler* sampler; }; struct UniformBufferBinding diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index e69644a2f..c7f0fdfd4 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -66,11 +66,13 @@ namespace Nz MaterialPipeline::Initialize(); RenderPipelineLayoutInfo referenceLayoutInfo; + FillDrawDataPipelineLayout(referenceLayoutInfo); FillViewerPipelineLayout(referenceLayoutInfo); FillWorldPipelineLayout(referenceLayoutInfo); m_referencePipelineLayout = m_renderDevice->InstantiateRenderPipelineLayout(std::move(referenceLayoutInfo)); + BuildDefaultTextures(); BuildFullscreenVertexBuffer(); BuildBlitPipeline(); RegisterMaterialPasses(); @@ -86,10 +88,22 @@ namespace Nz m_fullscreenVertexDeclaration.reset(); m_blitPipeline.reset(); m_blitPipelineLayout.reset(); + m_defaultTextures.whiteTexture2d.reset(); + } + + void Graphics::FillDrawDataPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set) + { + // TextureOverlay + layoutInfo.bindings.push_back({ + set, 0, + ShaderBindingType::Texture, + ShaderStageType_All + }); } void Graphics::FillViewerPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set) { + // ViewerData layoutInfo.bindings.push_back({ set, 0, ShaderBindingType::UniformBuffer, @@ -99,6 +113,7 @@ namespace Nz void Graphics::FillWorldPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set) { + // InstanceData layoutInfo.bindings.push_back({ set, 0, ShaderBindingType::UniformBuffer, @@ -138,6 +153,22 @@ namespace Nz m_blitPipeline = m_renderDevice->InstantiateRenderPipeline(std::move(pipelineInfo)); } + void Graphics::BuildDefaultTextures() + { + // White texture 2D + { + Nz::TextureInfo texInfo; + texInfo.width = texInfo.height = texInfo.depth = texInfo.mipmapLevel = 1; + texInfo.pixelFormat = PixelFormat::BGRA8; + texInfo.type = ImageType::E2D; + + std::array texData = { 0xFF, 0xFF, 0xFF, 0xFF }; + + m_defaultTextures.whiteTexture2d = m_renderDevice->InstantiateTexture(texInfo); + m_defaultTextures.whiteTexture2d->Update(texData.data()); + } + } + void Graphics::BuildFullscreenVertexBuffer() { m_fullscreenVertexDeclaration = VertexDeclaration::Get(VertexLayout::XY_UV); diff --git a/src/Nazara/Graphics/Resources/Shaders/basic_material.nzsl b/src/Nazara/Graphics/Resources/Shaders/basic_material.nzsl index bc6e96207..3b98f55fc 100644 --- a/src/Nazara/Graphics/Resources/Shaders/basic_material.nzsl +++ b/src/Nazara/Graphics/Resources/Shaders/basic_material.nzsl @@ -8,7 +8,7 @@ option ColorLocation: i32 = -1; option UvLocation: i32 = -1; const HasVertexColor = (ColorLocation >= 0); -const HasUV = (UvLocation >= 0) && (HasDiffuseTexture || HasAlphaTexture); +const HasUV = (UvLocation >= 0); [layout(std140)] struct BasicSettings @@ -42,9 +42,10 @@ external { [set(0), binding(0)] viewerData: uniform, [set(1), binding(0)] instanceData: uniform, - [set(2), binding(0)] settings: uniform, - [set(2), binding(2)] MaterialAlphaMap: sampler2D, - [set(2), binding(1)] MaterialDiffuseMap: sampler2D + [set(2), binding(0)] TextureOverlay: sampler2D, + [set(3), binding(0)] settings: uniform, + [set(3), binding(2)] MaterialAlphaMap: sampler2D, + [set(3), binding(1)] MaterialDiffuseMap: sampler2D } // Fragment stage @@ -64,6 +65,10 @@ fn main(input: FragIn) -> FragOut { let diffuseColor = settings.DiffuseColor; + const if (HasUV) + //TODO: diffuseColor *= TextureOverlay.Sample(input.uv); + diffuseColor = diffuseColor * TextureOverlay.Sample(input.uv); + const if (HasVertexColor) //TODO: diffuseColor *= input.color; diffuseColor = diffuseColor * input.color; diff --git a/src/Nazara/Graphics/Resources/Shaders/depth_material.nzsl b/src/Nazara/Graphics/Resources/Shaders/depth_material.nzsl index b9d7513dd..9bfdc1ae8 100644 --- a/src/Nazara/Graphics/Resources/Shaders/depth_material.nzsl +++ b/src/Nazara/Graphics/Resources/Shaders/depth_material.nzsl @@ -36,9 +36,10 @@ external { [set(0), binding(0)] viewerData: uniform, [set(1), binding(0)] instanceData: uniform, - [set(2), binding(0)] settings: uniform, - [set(2), binding(2)] MaterialAlphaMap: sampler2D, - [set(2), binding(1)] MaterialDiffuseMap: sampler2D + [set(2), binding(0)] TextureOverlay: sampler2D, + [set(3), binding(0)] settings: uniform, + [set(3), binding(2)] MaterialAlphaMap: sampler2D, + [set(3), binding(1)] MaterialDiffuseMap: sampler2D } // Fragment stage @@ -51,6 +52,11 @@ struct FragIn fn main(input: FragIn) { let alpha = settings.DiffuseColor.a; + + const if (HasUV) + //TODO: diffuseColor *= TextureOverlay.Sample(input.uv); + alpha = alpha * TextureOverlay.Sample(input.uv).a; + const if (HasDiffuseTexture) // TODO: alpha *= MaterialDiffuseMap.Sample(input.uv).a; alpha = alpha * MaterialDiffuseMap.Sample(input.uv).a; diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 1cdcbf32c..657c7c67d 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -38,7 +38,9 @@ namespace Nz }; const auto& renderPipeline = materialPass->GetPipeline()->GetRenderPipeline(vertexBufferData); - elements.emplace_back(std::make_unique(0, renderPipeline, vertexDeclaration, 1, m_vertices.data(), materialPass->GetShaderBinding(), worldInstance.GetShaderBinding())); + const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTexture2d; + + elements.emplace_back(std::make_unique(0, renderPipeline, vertexDeclaration, whiteTexture, 1, m_vertices.data(), materialPass->GetShaderBinding(), worldInstance.GetShaderBinding())); } const std::shared_ptr& Sprite::GetMaterial(std::size_t i) const diff --git a/src/Nazara/Graphics/SpriteChainRenderer.cpp b/src/Nazara/Graphics/SpriteChainRenderer.cpp index 3dc6c71cc..2b91e1a62 100644 --- a/src/Nazara/Graphics/SpriteChainRenderer.cpp +++ b/src/Nazara/Graphics/SpriteChainRenderer.cpp @@ -52,6 +52,8 @@ namespace Nz void SpriteChainRenderer::Prepare(ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer* elements, std::size_t elementCount) { + Graphics* graphics = Graphics::Instance(); + auto& data = static_cast(rendererData); std::size_t firstQuadIndex = 0; @@ -61,14 +63,23 @@ namespace Nz const VertexDeclaration* currentVertexDeclaration = nullptr; AbstractBuffer* currentVertexBuffer = nullptr; const RenderPipeline* currentPipeline = nullptr; + const ShaderBinding* currentDrawDataBinding = nullptr; const ShaderBinding* currentInstanceBinding = nullptr; const ShaderBinding* currentMaterialBinding = nullptr; + const Texture* currentTextureOverlay = nullptr; auto FlushDrawCall = [&]() { currentDrawCall = nullptr; }; + auto FlushDrawData = [&]() + { + FlushDrawCall(); + + currentDrawDataBinding = nullptr; + }; + auto Flush = [&]() { // changing vertex buffer always mean we have to switch draw calls @@ -85,6 +96,7 @@ namespace Nz }; std::size_t oldDrawCallCount = data.drawCalls.size(); + const auto& defaultSampler = graphics->GetSamplerCache().Get({}); for (std::size_t i = 0; i < elementCount; ++i) { @@ -122,6 +134,12 @@ namespace Nz currentInstanceBinding = &spriteChain.GetInstanceBinding(); } + if (currentTextureOverlay != spriteChain.GetTextureOverlay()) + { + FlushDrawData(); + currentTextureOverlay = spriteChain.GetTextureOverlay(); + } + std::size_t remainingQuads = spriteChain.GetSpriteCount(); while (remainingQuads > 0) { @@ -149,11 +167,29 @@ namespace Nz data.vertexBuffers.emplace_back(std::move(vertexBuffer)); } + if (!currentDrawDataBinding) + { + ShaderBindingPtr drawDataBinding = Graphics::Instance()->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::DrawDataBindingSet); + drawDataBinding->Update({ + { + 0, + ShaderBinding::TextureBinding { + currentTextureOverlay, defaultSampler.get() + } + } + }); + + currentDrawDataBinding = drawDataBinding.get(); + + data.shaderBindings.emplace_back(std::move(drawDataBinding)); + } + if (!currentDrawCall) { data.drawCalls.push_back(SpriteChainRendererData::DrawCall{ currentVertexBuffer, currentPipeline, + currentDrawDataBinding, currentInstanceBinding, currentMaterialBinding, 6 * firstQuadIndex, @@ -216,6 +252,7 @@ namespace Nz const AbstractBuffer* currentVertexBuffer = nullptr; const RenderPipeline* currentPipeline = nullptr; + const ShaderBinding* currentDrawDataBinding = nullptr; const ShaderBinding* currentInstanceBinding = nullptr; const ShaderBinding* currentMaterialBinding = nullptr; @@ -241,6 +278,12 @@ namespace Nz currentPipeline = drawCall.renderPipeline; } + if (currentDrawDataBinding != drawCall.drawDataBinding) + { + commandBuffer.BindShaderBinding(Graphics::DrawDataBindingSet, *drawCall.drawDataBinding); + currentDrawDataBinding = drawCall.drawDataBinding; + } + if (currentMaterialBinding != drawCall.materialBinding) { commandBuffer.BindShaderBinding(Graphics::MaterialBindingSet, *drawCall.materialBinding); @@ -270,6 +313,10 @@ namespace Nz } data.vertexBuffers.clear(); + for (auto& shaderBinding : data.shaderBindings) + currentFrame.PushForRelease(std::move(shaderBinding)); + data.shaderBindings.clear(); + data.drawCalls.clear(); } } diff --git a/src/Nazara/Graphics/SubmeshRenderer.cpp b/src/Nazara/Graphics/SubmeshRenderer.cpp index dd7a7dbe8..6520f7515 100644 --- a/src/Nazara/Graphics/SubmeshRenderer.cpp +++ b/src/Nazara/Graphics/SubmeshRenderer.cpp @@ -10,6 +10,23 @@ namespace Nz { + SubmeshRenderer::SubmeshRenderer() + { + Graphics* graphics = Graphics::Instance(); + const auto& whiteTexture = graphics->GetDefaultTextures().whiteTexture2d; + const auto& defaultSampler = graphics->GetSamplerCache().Get({}); + + m_renderDataBinding = graphics->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::DrawDataBindingSet); + m_renderDataBinding->Update({ + { + 0, + ShaderBinding::TextureBinding { + whiteTexture.get(), defaultSampler.get() + } + } + }); + } + std::unique_ptr SubmeshRenderer::InstanciateData() { return {}; @@ -22,6 +39,8 @@ namespace Nz const RenderPipeline* currentPipeline = nullptr; const ShaderBinding* currentMaterialBinding = nullptr; + commandBuffer.BindShaderBinding(Graphics::DrawDataBindingSet, *m_renderDataBinding); + for (std::size_t i = 0; i < elementCount; ++i) { assert(elements[i]->GetElementType() == UnderlyingCast(BasicRenderElement::Submesh)); diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp index eec8866d7..1f98de873 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp @@ -68,11 +68,11 @@ namespace Nz { auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, binding.bindingIndex); - if (OpenGLTexture* glTexture = static_cast(arg.texture)) + if (const OpenGLTexture* glTexture = static_cast(arg.texture)) { textureDescriptor.texture = glTexture->GetTexture().GetObjectId(); - if (OpenGLTextureSampler* glSampler = static_cast(arg.sampler)) + if (const OpenGLTextureSampler* glSampler = static_cast(arg.sampler)) textureDescriptor.sampler = glSampler->GetSampler(glTexture->GetLevelCount() > 1).GetObjectId(); else textureDescriptor.sampler = 0; diff --git a/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp b/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp index abec596e4..50c299e0e 100644 --- a/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp +++ b/src/Nazara/VulkanRenderer/VulkanShaderBinding.cpp @@ -34,8 +34,8 @@ namespace Nz if constexpr (std::is_same_v) { - VulkanTexture* vkTexture = static_cast(arg.texture); - VulkanTextureSampler* vkSampler = static_cast(arg.sampler); + const VulkanTexture* vkTexture = static_cast(arg.texture); + const VulkanTextureSampler* vkSampler = static_cast(arg.sampler); VkDescriptorImageInfo& imageInfo = imageBinding.emplace_back(); imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;