pooled shared ptr (#1316)
This commit is contained in:
@@ -554,7 +554,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
if (shaderdump_enabled)
|
||||
{
|
||||
auto vec = std::make_shared<std::vector<uint8_t>>();
|
||||
auto vec = wi::allocator::make_shared<std::vector<uint8_t>>();
|
||||
|
||||
if (wi::helper::FileRead(shaderbinaryfilename, *vec))
|
||||
{
|
||||
@@ -566,7 +566,8 @@ int main(int argc, char* argv[])
|
||||
std::cout << "up-to-date: " << shaderbinaryfilename << std::endl;
|
||||
locker.unlock();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
locker.lock();
|
||||
std::cerr << "ERROR reading binary shader: " << shaderbinaryfilename << std::endl;
|
||||
locker.unlock();
|
||||
|
||||
+282
-2
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "CommonInclude.h"
|
||||
#include "wiVector.h"
|
||||
#include "wiSpinLock.h"
|
||||
|
||||
#include "Utility/offsetAllocator.hpp"
|
||||
|
||||
@@ -182,7 +183,7 @@ namespace wi::allocator
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
void operator=(const Allocation& other)
|
||||
Allocation& operator=(const Allocation& other)
|
||||
{
|
||||
Reset();
|
||||
allocator = other.allocator;
|
||||
@@ -192,8 +193,9 @@ namespace wi::allocator
|
||||
{
|
||||
internal_state->refcount.fetch_add(1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void operator=(Allocation&& other) noexcept
|
||||
Allocation& operator=(Allocation&& other) noexcept
|
||||
{
|
||||
Reset();
|
||||
allocator = std::move(other.allocator);
|
||||
@@ -202,6 +204,7 @@ namespace wi::allocator
|
||||
other.allocator = nullptr;
|
||||
other.internal_state = nullptr;
|
||||
other.byte_offset = ~0ull;
|
||||
return *this;
|
||||
}
|
||||
void Reset()
|
||||
{
|
||||
@@ -253,4 +256,281 @@ namespace wi::allocator
|
||||
return allocator->allocator.storageReport().totalFreeSpace == page_count;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Interface for allocating pooled shared_ptr
|
||||
struct SharedBlockAllocator
|
||||
{
|
||||
virtual void init_refcount(void* ptr) = 0;
|
||||
virtual uint32_t get_refcount(void* ptr) = 0;
|
||||
virtual uint32_t inc_refcount(void* ptr) = 0;
|
||||
virtual uint32_t dec_refcount(void* ptr) = 0;
|
||||
virtual uint32_t get_refcount_weak(void* ptr) = 0;
|
||||
virtual uint32_t inc_refcount_weak(void* ptr) = 0;
|
||||
virtual uint32_t dec_refcount_weak(void* ptr) = 0;
|
||||
};
|
||||
|
||||
// The per-type block allocators can be indexed with bottom 8 bits of the shared_ptr's handle:
|
||||
inline SharedBlockAllocator* block_allocators[256] = {};
|
||||
inline std::atomic<uint8_t> next_allocator_id{ 0 };
|
||||
inline uint8_t register_shared_block_allocator(SharedBlockAllocator* allocator)
|
||||
{
|
||||
uint8_t id = next_allocator_id.fetch_add(1);
|
||||
assert(id < arraysize(block_allocators));
|
||||
block_allocators[id] = allocator;
|
||||
return id;
|
||||
}
|
||||
inline uint8_t get_shared_block_allocator_count() { return next_allocator_id.load(); }
|
||||
|
||||
// Shared ptr using a block allocation strategy, refcounted, thread-safe, reduced size using single uint64_t handle
|
||||
// This makes it easy to swap-out std::shared_ptr, but not feature complete, only has minimal feature set
|
||||
// Use this if you require many object of the same type, their memory allocation will be pooled
|
||||
// If you require just a single object, it will be better to use std::shared_ptr instead
|
||||
template<typename T>
|
||||
struct shared_ptr
|
||||
{
|
||||
uint64_t handle = 0;
|
||||
|
||||
constexpr bool IsValid() const { return handle != 0; }
|
||||
|
||||
constexpr T* get_ptr() const { return (T*)(handle & (~0ull << 8ull)); }
|
||||
constexpr SharedBlockAllocator* get_allocator() const { return block_allocators[handle & 0xFF]; }
|
||||
|
||||
constexpr T* operator->() const { return get_ptr(); }
|
||||
constexpr operator T* () const { return get_ptr(); }
|
||||
constexpr T* get() const { return get_ptr(); }
|
||||
|
||||
template<typename U>
|
||||
operator shared_ptr<U>& () const { return *(shared_ptr<U>*)this; }
|
||||
|
||||
shared_ptr() = default;
|
||||
shared_ptr(const shared_ptr& other) { copy(other); }
|
||||
shared_ptr(shared_ptr&& other) noexcept { move(other); }
|
||||
~shared_ptr() noexcept { reset(); }
|
||||
shared_ptr& operator=(const shared_ptr& other) { copy(other); return *this; }
|
||||
shared_ptr& operator=(shared_ptr&& other) noexcept { move(other); return *this; }
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
get_allocator()->dec_refcount(get_ptr());
|
||||
}
|
||||
handle = 0;
|
||||
}
|
||||
void copy(const shared_ptr& other)
|
||||
{
|
||||
reset();
|
||||
handle = other.handle;
|
||||
if (IsValid())
|
||||
{
|
||||
get_allocator()->inc_refcount(get_ptr());
|
||||
}
|
||||
}
|
||||
void move(shared_ptr& other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return;
|
||||
reset();
|
||||
handle = other.handle;
|
||||
other.handle = 0;
|
||||
}
|
||||
uint32_t use_count() const { return IsValid() ? get_allocator()->get_refcount(get_ptr()) : 0; }
|
||||
};
|
||||
|
||||
// Similar to std::weak_ptr but works with the shared block allocator, and reduced feature set
|
||||
template<typename T>
|
||||
struct weak_ptr
|
||||
{
|
||||
uint64_t handle = 0;
|
||||
|
||||
constexpr bool IsValid() const { return handle != 0; }
|
||||
|
||||
constexpr T* get_ptr() const { return (T*)(handle & (~0ull << 8ull)); }
|
||||
constexpr SharedBlockAllocator* get_allocator() const { return block_allocators[handle & 0xFF]; }
|
||||
|
||||
template<typename U>
|
||||
operator weak_ptr<U>& () const { return *(weak_ptr<U>*)this; }
|
||||
|
||||
weak_ptr() = default;
|
||||
weak_ptr(const weak_ptr& other) { copy(other); }
|
||||
weak_ptr(weak_ptr&& other) noexcept { move(other); }
|
||||
~weak_ptr() noexcept { reset(); }
|
||||
weak_ptr& operator=(const weak_ptr& other) { copy(other); return *this; }
|
||||
weak_ptr& operator=(weak_ptr&& other) noexcept { move(other); return *this; }
|
||||
|
||||
weak_ptr(const shared_ptr<T>& other)
|
||||
{
|
||||
reset();
|
||||
handle = other.handle;
|
||||
if (IsValid())
|
||||
{
|
||||
get_allocator()->inc_refcount_weak(get_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<T> lock()
|
||||
{
|
||||
if (!IsValid())
|
||||
return {};
|
||||
|
||||
SharedBlockAllocator* alloc = get_allocator();
|
||||
T* ptr = get_ptr();
|
||||
|
||||
uint32_t old_strong = alloc->inc_refcount(ptr);
|
||||
if (old_strong == 0)
|
||||
{
|
||||
alloc->dec_refcount(ptr); // undo refcount
|
||||
return {};
|
||||
}
|
||||
|
||||
shared_ptr<T> ret;
|
||||
ret.handle = handle;
|
||||
return ret; // Already incremented refcount
|
||||
}
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
get_allocator()->dec_refcount_weak(get_ptr());
|
||||
}
|
||||
handle = 0;
|
||||
}
|
||||
void copy(const weak_ptr& other)
|
||||
{
|
||||
reset();
|
||||
handle = other.handle;
|
||||
if (IsValid())
|
||||
{
|
||||
get_allocator()->inc_refcount_weak(get_ptr());
|
||||
}
|
||||
}
|
||||
void move(weak_ptr& other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return;
|
||||
reset();
|
||||
handle = other.handle;
|
||||
other.handle = 0;
|
||||
}
|
||||
uint32_t use_count() const { return get_allocator()->get_refcount(get_ptr()); }
|
||||
bool expired() const noexcept
|
||||
{
|
||||
return !IsValid() || use_count() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Implementation of a thread-safe refcounted block allocator
|
||||
template<typename T, size_t block_size = 256>
|
||||
struct SharedBlockAllocatorImpl final : public SharedBlockAllocator
|
||||
{
|
||||
const uint8_t allocator_id = register_shared_block_allocator(this);
|
||||
|
||||
struct alignas(std::max(size_t(256), alignof(T))) RawStruct // 256 alignment is used at least because I use bottom 8 bits of pointer as allocator id
|
||||
{
|
||||
uint8_t data[sizeof(T)];
|
||||
std::atomic<uint32_t> refcount;
|
||||
std::atomic<uint32_t> refcount_weak;
|
||||
};
|
||||
static_assert(offsetof(RawStruct, data) == 0); // we assume that data is located at 0 when casting ptr to T*, this avoids having to do a function call that would return T* like the refcounts
|
||||
|
||||
struct Block
|
||||
{
|
||||
std::unique_ptr<RawStruct[]> mem;
|
||||
};
|
||||
wi::vector<Block> blocks;
|
||||
wi::vector<RawStruct*> free_list;
|
||||
//std::mutex locker;
|
||||
wi::SpinLock locker;
|
||||
|
||||
template<typename... ARG>
|
||||
inline shared_ptr<T> allocate(ARG&&... args)
|
||||
{
|
||||
locker.lock();
|
||||
if (free_list.empty())
|
||||
{
|
||||
Block& block = blocks.emplace_back();
|
||||
block.mem.reset(new RawStruct[block_size]);
|
||||
RawStruct* ptr = block.mem.get();
|
||||
free_list.reserve(block_size);
|
||||
for (size_t i = 0; i < block_size; ++i)
|
||||
{
|
||||
free_list.push_back(ptr + i);
|
||||
}
|
||||
}
|
||||
RawStruct* ptr = free_list.back();
|
||||
assert((uint64_t)ptr == ((uint64_t)ptr & (~0ull << 8ull))); // The pointer lower 8 bits must be 0, it will be used as allocator index
|
||||
free_list.pop_back();
|
||||
locker.unlock();
|
||||
|
||||
// Construction can be outside of lock, this structure wasn't shared yet:
|
||||
new (ptr) T(std::forward<ARG>(args)...);
|
||||
init_refcount(ptr);
|
||||
shared_ptr<T> allocation;
|
||||
allocation.handle = uint64_t(ptr) | uint64_t(allocator_id);
|
||||
return allocation;
|
||||
}
|
||||
|
||||
void reclaim(void* ptr)
|
||||
{
|
||||
std::scoped_lock lck(locker);
|
||||
free_list.push_back((RawStruct*)ptr);
|
||||
}
|
||||
|
||||
void init_refcount(void* ptr) override
|
||||
{
|
||||
static_cast<RawStruct*>(ptr)->refcount.store(1, std::memory_order_relaxed);
|
||||
static_cast<RawStruct*>(ptr)->refcount_weak.store(1, std::memory_order_relaxed);
|
||||
}
|
||||
uint32_t get_refcount(void* ptr) override
|
||||
{
|
||||
return static_cast<RawStruct*>(ptr)->refcount.load(std::memory_order_acquire);
|
||||
}
|
||||
uint32_t inc_refcount(void* ptr) override
|
||||
{
|
||||
return static_cast<RawStruct*>(ptr)->refcount.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
uint32_t dec_refcount(void* ptr) override
|
||||
{
|
||||
uint32_t old = static_cast<RawStruct*>(ptr)->refcount.fetch_sub(1, std::memory_order_acq_rel);
|
||||
if (old == 1)
|
||||
{
|
||||
static_cast<T*>(ptr)->~T();
|
||||
dec_refcount_weak(ptr);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
uint32_t get_refcount_weak(void* ptr) override
|
||||
{
|
||||
return static_cast<RawStruct*>(ptr)->refcount_weak.load(std::memory_order_acquire);
|
||||
}
|
||||
uint32_t inc_refcount_weak(void* ptr) override
|
||||
{
|
||||
return static_cast<RawStruct*>(ptr)->refcount_weak.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
uint32_t dec_refcount_weak(void* ptr) override
|
||||
{
|
||||
uint32_t old = static_cast<RawStruct*>(ptr)->refcount_weak.fetch_sub(1, std::memory_order_acq_rel);
|
||||
if (old == 1)
|
||||
{
|
||||
reclaim(ptr);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
};
|
||||
|
||||
// The allocators are global intentionally, this avoids runtime construction, guard check
|
||||
template<typename T, size_t block_size = 256>
|
||||
inline static SharedBlockAllocatorImpl<T, block_size>* shared_block_allocator = new SharedBlockAllocatorImpl<T, block_size>; // only destroyed after program exit, never earlier
|
||||
|
||||
// Create a new shared pooled object:
|
||||
template<typename T, size_t block_size = 256, typename... ARG>
|
||||
inline shared_ptr<T> make_shared(ARG&&... args)
|
||||
{
|
||||
return shared_block_allocator<T, block_size>->allocate(std::forward<ARG>(args)...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace wi::audio
|
||||
struct SoundInstanceInternal : public IXAudio2VoiceCallback
|
||||
{
|
||||
std::shared_ptr<AudioInternal> audio;
|
||||
std::shared_ptr<SoundInternal> soundinternal;
|
||||
wi::allocator::shared_ptr<SoundInternal> soundinternal;
|
||||
IXAudio2SourceVoice* sourceVoice = nullptr;
|
||||
XAUDIO2_VOICE_DETAILS voiceDetails = {};
|
||||
wi::vector<float> outputMatrix;
|
||||
@@ -352,7 +352,7 @@ namespace wi::audio
|
||||
{
|
||||
if (audio_internal == nullptr || !audio_internal->IsValid())
|
||||
return false;
|
||||
std::shared_ptr<SoundInternal> soundinternal = std::make_shared<SoundInternal>();
|
||||
auto soundinternal = wi::allocator::make_shared<SoundInternal>();
|
||||
soundinternal->audio = audio_internal;
|
||||
sound->internal_state = soundinternal;
|
||||
|
||||
@@ -429,8 +429,8 @@ namespace wi::audio
|
||||
if (sound == nullptr || !sound->IsValid())
|
||||
return false;
|
||||
HRESULT hr;
|
||||
const auto& soundinternal = std::static_pointer_cast<SoundInternal>(sound->internal_state);
|
||||
std::shared_ptr<SoundInstanceInternal> instanceinternal = std::make_shared<SoundInstanceInternal>();
|
||||
auto soundinternal = wi::allocator::shared_ptr<SoundInternal>(sound->internal_state);
|
||||
auto instanceinternal = wi::allocator::make_shared<SoundInstanceInternal>();
|
||||
instance->internal_state = instanceinternal;
|
||||
|
||||
instanceinternal->audio = audio_internal;
|
||||
@@ -893,7 +893,7 @@ namespace wi::audio
|
||||
};
|
||||
struct SoundInstanceInternal{
|
||||
std::shared_ptr<AudioInternal> audio;
|
||||
std::shared_ptr<SoundInternal> soundinternal;
|
||||
wi::allocator::shared_ptr<SoundInternal> soundinternal;
|
||||
FAudioSourceVoice* sourceVoice = nullptr;
|
||||
FAudioVoiceDetails voiceDetails = {};
|
||||
wi::vector<float> outputMatrix;
|
||||
@@ -979,7 +979,7 @@ namespace wi::audio
|
||||
{
|
||||
if (audio_internal == nullptr || !audio_internal->IsValid())
|
||||
return false;
|
||||
std::shared_ptr<SoundInternal> soundinternal = std::make_shared<SoundInternal>();
|
||||
auto soundinternal = wi::allocator::make_shared<SoundInternal>();
|
||||
soundinternal->audio = audio_internal;
|
||||
sound->internal_state = soundinternal;
|
||||
|
||||
@@ -1056,8 +1056,8 @@ namespace wi::audio
|
||||
if (sound == nullptr || !sound->IsValid())
|
||||
return false;
|
||||
uint32_t res;
|
||||
const auto& soundinternal = std::static_pointer_cast<SoundInternal>(sound->internal_state);
|
||||
std::shared_ptr<SoundInstanceInternal> instanceinternal = std::make_shared<SoundInstanceInternal>();
|
||||
auto soundinternal = wi::allocator::shared_ptr<SoundInternal>(sound->internal_state);
|
||||
auto instanceinternal = wi::allocator::make_shared<SoundInstanceInternal>();
|
||||
instance->internal_state = instanceinternal;
|
||||
|
||||
instanceinternal->audio = audio_internal;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "CommonInclude.h"
|
||||
#include "wiMath.h"
|
||||
#include "wiAllocator.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -28,14 +29,14 @@ namespace wi::audio
|
||||
// Use SoundInstance for playback the sound data
|
||||
struct Sound
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state.get() != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
};
|
||||
// SoundInstance can be used to play back a Sound with specified effects
|
||||
struct SoundInstance
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state.get() != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
// You can specify these params before creating the sound instance:
|
||||
// The sound instance will need to be recreated for changes to take effect
|
||||
|
||||
+20
-19
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "CommonInclude.h"
|
||||
#include "wiVector.h"
|
||||
#include "wiAllocator.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
@@ -840,8 +841,8 @@ namespace wi::graphics
|
||||
|
||||
struct Sampler
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
SamplerDesc desc;
|
||||
|
||||
@@ -850,22 +851,22 @@ namespace wi::graphics
|
||||
|
||||
struct Shader
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
ShaderStage stage = ShaderStage::Count;
|
||||
};
|
||||
|
||||
struct GPUResource
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
// These are only valid if the resource was created with CPU access (USAGE::UPLOAD or USAGE::READBACK)
|
||||
void* mapped_data = nullptr; // for buffers, it is a pointer to the buffer data; for textures, it is a pointer to texture data with linear tiling;
|
||||
size_t mapped_size = 0; // for buffers, it is the full buffer size; for textures it is the full texture size including all subresources;
|
||||
|
||||
uint32_t sparse_page_size = 0ull; // specifies the required alignment of backing allocation for sparse tile pool
|
||||
uint32_t sparse_page_size = 0; // specifies the required alignment of backing allocation for sparse tile pool
|
||||
|
||||
enum class Type : uint8_t
|
||||
{
|
||||
@@ -887,9 +888,9 @@ namespace wi::graphics
|
||||
|
||||
// Dynamic allocation and destruction of this object is not allowed because virtual table is not used
|
||||
static void* operator new (size_t) = delete;
|
||||
static void* operator new[](size_t) = delete;
|
||||
static void* operator new[] (size_t) = delete;
|
||||
static void operator delete (void*) = delete;
|
||||
static void operator delete[](void*) = delete;
|
||||
static void operator delete[] (void*) = delete;
|
||||
static void* operator new (size_t, void*) = delete;
|
||||
static void* operator new[](size_t, void*) = delete;
|
||||
};
|
||||
@@ -924,8 +925,8 @@ namespace wi::graphics
|
||||
|
||||
struct VideoDecoder
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
VideoDesc desc;
|
||||
constexpr const VideoDesc& GetDesc() const { return desc; }
|
||||
@@ -1159,8 +1160,8 @@ namespace wi::graphics
|
||||
|
||||
struct GPUQueryHeap
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
GPUQueryHeapDesc desc;
|
||||
|
||||
@@ -1169,8 +1170,8 @@ namespace wi::graphics
|
||||
|
||||
struct PipelineState
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
PipelineStateDesc desc;
|
||||
|
||||
@@ -1179,8 +1180,8 @@ namespace wi::graphics
|
||||
|
||||
struct SwapChain
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
SwapChainDesc desc;
|
||||
|
||||
@@ -1329,8 +1330,8 @@ namespace wi::graphics
|
||||
};
|
||||
struct RaytracingPipelineState
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
RaytracingPipelineStateDesc desc;
|
||||
|
||||
|
||||
@@ -1438,7 +1438,7 @@ namespace dx12_internal
|
||||
|
||||
ComPtr<ID3D12VersionedRootSignatureDeserializer> rootsig_deserializer;
|
||||
const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* rootsig_desc = nullptr;
|
||||
std::shared_ptr<void> rootsig_desc_lifetime_extender;
|
||||
wi::allocator::shared_ptr<void> rootsig_desc_lifetime_extender;
|
||||
RootSignatureOptimizer rootsig_optimizer;
|
||||
|
||||
struct PSO_STREAM
|
||||
@@ -3046,11 +3046,7 @@ std::mutex queue_locker;
|
||||
|
||||
bool GraphicsDevice_DX12::CreateSwapChain(const SwapChainDesc* desc, wi::platform::window_type window, SwapChain* swapchain) const
|
||||
{
|
||||
auto internal_state = std::static_pointer_cast<SwapChain_DX12>(swapchain->internal_state);
|
||||
if (swapchain->internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<SwapChain_DX12>();
|
||||
}
|
||||
auto internal_state = swapchain->IsValid() ? wi::allocator::shared_ptr<SwapChain_DX12>(swapchain->internal_state) : wi::allocator::make_shared<SwapChain_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
swapchain->internal_state = internal_state;
|
||||
swapchain->desc = *desc;
|
||||
@@ -3264,7 +3260,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreateBuffer2(const GPUBufferDesc* desc, const std::function<void(void*)>& init_callback, GPUBuffer* buffer, const GPUResource* alias, uint64_t alias_offset) const
|
||||
{
|
||||
auto internal_state = std::make_shared<Resource_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<Resource_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
buffer->internal_state = internal_state;
|
||||
buffer->type = GPUResource::Type::BUFFER;
|
||||
@@ -3495,7 +3491,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreateTexture(const TextureDesc* desc, const SubresourceData* initial_data, Texture* texture, const GPUResource* alias, uint64_t alias_offset) const
|
||||
{
|
||||
auto internal_state = std::make_shared<Texture_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<Texture_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
texture->internal_state = internal_state;
|
||||
texture->type = GPUResource::Type::TEXTURE;
|
||||
@@ -3914,7 +3910,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreateShader(ShaderStage stage, const void* shadercode, size_t shadercode_size, Shader* shader) const
|
||||
{
|
||||
auto internal_state = std::make_shared<PipelineState_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<PipelineState_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
shader->internal_state = internal_state;
|
||||
|
||||
@@ -3974,7 +3970,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreateSampler(const SamplerDesc* desc, Sampler* sampler) const
|
||||
{
|
||||
auto internal_state = std::make_shared<Sampler_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<Sampler_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
sampler->internal_state = internal_state;
|
||||
|
||||
@@ -4020,7 +4016,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreateQueryHeap(const GPUQueryHeapDesc* desc, GPUQueryHeap* queryheap) const
|
||||
{
|
||||
auto internal_state = std::make_shared<QueryHeap_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<QueryHeap_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
queryheap->internal_state = internal_state;
|
||||
queryheap->desc = *desc;
|
||||
@@ -4046,7 +4042,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info) const
|
||||
{
|
||||
auto internal_state = std::make_shared<PipelineState_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<PipelineState_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
pso->internal_state = internal_state;
|
||||
|
||||
@@ -4286,7 +4282,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const
|
||||
{
|
||||
auto internal_state = std::make_shared<BVH_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<BVH_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
bvh->internal_state = internal_state;
|
||||
bvh->type = GPUResource::Type::RAYTRACING_ACCELERATION_STRUCTURE;
|
||||
@@ -4423,7 +4419,7 @@ std::mutex queue_locker;
|
||||
}
|
||||
bool GraphicsDevice_DX12::CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const
|
||||
{
|
||||
auto internal_state = std::make_shared<RTPipelineState_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<RTPipelineState_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
rtpso->internal_state = internal_state;
|
||||
rtpso->desc = *desc;
|
||||
@@ -4605,7 +4601,7 @@ std::mutex queue_locker;
|
||||
video_decoder->support |= VideoDecoderSupportFlags::DPB_INDIVIDUAL_TEXTURES_SUPPORTED;
|
||||
}
|
||||
|
||||
auto internal_state = std::make_shared<VideoDecoder_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<VideoDecoder_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
video_decoder->internal_state = internal_state;
|
||||
video_decoder->desc = *desc;
|
||||
@@ -5790,7 +5786,7 @@ std::mutex queue_locker;
|
||||
{
|
||||
auto swapchain_internal = to_internal(swapchain);
|
||||
|
||||
auto internal_state = std::make_shared<Texture_DX12>();
|
||||
auto internal_state = wi::allocator::make_shared<Texture_DX12>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
internal_state->resource = swapchain_internal->backBuffers[swapchain_internal->GetBufferIndex()];
|
||||
|
||||
|
||||
@@ -2163,13 +2163,14 @@ using namespace vulkan_internal;
|
||||
// Blending:
|
||||
uint32_t numBlendAttachments = 0;
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachments[8] = {};
|
||||
static BlendState::RenderTargetBlendState default_blend;
|
||||
for (size_t i = 0; i < commandlist.renderpass_info.rt_count; ++i)
|
||||
{
|
||||
size_t attachmentIndex = 0;
|
||||
if (pso->desc.bs->independent_blend_enable)
|
||||
if (pso->desc.bs != nullptr && pso->desc.bs->independent_blend_enable)
|
||||
attachmentIndex = i;
|
||||
|
||||
const auto& desc = pso->desc.bs->render_target[attachmentIndex];
|
||||
const auto& desc = pso->desc.bs == nullptr ? default_blend : pso->desc.bs->render_target[attachmentIndex];
|
||||
VkPipelineColorBlendAttachmentState& attachment = colorBlendAttachments[numBlendAttachments];
|
||||
numBlendAttachments++;
|
||||
|
||||
@@ -3755,11 +3756,7 @@ using namespace vulkan_internal;
|
||||
|
||||
bool GraphicsDevice_Vulkan::CreateSwapChain(const SwapChainDesc* desc, wi::platform::window_type window, SwapChain* swapchain) const
|
||||
{
|
||||
auto internal_state = std::static_pointer_cast<SwapChain_Vulkan>(swapchain->internal_state);
|
||||
if (swapchain->internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<SwapChain_Vulkan>();
|
||||
}
|
||||
auto internal_state = swapchain->IsValid() ? wi::allocator::shared_ptr<SwapChain_Vulkan>(swapchain->internal_state) : wi::allocator::make_shared<SwapChain_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
internal_state->desc = *desc;
|
||||
swapchain->internal_state = internal_state;
|
||||
@@ -3818,7 +3815,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreateBuffer2(const GPUBufferDesc* desc, const std::function<void(void*)>& init_callback, GPUBuffer* buffer, const GPUResource* alias, uint64_t alias_offset) const
|
||||
{
|
||||
auto internal_state = std::make_shared<Buffer_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<Buffer_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
buffer->internal_state = internal_state;
|
||||
buffer->type = GPUResource::Type::BUFFER;
|
||||
@@ -4161,7 +4158,7 @@ using namespace vulkan_internal;
|
||||
alias_offset = 0;
|
||||
#endif // PLATFORM_LINUX
|
||||
|
||||
auto internal_state = std::make_shared<Texture_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<Texture_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
internal_state->defaultLayout = _ConvertImageLayout(desc->layout);
|
||||
texture->internal_state = internal_state;
|
||||
@@ -4763,7 +4760,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreateShader(ShaderStage stage, const void* shadercode, size_t shadercode_size, Shader* shader) const
|
||||
{
|
||||
auto internal_state = std::make_shared<Shader_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<Shader_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
shader->internal_state = internal_state;
|
||||
shader->stage = stage;
|
||||
@@ -5073,7 +5070,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreateSampler(const SamplerDesc* desc, Sampler* sampler) const
|
||||
{
|
||||
auto internal_state = std::make_shared<Sampler_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<Sampler_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
sampler->internal_state = internal_state;
|
||||
sampler->desc = *desc;
|
||||
@@ -5311,7 +5308,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreateQueryHeap(const GPUQueryHeapDesc* desc, GPUQueryHeap* queryheap) const
|
||||
{
|
||||
auto internal_state = std::make_shared<QueryHeap_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<QueryHeap_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
queryheap->internal_state = internal_state;
|
||||
queryheap->desc = *desc;
|
||||
@@ -5337,7 +5334,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info) const
|
||||
{
|
||||
auto internal_state = std::make_shared<PipelineState_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<PipelineState_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
pso->internal_state = internal_state;
|
||||
pso->desc = *desc;
|
||||
@@ -5967,7 +5964,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const
|
||||
{
|
||||
auto internal_state = std::make_shared<BVH_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<BVH_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
bvh->internal_state = internal_state;
|
||||
bvh->type = GPUResource::Type::RAYTRACING_ACCELERATION_STRUCTURE;
|
||||
@@ -6145,7 +6142,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const
|
||||
{
|
||||
auto internal_state = std::make_shared<RTPipelineState_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<RTPipelineState_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
rtpso->internal_state = internal_state;
|
||||
rtpso->desc = *desc;
|
||||
@@ -6242,7 +6239,7 @@ using namespace vulkan_internal;
|
||||
}
|
||||
bool GraphicsDevice_Vulkan::CreateVideoDecoder(const VideoDesc* desc, VideoDecoder* video_decoder) const
|
||||
{
|
||||
auto internal_state = std::make_shared<VideoDecoder_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<VideoDecoder_Vulkan>();
|
||||
internal_state->allocationhandler = allocationhandler;
|
||||
video_decoder->internal_state = internal_state;
|
||||
video_decoder->desc = *desc;
|
||||
@@ -7537,7 +7534,7 @@ using namespace vulkan_internal;
|
||||
{
|
||||
auto swapchain_internal = to_internal(swapchain);
|
||||
|
||||
auto internal_state = std::make_shared<Texture_Vulkan>();
|
||||
auto internal_state = wi::allocator::make_shared<Texture_Vulkan>();
|
||||
internal_state->resource = swapchain_internal->swapChainImages[swapchain_internal->swapChainImageIndex];
|
||||
|
||||
Texture result;
|
||||
|
||||
@@ -138,6 +138,10 @@ namespace wi::initializer
|
||||
wilog("\nNo embedded shaders found, shaders will be compiled at runtime if needed.\n\tShader source path: %s\n\tShader binary path: %s", wi::renderer::GetShaderSourcePath().c_str(), wi::renderer::GetShaderPath().c_str());
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
wilog("\nNumber of shared block allocated types: %d", (int)wi::allocator::get_shared_block_allocator_count());
|
||||
#endif // _DEBUG
|
||||
|
||||
wi::backlog::post("");
|
||||
wi::jobsystem::Initialize();
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace wi
|
||||
|
||||
// This is an identifier of RenderPath subtype that is used for lua binding.
|
||||
static constexpr const char* script_check_identifier = relative_path(__FILE__);
|
||||
virtual const char* GetScriptBindingID() const { return script_check_identifier; }
|
||||
const char* GetScriptBindingID() const override { return script_check_identifier; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace wi
|
||||
|
||||
// This is an identifier of RenderPath subtype that is used for lua binding.
|
||||
static constexpr const char* script_check_identifier = relative_path(__FILE__);
|
||||
virtual const char* GetScriptBindingID() const { return script_check_identifier; }
|
||||
const char* GetScriptBindingID() const override { return script_check_identifier; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -369,7 +369,7 @@ namespace wi
|
||||
|
||||
// This is an identifier of RenderPath subtype that is used for lua binding.
|
||||
static constexpr const char* script_check_identifier = relative_path(__FILE__);
|
||||
virtual const char* GetScriptBindingID() const { return script_check_identifier; }
|
||||
const char* GetScriptBindingID() const override { return script_check_identifier; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace wi
|
||||
|
||||
// This is an identifier of RenderPath subtype that is used for lua binding.
|
||||
static constexpr const char* script_check_identifier = relative_path(__FILE__);
|
||||
virtual const char* GetScriptBindingID() const { return script_check_identifier; }
|
||||
const char* GetScriptBindingID() const override { return script_check_identifier; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,14 @@
|
||||
|
||||
using namespace wi::graphics;
|
||||
|
||||
//#define RESOURCE_LOGGING
|
||||
|
||||
#ifdef RESOURCE_LOGGING
|
||||
#define resource_log(str,...) wilog(str, ## __VA_ARGS__)
|
||||
#else
|
||||
#define resource_log(str,...)
|
||||
#endif // RESOURCE_LOGGING
|
||||
|
||||
namespace wi
|
||||
{
|
||||
struct StreamingTexture
|
||||
@@ -112,7 +120,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->filedata = data;
|
||||
@@ -121,7 +129,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->filedata = data;
|
||||
@@ -130,7 +138,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->texture = texture;
|
||||
@@ -140,7 +148,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->tile_pool = tile_pool;
|
||||
@@ -151,7 +159,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->sound = sound;
|
||||
@@ -160,7 +168,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->script = script;
|
||||
@@ -169,7 +177,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->video = video;
|
||||
@@ -179,7 +187,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->timestamp = 0;
|
||||
@@ -189,7 +197,7 @@ namespace wi
|
||||
{
|
||||
if (internal_state == nullptr)
|
||||
{
|
||||
internal_state = std::make_shared<ResourceInternal>();
|
||||
internal_state = wi::allocator::make_shared<ResourceInternal>();
|
||||
}
|
||||
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
|
||||
resourceinternal->streaming_resolution.fetch_or(resolution);
|
||||
@@ -198,7 +206,7 @@ namespace wi
|
||||
namespace resourcemanager
|
||||
{
|
||||
static std::mutex locker;
|
||||
static std::unordered_map<std::string, std::weak_ptr<ResourceInternal>> resources;
|
||||
static wi::unordered_map<std::string, wi::allocator::weak_ptr<ResourceInternal>> resources;
|
||||
static Mode mode = Mode::NO_EMBEDDING;
|
||||
|
||||
void SetMode(Mode param)
|
||||
@@ -907,8 +915,8 @@ namespace wi
|
||||
)
|
||||
{
|
||||
locker.lock();
|
||||
std::weak_ptr<ResourceInternal>& weak_resource = resources[name];
|
||||
std::shared_ptr<ResourceInternal> resource = weak_resource.lock();
|
||||
wi::allocator::weak_ptr<ResourceInternal>& weak_resource = resources[name];
|
||||
wi::allocator::shared_ptr<ResourceInternal> resource = weak_resource.lock();
|
||||
|
||||
uint64_t timestamp = 0;
|
||||
if(!container_filename.empty())
|
||||
@@ -922,7 +930,7 @@ namespace wi
|
||||
|
||||
if (resource == nullptr || resource->timestamp < timestamp)
|
||||
{
|
||||
resource = std::make_shared<ResourceInternal>();
|
||||
resource = wi::allocator::make_shared<ResourceInternal>();
|
||||
resources[name] = resource;
|
||||
resource->filename = name;
|
||||
|
||||
@@ -957,6 +965,7 @@ namespace wi
|
||||
}
|
||||
else
|
||||
{
|
||||
resource_log("\tResource reused: %s", name.c_str());
|
||||
Resource retVal;
|
||||
retVal.internal_state = resource;
|
||||
locker.unlock();
|
||||
@@ -989,6 +998,7 @@ namespace wi
|
||||
}
|
||||
else
|
||||
{
|
||||
resource_log("\tResource loading: %s", name.c_str());
|
||||
success = LoadResourceDirectly(name, flags, filedata, filesize, resource.get());
|
||||
}
|
||||
|
||||
@@ -1027,10 +1037,10 @@ namespace wi
|
||||
}
|
||||
|
||||
wi::jobsystem::context streaming_ctx;
|
||||
wi::vector<std::shared_ptr<ResourceInternal>> streaming_texture_jobs;
|
||||
wi::vector<wi::allocator::shared_ptr<ResourceInternal>> streaming_texture_jobs;
|
||||
struct StreamingTextureReplace
|
||||
{
|
||||
std::shared_ptr<ResourceInternal> resource;
|
||||
wi::allocator::shared_ptr<ResourceInternal> resource;
|
||||
Texture texture;
|
||||
int srgb_subresource = -1;
|
||||
};
|
||||
@@ -1069,8 +1079,8 @@ namespace wi
|
||||
return; // Streaming is not that important, we can abandon it if some resource loading is holding the lock
|
||||
for (auto& x : resources)
|
||||
{
|
||||
std::weak_ptr<ResourceInternal>& weak_resource = x.second;
|
||||
std::shared_ptr<ResourceInternal> resource = weak_resource.lock();
|
||||
wi::allocator::weak_ptr<ResourceInternal>& weak_resource = x.second;
|
||||
wi::allocator::shared_ptr<ResourceInternal> resource = weak_resource.lock();
|
||||
if (resource != nullptr && resource->texture.IsValid() && has_flag(resource->flags, Flags::STREAMING))
|
||||
{
|
||||
const TextureDesc& desc = resource->texture.desc;
|
||||
@@ -1123,16 +1133,31 @@ namespace wi
|
||||
|
||||
streaming_texture_jobs.clear();
|
||||
|
||||
// Gather the streaming jobs:
|
||||
static wi::vector<const std::string*> removals; // string ptr to avoid string copies, or string constructions from char*
|
||||
|
||||
// Gather the streaming jobs, unload lost resources:
|
||||
for (auto& x : resources)
|
||||
{
|
||||
std::weak_ptr<ResourceInternal>& weak_resource = x.second;
|
||||
std::shared_ptr<ResourceInternal> resource = weak_resource.lock();
|
||||
if (x.second.expired())
|
||||
{
|
||||
removals.push_back(&x.first);
|
||||
continue;
|
||||
}
|
||||
|
||||
wi::allocator::weak_ptr<ResourceInternal>& weak_resource = x.second;
|
||||
wi::allocator::shared_ptr<ResourceInternal> resource = weak_resource.lock();
|
||||
if (resource != nullptr && resource->texture.IsValid() && resource->streaming_texture.mip_count > 1)
|
||||
{
|
||||
streaming_texture_jobs.push_back(resource);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& x : removals)
|
||||
{
|
||||
resource_log("\tResource lost: %s", x->c_str());
|
||||
resources.erase(*x);
|
||||
}
|
||||
removals.clear();
|
||||
locker.unlock();
|
||||
|
||||
if (streaming_texture_jobs.empty())
|
||||
@@ -1400,7 +1425,7 @@ namespace wi
|
||||
auto it = resources.find(name);
|
||||
if (it == resources.end())
|
||||
continue;
|
||||
std::shared_ptr<ResourceInternal> resource = it->second.lock();
|
||||
wi::allocator::shared_ptr<ResourceInternal> resource = it->second.lock();
|
||||
if (resource != nullptr)
|
||||
{
|
||||
serializable_count++;
|
||||
@@ -1414,7 +1439,7 @@ namespace wi
|
||||
auto it = resources.find(name);
|
||||
if (it == resources.end())
|
||||
continue;
|
||||
std::shared_ptr<ResourceInternal> resource = it->second.lock();
|
||||
wi::allocator::shared_ptr<ResourceInternal> resource = it->second.lock();
|
||||
|
||||
if (resource != nullptr)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "wiVector.h"
|
||||
#include "wiVideo.h"
|
||||
#include "wiUnorderedSet.h"
|
||||
#include "wiAllocator.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -17,7 +18,7 @@ namespace wi
|
||||
// It can be loaded from file or memory using wi::resourcemanager::Load()
|
||||
struct Resource
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state.get() != nullptr; }
|
||||
|
||||
const wi::vector<uint8_t>& GetFileData() const;
|
||||
|
||||
@@ -549,7 +549,7 @@ namespace wi::shadercompiler
|
||||
output.shadersize = pShader->GetBufferSize();
|
||||
|
||||
// keep the blob alive == keep shader pointer valid!
|
||||
auto internal_state = std::make_shared<ComPtr<IDxcBlob>>();
|
||||
auto internal_state = wi::allocator::make_shared<ComPtr<IDxcBlob>>();
|
||||
*internal_state = pShader;
|
||||
output.internal_state = internal_state;
|
||||
}
|
||||
@@ -724,7 +724,7 @@ namespace wi::shadercompiler
|
||||
output.shadersize = code->GetBufferSize();
|
||||
|
||||
// keep the blob alive == keep shader pointer valid!
|
||||
auto internal_state = std::make_shared<ComPtr<ID3D10Blob>>();
|
||||
auto internal_state = wi::allocator::make_shared<ComPtr<ID3D10Blob>>();
|
||||
*internal_state = code;
|
||||
output.internal_state = internal_state;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "wiGraphics.h"
|
||||
#include "wiVector.h"
|
||||
#include "wiAllocator.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -28,8 +29,8 @@ namespace wi::shadercompiler
|
||||
};
|
||||
struct CompilerOutput
|
||||
{
|
||||
std::shared_ptr<void> internal_state;
|
||||
inline bool IsValid() const { return internal_state.get() != nullptr; }
|
||||
wi::allocator::shared_ptr<void> internal_state;
|
||||
constexpr bool IsValid() const { return internal_state.IsValid(); }
|
||||
|
||||
const uint8_t* shaderdata = nullptr;
|
||||
size_t shadersize = 0;
|
||||
|
||||
@@ -1638,7 +1638,7 @@ namespace wi::terrain
|
||||
|
||||
if (chunk_data.vt == nullptr)
|
||||
{
|
||||
chunk_data.vt = std::make_shared<VirtualTexture>();
|
||||
chunk_data.vt = wi::allocator::make_shared<VirtualTexture>();
|
||||
}
|
||||
VirtualTexture& vt = *chunk_data.vt;
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace wi::terrain
|
||||
void init(uint32_t resolution);
|
||||
void reset();
|
||||
};
|
||||
wi::unordered_map<uint32_t, wi::vector<std::shared_ptr<Residency>>> free_residencies; // per resolution residencies
|
||||
wi::unordered_map<uint32_t, wi::vector<wi::allocator::shared_ptr<Residency>>> free_residencies; // per resolution residencies
|
||||
|
||||
bool allocate_tile(Tile& tile)
|
||||
{
|
||||
@@ -142,20 +142,20 @@ namespace wi::terrain
|
||||
return ~0ull;
|
||||
return physical_tiles[tile.x + tile.y * physical_tile_count_x].free_frames;
|
||||
}
|
||||
std::shared_ptr<Residency> allocate_residency(uint32_t resolution)
|
||||
wi::allocator::shared_ptr<Residency> allocate_residency(uint32_t resolution)
|
||||
{
|
||||
if (free_residencies[resolution].empty())
|
||||
{
|
||||
std::shared_ptr<Residency> residency = std::make_shared<Residency>();
|
||||
wi::allocator::shared_ptr<Residency> residency = wi::allocator::make_shared<Residency>();
|
||||
residency->init(resolution);
|
||||
free_residencies[resolution].push_back(residency);
|
||||
}
|
||||
std::shared_ptr<Residency> residency = free_residencies[resolution].back();
|
||||
wi::allocator::shared_ptr<Residency> residency = free_residencies[resolution].back();
|
||||
free_residencies[resolution].pop_back();
|
||||
residency->reset();
|
||||
return residency;
|
||||
}
|
||||
void free_residency(std::shared_ptr<Residency>& residency)
|
||||
void free_residency(wi::allocator::shared_ptr<Residency>& residency)
|
||||
{
|
||||
if (residency == nullptr)
|
||||
return;
|
||||
@@ -170,7 +170,7 @@ namespace wi::terrain
|
||||
|
||||
struct VirtualTexture
|
||||
{
|
||||
std::shared_ptr<VirtualTextureAtlas::Residency> residency;
|
||||
wi::allocator::shared_ptr<VirtualTextureAtlas::Residency> residency;
|
||||
wi::vector<VirtualTextureAtlas::Tile> tiles;
|
||||
uint32_t lod_count = 0;
|
||||
uint32_t resolution = 0;
|
||||
@@ -231,7 +231,7 @@ namespace wi::terrain
|
||||
XMFLOAT3 position = XMFLOAT3(0, 0, 0);
|
||||
bool visible = true;
|
||||
bool invalidated = false;
|
||||
std::shared_ptr<VirtualTexture> vt;
|
||||
wi::allocator::shared_ptr<VirtualTexture> vt;
|
||||
wi::vector<uint16_t> heightmap_data;
|
||||
wi::graphics::Texture heightmap;
|
||||
|
||||
|
||||
@@ -12,5 +12,13 @@
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="wi::allocator::shared_ptr<*>">
|
||||
<DisplayString>{{ handle={handle} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[ptr]">reinterpret_cast<$T1*>(handle & (~0ull << 8ull))</Item>
|
||||
<Item Name="[allocator]">block_allocators[handle & 0xFF]</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
|
||||
Reference in New Issue
Block a user