Files
OpenVulkano/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp
2024-08-21 13:13:43 +02:00

146 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 IRenderResource<Scene::Texture>, public IRecordable, public Image
{
public:
vk::Sampler m_sampler;
vk::DescriptorSet m_descriptorSet;
VulkanTexture() : IRenderResource<Scene::Texture>(nullptr) {}
virtual void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z });
resManager->CopyDataToImage(texture->size, texture->textureBuffer, this);
texture->updated = false;
m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(*texture->m_samplerConfig));
SetDescriptorSet(resManager, descriptorSetLayout, binding);
UpdateAddress(texture);
UpdateRenderResource(GetOwnerResource());
}
void InitSharedMem(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
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);
UpdateAddress(texture);
UpdateRenderResource(GetOwnerResource());
}
virtual ~VulkanTexture() override
{
if (m_sampler) Close();
}
void Close() override
{
ResetRenderResource(GetOwnerResource());
Image::Close();
}
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);
}
void Release() override
{
//TODO
}
};
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(GetOwner()->updated)
{
context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this);
GetOwner()->updated = false;
}
VulkanTexture::Record(context);
}
void Record(VulkanDrawContext* context, int setId) override
{
if(GetOwner()->updated)
{
context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this);
GetOwner()->updated = false;
}
VulkanTexture::Record(context, setId);
}
};
}