// 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 #include #include #include #include #include #include #include namespace Nz { /*! * \ingroup graphics * \class Nz::Material * \brief Graphics class that represents a material */ /*! * \brief Constructs a Material object with default states * * \see Reset */ Material::Material(std::shared_ptr settings) : m_settings(std::move(settings)), m_enabledConditions(0), m_pipelineUpdated(false), m_shadowCastingEnabled(true) { m_pipelineInfo.settings = m_settings; const auto& shaders = m_settings->GetShaders(); for (std::size_t i = 0; i < ShaderStageTypeCount; ++i) m_pipelineInfo.shaders[i].uberShader = shaders[i]; m_textures.resize(m_settings->GetTextures().size()); m_uniformBuffers.reserve(m_settings->GetUniformBlocks().size()); for (const auto& uniformBufferInfo : m_settings->GetUniformBlocks()) { auto& uniformBuffer = m_uniformBuffers.emplace_back(); uniformBuffer.buffer = Graphics::Instance()->GetRenderDevice().InstantiateBuffer(Nz::BufferType_Uniform); if (!uniformBuffer.buffer->Initialize(uniformBufferInfo.blockSize, BufferUsage_Dynamic)) throw std::runtime_error("failed to initialize UBO memory"); assert(uniformBufferInfo.defaultValues.size() <= uniformBufferInfo.blockSize); uniformBuffer.buffer->Fill(uniformBufferInfo.defaultValues.data(), 0, uniformBufferInfo.defaultValues.size()); uniformBuffer.data.resize(uniformBufferInfo.blockSize); std::memcpy(uniformBuffer.data.data(), uniformBufferInfo.defaultValues.data(), uniformBufferInfo.defaultValues.size()); } } void Material::UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder) { for (auto& ubo : m_uniformBuffers) { if (ubo.dataInvalidated) { auto& allocation = uploadPool.Allocate(ubo.data.size()); std::memcpy(allocation.mappedPtr, ubo.data.data(), ubo.data.size()); builder.CopyBuffer(allocation, ubo.buffer.get()); ubo.dataInvalidated = false; } } } void Material::UpdateShaderBinding(ShaderBinding& shaderBinding) const { // TODO: Use StackVector std::vector bindings; std::size_t bindingIndex = 0; for (const auto& textureSlot : m_textures) { 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, ShaderBinding::TextureBinding { textureSlot.texture.get(), textureSlot.sampler.get() } }); } bindingIndex++; } for (const auto& ubo : m_uniformBuffers) { bindings.push_back({ bindingIndex++, ShaderBinding::UniformBufferBinding { ubo.buffer.get(), 0, ubo.buffer->GetSize() } }); } shaderBinding.Update(bindings.data(), bindings.size()); } }