Add ondemand texture loading for vulkan
This commit is contained in:
parent
eace871c66
commit
e0636495f0
@ -13,15 +13,20 @@ irr::video::ITexture* createFontTexture(const std::string& name,
|
|||||||
unsigned size, bool single_channel);
|
unsigned size, bool single_channel);
|
||||||
irr::video::ITexture* createTexture(irr::video::IImage* img,
|
irr::video::ITexture* createTexture(irr::video::IImage* img,
|
||||||
const std::string& name);
|
const std::string& name);
|
||||||
|
irr::core::dimension2d<irr::u32> getResizingTarget(
|
||||||
|
const irr::core::dimension2d<irr::u32>& orig_size,
|
||||||
|
const irr::core::dimension2d<irr::u32>& max_size);
|
||||||
irr::video::IImage* getResizedImage(const std::string& path,
|
irr::video::IImage* getResizedImage(const std::string& path,
|
||||||
const irr::core::dimension2d<irr::u32>& max_size,
|
const irr::core::dimension2d<irr::u32>& max_size,
|
||||||
irr::core::dimension2d<irr::u32>* orig_size = NULL);
|
irr::core::dimension2d<irr::u32>* orig_size = NULL);
|
||||||
irr::video::IImage* getResizedImageFullPath(const irr::io::path& fullpath,
|
irr::video::IImage* getResizedImageFullPath(const irr::io::path& fullpath,
|
||||||
const irr::core::dimension2d<irr::u32>& max_size,
|
const irr::core::dimension2d<irr::u32>& max_size,
|
||||||
irr::core::dimension2d<irr::u32>* orig_size = NULL);
|
irr::core::dimension2d<irr::u32>* orig_size = NULL,
|
||||||
|
const irr::core::dimension2d<irr::u32>* target_size = NULL);
|
||||||
irr::video::IImage* getResizedImage(irr::io::IReadFile* file,
|
irr::video::IImage* getResizedImage(irr::io::IReadFile* file,
|
||||||
const irr::core::dimension2d<irr::u32>& max_size,
|
const irr::core::dimension2d<irr::u32>& max_size,
|
||||||
irr::core::dimension2d<irr::u32>* orig_size = NULL);
|
irr::core::dimension2d<irr::u32>* orig_size = NULL,
|
||||||
|
const irr::core::dimension2d<irr::u32>* target_size = NULL);
|
||||||
irr::video::ITexture* createTexture(const std::string& path,
|
irr::video::ITexture* createTexture(const std::string& path,
|
||||||
std::function<void(irr::video::IImage*)> image_mani = nullptr);
|
std::function<void(irr::video::IImage*)> image_mani = nullptr);
|
||||||
}; // GE
|
}; // GE
|
||||||
|
@ -10,6 +10,7 @@ namespace irr
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -21,12 +22,14 @@ enum GEVulkanSampler : unsigned;
|
|||||||
|
|
||||||
class GEVulkanTextureDescriptor
|
class GEVulkanTextureDescriptor
|
||||||
{
|
{
|
||||||
typedef std::array<std::shared_ptr<VkImageView>,
|
typedef std::array<std::shared_ptr<std::atomic<VkImageView> >,
|
||||||
_IRR_MATERIAL_MAX_TEXTURES_> TextureList;
|
_IRR_MATERIAL_MAX_TEXTURES_> TextureList;
|
||||||
|
|
||||||
std::map<TextureList, int> m_texture_list;
|
std::map<TextureList, int> m_texture_list;
|
||||||
|
|
||||||
std::shared_ptr<VkImageView> m_white_image, m_transparent_image;
|
std::shared_ptr<std::atomic<VkImageView> > m_white_image;
|
||||||
|
|
||||||
|
std::shared_ptr<std::atomic<VkImageView> > m_transparent_image;
|
||||||
|
|
||||||
VkDescriptorSetLayout m_descriptor_set_layout;
|
VkDescriptorSetLayout m_descriptor_set_layout;
|
||||||
|
|
||||||
@ -68,7 +71,7 @@ public:
|
|||||||
{
|
{
|
||||||
for (auto& t : p.first)
|
for (auto& t : p.first)
|
||||||
{
|
{
|
||||||
if (*(t.get()) == VK_NULL_HANDLE)
|
if (t.get()->load() == VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
has_deleted_image_view = true;
|
has_deleted_image_view = true;
|
||||||
break;
|
break;
|
||||||
|
@ -23,15 +23,32 @@ video::IImage* getResizedImage(const std::string& path,
|
|||||||
return image;
|
return image;
|
||||||
} // getResizedImage
|
} // getResizedImage
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
core::dimension2du getResizingTarget(const core::dimension2du& orig_size,
|
||||||
|
const core::dimension2du& max_size)
|
||||||
|
{
|
||||||
|
bool has_npot = !getGEConfig()->m_disable_npot_texture &&
|
||||||
|
getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT);
|
||||||
|
|
||||||
|
core::dimension2du tex_size = orig_size.getOptimalSize(!has_npot);
|
||||||
|
if (tex_size.Width > max_size.Width)
|
||||||
|
tex_size.Width = max_size.Width;
|
||||||
|
if (tex_size.Height > max_size.Height)
|
||||||
|
tex_size.Height = max_size.Height;
|
||||||
|
return tex_size;
|
||||||
|
} // getResizingTarget
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
video::IImage* getResizedImageFullPath(const io::path& fullpath,
|
video::IImage* getResizedImageFullPath(const io::path& fullpath,
|
||||||
const core::dimension2d<u32>& max_size,
|
const core::dimension2d<u32>& max_size,
|
||||||
core::dimension2d<u32>* orig_size)
|
core::dimension2d<u32>* orig_size,
|
||||||
|
const core::dimension2d<u32>* target_size)
|
||||||
{
|
{
|
||||||
io::IReadFile* file = io::createReadFile(fullpath);
|
io::IReadFile* file = io::createReadFile(fullpath);
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
video::IImage* texture_image = getResizedImage(file, max_size, orig_size);
|
video::IImage* texture_image = getResizedImage(file, max_size, orig_size,
|
||||||
|
target_size);
|
||||||
file->drop();
|
file->drop();
|
||||||
return texture_image;
|
return texture_image;
|
||||||
} // getResizedImageFullPath
|
} // getResizedImageFullPath
|
||||||
@ -39,7 +56,8 @@ video::IImage* getResizedImageFullPath(const io::path& fullpath,
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
video::IImage* getResizedImage(irr::io::IReadFile* file,
|
video::IImage* getResizedImage(irr::io::IReadFile* file,
|
||||||
const core::dimension2du& max_size,
|
const core::dimension2du& max_size,
|
||||||
core::dimension2d<u32>* orig_size)
|
core::dimension2d<u32>* orig_size,
|
||||||
|
const core::dimension2d<u32>* target_size)
|
||||||
{
|
{
|
||||||
video::IImage* image = getDriver()->createImageFromFile(file);
|
video::IImage* image = getDriver()->createImageFromFile(file);
|
||||||
if (image == NULL)
|
if (image == NULL)
|
||||||
@ -48,14 +66,11 @@ video::IImage* getResizedImage(irr::io::IReadFile* file,
|
|||||||
*orig_size = image->getDimension();
|
*orig_size = image->getDimension();
|
||||||
|
|
||||||
core::dimension2du img_size = image->getDimension();
|
core::dimension2du img_size = image->getDimension();
|
||||||
bool has_npot = !getGEConfig()->m_disable_npot_texture &&
|
core::dimension2du tex_size;
|
||||||
getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT);
|
if (target_size)
|
||||||
|
tex_size = *target_size;
|
||||||
core::dimension2du tex_size = img_size.getOptimalSize(!has_npot);
|
else
|
||||||
if (tex_size.Width > max_size.Width)
|
tex_size = getResizingTarget(img_size, max_size);
|
||||||
tex_size.Width = max_size.Width;
|
|
||||||
if (tex_size.Height > max_size.Height)
|
|
||||||
tex_size.Height = max_size.Height;
|
|
||||||
|
|
||||||
if (image->getColorFormat() != video::ECF_A8R8G8B8 ||
|
if (image->getColorFormat() != video::ECF_A8R8G8B8 ||
|
||||||
tex_size != img_size)
|
tex_size != img_size)
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
|
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual u64 getTextureHandler() const
|
virtual u64 getTextureHandler() const
|
||||||
{ return (u64)*(m_image_view.get()); }
|
{ return (u64)(m_image_view.get()->load()); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual unsigned int getTextureSize() const { return m_texture_size; }
|
virtual unsigned int getTextureSize() const { return m_texture_size; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -48,7 +48,7 @@ public:
|
|||||||
virtual void updateTexture(void* data, irr::video::ECOLOR_FORMAT format,
|
virtual void updateTexture(void* data, irr::video::ECOLOR_FORMAT format,
|
||||||
u32 w, u32 h, u32 x, u32 y) {}
|
u32 w, u32 h, u32 x, u32 y) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual std::shared_ptr<VkImageView> getImageView() const
|
virtual std::shared_ptr<std::atomic<VkImageView> > getImageView() const
|
||||||
{ return m_image_view; }
|
{ return m_image_view; }
|
||||||
}; // GEVulkanDepthTexture
|
}; // GEVulkanDepthTexture
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
|
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual u64 getTextureHandler() const
|
virtual u64 getTextureHandler() const
|
||||||
{ return (u64)*(m_image_view.get()); }
|
{ return (u64)(m_image_view.get()->load()); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual unsigned int getTextureSize() const { return m_texture_size; }
|
virtual unsigned int getTextureSize() const { return m_texture_size; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -45,7 +45,7 @@ public:
|
|||||||
virtual void updateTexture(void* data, irr::video::ECOLOR_FORMAT format,
|
virtual void updateTexture(void* data, irr::video::ECOLOR_FORMAT format,
|
||||||
u32 w, u32 h, u32 x, u32 y) {}
|
u32 w, u32 h, u32 x, u32 y) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual std::shared_ptr<VkImageView> getImageView() const
|
virtual std::shared_ptr<std::atomic<VkImageView> > getImageView() const
|
||||||
{ return m_image_view; }
|
{ return m_image_view; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void createRTT();
|
void createRTT();
|
||||||
|
@ -15,7 +15,9 @@ extern "C"
|
|||||||
#include <mipmap/imgresize.h>
|
#include <mipmap/imgresize.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <IAttributes.h>
|
#include <IAttributes.h>
|
||||||
|
#include <IImageLoader.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace GE
|
namespace GE
|
||||||
@ -27,7 +29,8 @@ GEVulkanTexture::GEVulkanTexture(const std::string& path,
|
|||||||
m_vulkan_device(getVKDriver()->getDevice()),
|
m_vulkan_device(getVKDriver()->getDevice()),
|
||||||
m_image(VK_NULL_HANDLE), m_vma_allocation(VK_NULL_HANDLE),
|
m_image(VK_NULL_HANDLE), m_vma_allocation(VK_NULL_HANDLE),
|
||||||
m_texture_size(0), m_disable_reload(false),
|
m_texture_size(0), m_disable_reload(false),
|
||||||
m_has_mipmaps(true),
|
m_has_mipmaps(true), m_ondemand_load(false),
|
||||||
|
m_ondemand_loading(false),
|
||||||
m_internal_format(VK_FORMAT_R8G8B8A8_UNORM),
|
m_internal_format(VK_FORMAT_R8G8B8A8_UNORM),
|
||||||
m_vk(getVKDriver())
|
m_vk(getVKDriver())
|
||||||
{
|
{
|
||||||
@ -40,6 +43,24 @@ GEVulkanTexture::GEVulkanTexture(const std::string& path,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ondemand_load)
|
||||||
|
{
|
||||||
|
video::IImageLoader* loader = NULL;
|
||||||
|
io::IReadFile* file = io::createReadFile(m_full_path);
|
||||||
|
getDriver()->createImageFromFile(file, &loader);
|
||||||
|
if (loader && loader->getImageSize(file, &m_orig_size))
|
||||||
|
{
|
||||||
|
m_size = getResizingTarget(m_orig_size, m_max_size);
|
||||||
|
if (m_size.Width < 4 || m_size.Height < 4)
|
||||||
|
m_has_mipmaps = false;
|
||||||
|
setPlaceHolderView();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LoadingFailed = true;
|
||||||
|
file->drop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_size_lock.lock();
|
m_size_lock.lock();
|
||||||
m_image_view_lock.lock();
|
m_image_view_lock.lock();
|
||||||
GEVulkanCommandLoader::addMultiThreadingCommand(
|
GEVulkanCommandLoader::addMultiThreadingCommand(
|
||||||
@ -53,7 +74,8 @@ GEVulkanTexture::GEVulkanTexture(video::IImage* img, const std::string& name)
|
|||||||
m_vulkan_device(getVKDriver()->getDevice()),
|
m_vulkan_device(getVKDriver()->getDevice()),
|
||||||
m_image(VK_NULL_HANDLE), m_vma_allocation(VK_NULL_HANDLE),
|
m_image(VK_NULL_HANDLE), m_vma_allocation(VK_NULL_HANDLE),
|
||||||
m_texture_size(0), m_disable_reload(true),
|
m_texture_size(0), m_disable_reload(true),
|
||||||
m_has_mipmaps(true),
|
m_has_mipmaps(true), m_ondemand_load(false),
|
||||||
|
m_ondemand_loading(false),
|
||||||
m_internal_format(VK_FORMAT_R8G8B8A8_UNORM),
|
m_internal_format(VK_FORMAT_R8G8B8A8_UNORM),
|
||||||
m_vk(getVKDriver())
|
m_vk(getVKDriver())
|
||||||
{
|
{
|
||||||
@ -79,6 +101,7 @@ GEVulkanTexture::GEVulkanTexture(const std::string& name, unsigned int size,
|
|||||||
m_locked_data(NULL), m_vulkan_device(getVKDriver()->getDevice()),
|
m_locked_data(NULL), m_vulkan_device(getVKDriver()->getDevice()),
|
||||||
m_image(VK_NULL_HANDLE), m_vma_allocation(VK_NULL_HANDLE),
|
m_image(VK_NULL_HANDLE), m_vma_allocation(VK_NULL_HANDLE),
|
||||||
m_texture_size(0), m_disable_reload(true), m_has_mipmaps(true),
|
m_texture_size(0), m_disable_reload(true), m_has_mipmaps(true),
|
||||||
|
m_ondemand_load(false), m_ondemand_loading(false),
|
||||||
m_internal_format(single_channel ?
|
m_internal_format(single_channel ?
|
||||||
VK_FORMAT_R8_UNORM : VK_FORMAT_R8G8B8A8_UNORM),
|
VK_FORMAT_R8_UNORM : VK_FORMAT_R8G8B8A8_UNORM),
|
||||||
m_vk(getVKDriver())
|
m_vk(getVKDriver())
|
||||||
@ -100,8 +123,7 @@ GEVulkanTexture::GEVulkanTexture(const std::string& name, unsigned int size,
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
GEVulkanTexture::~GEVulkanTexture()
|
GEVulkanTexture::~GEVulkanTexture()
|
||||||
{
|
{
|
||||||
m_image_view_lock.lock();
|
waitImageView();
|
||||||
m_image_view_lock.unlock();
|
|
||||||
|
|
||||||
if (m_image_view || m_image != VK_NULL_HANDLE ||
|
if (m_image_view || m_image != VK_NULL_HANDLE ||
|
||||||
m_vma_allocation != VK_NULL_HANDLE)
|
m_vma_allocation != VK_NULL_HANDLE)
|
||||||
@ -390,12 +412,18 @@ bool GEVulkanTexture::createImageView(VkImageAspectFlags aspect_flags)
|
|||||||
view_info.components.a = VK_COMPONENT_SWIZZLE_R;
|
view_info.components.a = VK_COMPONENT_SWIZZLE_R;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VkImageView> image_view = std::make_shared<VkImageView>();
|
auto image_view = std::make_shared<std::atomic<VkImageView> >();
|
||||||
|
VkImageView view_ptr = NULL;
|
||||||
VkResult result = vkCreateImageView(m_vulkan_device, &view_info, NULL,
|
VkResult result = vkCreateImageView(m_vulkan_device, &view_info, NULL,
|
||||||
image_view.get());
|
&view_ptr);
|
||||||
if (result == VK_SUCCESS)
|
if (result == VK_SUCCESS)
|
||||||
{
|
{
|
||||||
|
image_view.get()->store(view_ptr);
|
||||||
m_image_view = image_view;
|
m_image_view = image_view;
|
||||||
|
|
||||||
|
if (m_placeholder_view)
|
||||||
|
m_placeholder_view.get()->store(VK_NULL_HANDLE);
|
||||||
|
m_ondemand_loading.store(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -406,12 +434,16 @@ void GEVulkanTexture::clearVulkanData()
|
|||||||
{
|
{
|
||||||
if (m_image_view)
|
if (m_image_view)
|
||||||
{
|
{
|
||||||
vkDestroyImageView(m_vulkan_device, *m_image_view.get(), NULL);
|
vkDestroyImageView(m_vulkan_device, m_image_view.get()->load(), NULL);
|
||||||
*(m_image_view.get()) = VK_NULL_HANDLE;
|
m_image_view.get()->store(VK_NULL_HANDLE);
|
||||||
m_image_view.reset();
|
m_image_view.reset();
|
||||||
}
|
}
|
||||||
if (m_image != VK_NULL_HANDLE)
|
if (m_image != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
vmaDestroyImage(m_vk->getVmaAllocator(), m_image, m_vma_allocation);
|
vmaDestroyImage(m_vk->getVmaAllocator(), m_image, m_vma_allocation);
|
||||||
|
m_image = VK_NULL_HANDLE;
|
||||||
|
m_vma_allocation = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
} // clearVulkanData
|
} // clearVulkanData
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -422,17 +454,30 @@ void GEVulkanTexture::reloadInternal()
|
|||||||
|
|
||||||
clearVulkanData();
|
clearVulkanData();
|
||||||
|
|
||||||
video::IImage* texture_image = getResizedImageFullPath(m_full_path,
|
video::IImage* texture_image = NULL;
|
||||||
m_max_size, &m_orig_size);
|
if (m_ondemand_load)
|
||||||
|
{
|
||||||
|
texture_image = getResizedImageFullPath(m_full_path, m_max_size,
|
||||||
|
NULL, &m_size);
|
||||||
|
if (texture_image == NULL)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Missing texture_image in getResizedImageFullPath");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texture_image = getResizedImageFullPath(m_full_path, m_max_size,
|
||||||
|
&m_orig_size);
|
||||||
if (texture_image == NULL)
|
if (texture_image == NULL)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"Missing texture_image in getResizedImageFullPath");
|
"Missing texture_image in getResizedImageFullPath");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_size = texture_image->getDimension();
|
m_size = texture_image->getDimension();
|
||||||
if (m_size.Width < 4 || m_size.Height < 4)
|
if (m_size.Width < 4 || m_size.Height < 4)
|
||||||
m_has_mipmaps = false;
|
m_has_mipmaps = false;
|
||||||
|
}
|
||||||
m_size_lock.unlock();
|
m_size_lock.unlock();
|
||||||
|
|
||||||
if (m_image_mani)
|
if (m_image_mani)
|
||||||
@ -492,7 +537,7 @@ uint8_t* GEVulkanTexture::getTextureData()
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
video::IImage* texture_image = getResizedImageFullPath(m_full_path,
|
video::IImage* texture_image = getResizedImageFullPath(m_full_path,
|
||||||
m_max_size, &m_orig_size);
|
m_max_size, NULL, &m_size);
|
||||||
if (texture_image == NULL)
|
if (texture_image == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
texture_image->setDeleteMemory(false);
|
texture_image->setDeleteMemory(false);
|
||||||
@ -501,8 +546,8 @@ uint8_t* GEVulkanTexture::getTextureData()
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_image_view_lock.lock();
|
if (!waitImageView())
|
||||||
m_image_view_lock.unlock();
|
return NULL;
|
||||||
|
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
VmaAllocation buffer_allocation;
|
VmaAllocation buffer_allocation;
|
||||||
@ -567,8 +612,8 @@ cleanup:
|
|||||||
void GEVulkanTexture::updateTexture(void* data, video::ECOLOR_FORMAT format,
|
void GEVulkanTexture::updateTexture(void* data, video::ECOLOR_FORMAT format,
|
||||||
u32 w, u32 h, u32 x, u32 y)
|
u32 w, u32 h, u32 x, u32 y)
|
||||||
{
|
{
|
||||||
m_image_view_lock.lock();
|
if (!waitImageView())
|
||||||
m_image_view_lock.unlock();
|
return;
|
||||||
|
|
||||||
VkBuffer staging_buffer;
|
VkBuffer staging_buffer;
|
||||||
VmaAllocation staging_buffer_allocation;
|
VmaAllocation staging_buffer_allocation;
|
||||||
@ -743,14 +788,19 @@ void GEVulkanTexture::bgraConversion(uint8_t* img_data)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void GEVulkanTexture::reload()
|
void GEVulkanTexture::reload()
|
||||||
{
|
{
|
||||||
m_image_view_lock.lock();
|
if (!waitImageView())
|
||||||
m_image_view_lock.unlock();
|
return;
|
||||||
|
|
||||||
if (m_image_view || m_image != VK_NULL_HANDLE ||
|
if (m_image_view || m_image != VK_NULL_HANDLE ||
|
||||||
m_vma_allocation != VK_NULL_HANDLE)
|
m_vma_allocation != VK_NULL_HANDLE)
|
||||||
m_vk->waitIdle();
|
m_vk->waitIdle();
|
||||||
|
|
||||||
if (!m_disable_reload)
|
if (m_ondemand_load)
|
||||||
|
{
|
||||||
|
clearVulkanData();
|
||||||
|
setPlaceHolderView();
|
||||||
|
}
|
||||||
|
else if (!m_disable_reload)
|
||||||
{
|
{
|
||||||
m_size_lock.lock();
|
m_size_lock.lock();
|
||||||
m_image_view_lock.lock();
|
m_image_view_lock.lock();
|
||||||
@ -759,4 +809,35 @@ void GEVulkanTexture::reload()
|
|||||||
}
|
}
|
||||||
} // reload
|
} // reload
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void GEVulkanTexture::setPlaceHolderView()
|
||||||
|
{
|
||||||
|
auto tex = static_cast<GEVulkanTexture*>(m_vk->getTransparentTexture());
|
||||||
|
auto image_view = std::make_shared<std::atomic<VkImageView> >();
|
||||||
|
image_view.get()->store((VkImageView)tex->getTextureHandler());
|
||||||
|
if (m_placeholder_view)
|
||||||
|
m_placeholder_view.get()->store(VK_NULL_HANDLE);
|
||||||
|
m_placeholder_view = image_view;
|
||||||
|
} // setPlaceHolderView
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
std::shared_ptr<std::atomic<VkImageView> > GEVulkanTexture::getImageViewLive() const
|
||||||
|
{
|
||||||
|
assert(m_ondemand_load && m_placeholder_view);
|
||||||
|
if (m_ondemand_loading.load() == false)
|
||||||
|
{
|
||||||
|
if (m_image_view)
|
||||||
|
return m_image_view;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GEVulkanTexture* tex = const_cast<GEVulkanTexture*>(this);
|
||||||
|
GEVulkanCommandLoader::addMultiThreadingCommand(
|
||||||
|
std::bind(&GEVulkanTexture::reloadInternal, tex));
|
||||||
|
m_ondemand_loading.store(true);
|
||||||
|
return m_placeholder_view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_placeholder_view;
|
||||||
|
} // getImageViewLive
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "ge_spin_lock.hpp"
|
#include "ge_spin_lock.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -34,7 +35,9 @@ protected:
|
|||||||
|
|
||||||
VmaAllocation m_vma_allocation;
|
VmaAllocation m_vma_allocation;
|
||||||
|
|
||||||
std::shared_ptr<VkImageView> m_image_view;
|
std::shared_ptr<std::atomic<VkImageView> > m_image_view;
|
||||||
|
|
||||||
|
std::shared_ptr<std::atomic<VkImageView> > m_placeholder_view;
|
||||||
|
|
||||||
unsigned int m_texture_size;
|
unsigned int m_texture_size;
|
||||||
|
|
||||||
@ -42,6 +45,10 @@ protected:
|
|||||||
|
|
||||||
bool m_has_mipmaps;
|
bool m_has_mipmaps;
|
||||||
|
|
||||||
|
bool m_ondemand_load;
|
||||||
|
|
||||||
|
mutable std::atomic<bool> m_ondemand_loading;
|
||||||
|
|
||||||
GESpinLock m_size_lock;
|
GESpinLock m_size_lock;
|
||||||
|
|
||||||
GESpinLock m_image_view_lock;
|
GESpinLock m_image_view_lock;
|
||||||
@ -87,7 +94,28 @@ protected:
|
|||||||
bool isSingleChannel() const
|
bool isSingleChannel() const
|
||||||
{ return m_internal_format == VK_FORMAT_R8_UNORM; }
|
{ return m_internal_format == VK_FORMAT_R8_UNORM; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
GEVulkanTexture() : video::ITexture(""), m_disable_reload(true) {}
|
void setPlaceHolderView();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
std::shared_ptr<std::atomic<VkImageView> > getImageViewLive() const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool waitImageView()
|
||||||
|
{
|
||||||
|
if (!m_ondemand_load)
|
||||||
|
{
|
||||||
|
m_image_view_lock.lock();
|
||||||
|
m_image_view_lock.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (m_ondemand_loading.load());
|
||||||
|
if (m_image == VK_NULL_HANDLE)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
GEVulkanTexture() : video::ITexture(""), m_disable_reload(true),
|
||||||
|
m_ondemand_load(false), m_ondemand_loading(false) {}
|
||||||
public:
|
public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
GEVulkanTexture(const std::string& path,
|
GEVulkanTexture(const std::string& path,
|
||||||
@ -113,16 +141,22 @@ public:
|
|||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual const core::dimension2d<u32>& getOriginalSize() const
|
virtual const core::dimension2d<u32>& getOriginalSize() const
|
||||||
|
{
|
||||||
|
if (!m_ondemand_load)
|
||||||
{
|
{
|
||||||
m_size_lock.lock();
|
m_size_lock.lock();
|
||||||
m_size_lock.unlock();
|
m_size_lock.unlock();
|
||||||
|
}
|
||||||
return m_orig_size;
|
return m_orig_size;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual const core::dimension2d<u32>& getSize() const
|
virtual const core::dimension2d<u32>& getSize() const
|
||||||
|
{
|
||||||
|
if (!m_ondemand_load)
|
||||||
{
|
{
|
||||||
m_size_lock.lock();
|
m_size_lock.lock();
|
||||||
m_size_lock.unlock();
|
m_size_lock.unlock();
|
||||||
|
}
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -139,16 +173,27 @@ public:
|
|||||||
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
|
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual u64 getTextureHandler() const
|
virtual u64 getTextureHandler() const
|
||||||
|
{
|
||||||
|
if (!m_ondemand_load)
|
||||||
{
|
{
|
||||||
m_image_view_lock.lock();
|
m_image_view_lock.lock();
|
||||||
m_image_view_lock.unlock();
|
m_image_view_lock.unlock();
|
||||||
return m_image_view ? (u64)*(m_image_view.get()) : 0;
|
return m_image_view ? (u64)(m_image_view.get()->load()) : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto image_view = getImageViewLive();
|
||||||
|
return (u64)(image_view.get()->load());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual unsigned int getTextureSize() const
|
virtual unsigned int getTextureSize() const
|
||||||
|
{
|
||||||
|
if (!m_ondemand_load)
|
||||||
{
|
{
|
||||||
m_image_view_lock.lock();
|
m_image_view_lock.lock();
|
||||||
m_image_view_lock.unlock();
|
m_image_view_lock.unlock();
|
||||||
|
}
|
||||||
return m_texture_size;
|
return m_texture_size;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -157,12 +202,17 @@ public:
|
|||||||
virtual void updateTexture(void* data, irr::video::ECOLOR_FORMAT format,
|
virtual void updateTexture(void* data, irr::video::ECOLOR_FORMAT format,
|
||||||
u32 w, u32 h, u32 x, u32 y);
|
u32 w, u32 h, u32 x, u32 y);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual std::shared_ptr<VkImageView> getImageView() const
|
virtual std::shared_ptr<std::atomic<VkImageView> > getImageView() const
|
||||||
|
{
|
||||||
|
if (!m_ondemand_load)
|
||||||
{
|
{
|
||||||
m_image_view_lock.lock();
|
m_image_view_lock.lock();
|
||||||
m_image_view_lock.unlock();
|
m_image_view_lock.unlock();
|
||||||
return m_image_view;
|
return m_image_view;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return getImageViewLive();
|
||||||
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
VkFormat getInternalFormat() const { return m_internal_format; }
|
VkFormat getInternalFormat() const { return m_internal_format; }
|
||||||
}; // GEVulkanTexture
|
}; // GEVulkanTexture
|
||||||
|
@ -131,9 +131,9 @@ void GEVulkanTextureDescriptor::updateDescriptor()
|
|||||||
VkDescriptorImageInfo info;
|
VkDescriptorImageInfo info;
|
||||||
info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
info.sampler = m_vk->getSampler(m_sampler_use);
|
info.sampler = m_vk->getSampler(m_sampler_use);
|
||||||
info.imageView = *(p.first[i].get());
|
info.imageView = p.first[i].get()->load();
|
||||||
if (info.imageView == VK_NULL_HANDLE)
|
if (info.imageView == VK_NULL_HANDLE)
|
||||||
info.imageView = *m_transparent_image.get();
|
info.imageView = m_transparent_image.get()->load();
|
||||||
image_infos[p.second * m_max_layer + i] = info;
|
image_infos[p.second * m_max_layer + i] = info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ void GEVulkanTextureDescriptor::updateDescriptor()
|
|||||||
{
|
{
|
||||||
VkDescriptorImageInfo dummy_info;
|
VkDescriptorImageInfo dummy_info;
|
||||||
dummy_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
dummy_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
dummy_info.imageView = *m_transparent_image.get();
|
dummy_info.imageView = m_transparent_image.get()->load();
|
||||||
dummy_info.sampler = m_vk->getSampler(m_sampler_use);
|
dummy_info.sampler = m_vk->getSampler(m_sampler_use);
|
||||||
image_infos.resize(m_max_texture_list * m_max_layer, dummy_info);
|
image_infos.resize(m_max_texture_list * m_max_layer, dummy_info);
|
||||||
}
|
}
|
||||||
|
@ -1298,13 +1298,19 @@ IImage* CNullDriver::createImageFromFile(io::IReadFile* file, video::IImageLoade
|
|||||||
{
|
{
|
||||||
if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
|
if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
|
||||||
{
|
{
|
||||||
|
// reset file position which might have changed due to previous loadImage calls
|
||||||
|
file->seek(0);
|
||||||
if (loader)
|
if (loader)
|
||||||
{
|
{
|
||||||
|
if (SurfaceLoader[i]->isALoadableFileFormat(file))
|
||||||
|
{
|
||||||
|
file->seek(0);
|
||||||
*loader = SurfaceLoader[i];
|
*loader = SurfaceLoader[i];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// reset file position which might have changed due to previous loadImage calls
|
else
|
||||||
file->seek(0);
|
continue;
|
||||||
|
}
|
||||||
image = SurfaceLoader[i]->loadImage(file);
|
image = SurfaceLoader[i]->loadImage(file);
|
||||||
if (image)
|
if (image)
|
||||||
return image;
|
return image;
|
||||||
@ -1318,12 +1324,12 @@ IImage* CNullDriver::createImageFromFile(io::IReadFile* file, video::IImageLoade
|
|||||||
file->seek(0);
|
file->seek(0);
|
||||||
if (SurfaceLoader[i]->isALoadableFileFormat(file))
|
if (SurfaceLoader[i]->isALoadableFileFormat(file))
|
||||||
{
|
{
|
||||||
|
file->seek(0);
|
||||||
if (loader)
|
if (loader)
|
||||||
{
|
{
|
||||||
*loader = SurfaceLoader[i];
|
*loader = SurfaceLoader[i];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
file->seek(0);
|
|
||||||
image = SurfaceLoader[i]->loadImage(file);
|
image = SurfaceLoader[i]->loadImage(file);
|
||||||
if (image)
|
if (image)
|
||||||
return image;
|
return image;
|
||||||
|
Loading…
Reference in New Issue
Block a user