Add ondemand texture loading for vulkan

This commit is contained in:
Benau 2022-08-12 13:07:53 +08:00
parent eace871c66
commit e0636495f0
9 changed files with 229 additions and 69 deletions

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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();

View File

@ -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)
if (texture_image == NULL)
{ {
throw std::runtime_error( texture_image = getResizedImageFullPath(m_full_path, m_max_size,
"Missing texture_image in getResizedImageFullPath"); 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)
{
throw std::runtime_error(
"Missing texture_image in getResizedImageFullPath");
}
m_size = texture_image->getDimension();
if (m_size.Width < 4 || m_size.Height < 4)
m_has_mipmaps = false;
} }
m_size = texture_image->getDimension();
if (m_size.Width < 4 || m_size.Height < 4)
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
} }

View File

@ -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,
@ -114,15 +142,21 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getOriginalSize() const virtual const core::dimension2d<u32>& getOriginalSize() const
{ {
m_size_lock.lock(); if (!m_ondemand_load)
m_size_lock.unlock(); {
m_size_lock.lock();
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
{ {
m_size_lock.lock(); if (!m_ondemand_load)
m_size_lock.unlock(); {
m_size_lock.lock();
m_size_lock.unlock();
}
return m_size; return m_size;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -140,15 +174,26 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual u64 getTextureHandler() const virtual u64 getTextureHandler() const
{ {
m_image_view_lock.lock(); if (!m_ondemand_load)
m_image_view_lock.unlock(); {
return m_image_view ? (u64)*(m_image_view.get()) : 0; m_image_view_lock.lock();
m_image_view_lock.unlock();
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
{ {
m_image_view_lock.lock(); if (!m_ondemand_load)
m_image_view_lock.unlock(); {
m_image_view_lock.lock();
m_image_view_lock.unlock();
}
return m_texture_size; return m_texture_size;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -157,11 +202,16 @@ 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
{ {
m_image_view_lock.lock(); if (!m_ondemand_load)
m_image_view_lock.unlock(); {
return m_image_view; m_image_view_lock.lock();
m_image_view_lock.unlock();
return m_image_view;
}
else
return getImageViewLive();
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
VkFormat getInternalFormat() const { return m_internal_format; } VkFormat getInternalFormat() const { return m_internal_format; }

View File

@ -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);
} }

View File

@ -1298,13 +1298,19 @@ IImage* CNullDriver::createImageFromFile(io::IReadFile* file, video::IImageLoade
{ {
if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName())) if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
{ {
if (loader)
{
*loader = SurfaceLoader[i];
return 0;
}
// reset file position which might have changed due to previous loadImage calls // reset file position which might have changed due to previous loadImage calls
file->seek(0); file->seek(0);
if (loader)
{
if (SurfaceLoader[i]->isALoadableFileFormat(file))
{
file->seek(0);
*loader = SurfaceLoader[i];
return 0;
}
else
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;