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()
.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
// ----------------------------------------------------------------------------
@ -69,6 +79,9 @@ GEVulkanTexture::GEVulkanTexture(const std::string& name, unsigned int size,
// ----------------------------------------------------------------------------
GEVulkanTexture::~GEVulkanTexture()
{
m_image_view_lock.lock();
m_image_view_lock.unlock();
vkDeviceWaitIdle(m_vulkan_device);
clearVulkanData();
} // ~GEVulkanTexture
@ -349,14 +362,21 @@ void GEVulkanTexture::reloadInternal()
return;
clearVulkanData();
video::IImage* texture_image = getResizedImage(NamedPath.getPtr(),
m_max_size, &m_orig_size);
if (texture_image == NULL)
io::IReadFile* file = io::createReadFile(m_full_path);
if (file == NULL)
{
LoadingFailed = true;
return;
// We checked for file existence so we should always get a file
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_lock.unlock();
if (m_image_mani)
m_image_mani(texture_image);
@ -364,6 +384,8 @@ void GEVulkanTexture::reloadInternal()
uint8_t* data = (uint8_t*)texture_image->lock();
bgraConversion(data);
upload(data);
m_image_view_lock.unlock();
texture_image->unlock();
texture_image->drop();
} // reloadInternal
@ -404,6 +426,9 @@ void* GEVulkanTexture::lock(video::E_TEXTURE_LOCK_MODE mode, u32 mipmap_level)
// ----------------------------------------------------------------------------
uint8_t* GEVulkanTexture::getTextureData()
{
m_image_view_lock.lock();
m_image_view_lock.unlock();
VkBuffer buffer;
VkDeviceMemory buffer_memory;
VkDeviceSize image_size =
@ -462,6 +487,9 @@ cleanup:
void GEVulkanTexture::updateTexture(void* data, video::ECOLOR_FORMAT format,
u32 w, u32 h, u32 x, u32 y)
{
m_image_view_lock.lock();
m_image_view_lock.unlock();
VkBuffer staging_buffer;
VkDeviceMemory staging_buffer_memory;
if (m_single_channel)
@ -555,4 +583,20 @@ void GEVulkanTexture::bgraConversion(uint8_t* img_data)
}
} // 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 "ge_spin_lock.hpp"
#include <functional>
#include <string>
#include <ITexture.h>
@ -34,6 +36,12 @@ private:
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);
// ------------------------------------------------------------------------
@ -83,9 +91,18 @@ public:
}
// ------------------------------------------------------------------------
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
{ return video::EDT_VULKAN; }
@ -99,16 +116,22 @@ public:
// ------------------------------------------------------------------------
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 u64 getTextureHandler() const
{
vkDeviceWaitIdle(m_vulkan_device);
reloadInternal();
m_image_view_lock.lock();
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,
u32 w, u32 h, u32 x, u32 y);
}; // GEVulkanTexture