forked from 0ad/0ad
Moves single descriptor set binding management for Vulkan to a separate class.
Differential Revision: https://code.wildfiregames.com/D5163 This was SVN commit r27921.
This commit is contained in:
parent
c78ad51057
commit
a905932712
@ -18,7 +18,9 @@
|
||||
#ifndef INCLUDED_RENDERER_BACKEND_VULKAN_DESCRIPTORMANAGER
|
||||
#define INCLUDED_RENDERER_BACKEND_VULKAN_DESCRIPTORMANAGER
|
||||
|
||||
#include "ps/CStrIntern.h"
|
||||
#include "renderer/backend/Sampler.h"
|
||||
#include "renderer/backend/vulkan/Device.h"
|
||||
#include "renderer/backend/vulkan/Texture.h"
|
||||
|
||||
#include <glad/vulkan.h>
|
||||
@ -136,6 +138,73 @@ private:
|
||||
std::unique_ptr<ITexture> m_ErrorTexture;
|
||||
};
|
||||
|
||||
// TODO: ideally we might want to separate a set and its mapping.
|
||||
template<typename DeviceObject>
|
||||
class CSingleTypeDescriptorSetBinding
|
||||
{
|
||||
public:
|
||||
CSingleTypeDescriptorSetBinding(CDevice* device, const VkDescriptorType type,
|
||||
const uint32_t size, std::unordered_map<CStrIntern, uint32_t> mapping)
|
||||
: m_Device{device}, m_Type{type}, m_Mapping{std::move(mapping)}
|
||||
{
|
||||
m_BoundDeviceObjects.resize(size);
|
||||
m_BoundUIDs.resize(size);
|
||||
m_DescriptorSetLayout =
|
||||
m_Device->GetDescriptorManager().GetSingleTypeDescritorSetLayout(m_Type, size);
|
||||
}
|
||||
|
||||
int32_t GetBindingSlot(const CStrIntern name) const
|
||||
{
|
||||
const auto it = m_Mapping.find(name);
|
||||
return it != m_Mapping.end() ? it->second : -1;
|
||||
}
|
||||
|
||||
void SetObject(const int32_t bindingSlot, DeviceObject* object)
|
||||
{
|
||||
if (m_BoundUIDs[bindingSlot] == object->GetUID())
|
||||
return;
|
||||
m_BoundUIDs[bindingSlot] = object->GetUID();
|
||||
m_BoundDeviceObjects[bindingSlot] = object;
|
||||
m_Outdated = true;
|
||||
}
|
||||
|
||||
bool IsOutdated() const { return m_Outdated; }
|
||||
|
||||
VkDescriptorSet UpdateAndReturnDescriptorSet()
|
||||
{
|
||||
ENSURE(m_Outdated);
|
||||
m_Outdated = false;
|
||||
|
||||
VkDescriptorSet descriptorSet =
|
||||
m_Device->GetDescriptorManager().GetSingleTypeDescritorSet(
|
||||
m_Type, m_DescriptorSetLayout, m_BoundUIDs, m_BoundDeviceObjects);
|
||||
ENSURE(descriptorSet != VK_NULL_HANDLE);
|
||||
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
void Unbind()
|
||||
{
|
||||
std::fill(m_BoundDeviceObjects.begin(), m_BoundDeviceObjects.end(), nullptr);
|
||||
std::fill(m_BoundUIDs.begin(), m_BoundUIDs.end(), INVALID_DEVICE_OBJECT_UID);
|
||||
m_Outdated = true;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout GetDescriptorSetLayout() { return m_DescriptorSetLayout; }
|
||||
|
||||
private:
|
||||
CDevice* const m_Device;
|
||||
const VkDescriptorType m_Type;
|
||||
const std::unordered_map<CStrIntern, uint32_t> m_Mapping;
|
||||
|
||||
bool m_Outdated{true};
|
||||
|
||||
VkDescriptorSetLayout m_DescriptorSetLayout{VK_NULL_HANDLE};
|
||||
|
||||
std::vector<DeviceObject*> m_BoundDeviceObjects;
|
||||
std::vector<DeviceObjectUID> m_BoundUIDs;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
} // namespace Backend
|
||||
|
@ -1073,7 +1073,7 @@ void CDeviceCommandContext::PreDraw()
|
||||
{
|
||||
ENSURE(m_InsidePass);
|
||||
ApplyPipelineStateIfDirty();
|
||||
m_ShaderProgram->PreDraw(m_CommandContext->GetCommandBuffer());
|
||||
m_ShaderProgram->PreDraw(*m_CommandContext);
|
||||
if (m_ShaderProgram->IsMaterialConstantsDataOutdated())
|
||||
{
|
||||
const VkDeviceSize alignment =
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "graphics/ShaderDefines.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/containers/StaticVector.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "ps/CStrInternStatic.h"
|
||||
#include "ps/Filesystem.h"
|
||||
@ -28,6 +29,7 @@
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "renderer/backend/vulkan/DescriptorManager.h"
|
||||
#include "renderer/backend/vulkan/Device.h"
|
||||
#include "renderer/backend/vulkan/RingCommandContext.h"
|
||||
#include "renderer/backend/vulkan/Texture.h"
|
||||
#include "renderer/backend/vulkan/Utilities.h"
|
||||
|
||||
@ -226,6 +228,9 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(
|
||||
return true;
|
||||
};
|
||||
|
||||
uint32_t texturesDescriptorSetSize = 0;
|
||||
std::unordered_map<CStrIntern, uint32_t> textureMapping;
|
||||
|
||||
auto addDescriptorSets = [&](const XMBElement& element) -> bool
|
||||
{
|
||||
const bool useDescriptorIndexing =
|
||||
@ -300,9 +305,9 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(
|
||||
return false;
|
||||
}
|
||||
const CStrIntern name{attributes.GetNamedItem(at_name)};
|
||||
shaderProgram->m_TextureMapping[name] = binding;
|
||||
shaderProgram->m_TexturesDescriptorSetSize =
|
||||
std::max(shaderProgram->m_TexturesDescriptorSetSize, binding + 1);
|
||||
textureMapping[name] = binding;
|
||||
texturesDescriptorSetSize =
|
||||
std::max(texturesDescriptorSetSize, binding + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -470,16 +475,12 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(
|
||||
|
||||
std::vector<VkDescriptorSetLayout> layouts =
|
||||
device->GetDescriptorManager().GetDescriptorSetLayouts();
|
||||
if (shaderProgram->m_TexturesDescriptorSetSize > 0)
|
||||
if (texturesDescriptorSetSize > 0)
|
||||
{
|
||||
ENSURE(!device->GetDescriptorManager().UseDescriptorIndexing());
|
||||
shaderProgram->m_BoundTextures.resize(shaderProgram->m_TexturesDescriptorSetSize);
|
||||
shaderProgram->m_BoundTexturesUID.resize(shaderProgram->m_TexturesDescriptorSetSize);
|
||||
shaderProgram->m_BoundTexturesOutdated = true;
|
||||
shaderProgram->m_TexturesDescriptorSetLayout =
|
||||
device->GetDescriptorManager().GetSingleTypeDescritorSetLayout(
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderProgram->m_TexturesDescriptorSetSize);
|
||||
layouts.emplace_back(shaderProgram->m_TexturesDescriptorSetLayout);
|
||||
shaderProgram->m_TextureBinding.emplace(
|
||||
device, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, texturesDescriptorSetSize, std::move(textureMapping));
|
||||
layouts.emplace_back(shaderProgram->m_TextureBinding->GetDescriptorSetLayout());
|
||||
}
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{};
|
||||
@ -524,8 +525,8 @@ int32_t CShaderProgram::GetBindingSlot(const CStrIntern name) const
|
||||
return it->second;
|
||||
if (auto it = m_UniformMapping.find(name); it != m_UniformMapping.end())
|
||||
return it->second + m_PushConstants.size();
|
||||
if (auto it = m_TextureMapping.find(name); it != m_TextureMapping.end())
|
||||
return it->second + m_PushConstants.size() + m_UniformMapping.size();
|
||||
if (const int32_t bindingSlot = m_TextureBinding.has_value() ? m_TextureBinding->GetBindingSlot(name) : -1; bindingSlot != -1)
|
||||
return bindingSlot + m_PushConstants.size() + m_UniformMapping.size();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -548,19 +549,13 @@ void CShaderProgram::Bind()
|
||||
|
||||
void CShaderProgram::Unbind()
|
||||
{
|
||||
if (m_TexturesDescriptorSetSize > 0)
|
||||
{
|
||||
for (CTexture*& texture : m_BoundTextures)
|
||||
texture = nullptr;
|
||||
for (DeviceObjectUID& uid : m_BoundTexturesUID)
|
||||
uid = 0;
|
||||
m_BoundTexturesOutdated = true;
|
||||
}
|
||||
if (m_TextureBinding.has_value())
|
||||
m_TextureBinding->Unbind();
|
||||
}
|
||||
|
||||
void CShaderProgram::PreDraw(VkCommandBuffer commandBuffer)
|
||||
void CShaderProgram::PreDraw(CRingCommandContext& commandContext)
|
||||
{
|
||||
UpdateActiveDescriptorSet(commandBuffer);
|
||||
BindOutdatedDescriptorSets(commandContext);
|
||||
if (m_PushConstantDataMask)
|
||||
{
|
||||
for (uint32_t index = 0; index < 32;)
|
||||
@ -574,7 +569,7 @@ void CShaderProgram::PreDraw(VkCommandBuffer commandBuffer)
|
||||
while (indexEnd < 32 && (m_PushConstantDataMask & (1 << indexEnd)) && m_PushConstantDataFlags[index] == m_PushConstantDataFlags[indexEnd])
|
||||
++indexEnd;
|
||||
vkCmdPushConstants(
|
||||
commandBuffer, GetPipelineLayout(),
|
||||
commandContext.GetCommandBuffer(), GetPipelineLayout(),
|
||||
m_PushConstantDataFlags[index],
|
||||
index * 4, (indexEnd - index) * 4, m_PushConstantData.data() + index * 4);
|
||||
index = indexEnd;
|
||||
@ -583,22 +578,22 @@ void CShaderProgram::PreDraw(VkCommandBuffer commandBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
void CShaderProgram::UpdateActiveDescriptorSet(
|
||||
VkCommandBuffer commandBuffer)
|
||||
void CShaderProgram::BindOutdatedDescriptorSets(
|
||||
CRingCommandContext& commandContext)
|
||||
{
|
||||
if (m_BoundTexturesOutdated)
|
||||
// TODO: combine calls after more sets to bind.
|
||||
PS::StaticVector<std::tuple<uint32_t, VkDescriptorSet>, 1> descriptortSets;
|
||||
if (m_TextureBinding.has_value() && m_TextureBinding->IsOutdated())
|
||||
{
|
||||
m_BoundTexturesOutdated = false;
|
||||
|
||||
m_ActiveTexturesDescriptorSet =
|
||||
m_Device->GetDescriptorManager().GetSingleTypeDescritorSet(
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_TexturesDescriptorSetLayout,
|
||||
m_BoundTexturesUID, m_BoundTextures);
|
||||
ENSURE(m_ActiveTexturesDescriptorSet != VK_NULL_HANDLE);
|
||||
constexpr uint32_t TEXTURE_BINDING_SET = 1u;
|
||||
descriptortSets.emplace_back(TEXTURE_BINDING_SET, m_TextureBinding->UpdateAndReturnDescriptorSet());
|
||||
}
|
||||
|
||||
for (const auto [firstSet, descriptorSet] : descriptortSets)
|
||||
{
|
||||
vkCmdBindDescriptorSets(
|
||||
commandBuffer, GetPipelineBindPoint(), GetPipelineLayout(),
|
||||
1, 1, &m_ActiveTexturesDescriptorSet, 0, nullptr);
|
||||
commandContext.GetCommandBuffer(), GetPipelineBindPoint(), GetPipelineLayout(),
|
||||
firstSet, 1, &descriptorSet, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -686,13 +681,9 @@ void CShaderProgram::SetTexture(const int32_t bindingSlot, CTexture* texture)
|
||||
else
|
||||
{
|
||||
ENSURE(bindingSlot >= static_cast<int32_t>(m_PushConstants.size() + m_UniformMapping.size()));
|
||||
ENSURE(m_TextureBinding.has_value());
|
||||
const uint32_t index = bindingSlot - (m_PushConstants.size() + m_UniformMapping.size());
|
||||
if (m_BoundTexturesUID[index] != texture->GetUID())
|
||||
{
|
||||
m_BoundTextures[index] = texture;
|
||||
m_BoundTexturesUID[index] = texture->GetUID();
|
||||
m_BoundTexturesOutdated = true;
|
||||
}
|
||||
m_TextureBinding->SetObject(index, texture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,14 @@
|
||||
#define INCLUDED_RENDERER_BACKEND_VULKAN_SHADERPROGRAM
|
||||
|
||||
#include "renderer/backend/IShaderProgram.h"
|
||||
#include "renderer/backend/vulkan/DescriptorManager.h"
|
||||
#include "renderer/backend/vulkan/Texture.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <glad/vulkan.h>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@ -41,6 +43,7 @@ namespace Vulkan
|
||||
{
|
||||
|
||||
class CDevice;
|
||||
class CRingCommandContext;
|
||||
|
||||
class CVertexInputLayout : public IVertexInputLayout
|
||||
{
|
||||
@ -91,7 +94,7 @@ public:
|
||||
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void PreDraw(VkCommandBuffer commandBuffer);
|
||||
void PreDraw(CRingCommandContext& commandContext);
|
||||
|
||||
VkPipelineLayout GetPipelineLayout() const { return m_PipelineLayout; }
|
||||
VkPipelineBindPoint GetPipelineBindPoint() const { return VK_PIPELINE_BIND_POINT_GRAPHICS; }
|
||||
@ -131,8 +134,8 @@ private:
|
||||
static std::unique_ptr<CShaderProgram> Create(
|
||||
CDevice* device, const CStr& name, const CShaderDefines& defines);
|
||||
|
||||
void UpdateActiveDescriptorSet(
|
||||
VkCommandBuffer commandBuffer);
|
||||
void BindOutdatedDescriptorSets(
|
||||
CRingCommandContext& commandContext);
|
||||
|
||||
CDevice* m_Device = nullptr;
|
||||
|
||||
@ -166,14 +169,7 @@ private:
|
||||
std::unordered_map<CStrIntern, uint32_t> m_UniformMapping;
|
||||
std::unordered_map<CStrIntern, uint32_t> m_PushConstantMapping;
|
||||
|
||||
uint32_t m_TexturesDescriptorSetSize = 0;
|
||||
bool m_BoundTexturesOutdated = false;
|
||||
|
||||
VkDescriptorSetLayout m_TexturesDescriptorSetLayout = VK_NULL_HANDLE;
|
||||
std::vector<CTexture*> m_BoundTextures;
|
||||
std::vector<DeviceObjectUID> m_BoundTexturesUID;
|
||||
VkDescriptorSet m_ActiveTexturesDescriptorSet = VK_NULL_HANDLE;
|
||||
std::unordered_map<CStrIntern, uint32_t> m_TextureMapping;
|
||||
std::optional<CSingleTypeDescriptorSetBinding<CTexture>> m_TextureBinding;
|
||||
|
||||
std::unordered_map<VertexAttributeStream, uint32_t> m_StreamLocations;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user