AsynchronousVk.h#
↰ Parent directory (Vulkan
)
Contains a futures system for asynchronous loading of resources into Vulkan.
Includes#
PVRCore/Threading.h
PVRCore/texture/Texture.h
PVRCore/texture/TextureLoadAsync.h
PVRUtils/Vulkan/HelperVk.h
PVRVk/ImageVk.h
Included By#
Namespaces#
Classes#
Functions#
Typedefs#
Source Code#
#pragma once
#include "PVRCore/Threading.h"
#include "PVRCore/texture/Texture.h"
#include "PVRCore/texture/TextureLoadAsync.h"
#include "PVRVk/ImageVk.h"
#include "PVRUtils/Vulkan/HelperVk.h"
namespace pvr {
namespace utils {
typedef std::shared_ptr<Texture> TexturePtr;
typedef std::shared_ptr<async::IFrameworkAsyncResult<TexturePtr>> AsyncTexture;
typedef std::shared_ptr<async::IFrameworkAsyncResult<pvrvk::ImageView>> AsyncApiTexture;
struct ImageUploadFuture_ : public async::IFrameworkAsyncResult<pvrvk::ImageView>, public std::enable_shared_from_this<ImageUploadFuture_>
{
public:
typedef IFrameworkAsyncResult<pvrvk::ImageView>::Callback CallbackType;
ImageUploadFuture_() {}
pvrvk::Queue _queue;
pvrvk::Device _device;
AsyncTexture _texture;
pvrvk::CommandPool _cmdPool;
async::Mutex* _cmdQueueMutex;
bool _allowDecompress;
mutable async::SemaphorePtr _resultSemaphore;
bool _callbackBeforeSignal = false;
void setCallBack(CallbackType callback) { setTheCallback(callback); }
void loadNow()
{
_result = customUploadImage();
_successful = _result != nullptr;
if (_callbackBeforeSignal)
{
callBack();
_resultSemaphore->signal();
}
else
{
_resultSemaphore->signal();
callBack();
}
}
const pvrvk::ImageView& getResult() { return _result; }
private:
pvrvk::ImageView customUploadImage()
{
Texture& assetTexture = *_texture->get();
pvrvk::CommandBuffer cmdBuffer = _cmdPool->allocateCommandBuffer();
cmdBuffer->begin();
pvrvk::ImageView results = uploadImageAndView(_device, assetTexture, _allowDecompress, cmdBuffer);
cmdBuffer->end();
pvrvk::SubmitInfo submitInfo;
submitInfo.commandBuffers = &cmdBuffer;
submitInfo.numCommandBuffers = 1;
pvrvk::Fence fence = _device->createFence();
if (_cmdQueueMutex != nullptr)
{
std::lock_guard<pvr::async::Mutex> lock(*_cmdQueueMutex);
_queue->submit(&submitInfo, 1, fence);
}
else
{
_queue->submit(&submitInfo, 1, fence);
}
fence->wait();
return results;
}
void callBack() { executeCallBack(shared_from_this()); }
pvrvk::ImageView _result;
pvrvk::ImageView get_() const
{
if (!_inCallback)
{
_resultSemaphore->wait();
_resultSemaphore->signal();
}
return _result;
}
pvrvk::ImageView getNoWait() const { return _result; }
bool isComplete_() const
{
if (_resultSemaphore->tryWait())
{
_resultSemaphore->signal();
return true;
}
return false;
}
void cleanup_() {}
void destroyObject() {}
};
typedef std::shared_ptr<ImageUploadFuture_> ImageUploadFuture;
inline void imageUploadAsyncWorker(ImageUploadFuture uploadFuture) { uploadFuture->loadNow(); }
class ImageApiAsyncUploader : public async::AsyncScheduler<pvrvk::ImageView, ImageUploadFuture, imageUploadAsyncWorker>
{
private:
pvrvk::Device _device;
pvrvk::Queue _queueVk;
pvrvk::CommandPool _cmdPool;
async::Mutex* _cmdQueueMutex;
public:
ImageApiAsyncUploader() : _cmdQueueMutex(nullptr) { _myInfo = "ImageApiAsyncUploader"; }
typedef async::IFrameworkAsyncResult<pvrvk::ImageView>::Callback CallbackType;
void init(pvrvk::Device& device, pvrvk::Queue& queue, async::Mutex* queueSemaphore = nullptr)
{
_device = device;
_queueVk = queue;
_cmdPool = device->createCommandPool(pvrvk::CommandPoolCreateInfo(queue->getFamilyIndex(), pvrvk::CommandPoolCreateFlags::e_RESET_COMMAND_BUFFER_BIT));
_cmdQueueMutex = queueSemaphore;
}
AsyncApiTexture uploadTextureAsync(const AsyncTexture& texture, bool allowDecompress = true, CallbackType callback = nullptr, bool callbackBeforeSignal = false)
{
assertion(_queueVk != nullptr, "Queue has not been initialized");
auto future = std::make_shared<ImageUploadFuture_>();
auto& params = *future;
params._allowDecompress = allowDecompress;
params._queue = _queueVk;
params._device = _device;
params._texture = texture;
params._resultSemaphore = std::make_shared<async::Semaphore>();
params._cmdPool = _cmdPool;
params.setCallBack(callback);
params._callbackBeforeSignal = callbackBeforeSignal;
params._cmdQueueMutex = _cmdQueueMutex;
_queueSemaphore.wait();
_queue.emplace_back(future);
_queueSemaphore.signal();
_workSemaphore.signal();
return future;
}
};
} // namespace utils
} // namespace pvr