Add multithreading GEVulkanTexture loading

This commit is contained in:
Benau 2022-04-18 12:16:27 +08:00
parent 059fc9ebfd
commit 5d23d8d790
3 changed files with 96 additions and 15 deletions

View File

@ -0,0 +1,14 @@
#ifndef HEADER_GE_SPIN_LOCK_HPP
#define HEADER_GE_SPIN_LOCK_HPP
#include <atomic>
class GESpinLock
{
mutable std::atomic_flag m_locked = ATOMIC_FLAG_INIT;
public:
void lock() const
{ while (m_locked.test_and_set(std::memory_order_acquire)); }
void unlock() const { m_locked.clear(std::memory_order_release); }
};
#endif

View File

@ -23,7 +23,17 @@ GEVulkanTexture::GEVulkanTexture(const std::string& path,
{ {
m_max_size = getDriver()->getDriverAttributes() m_max_size = getDriver()->getDriverAttributes()
.getAttributeAsDimension2d("MAX_TEXTURE_SIZE"); .getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
reloadInternal(); m_full_path = getDriver()->getFileSystem()->getAbsolutePath(NamedPath);
if (!getDriver()->getFileSystem()->existFileOnly(m_full_path))
{
LoadingFailed = true;
return;
}
m_size_lock.lock();
m_image_view_lock.lock();
GEVulkanCommandLoader::addMultiThreadingCommand(
std::bind(&GEVulkanTexture::reloadInternal, this));
} // GEVulkanTexture } // GEVulkanTexture
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -69,6 +79,9 @@ GEVulkanTexture::GEVulkanTexture(const std::string& name, unsigned int size,
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
GEVulkanTexture::~GEVulkanTexture() GEVulkanTexture::~GEVulkanTexture()
{ {
m_image_view_lock.lock();
m_image_view_lock.unlock();
vkDeviceWaitIdle(m_vulkan_device); vkDeviceWaitIdle(m_vulkan_device);
clearVulkanData(); clearVulkanData();
} // ~GEVulkanTexture } // ~GEVulkanTexture
@ -349,14 +362,21 @@ void GEVulkanTexture::reloadInternal()
return; return;
clearVulkanData(); clearVulkanData();
video::IImage* texture_image = getResizedImage(NamedPath.getPtr(),
m_max_size, &m_orig_size); io::IReadFile* file = io::createReadFile(m_full_path);
if (texture_image == NULL) if (file == NULL)
{ {
LoadingFailed = true; // We checked for file existence so we should always get a file
return; throw std::runtime_error("File missing in getResizedImage");
} }
video::IImage* texture_image = getResizedImage(file, m_max_size,
&m_orig_size);
if (texture_image == NULL)
throw std::runtime_error("Missing texture_image in getResizedImage");
file->drop();
m_size = texture_image->getDimension(); m_size = texture_image->getDimension();
m_size_lock.unlock();
if (m_image_mani) if (m_image_mani)
m_image_mani(texture_image); m_image_mani(texture_image);
@ -364,6 +384,8 @@ void GEVulkanTexture::reloadInternal()
uint8_t* data = (uint8_t*)texture_image->lock(); uint8_t* data = (uint8_t*)texture_image->lock();
bgraConversion(data); bgraConversion(data);
upload(data); upload(data);
m_image_view_lock.unlock();
texture_image->unlock(); texture_image->unlock();
texture_image->drop(); texture_image->drop();
} // reloadInternal } // reloadInternal
@ -404,6 +426,9 @@ void* GEVulkanTexture::lock(video::E_TEXTURE_LOCK_MODE mode, u32 mipmap_level)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
uint8_t* GEVulkanTexture::getTextureData() uint8_t* GEVulkanTexture::getTextureData()
{ {
m_image_view_lock.lock();
m_image_view_lock.unlock();
VkBuffer buffer; VkBuffer buffer;
VkDeviceMemory buffer_memory; VkDeviceMemory buffer_memory;
VkDeviceSize image_size = VkDeviceSize image_size =
@ -462,6 +487,9 @@ 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();
m_image_view_lock.unlock();
VkBuffer staging_buffer; VkBuffer staging_buffer;
VkDeviceMemory staging_buffer_memory; VkDeviceMemory staging_buffer_memory;
if (m_single_channel) if (m_single_channel)
@ -555,4 +583,20 @@ void GEVulkanTexture::bgraConversion(uint8_t* img_data)
} }
} // bgraConversion } // bgraConversion
//-----------------------------------------------------------------------------
void GEVulkanTexture::reload()
{
m_image_view_lock.lock();
m_image_view_lock.unlock();
vkDeviceWaitIdle(m_vulkan_device);
if (!m_disable_reload)
{
m_size_lock.lock();
m_image_view_lock.lock();
GEVulkanCommandLoader::addMultiThreadingCommand(
std::bind(&GEVulkanTexture::reloadInternal, this));
}
} // reload
} }

View File

@ -3,6 +3,8 @@
#include "vulkan_wrapper.h" #include "vulkan_wrapper.h"
#include "ge_spin_lock.hpp"
#include <functional> #include <functional>
#include <string> #include <string>
#include <ITexture.h> #include <ITexture.h>
@ -34,6 +36,12 @@ private:
const bool m_single_channel; const bool m_single_channel;
GESpinLock m_size_lock;
GESpinLock m_image_view_lock;
io::path m_full_path;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool createTextureImage(uint8_t* texture_data); bool createTextureImage(uint8_t* texture_data);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -83,9 +91,18 @@ public:
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getOriginalSize() const virtual const core::dimension2d<u32>& getOriginalSize() const
{ return m_orig_size; } {
m_size_lock.lock();
m_size_lock.unlock();
return m_orig_size;
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getSize() const { return m_size; } virtual const core::dimension2d<u32>& getSize() const
{
m_size_lock.lock();
m_size_lock.unlock();
return m_size;
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual video::E_DRIVER_TYPE getDriverType() const virtual video::E_DRIVER_TYPE getDriverType() const
{ return video::EDT_VULKAN; } { return video::EDT_VULKAN; }
@ -99,16 +116,22 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {} virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual u64 getTextureHandler() const { return (u64)m_image_view; } virtual u64 getTextureHandler() const
// ------------------------------------------------------------------------
virtual unsigned int getTextureSize() const { return m_texture_size; }
// ------------------------------------------------------------------------
virtual void reload()
{ {
vkDeviceWaitIdle(m_vulkan_device); m_image_view_lock.lock();
reloadInternal(); m_image_view_lock.unlock();
return (u64)m_image_view;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual unsigned int getTextureSize() const
{
m_image_view_lock.lock();
m_image_view_lock.unlock();
return m_texture_size;
}
// ------------------------------------------------------------------------
virtual void reload();
// ------------------------------------------------------------------------
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);
}; // GEVulkanTexture }; // GEVulkanTexture