158 lines
6.6 KiB
C++
158 lines
6.6 KiB
C++
#include "texture.h"
|
|
|
|
|
|
#include "buffer_vk.h"
|
|
#include "application/application.h"
|
|
#include "renderer.h"
|
|
#include "utils/utils.hpp"
|
|
|
|
|
|
texture::texture() {
|
|
format = vk::Format::eUndefined;
|
|
width_ = 0;
|
|
height_ = 0;
|
|
image = nullptr;
|
|
image_view = nullptr;
|
|
sampler = nullptr;
|
|
memory = nullptr;
|
|
}
|
|
|
|
texture::~texture() {
|
|
if (image) {
|
|
const renderer* render_vk = application::get()->get_renderer();
|
|
const vk::Device& device = render_vk->device;
|
|
device.destroyImage(image);
|
|
device.destroyImageView(image_view);
|
|
device.destroySampler(sampler);
|
|
device.freeMemory(memory);
|
|
}
|
|
}
|
|
|
|
bool texture::init_data(const uint8_t* data, int width, int height, vk::Format in_format) {
|
|
width_ = width;
|
|
height_ = height;
|
|
format = in_format;
|
|
|
|
const renderer* r = application::get()->get_renderer();
|
|
const vk::Device& device = r->device;
|
|
const vk::PhysicalDevice& physical_device = r->physical_device;
|
|
|
|
vk::ImageCreateInfo image_info;
|
|
image_info.setImageType(vk::ImageType::e2D);
|
|
image_info.setFormat(format);
|
|
image_info.setExtent({static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1});
|
|
image_info.setMipLevels(1);
|
|
image_info.setArrayLayers(1);
|
|
image_info.setSamples(vk::SampleCountFlagBits::e1);
|
|
image_info.setTiling(vk::ImageTiling::eOptimal);
|
|
image_info.setUsage(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst);
|
|
image_info.setSharingMode(vk::SharingMode::eExclusive);
|
|
image_info.setInitialLayout(vk::ImageLayout::eUndefined);
|
|
image = device.createImage(image_info);
|
|
|
|
const vk::PhysicalDeviceMemoryProperties memory_properties = physical_device.getMemoryProperties();
|
|
const vk::MemoryRequirements memory_requirements = device.getImageMemoryRequirements(image);
|
|
const uint32_t memory_type = vk::su::findMemoryType(memory_properties, memory_requirements.memoryTypeBits,
|
|
vk::MemoryPropertyFlagBits::eDeviceLocal);
|
|
|
|
vk::MemoryAllocateInfo memory_allocate_info;
|
|
memory_allocate_info.setAllocationSize(memory_requirements.size);
|
|
memory_allocate_info.setMemoryTypeIndex(memory_type);
|
|
memory = device.allocateMemory(memory_allocate_info);
|
|
device.bindImageMemory(image, memory, 0);
|
|
|
|
vk::ImageViewCreateInfo view_info;
|
|
view_info.setImage(image);
|
|
view_info.setViewType(vk::ImageViewType::e2D);
|
|
view_info.setFormat(format);
|
|
view_info.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
|
image_view = device.createImageView(view_info);
|
|
|
|
vk::SamplerCreateInfo sampler_info;
|
|
sampler_info.setMagFilter(vk::Filter::eLinear);
|
|
sampler_info.setMinFilter(vk::Filter::eLinear);
|
|
sampler_info.setMipmapMode(vk::SamplerMipmapMode::eLinear);
|
|
sampler_info.setAddressModeU(vk::SamplerAddressMode::eRepeat);
|
|
sampler_info.setAddressModeV(vk::SamplerAddressMode::eRepeat);
|
|
sampler_info.setAddressModeW(vk::SamplerAddressMode::eRepeat);
|
|
sampler_info.setMinLod(-1000);
|
|
sampler_info.setMaxLod(1000);
|
|
sampler_info.setMaxAnisotropy(1);
|
|
sampler = device.createSampler(sampler_info);
|
|
|
|
descriptor_set = ImGui_ImplVulkan_AddTexture(sampler, image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
uint32_t image_size = width * height * 4;
|
|
|
|
if (data) {
|
|
upload(data, image_size);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void texture::upload(const void* data, size_t size) {
|
|
renderer* r = application::get()->get_renderer();
|
|
const vk::Device& device = r->device;
|
|
|
|
// Create Upload Buffer
|
|
vk::BufferCreateInfo buffer_info;
|
|
buffer_info.setSize(size);
|
|
buffer_info.setUsage(vk::BufferUsageFlagBits::eTransferSrc);
|
|
buffer_info.setSharingMode(vk::SharingMode::eExclusive);
|
|
vk::Buffer upload_buffer = device.createBuffer(buffer_info);
|
|
|
|
vk::MemoryRequirements req = device.getBufferMemoryRequirements(upload_buffer);
|
|
uint32_t upload_memory_type = vk::su::findMemoryType(r->physical_device.getMemoryProperties(), req.memoryTypeBits,
|
|
vk::MemoryPropertyFlagBits::eHostVisible);
|
|
vk::MemoryAllocateInfo alloc_info;
|
|
alloc_info.setAllocationSize(req.size);
|
|
alloc_info.setMemoryTypeIndex(upload_memory_type);
|
|
vk::DeviceMemory upload_memory = device.allocateMemory(alloc_info);
|
|
device.bindBufferMemory(upload_buffer, upload_memory, 0);
|
|
|
|
void* p = device.mapMemory(upload_memory, 0, size);
|
|
memcpy(p, data, size);
|
|
vk::MappedMemoryRange memory_range;
|
|
memory_range.setMemory(upload_memory);
|
|
memory_range.setSize(size);
|
|
device.flushMappedMemoryRanges(memory_range);
|
|
device.unmapMemory(upload_memory);
|
|
|
|
const vk::CommandBuffer command_buffer = r->create_command_buffer(vk::CommandBufferLevel::ePrimary, true);
|
|
|
|
vk::ImageMemoryBarrier copy_barrier;
|
|
copy_barrier.setDstAccessMask(vk::AccessFlagBits::eTransferWrite);
|
|
copy_barrier.setOldLayout(vk::ImageLayout::eUndefined);
|
|
copy_barrier.setNewLayout(vk::ImageLayout::eTransferDstOptimal);
|
|
copy_barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
|
|
copy_barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
|
|
copy_barrier.setImage(image);
|
|
copy_barrier.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
|
command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eTransfer, {}, {}, {},
|
|
copy_barrier);
|
|
|
|
vk::BufferImageCopy region;
|
|
region.setImageSubresource({vk::ImageAspectFlagBits::eColor, 0, 0, 1});
|
|
region.setImageExtent({static_cast<uint32_t>(width_), static_cast<uint32_t>(height_), 1});
|
|
command_buffer.copyBufferToImage(upload_buffer, image, vk::ImageLayout::eTransferDstOptimal, region);
|
|
|
|
vk::ImageMemoryBarrier use_barrier;
|
|
use_barrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
|
|
use_barrier.setDstAccessMask(vk::AccessFlagBits::eShaderRead);
|
|
use_barrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal);
|
|
use_barrier.setNewLayout(vk::ImageLayout::eShaderReadOnlyOptimal);
|
|
use_barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
|
|
use_barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
|
|
use_barrier.setImage(image);
|
|
use_barrier.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
|
command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {},
|
|
{}, {}, use_barrier);
|
|
|
|
r->end_command_buffer(command_buffer);
|
|
device.waitIdle();
|
|
|
|
device.destroyBuffer(upload_buffer);
|
|
device.freeMemory(upload_memory);
|
|
|
|
// device.freeCommandBuffers(command_pool, command_buffer);
|
|
}
|