Files
OpenVulkano/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp
2024-08-06 10:32:55 +03:00

141 lines
5.0 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "IRecordable.hpp"
#include "Vulkan/Image.hpp"
#include "Vulkan/Context.hpp"
#include "Vulkan/Resources/ResourceManager.hpp"
#include "Vulkan/Scene/VulkanShader.hpp"
#include "Scene/Texture.hpp"
#include "Scene/Shader/Shader.hpp"
namespace OpenVulkano::Vulkan
{
class VulkanTexture : public Scene::RenderTexture, public IRecordable, public Image
{
public:
static inline vk::SamplerCreateInfo DEFAULT_SAMPLER_CONFIG { {}, vk::Filter::eLinear, vk::Filter::eLinear };
vk::Sampler m_sampler;
vk::DescriptorSet m_descriptorSet;
virtual void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
m_texture = texture;
Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z });
resManager->CopyDataToImage(m_texture->size, m_texture->textureBuffer, this);
texture->updated = false;
m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(*texture->m_samplerConfig));
SetDescriptorSet(resManager, descriptorSetLayout, binding);
texture->renderTexture = this;
}
void InitSharedMem(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
m_texture = texture;
Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z }, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible);
texture->updated = false;
texture->textureBuffer = Map();
m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(*texture->m_samplerConfig));
SetDescriptorSet(resManager, descriptorSetLayout, binding);
texture->renderTexture = this;
}
virtual ~VulkanTexture() override
{
if (m_sampler) Close();
}
void Close() override
{
Image::Close();
if (m_texture) m_texture->renderTexture = nullptr;
m_texture = nullptr;
}
void SetDescriptorSet(ResourceManager* resManager, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
// Setup Descriptor set
const vk::DescriptorSetAllocateInfo descSetAllocInfo = { ResourceManager::INSTANCE->descriptorPool, 1, descriptorSetLayout };
m_descriptorSet = resManager->GetContext()->device->device.allocateDescriptorSets(descSetAllocInfo)[0];
vk::DescriptorImageInfo imageInfo = { m_sampler, view, vk::ImageLayout::eShaderReadOnlyOptimal };
vk::WriteDescriptorSet writeDescriptorSet = { m_descriptorSet, binding.bindingId, 0, 1 };
writeDescriptorSet.descriptorType = static_cast<vk::DescriptorType>(binding.descriptorType);
writeDescriptorSet.pImageInfo = &imageInfo;
resManager->GetContext()->device->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
}
void Record(VulkanDrawContext* context) override
{
int setId = -1, i = 0;
for (const auto& descriptorSet : context->GetShader()->shader->descriptorSets)
{
for (const auto& descriptor : descriptorSet)
{
if (descriptor.descriptorType < 6)
{
if (setId != -1) [[unlikely]]
{
Logger::RENDER->error("Found multiple possible descriptor set for texture! Use 'Record(VulkanDrawContext* context, int setId)' explicitly when using multiple sets containing textures!");
}
setId = i;
break;
}
}
i++;
}
if (setId == -1) [[unlikely]]
{
Logger::RENDER->error("Failed to discover setId for texture binding.");
return;
}
else [[likely]]
{
Record(context, setId + 2); // Set 0 and 1 are automatically bound special sets for the camera and the node
}
}
virtual void Record(VulkanDrawContext* context, int setId)
{
context->commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, context->GetShader()->pipelineLayout, setId, 1, &m_descriptorSet, 0, nullptr);
}
};
class VulkanTextureDynamic : public VulkanTexture
{
public:
void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) override
{
VulkanTexture::Init(resManager, texture, descriptorSetLayout, binding);
}
void Record(VulkanDrawContext* context) override
{
if(m_texture->updated)
{
context->renderer->GetResourceManager().CopyDataToImage(m_texture->size, m_texture->textureBuffer, this);
m_texture->updated = false;
}
VulkanTexture::Record(context);
}
void Record(VulkanDrawContext* context, int setId) override
{
if(m_texture->updated)
{
context->renderer->GetResourceManager().CopyDataToImage(m_texture->size, m_texture->textureBuffer, this);
m_texture->updated = false;
}
VulkanTexture::Record(context, setId);
}
};
}