Add GEVulkanTexture

This commit is contained in:
Benau 2022-03-01 13:22:20 +08:00
parent fcf7cf953f
commit 8b68f52e57
8 changed files with 643 additions and 7 deletions

View File

@ -26,6 +26,7 @@ set(GE_SOURCES
src/ge_texture.cpp
src/ge_dx9_texture.cpp
src/ge_vulkan_driver.cpp
src/ge_vulkan_texture.cpp
src/ge_gl_texture.cpp
)

View File

@ -5,6 +5,7 @@
namespace GE
{
class GEVulkanDriver;
struct GEConfig
{
bool m_disable_npot_texture;
@ -12,6 +13,7 @@ bool m_disable_npot_texture;
void init(irr::video::IVideoDriver* driver);
irr::video::IVideoDriver* getDriver();
GE::GEVulkanDriver* getVKDriver();
GEConfig* getGEConfig();
void deinit();
}

View File

@ -273,6 +273,13 @@ namespace GE
return VK_NULL_HANDLE;
return m_vk.samplers.at(s);
}
VkDevice getDevice() const { return m_vk.device; }
bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties, VkBuffer& buffer,
VkDeviceMemory& buffer_memory);
VkPhysicalDevice getPhysicalDevice() const { return m_physical_device; }
VkCommandBuffer beginSingleTimeCommands();
void endSingleTimeCommands(VkCommandBuffer command_buffer);
private:
struct SwapChainSupportDetails
@ -286,13 +293,6 @@ namespace GE
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0) { return NULL; }
//! returns the current size of the screen or rendertarget
virtual const core::dimension2d<u32>& getCurrentRenderTargetSize() const
{
static core::dimension2d<u32> unused;
return unused;
}
//! Adds a new material renderer to the VideoDriver, based on a high level shading
//! language.
virtual s32 addHighLevelShaderMaterial(

View File

@ -1,4 +1,5 @@
#include "ge_main.hpp"
#include "ge_vulkan_driver.hpp"
namespace GE
{
@ -15,6 +16,11 @@ irr::video::IVideoDriver* getDriver()
return g_driver;
}
GE::GEVulkanDriver* getVKDriver()
{
return dynamic_cast<GE::GEVulkanDriver*>(g_driver);
}
GEConfig* getGEConfig()
{
return &g_config;

View File

@ -1,6 +1,7 @@
#include "ge_main.hpp"
#include "ge_dx9_texture.hpp"
#include "ge_gl_texture.hpp"
#include "ge_vulkan_texture.hpp"
#include "ge_texture.hpp"
#include <IVideoDriver.h>
@ -60,6 +61,8 @@ irr::video::ITexture* createTexture(const std::string& path,
case video::EDT_DIRECT3D9:
return new GEDX9Texture(path, image_mani);
#endif
case video::EDT_VULKAN:
return new GEVulkanTexture(path, image_mani);
default:
return NULL;
}
@ -78,6 +81,8 @@ irr::video::ITexture* createTexture(video::IImage* img,
case video::EDT_DIRECT3D9:
return new GEDX9Texture(img, name);
#endif
case video::EDT_VULKAN:
return new GEVulkanTexture(img, name);
default:
return NULL;
}
@ -96,6 +101,8 @@ irr::video::ITexture* createFontTexture(const std::string& name,
case video::EDT_DIRECT3D9:
return new GEDX9Texture(name, size);
#endif
case video::EDT_VULKAN:
return new GEVulkanTexture(name, size, single_channel);
default:
return NULL;
}

View File

@ -1007,6 +1007,97 @@ void GEVulkanDriver::createSamplers()
m_vk.samplers[GVS_NEAREST] = sampler;
} // createSamplers
// ----------------------------------------------------------------------------
bool GEVulkanDriver::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties,
VkBuffer& buffer,
VkDeviceMemory& buffer_memory)
{
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size;
buffer_info.usage = usage;
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkResult result = vkCreateBuffer(m_vk.device, &buffer_info, NULL, &buffer);
if (result != VK_SUCCESS)
return false;
VkMemoryRequirements mem_requirements;
vkGetBufferMemoryRequirements(m_vk.device, buffer, &mem_requirements);
VkPhysicalDeviceMemoryProperties mem_properties;
vkGetPhysicalDeviceMemoryProperties(m_physical_device, &mem_properties);
uint32_t memory_type_index = std::numeric_limits<uint32_t>::max();
uint32_t type_filter = mem_requirements.memoryTypeBits;
for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++)
{
if ((type_filter & (1 << i)) &&
(mem_properties.memoryTypes[i].propertyFlags & properties) == properties)
{
memory_type_index = i;
break;
}
}
if (memory_type_index == std::numeric_limits<uint32_t>::max())
return false;
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = mem_requirements.size;
alloc_info.memoryTypeIndex = memory_type_index;
result = vkAllocateMemory(m_vk.device, &alloc_info, NULL, &buffer_memory);
if (result != VK_SUCCESS)
return false;
vkBindBufferMemory(m_vk.device, buffer, buffer_memory, 0);
return true;
} // createBuffer
// ----------------------------------------------------------------------------
VkCommandBuffer GEVulkanDriver::beginSingleTimeCommands()
{
VkCommandBufferAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
alloc_info.commandPool = m_vk.command_pool;
alloc_info.commandBufferCount = 1;
VkCommandBuffer command_buffer;
vkAllocateCommandBuffers(m_vk.device, &alloc_info, &command_buffer);
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(command_buffer, &begin_info);
return command_buffer;
} // beginSingleTimeCommands
// ----------------------------------------------------------------------------
void GEVulkanDriver::endSingleTimeCommands(VkCommandBuffer command_buffer)
{
vkEndCommandBuffer(command_buffer);
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer;
vkQueueSubmit(m_graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
vkQueueWaitIdle(m_graphics_queue);
vkFreeCommandBuffers(m_vk.device, m_vk.command_pool, 1, &command_buffer);
} // beginSingleTimeCommands
// ----------------------------------------------------------------------------
void GEVulkanDriver::OnResize(const core::dimension2d<u32>& size)
{

View File

@ -0,0 +1,423 @@
#include "ge_vulkan_texture.hpp"
#include "ge_vulkan_driver.hpp"
#include "ge_gl_utils.hpp"
#include "ge_main.hpp"
#include "ge_texture.hpp"
#include <limits>
#include <vector>
namespace GE
{
GEVulkanTexture::GEVulkanTexture(const std::string& path,
std::function<void(video::IImage*)> image_mani)
: video::ITexture(path.c_str()), m_image_mani(image_mani),
m_locked_data(NULL),
m_vulkan_device(getVKDriver()->getDevice()),
m_image(VK_NULL_HANDLE), m_image_memory(VK_NULL_HANDLE),
m_image_view(VK_NULL_HANDLE), m_texture_size(0),
m_disable_reload(false), m_single_channel(false)
{
reload();
} // GEVulkanTexture
// ----------------------------------------------------------------------------
GEVulkanTexture::GEVulkanTexture(video::IImage* img, const std::string& name)
: video::ITexture(name.c_str()), m_image_mani(nullptr),
m_locked_data(NULL),
m_vulkan_device(getVKDriver()->getDevice()),
m_image(VK_NULL_HANDLE), m_image_memory(VK_NULL_HANDLE),
m_image_view(VK_NULL_HANDLE), m_texture_size(0),
m_disable_reload(true), m_single_channel(false)
{
if (!img)
return;
m_size = m_orig_size = img->getDimension();
uint8_t* data = (uint8_t*)img->lock();
upload(data);
img->unlock();
img->drop();
} // GEVulkanTexture
// ----------------------------------------------------------------------------
GEVulkanTexture::GEVulkanTexture(const std::string& name, unsigned int size,
bool single_channel)
: video::ITexture(name.c_str()), m_image_mani(nullptr),
m_locked_data(NULL), m_vulkan_device(getVKDriver()->getDevice()),
m_image(VK_NULL_HANDLE), m_image_memory(VK_NULL_HANDLE),
m_image_view(VK_NULL_HANDLE), m_texture_size(0),
m_disable_reload(true), m_single_channel(single_channel)
{
m_orig_size.Width = size;
m_orig_size.Height = size;
m_size = m_orig_size;
std::vector<uint8_t> data;
data.resize(size * size * (m_single_channel ? 1 : 4), 0);
upload(data.data());
} // GEVulkanTexture
// ----------------------------------------------------------------------------
GEVulkanTexture::~GEVulkanTexture()
{
clearVulkanData();
} // ~GEVulkanTexture
// ----------------------------------------------------------------------------
bool GEVulkanTexture::createTextureImage(uint8_t* texture_data)
{
unsigned channels = (m_single_channel ? 1 : 4);
VkDeviceSize image_size = m_size.Width * m_size.Height * channels;
VkBuffer staging_buffer;
VkDeviceMemory staging_buffer_memory;
bool success = getVKDriver()->createBuffer(image_size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, staging_buffer,
staging_buffer_memory);
if (!success)
return false;
void* data;
vkMapMemory(m_vulkan_device, staging_buffer_memory, 0, image_size, 0, &data);
memcpy(data, texture_data, (size_t)(image_size));
vkUnmapMemory(m_vulkan_device, staging_buffer_memory);
success = createImage(VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT);
if (!success)
return false;
transitionImageLayout(VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyBufferToImage(staging_buffer, m_size.Width, m_size.Height, 0, 0);
transitionImageLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
vkDestroyBuffer(m_vulkan_device, staging_buffer, NULL);
vkFreeMemory(m_vulkan_device, staging_buffer_memory, NULL);
return true;
} // createTextureImage
// ----------------------------------------------------------------------------
bool GEVulkanTexture::createImage(VkImageUsageFlags usage)
{
VkImageCreateInfo image_info = {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.extent.width = m_size.Width;
image_info.extent.height = m_size.Height;
image_info.extent.depth = 1;
image_info.mipLevels = 1;
image_info.arrayLayers = 1;
image_info.format =
(m_single_channel ? VK_FORMAT_R8_UNORM : VK_FORMAT_R8G8B8A8_UNORM);
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.usage = usage;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkResult result = vkCreateImage(m_vulkan_device, &image_info, NULL,
&m_image);
if (result != VK_SUCCESS)
return false;
VkMemoryRequirements mem_requirements;
vkGetImageMemoryRequirements(m_vulkan_device, m_image, &mem_requirements);
VkPhysicalDeviceMemoryProperties mem_properties;
vkGetPhysicalDeviceMemoryProperties(getVKDriver()->getPhysicalDevice(),
&mem_properties);
uint32_t memory_type_index = std::numeric_limits<uint32_t>::max();
uint32_t type_filter = mem_requirements.memoryTypeBits;
VkMemoryPropertyFlags properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++)
{
if ((type_filter & (1 << i)) &&
(mem_properties.memoryTypes[i].propertyFlags & properties) == properties)
{
memory_type_index = i;
break;
}
}
if (memory_type_index == std::numeric_limits<uint32_t>::max())
return false;
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = mem_requirements.size;
alloc_info.memoryTypeIndex = memory_type_index;
result = vkAllocateMemory(m_vulkan_device, &alloc_info, NULL,
&m_image_memory);
if (result != VK_SUCCESS)
return false;
vkBindImageMemory(m_vulkan_device, m_image, m_image_memory, 0);
return true;
} // createImage
// ----------------------------------------------------------------------------
void GEVulkanTexture::transitionImageLayout(VkImageLayout old_layout,
VkImageLayout new_layout)
{
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = old_layout;
barrier.newLayout = new_layout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = m_image;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
if (new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
{
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
}
else
{
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
VkPipelineStageFlags source_stage;
VkPipelineStageFlags destination_stage;
if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
{
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destination_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL &&
new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destination_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
else if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
{
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destination_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
else
{
return;
}
VkCommandBuffer command_buffer = getVKDriver()->beginSingleTimeCommands();
vkCmdPipelineBarrier(command_buffer, source_stage, destination_stage, 0, 0,
NULL, 0, NULL, 1, &barrier);
getVKDriver()->endSingleTimeCommands(command_buffer);
} // transitionImageLayout
// ----------------------------------------------------------------------------
void GEVulkanTexture::copyBufferToImage(VkBuffer buffer, u32 w, u32 h, s32 x,
s32 y)
{
VkCommandBuffer command_buffer = getVKDriver()->beginSingleTimeCommands();
VkBufferImageCopy region = {};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = {x, y, 0};
region.imageExtent = {w, h, 1};
vkCmdCopyBufferToImage(command_buffer, buffer, m_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
getVKDriver()->endSingleTimeCommands(command_buffer);
} // copyBufferToImage
// ----------------------------------------------------------------------------
bool GEVulkanTexture::createImageView(VkImageAspectFlags aspect_flags)
{
VkImageViewCreateInfo view_info = {};
view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_info.image = m_image;
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
view_info.format =
(m_single_channel ? VK_FORMAT_R8_UNORM : VK_FORMAT_R8G8B8A8_UNORM);
view_info.subresourceRange.aspectMask = aspect_flags;
view_info.subresourceRange.baseMipLevel = 0;
view_info.subresourceRange.levelCount = 1;
view_info.subresourceRange.baseArrayLayer = 0;
view_info.subresourceRange.layerCount = 1;
if (m_single_channel)
{
view_info.components.r = VK_COMPONENT_SWIZZLE_ONE;
view_info.components.g = VK_COMPONENT_SWIZZLE_ONE;
view_info.components.b = VK_COMPONENT_SWIZZLE_ONE;
view_info.components.a = VK_COMPONENT_SWIZZLE_R;
}
VkResult result = vkCreateImageView(m_vulkan_device, &view_info, NULL,
&m_image_view);
return (result == VK_SUCCESS);
} // createImageView
// ----------------------------------------------------------------------------
void GEVulkanTexture::clearVulkanData()
{
if (m_image_view != VK_NULL_HANDLE)
vkDestroyImageView(m_vulkan_device, m_image_view, NULL);
if (m_image != VK_NULL_HANDLE)
vkDestroyImage(m_vulkan_device, m_image, NULL);
if (m_image_memory != VK_NULL_HANDLE)
vkFreeMemory(m_vulkan_device, m_image_memory, NULL);
} // clearVulkanData
// ----------------------------------------------------------------------------
void GEVulkanTexture::reload()
{
if (m_disable_reload)
return;
clearVulkanData();
video::IImage* texture_image = getResizedImage(NamedPath.getPtr(),
&m_orig_size);
if (texture_image == NULL)
return;
m_size = texture_image->getDimension();
if (m_image_mani)
m_image_mani(texture_image);
uint8_t* data = (uint8_t*)texture_image->lock();
upload(data);
texture_image->unlock();
texture_image->drop();
} // reload
// ----------------------------------------------------------------------------
void GEVulkanTexture::upload(uint8_t* data)
{
if (!m_single_channel)
{
for (unsigned int i = 0; i < m_size.Width * m_size.Height; i++)
{
uint8_t tmp_val = data[i * 4];
data[i * 4] = data[i * 4 + 2];
data[i * 4 + 2] = tmp_val;
}
}
if (!createTextureImage(data))
return;
if (!createImageView(VK_IMAGE_ASPECT_COLOR_BIT))
return;
m_texture_size = m_size.Width * m_size.Height * (m_single_channel ? 1 : 4);
} // upload
// ----------------------------------------------------------------------------
void* GEVulkanTexture::lock(video::E_TEXTURE_LOCK_MODE mode, u32 mipmap_level)
{
return NULL;
} // lock
//-----------------------------------------------------------------------------
void GEVulkanTexture::updateTexture(void* data, video::ECOLOR_FORMAT format,
u32 w, u32 h, u32 x, u32 y)
{
VkBuffer staging_buffer;
VkDeviceMemory staging_buffer_memory;
if (m_single_channel)
{
if (format == video::ECF_R8)
{
unsigned image_size = w * h;
if (!getVKDriver()->createBuffer(image_size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, staging_buffer,
staging_buffer_memory))
return;
void* mapped_data;
vkMapMemory(m_vulkan_device, staging_buffer_memory, 0, image_size,
0, &mapped_data);
memcpy(mapped_data, data, (size_t)(image_size));
vkUnmapMemory(m_vulkan_device, staging_buffer_memory);
}
}
else
{
if (format == video::ECF_R8)
{
unsigned image_size = w * h * 4;
if (!getVKDriver()->createBuffer(w * h * 4,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, staging_buffer,
staging_buffer_memory))
return;
const unsigned int size = w * h;
std::vector<uint8_t> image_data(size * 4, 255);
uint8_t* orig_data = (uint8_t*)data;
for (unsigned int i = 0; i < size; i++)
image_data[4 * i + 3] = orig_data[i];
void* mapped_data;
vkMapMemory(m_vulkan_device, staging_buffer_memory, 0, image_size,
0, &mapped_data);
memcpy(mapped_data, image_data.data(), (size_t)(image_size));
vkUnmapMemory(m_vulkan_device, staging_buffer_memory);
}
else if (format == video::ECF_A8R8G8B8)
{
unsigned image_size = w * h * 4;
if (!getVKDriver()->createBuffer(w * h * 4,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, staging_buffer,
staging_buffer_memory))
return;
uint8_t* u8_data = (uint8_t*)data;
for (unsigned int i = 0; i < w * h; i++)
{
uint8_t tmp_val = u8_data[i * 4];
u8_data[i * 4] = u8_data[i * 4 + 2];
u8_data[i * 4 + 2] = tmp_val;
}
void* mapped_data;
vkMapMemory(m_vulkan_device, staging_buffer_memory, 0, image_size,
0, &mapped_data);
memcpy(mapped_data, u8_data, (size_t)(image_size));
vkUnmapMemory(m_vulkan_device, staging_buffer_memory);
}
}
copyBufferToImage(staging_buffer, w, h, x, y);
vkDestroyBuffer(m_vulkan_device, staging_buffer, NULL);
vkFreeMemory(m_vulkan_device, staging_buffer_memory, NULL);
} // updateTexture
}

View File

@ -0,0 +1,106 @@
#ifndef HEADER_GE_VULKAN_TEXTURE_HPP
#define HEADER_GE_VULKAN_TEXTURE_HPP
#include "glad/vulkan.h"
#include <functional>
#include <string>
#include <ITexture.h>
using namespace irr;
namespace GE
{
class GEVulkanTexture : public video::ITexture
{
private:
core::dimension2d<u32> m_size, m_orig_size;
std::function<void(video::IImage*)> m_image_mani;
uint8_t* m_locked_data;
VkDevice m_vulkan_device;
VkImage m_image;
VkDeviceMemory m_image_memory;
VkImageView m_image_view;
unsigned int m_texture_size;
const bool m_disable_reload;
bool m_single_channel;
// ------------------------------------------------------------------------
bool createTextureImage(uint8_t* texture_data);
// ------------------------------------------------------------------------
bool createImage(VkImageUsageFlags usage);
// ------------------------------------------------------------------------
bool createImageView(VkImageAspectFlags aspect_flags);
// ------------------------------------------------------------------------
void transitionImageLayout(VkImageLayout old_layout,
VkImageLayout new_layout);
// ------------------------------------------------------------------------
void copyBufferToImage(VkBuffer buffer, u32 w, u32 h, s32 x, s32 y);
// ------------------------------------------------------------------------
void upload(uint8_t* data);
// ------------------------------------------------------------------------
void clearVulkanData();
// ------------------------------------------------------------------------
public:
// ------------------------------------------------------------------------
GEVulkanTexture(const std::string& path,
std::function<void(video::IImage*)> image_mani = nullptr);
// ------------------------------------------------------------------------
GEVulkanTexture(video::IImage* img, const std::string& name);
// ------------------------------------------------------------------------
GEVulkanTexture(const std::string& name, unsigned int size,
bool single_channel);
// ------------------------------------------------------------------------
virtual ~GEVulkanTexture();
// ------------------------------------------------------------------------
virtual void* lock(video::E_TEXTURE_LOCK_MODE mode =
video::ETLM_READ_WRITE, u32 mipmap_level = 0);
// ------------------------------------------------------------------------
virtual void unlock()
{
if (m_locked_data)
{
delete [] m_locked_data;
m_locked_data = NULL;
}
}
// ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getOriginalSize() const
{ return m_orig_size; }
// ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getSize() const { return m_size; }
// ------------------------------------------------------------------------
virtual video::E_DRIVER_TYPE getDriverType() const
{ return video::EDT_VULKAN; }
// ------------------------------------------------------------------------
virtual video::ECOLOR_FORMAT getColorFormat() const
{ return video::ECF_A8R8G8B8; }
// ------------------------------------------------------------------------
virtual u32 getPitch() const { return 0; }
// ------------------------------------------------------------------------
virtual bool hasMipMaps() const { return false; }
// ------------------------------------------------------------------------
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
// ------------------------------------------------------------------------
virtual u64 getTextureHandler() const { return (u64)m_image_view; }
// ------------------------------------------------------------------------
virtual unsigned int getTextureSize() const { return m_texture_size; }
// ------------------------------------------------------------------------
virtual void reload();
// ------------------------------------------------------------------------
virtual void updateTexture(void* data, irr::video::ECOLOR_FORMAT format,
u32 w, u32 h, u32 x, u32 y);
}; // GEVulkanTexture
}
#endif