Graphics: Improve TextureSampler handling

This commit is contained in:
Jérôme Leclercq 2021-01-27 18:50:49 +01:00
parent 78c3f57333
commit b9151d8a7a
15 changed files with 181 additions and 27 deletions

View File

@ -89,19 +89,13 @@ int main()
return __LINE__;
}
std::shared_ptr<Nz::TextureSampler> textureSampler = device->InstantiateTextureSampler({});
std::shared_ptr<Nz::Material> material = std::make_shared<Nz::Material>(Nz::BasicMaterial::GetSettings());
material->EnableDepthBuffer(true);
Nz::BasicMaterial basicMat(*material);
basicMat.EnableAlphaTest(false);
basicMat.SetAlphaMap(alphaTexture);
basicMat.SetAlphaSampler(textureSampler);
basicMat.SetDiffuseMap(texture);
basicMat.SetDiffuseSampler(textureSampler);
Nz::Model model(std::move(gfxMesh));
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)

View File

@ -24,11 +24,11 @@ namespace Nz
inline void EnableAlphaTest(bool alphaTest);
inline const std::shared_ptr<Texture>& GetAlphaMap() const;
inline const std::shared_ptr<TextureSampler>& GetAlphaSampler() const;
inline const TextureSamplerInfo& GetAlphaSampler() const;
float GetAlphaTestThreshold() const;
Color GetDiffuseColor() const;
inline const std::shared_ptr<Texture>& GetDiffuseMap() const;
inline const std::shared_ptr<TextureSampler>& GetDiffuseSampler() const;
inline const TextureSamplerInfo& GetDiffuseSampler() const;
inline bool HasAlphaMap() const;
inline bool HasAlphaTest() const;
@ -37,11 +37,11 @@ namespace Nz
inline bool HasDiffuseMap() const;
inline void SetAlphaMap(std::shared_ptr<Texture> alphaMap);
inline void SetAlphaSampler(std::shared_ptr<TextureSampler> alphaSampler);
inline void SetAlphaSampler(TextureSamplerInfo alphaSampler);
void SetAlphaTestThreshold(float alphaThreshold);
void SetDiffuseColor(const Color& diffuse);
inline void SetDiffuseMap(std::shared_ptr<Texture> diffuseMap);
inline void SetDiffuseSampler(std::shared_ptr<TextureSampler> diffuseSampler);
inline void SetDiffuseSampler(TextureSamplerInfo diffuseSampler);
static inline const UniformOffsets& GetOffsets();
static inline const std::shared_ptr<MaterialSettings>& GetSettings();

View File

@ -35,7 +35,7 @@ namespace Nz
return m_material.GetTexture(m_textureIndexes.alpha);
}
inline const std::shared_ptr<TextureSampler>& BasicMaterial::GetAlphaSampler() const
inline const TextureSamplerInfo& BasicMaterial::GetAlphaSampler() const
{
NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot");
return m_material.GetTextureSampler(m_textureIndexes.alpha);
@ -47,7 +47,7 @@ namespace Nz
return m_material.GetTexture(m_textureIndexes.diffuse);
}
inline const std::shared_ptr<TextureSampler>& BasicMaterial::GetDiffuseSampler() const
inline const TextureSamplerInfo& BasicMaterial::GetDiffuseSampler() const
{
NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot");
return m_material.GetTextureSampler(m_textureIndexes.diffuse);
@ -88,7 +88,7 @@ namespace Nz
m_material.EnableCondition(m_conditionIndexes.hasAlphaMap, hasAlphaMap);
}
inline void BasicMaterial::SetAlphaSampler(std::shared_ptr<TextureSampler> alphaSampler)
inline void BasicMaterial::SetAlphaSampler(TextureSamplerInfo alphaSampler)
{
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
m_material.SetTextureSampler(m_textureIndexes.alpha, std::move(alphaSampler));
@ -104,7 +104,7 @@ namespace Nz
m_material.EnableCondition(m_conditionIndexes.hasDiffuseMap, hasDiffuseMap);
}
inline void BasicMaterial::SetDiffuseSampler(std::shared_ptr<TextureSampler> diffuseSampler)
inline void BasicMaterial::SetDiffuseSampler(TextureSamplerInfo diffuseSampler)
{
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
m_material.SetTextureSampler(m_textureIndexes.diffuse, std::move(diffuseSampler));

View File

@ -9,8 +9,10 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
#include <optional>
namespace Nz
{
@ -30,6 +32,7 @@ namespace Nz
~Graphics();
inline RenderDevice& GetRenderDevice();
inline TextureSamplerCache& GetSamplerCache();
inline const std::shared_ptr<AbstractBuffer>& GetViewerDataUBO();
struct Config
@ -38,6 +41,7 @@ namespace Nz
};
private:
std::optional<TextureSamplerCache> m_samplerCache;
std::shared_ptr<AbstractBuffer> m_viewerDataUBO;
std::shared_ptr<RenderDevice> m_renderDevice;

View File

@ -12,6 +12,11 @@ namespace Nz
return *m_renderDevice;
}
inline TextureSamplerCache& Graphics::GetSamplerCache()
{
return *m_samplerCache;
}
inline const std::shared_ptr<AbstractBuffer>& Graphics::GetViewerDataUBO()
{
return m_viewerDataUBO;

View File

@ -66,7 +66,7 @@ namespace Nz
inline const std::shared_ptr<UberShader>& GetShader(ShaderStageType shaderStage) const;
inline BlendFunc GetSrcBlend() const;
inline const std::shared_ptr<Texture>& GetTexture(std::size_t textureIndex) const;
inline const std::shared_ptr<TextureSampler>& GetTextureSampler(std::size_t textureIndex) const;
inline const TextureSamplerInfo& GetTextureSampler(std::size_t textureIndex) const;
inline const std::shared_ptr<AbstractBuffer>& GetUniformBuffer(std::size_t bufferIndex) const;
inline std::vector<UInt8>& GetUniformBufferData(std::size_t bufferIndex);
inline const std::vector<UInt8>& GetUniformBufferConstData(std::size_t bufferIndex);
@ -96,7 +96,7 @@ namespace Nz
inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr<AbstractBuffer> uniformBuffer);
inline void SetSrcBlend(BlendFunc func);
inline void SetTexture(std::size_t textureIndex, std::shared_ptr<Texture> texture);
inline void SetTextureSampler(std::size_t textureIndex, std::shared_ptr<TextureSampler> sampler);
inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo);
void UpdateShaderBinding(ShaderBinding& shaderBinding) const;
@ -106,12 +106,14 @@ namespace Nz
private:
inline void InvalidatePipeline();
inline void InvalidateShaderBinding();
inline void InvalidateTextureSampler(std::size_t textureIndex);
inline void UpdatePipeline() const;
struct MaterialTexture
{
std::shared_ptr<TextureSampler> sampler;
mutable std::shared_ptr<TextureSampler> sampler;
std::shared_ptr<Texture> texture;
TextureSamplerInfo samplerInfo;
};
struct UniformBuffer

View File

@ -436,10 +436,10 @@ namespace Nz
return m_textures[textureIndex].texture;
}
inline const std::shared_ptr<TextureSampler>& Material::GetTextureSampler(std::size_t textureIndex) const
inline const TextureSamplerInfo& Material::GetTextureSampler(std::size_t textureIndex) const
{
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
return m_textures[textureIndex].sampler;
return m_textures[textureIndex].samplerInfo;
}
inline const std::shared_ptr<AbstractBuffer>& Material::GetUniformBuffer(std::size_t bufferIndex) const
@ -695,13 +695,13 @@ namespace Nz
}
}
inline void Material::SetTextureSampler(std::size_t textureIndex, std::shared_ptr<TextureSampler> sampler)
inline void Material::SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo)
{
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
if (m_textures[textureIndex].sampler != sampler)
if (m_textures[textureIndex].samplerInfo != samplerInfo)
{
m_textures[textureIndex].sampler = std::move(sampler);
InvalidateShaderBinding();
m_textures[textureIndex].samplerInfo = std::move(samplerInfo);
InvalidateTextureSampler(textureIndex);
}
}
@ -731,6 +731,14 @@ namespace Nz
//TODO
}
inline void Material::InvalidateTextureSampler(std::size_t textureIndex)
{
assert(textureIndex < m_textures.size());
m_textures[textureIndex].sampler.reset();
InvalidateShaderBinding();
}
inline void Material::UpdatePipeline() const
{
for (auto& shader : m_pipelineInfo.shaders)

View File

@ -0,0 +1,40 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_TEXTURESAMPLERCACHE_HPP
#define NAZARA_TEXTURESAMPLERCACHE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
#include <unordered_map>
namespace Nz
{
class RenderDevice;
class NAZARA_GRAPHICS_API TextureSamplerCache
{
public:
inline TextureSamplerCache(std::shared_ptr<RenderDevice> device);
TextureSamplerCache(const TextureSamplerCache&) = delete;
TextureSamplerCache(TextureSamplerCache&&) = delete;
~TextureSamplerCache() = default;
const std::shared_ptr<TextureSampler>& Get(const TextureSamplerInfo& info);
TextureSamplerCache& operator=(const TextureSamplerCache&) = delete;
TextureSamplerCache& operator=(TextureSamplerCache&&) = delete;
private:
std::shared_ptr<RenderDevice> m_device;
std::unordered_map<TextureSamplerInfo, std::shared_ptr<TextureSampler>> m_samplers;
};
}
#include <Nazara/Graphics/TextureSamplerCache.inl>
#endif

View File

@ -0,0 +1,17 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <functional>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline TextureSamplerCache::TextureSamplerCache(std::shared_ptr<RenderDevice> device) :
m_device(std::move(device))
{
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@ -22,6 +22,9 @@ namespace Nz
SamplerWrap wrapModeU = SamplerWrap_Clamp;
SamplerWrap wrapModeV = SamplerWrap_Clamp;
SamplerWrap wrapModeW = SamplerWrap_Clamp;
inline bool operator==(const TextureSamplerInfo& samplerInfo) const;
inline bool operator!=(const TextureSamplerInfo& samplerInfo) const;
};
class NAZARA_RENDERER_API TextureSampler
@ -37,6 +40,9 @@ namespace Nz
};
}
template<>
struct std::hash<Nz::TextureSamplerInfo>;
#include <Nazara/Renderer/TextureSampler.inl>
#endif // NAZARA_TEXTURE_HPP

View File

@ -3,10 +3,60 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/TextureSampler.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
inline bool TextureSamplerInfo::operator==(const TextureSamplerInfo& samplerInfo) const
{
if (!NumberEquals(anisotropyLevel, samplerInfo.anisotropyLevel, 0.99f))
return false;
if (magFilter != samplerInfo.magFilter)
return false;
if (minFilter != samplerInfo.minFilter)
return false;
if (mipmapMode != samplerInfo.mipmapMode)
return false;
if (wrapModeU != samplerInfo.wrapModeU)
return false;
if (wrapModeV != samplerInfo.wrapModeV)
return false;
if (wrapModeW != samplerInfo.wrapModeW)
return false;
return true;
}
inline bool TextureSamplerInfo::operator!=(const TextureSamplerInfo& samplerInfo) const
{
return !operator==(samplerInfo);
}
}
template<>
struct std::hash<Nz::TextureSamplerInfo>
{
std::size_t operator()(const Nz::TextureSamplerInfo& sampler) const
{
std::size_t seed = 0;
Nz::HashCombine(seed, sampler.anisotropyLevel);
Nz::HashCombine(seed, sampler.magFilter);
Nz::HashCombine(seed, sampler.minFilter);
Nz::HashCombine(seed, sampler.mipmapMode);
Nz::HashCombine(seed, sampler.wrapModeU);
Nz::HashCombine(seed, sampler.wrapModeV);
Nz::HashCombine(seed, sampler.wrapModeW);
return seed;
}
};
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -39,6 +39,8 @@ namespace Nz
if (!m_renderDevice)
throw std::runtime_error("failed to instantiate render device");
m_samplerCache.emplace(m_renderDevice);
MaterialPipeline::Initialize();
Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets();

View File

@ -63,7 +63,14 @@ namespace Nz
for (const auto& textureSlot : m_textures)
{
if (textureSlot.texture && textureSlot.sampler)
if (!textureSlot.sampler)
{
TextureSamplerCache& samplerCache = Graphics::Instance()->GetSamplerCache();
textureSlot.sampler = samplerCache.Get(textureSlot.samplerInfo);
}
//TODO: Use "missing" texture
if (textureSlot.texture)
{
bindings.push_back({
bindingIndex,

View File

@ -0,0 +1,19 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
const std::shared_ptr<TextureSampler>& TextureSamplerCache::Get(const TextureSamplerInfo& info)
{
auto it = m_samplers.find(info);
if (it == m_samplers.end())
it = m_samplers.emplace(info, m_device->InstantiateTextureSampler(info)).first;
return it->second;
}
}

View File

@ -55,13 +55,13 @@ namespace Nz
VkMemoryRequirements requirement = newBlock.buffer.GetMemoryRequirements();
if (!newBlock.blockMemory.Create(m_device, requirement.size, requirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
throw std::runtime_error("Failed to allocate block memory: " + TranslateVulkanError(newBlock.blockMemory.GetLastErrorCode()));
throw std::runtime_error("failed to allocate block memory: " + TranslateVulkanError(newBlock.blockMemory.GetLastErrorCode()));
if (!newBlock.buffer.BindBufferMemory(newBlock.blockMemory))
throw std::runtime_error("Failed to bind buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode()));
throw std::runtime_error("failed to bind buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode()));
if (!newBlock.blockMemory.Map())
throw std::runtime_error("Failed to map buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode()));
throw std::runtime_error("failed to map buffer memory: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode()));
bestBlock.block = &m_blocks.emplace_back(std::move(newBlock));
bestBlock.alignedOffset = 0;