mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 07:20:49 +00:00
Use a VulkanDeviceAllocator for thin3d textures. Many devices have a hard limit on the total number of allocs and it's unnecessary to have the UI put pressure on that.
This commit is contained in:
parent
97bdc72d90
commit
d0c248368d
@ -1,5 +1,6 @@
|
||||
#include "Common/Vulkan/VulkanImage.h"
|
||||
#include "Common/Vulkan/VulkanMemory.h"
|
||||
#include "Common/Log.h"
|
||||
|
||||
VkResult VulkanTexture::Create(int w, int h, VkFormat format) {
|
||||
tex_width = w;
|
||||
@ -294,6 +295,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
|
||||
|
||||
res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem);
|
||||
if (res != VK_SUCCESS) {
|
||||
_assert_msg_(G3D, res != VK_ERROR_TOO_MANY_OBJECTS, "Too many Vulkan memory objects!");
|
||||
assert(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
|
||||
return false;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ class VulkanDeviceAllocator;
|
||||
// Not very optimal - if you have many small textures you should use other strategies.
|
||||
class VulkanTexture {
|
||||
public:
|
||||
VulkanTexture(VulkanContext *vulkan, VulkanDeviceAllocator *allocator = nullptr)
|
||||
VulkanTexture(VulkanContext *vulkan, VulkanDeviceAllocator *allocator)
|
||||
: vulkan_(vulkan), image(VK_NULL_HANDLE), mem(VK_NULL_HANDLE), view(VK_NULL_HANDLE),
|
||||
tex_width(0), tex_height(0), numMips_(1), format_(VK_FORMAT_UNDEFINED),
|
||||
mappableImage(VK_NULL_HANDLE), mappableMemory(VK_NULL_HANDLE),
|
||||
|
@ -146,6 +146,10 @@ public:
|
||||
|
||||
static const size_t ALLOCATE_FAILED = -1;
|
||||
|
||||
int GetBlockCount() const { return (int)slabs_.size(); }
|
||||
int GetMinSlabSize() const { return (int)minSlabSize_; }
|
||||
int GetMaxSlabSize() const { return (int)maxSlabSize_; }
|
||||
|
||||
private:
|
||||
static const size_t SLAB_GRAIN_SIZE = 1024;
|
||||
static const uint8_t SLAB_GRAIN_SHIFT = 10;
|
||||
|
@ -296,7 +296,7 @@ void DrawEngineVulkan::BeginFrame() {
|
||||
if (!nullTexture_) {
|
||||
ILOG("INIT : Creating null texture");
|
||||
VkCommandBuffer cmdInit = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
|
||||
nullTexture_ = new VulkanTexture(vulkan_);
|
||||
nullTexture_ = new VulkanTexture(vulkan_, textureCache_->GetAllocator());
|
||||
int w = 8;
|
||||
int h = 8;
|
||||
nullTexture_->CreateDirect(cmdInit, w, h, 1, VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
|
@ -205,7 +205,8 @@ void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFor
|
||||
|
||||
VkCommandBuffer initCmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
|
||||
|
||||
drawPixelsTex_ = new VulkanTexture(vulkan_);
|
||||
// There's only ever a few of these alive, don't need to stress the allocator with these big ones.
|
||||
drawPixelsTex_ = new VulkanTexture(vulkan_, nullptr);
|
||||
if (!drawPixelsTex_->CreateDirect(initCmd, width, height, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)) {
|
||||
// out of memory?
|
||||
delete drawPixelsTex_;
|
||||
|
@ -638,6 +638,8 @@ void GPU_Vulkan::DeviceRestore() {
|
||||
|
||||
void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
|
||||
const DrawEngineVulkanStats &drawStats = drawEngine_.GetStats();
|
||||
char texStats[256];
|
||||
textureCacheVulkan_->GetStats(texStats, sizeof(texStats));
|
||||
float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f;
|
||||
snprintf(buffer, bufsize - 1,
|
||||
"DL processing time: %0.2f ms\n"
|
||||
@ -652,7 +654,8 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
|
||||
"Textures active: %i, decoded: %i invalidated: %i\n"
|
||||
"Readbacks: %d\n"
|
||||
"Vertex, Fragment, Pipelines loaded: %i, %i, %i\n"
|
||||
"Pushbuffer space used: UBO %d, Vtx %d, Idx %d\n",
|
||||
"Pushbuffer space used: UBO %d, Vtx %d, Idx %d\n"
|
||||
"%s\n",
|
||||
gpuStats.msProcessingDisplayLists * 1000.0f,
|
||||
gpuStats.numDrawCalls,
|
||||
gpuStats.numFlushes,
|
||||
@ -674,7 +677,8 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
|
||||
pipelineManager_->GetNumPipelines(),
|
||||
drawStats.pushUBOSpaceUsed,
|
||||
drawStats.pushVertexSpaceUsed,
|
||||
drawStats.pushIndexSpaceUsed
|
||||
drawStats.pushIndexSpaceUsed,
|
||||
texStats
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -816,6 +816,10 @@ bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int leve
|
||||
// So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE);
|
||||
framebufferManager_->RebindFramebuffer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureCacheVulkan::GetStats(char *ptr, size_t size) {
|
||||
snprintf(ptr, size, "Alloc: %d blocks\nSlab min/max: %d/%d\n",
|
||||
allocator_->GetBlockCount(), allocator_->GetMinSlabSize(), allocator_->GetMaxSlabSize());
|
||||
}
|
||||
|
@ -107,6 +107,10 @@ public:
|
||||
|
||||
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
|
||||
|
||||
void GetStats(char *ptr, size_t size);
|
||||
|
||||
VulkanDeviceAllocator *GetAllocator() { return allocator_; }
|
||||
|
||||
protected:
|
||||
void BindTexture(TexCacheEntry *entry) override;
|
||||
void Unbind() override;
|
||||
|
@ -312,9 +312,9 @@ struct DescriptorSetKey {
|
||||
|
||||
class VKTexture : public Texture {
|
||||
public:
|
||||
VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, const TextureDesc &desc)
|
||||
VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, const TextureDesc &desc, VulkanDeviceAllocator *alloc)
|
||||
: vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) {
|
||||
bool result = Create(cmd, desc);
|
||||
bool result = Create(cmd, desc, alloc);
|
||||
assert(result);
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ public:
|
||||
private:
|
||||
void SetImageData(VkCommandBuffer cmd, int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data);
|
||||
|
||||
bool Create(VkCommandBuffer cmd, const TextureDesc &desc);
|
||||
bool Create(VkCommandBuffer cmd, const TextureDesc &desc, VulkanDeviceAllocator *alloc);
|
||||
|
||||
void Destroy() {
|
||||
if (vkTex_) {
|
||||
@ -497,6 +497,8 @@ private:
|
||||
|
||||
VulkanRenderManager renderManager_;
|
||||
|
||||
VulkanDeviceAllocator *allocator_ = nullptr;
|
||||
|
||||
VKPipeline *curPipeline_ = nullptr;
|
||||
VKBuffer *curVBuffers_[4]{};
|
||||
int curVBufferOffsets_[4]{};
|
||||
@ -657,7 +659,7 @@ enum class TextureState {
|
||||
PENDING_DESTRUCTION,
|
||||
};
|
||||
|
||||
bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc) {
|
||||
bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc, VulkanDeviceAllocator *alloc) {
|
||||
// Zero-sized textures not allowed.
|
||||
if (desc.width * desc.height * desc.depth == 0)
|
||||
return false;
|
||||
@ -666,7 +668,7 @@ bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc) {
|
||||
width_ = desc.width;
|
||||
height_ = desc.height;
|
||||
depth_ = desc.depth;
|
||||
vkTex_ = new VulkanTexture(vulkan_);
|
||||
vkTex_ = new VulkanTexture(vulkan_, alloc);
|
||||
if (desc.initData.size()) {
|
||||
for (int i = 0; i < (int)desc.initData.size(); i++) {
|
||||
this->SetImageData(cmd, 0, 0, 0, width_, height_, depth_, i, 0, desc.initData[i]);
|
||||
@ -758,9 +760,12 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
|
||||
pipelineCache_ = vulkan_->CreatePipelineCache();
|
||||
|
||||
renderManager_.SetSplitSubmit(splitSubmit);
|
||||
|
||||
allocator_ = new VulkanDeviceAllocator(vulkan_, 256 * 1024, 2048 * 1024);
|
||||
}
|
||||
|
||||
VKContext::~VKContext() {
|
||||
delete allocator_;
|
||||
// This also destroys all descriptor sets.
|
||||
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
|
||||
frame_[i].descSets_.clear();
|
||||
@ -996,7 +1001,7 @@ InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) {
|
||||
}
|
||||
|
||||
Texture *VKContext::CreateTexture(const TextureDesc &desc) {
|
||||
return new VKTexture(vulkan_, renderManager_.GetInitCmd(), desc);
|
||||
return new VKTexture(vulkan_, renderManager_.GetInitCmd(), desc, allocator_);
|
||||
}
|
||||
|
||||
void VKTexture::SetImageData(VkCommandBuffer cmd, int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) {
|
||||
|
Loading…
Reference in New Issue
Block a user