Merge pull request #9041 from unknownbrackets/vulkan

WIP: Progress toward device restore on Vulkan
This commit is contained in:
Henrik Rydgård 2016-12-01 15:58:32 +01:00 committed by GitHub
commit 405ac4f2cc
16 changed files with 285 additions and 90 deletions

View File

@ -66,18 +66,18 @@ class VulkanDeleteList {
};
public:
void QueueDeleteDescriptorPool(VkDescriptorPool pool) { descPools_.push_back(pool); }
void QueueDeleteShaderModule(VkShaderModule module) { modules_.push_back(module); }
void QueueDeleteBuffer(VkBuffer buffer) { buffers_.push_back(buffer); }
void QueueDeleteBufferView(VkBufferView bufferView) { bufferViews_.push_back(bufferView); }
void QueueDeleteImage(VkImage image) { images_.push_back(image); }
void QueueDeleteImageView(VkImageView imageView) { imageViews_.push_back(imageView); }
void QueueDeleteDeviceMemory(VkDeviceMemory deviceMemory) { deviceMemory_.push_back(deviceMemory); }
void QueueDeleteSampler(VkSampler sampler) { samplers_.push_back(sampler); }
void QueueDeletePipeline(VkPipeline pipeline) { pipelines_.push_back(pipeline); }
void QueueDeletePipelineCache(VkPipelineCache pipelineCache) { pipelineCaches_.push_back(pipelineCache); }
void QueueDeleteRenderPass(VkRenderPass renderPass) { renderPasses_.push_back(renderPass); }
void QueueDeleteFramebuffer(VkFramebuffer framebuffer) { framebuffers_.push_back(framebuffer); }
void QueueDeleteDescriptorPool(VkDescriptorPool &pool) { descPools_.push_back(pool); pool = VK_NULL_HANDLE; }
void QueueDeleteShaderModule(VkShaderModule &module) { modules_.push_back(module); module = VK_NULL_HANDLE; }
void QueueDeleteBuffer(VkBuffer &buffer) { buffers_.push_back(buffer); buffer = VK_NULL_HANDLE; }
void QueueDeleteBufferView(VkBufferView &bufferView) { bufferViews_.push_back(bufferView); bufferView = VK_NULL_HANDLE; }
void QueueDeleteImage(VkImage &image) { images_.push_back(image); image = VK_NULL_HANDLE; }
void QueueDeleteImageView(VkImageView &imageView) { imageViews_.push_back(imageView); imageView = VK_NULL_HANDLE; }
void QueueDeleteDeviceMemory(VkDeviceMemory &deviceMemory) { deviceMemory_.push_back(deviceMemory); deviceMemory = VK_NULL_HANDLE; }
void QueueDeleteSampler(VkSampler &sampler) { samplers_.push_back(sampler); sampler = VK_NULL_HANDLE; }
void QueueDeletePipeline(VkPipeline &pipeline) { pipelines_.push_back(pipeline); pipeline = VK_NULL_HANDLE; }
void QueueDeletePipelineCache(VkPipelineCache &pipelineCache) { pipelineCaches_.push_back(pipelineCache); pipelineCache = VK_NULL_HANDLE; }
void QueueDeleteRenderPass(VkRenderPass &renderPass) { renderPasses_.push_back(renderPass); renderPass = VK_NULL_HANDLE; }
void QueueDeleteFramebuffer(VkFramebuffer &framebuffer) { framebuffers_.push_back(framebuffer); framebuffer = VK_NULL_HANDLE; }
void QueueCallback(void(*func)(void *userdata), void *userdata) { callbacks_.push_back(Callback(func, userdata)); }
void Take(VulkanDeleteList &del) {

View File

@ -22,11 +22,9 @@ void VulkanTexture::CreateMappableImage() {
// If we already have a mappableImage, forget it.
if (mappableImage) {
vulkan_->Delete().QueueDeleteImage(mappableImage);
mappableImage = VK_NULL_HANDLE;
}
if (mappableMemory) {
vulkan_->Delete().QueueDeleteDeviceMemory(mappableMemory);
mappableMemory = VK_NULL_HANDLE;
}
bool U_ASSERT_ONLY pass;
@ -193,9 +191,6 @@ void VulkanTexture::Unlock() {
// Then drop the temporary mappable image - although should not be necessary...
vulkan_->Delete().QueueDeleteImage(mappableImage);
vulkan_->Delete().QueueDeleteDeviceMemory(mappableMemory);
mappableImage = VK_NULL_HANDLE;
mappableMemory = VK_NULL_HANDLE;
}
VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
@ -218,15 +213,12 @@ void VulkanTexture::Unlock() {
void VulkanTexture::Wipe() {
if (image) {
vulkan_->Delete().QueueDeleteImage(image);
image = VK_NULL_HANDLE;
}
if (view) {
vulkan_->Delete().QueueDeleteImageView(view);
view = VK_NULL_HANDLE;
}
if (mem && !allocator_) {
vulkan_->Delete().QueueDeleteDeviceMemory(mem);
mem = VK_NULL_HANDLE;
} else if (mem) {
allocator_->Free(mem, offset_);
mem = VK_NULL_HANDLE;
@ -371,25 +363,22 @@ void VulkanTexture::EndCreate() {
}
void VulkanTexture::Destroy() {
if (view) {
if (view != VK_NULL_HANDLE) {
vulkan_->Delete().QueueDeleteImageView(view);
}
if (image) {
vulkan_->Delete().QueueDeleteImage(image);
if (image != VK_NULL_HANDLE) {
if (mappableImage == image) {
mappableImage = VK_NULL_HANDLE;
}
vulkan_->Delete().QueueDeleteImage(image);
}
if (mem && !allocator_) {
vulkan_->Delete().QueueDeleteDeviceMemory(mem);
if (mem != VK_NULL_HANDLE && !allocator_) {
if (mappableMemory == mem) {
mappableMemory = VK_NULL_HANDLE;
}
} else if (mem) {
vulkan_->Delete().QueueDeleteDeviceMemory(mem);
} else if (mem != VK_NULL_HANDLE) {
allocator_->Free(mem, offset_);
mem = VK_NULL_HANDLE;
}
view = VK_NULL_HANDLE;
image = VK_NULL_HANDLE;
mem = VK_NULL_HANDLE;
}

View File

@ -29,7 +29,7 @@ public:
}
void Destroy(VulkanContext *vulkan) {
for (const BufInfo &info : buffers_) {
for (BufInfo &info : buffers_) {
vulkan->Delete().QueueDeleteBuffer(info.buffer);
vulkan->Delete().QueueDeleteDeviceMemory(info.deviceMemory);
}

View File

@ -99,6 +99,10 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan)
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
}
InitDeviceObjects();
}
void DrawEngineVulkan::InitDeviceObjects() {
// All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated.
VkDescriptorSetLayoutBinding bindings[5];
bindings[0].descriptorCount = 1;
@ -197,24 +201,62 @@ DrawEngineVulkan::~DrawEngineVulkan() {
FreeMemoryPages(transformed, TRANSFORMED_VERTEX_BUFFER_SIZE);
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
for (int i = 0; i < 2; i++) {
vulkan_->Delete().QueueDeleteDescriptorPool(frame_[i].descPool);
frame_[i].pushUBO->Destroy(vulkan_);
frame_[i].pushVertex->Destroy(vulkan_);
frame_[i].pushIndex->Destroy(vulkan_);
delete frame_[i].pushUBO;
delete frame_[i].pushVertex;
delete frame_[i].pushIndex;
DestroyDeviceObjects();
delete[] uvScale;
}
void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) {
if (descPool != VK_NULL_HANDLE) {
vulkan->Delete().QueueDeleteDescriptorPool(descPool);
}
vulkan_->Delete().QueueDeleteSampler(depalSampler_);
vulkan_->Delete().QueueDeleteSampler(nullSampler_);
if (pushUBO) {
pushUBO->Destroy(vulkan);
delete pushUBO;
pushUBO = nullptr;
}
if (pushVertex) {
pushVertex->Destroy(vulkan);
delete pushVertex;
pushVertex = nullptr;
}
if (pushIndex) {
pushIndex->Destroy(vulkan);
delete pushIndex;
pushIndex = nullptr;
}
}
void DrawEngineVulkan::DestroyDeviceObjects() {
for (int i = 0; i < 2; i++) {
frame_[i].Destroy(vulkan_);
}
if (depalSampler_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteSampler(depalSampler_);
if (nullSampler_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteSampler(nullSampler_);
if (pipelineLayout_ != VK_NULL_HANDLE)
vkDestroyPipelineLayout(vulkan_->GetDevice(), pipelineLayout_, nullptr);
pipelineLayout_ = VK_NULL_HANDLE;
if (descriptorSetLayout_ != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(vulkan_->GetDevice(), descriptorSetLayout_, nullptr);
descriptorSetLayout_ = VK_NULL_HANDLE;
if (nullTexture_) {
nullTexture_->Destroy();
delete nullTexture_;
nullTexture_ = nullptr;
}
delete[] uvScale;
vkDestroyPipelineLayout(vulkan_->GetDevice(), pipelineLayout_, nullptr);
vkDestroyDescriptorSetLayout(vulkan_->GetDevice(), descriptorSetLayout_, nullptr);
}
void DrawEngineVulkan::DeviceLost() {
DestroyDeviceObjects();
DirtyAllUBOs();
}
void DrawEngineVulkan::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
InitDeviceObjects();
}
void DrawEngineVulkan::BeginFrame() {
@ -243,7 +285,7 @@ void DrawEngineVulkan::BeginFrame() {
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
uint32_t bindOffset;
VkBuffer bindBuf;
uint32_t *data = (uint32_t *)frame_[0].pushUBO->Push(w * h * 4, &bindOffset, &bindBuf);
uint32_t *data = (uint32_t *)frame->pushUBO->Push(w * h * 4, &bindOffset, &bindBuf);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
// data[y*w + x] = ((x ^ y) & 1) ? 0xFF808080 : 0xFF000000; // gray/black checkerboard
@ -867,7 +909,6 @@ void DrawEngineVulkan::Resized() {
decJitCache_->Clear();
lastVTypeID_ = -1;
dec_ = NULL;
// TODO: We must also wipe pipelines.
for (auto iter = decoderMap_.begin(); iter != decoderMap_.end(); iter++) {
delete iter->second;
}

View File

@ -87,7 +87,9 @@ public:
framebufferManager_ = fbManager;
}
void Resized(); // TODO: Call
void Resized();
void DeviceLost();
void DeviceRestore(VulkanContext *vulkan);
void SetupVertexDecoder(u32 vertType);
void SetupVertexDecoderInternal(u32 vertType);
@ -160,6 +162,9 @@ public:
private:
struct FrameData;
void InitDeviceObjects();
void DestroyDeviceObjects();
void DecodeVerts(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf);
void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts);
@ -200,6 +205,8 @@ private:
VulkanPushBuffer *pushIndex;
// We do rolling allocation and reset instead of caching across frames. That we might do later.
std::map<DescriptorSetKey, VkDescriptorSet> descSets;
void Destroy(VulkanContext *vulkan);
};
int curFrame_;

View File

@ -94,6 +94,17 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(VulkanContext *vulkan) :
pipelinePostShader_(VK_NULL_HANDLE),
vulkan2D_(vulkan) {
InitDeviceObjects();
}
FramebufferManagerVulkan::~FramebufferManagerVulkan() {
delete[] convBuf_;
vulkan2D_.Shutdown();
DestroyDeviceObjects();
}
void FramebufferManagerVulkan::InitDeviceObjects() {
// Create a bunch of render pass objects, for normal rendering with a depth buffer,
// with and without pre-clearing of both depth/stencil and color, so 4 combos.
VkAttachmentDescription attachments[2] = {};
@ -189,33 +200,47 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(VulkanContext *vulkan) :
assert(res == VK_SUCCESS);
}
FramebufferManagerVulkan::~FramebufferManagerVulkan() {
delete[] convBuf_;
vulkan_->Delete().QueueDeleteRenderPass(rpLoadColorLoadDepth_);
vulkan_->Delete().QueueDeleteRenderPass(rpClearColorLoadDepth_);
vulkan_->Delete().QueueDeleteRenderPass(rpClearColorClearDepth_);
vulkan_->Delete().QueueDeleteRenderPass(rpLoadColorClearDepth_);
void FramebufferManagerVulkan::DestroyDeviceObjects() {
if (rpLoadColorLoadDepth_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteRenderPass(rpLoadColorLoadDepth_);
if (rpClearColorLoadDepth_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteRenderPass(rpClearColorLoadDepth_);
if (rpClearColorClearDepth_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteRenderPass(rpClearColorClearDepth_);
if (rpLoadColorClearDepth_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteRenderPass(rpLoadColorClearDepth_);
for (int i = 0; i < 2; i++) {
if (frameData_[i].numCommandBuffers_ > 0) {
vkFreeCommandBuffers(vulkan_->GetDevice(), frameData_[i].cmdPool_, frameData_[i].numCommandBuffers_, frameData_[i].commandBuffers_);
frameData_[i].numCommandBuffers_ = 0;
frameData_[i].totalCommandBuffers_ = 0;
}
if (frameData_[i].cmdPool_ != VK_NULL_HANDLE) {
vkDestroyCommandPool(vulkan_->GetDevice(), frameData_[i].cmdPool_, nullptr);
frameData_[i].cmdPool_ = VK_NULL_HANDLE;
}
if (frameData_[i].push_) {
frameData_[i].push_->Destroy(vulkan_);
delete frameData_[i].push_;
frameData_[i].push_ = nullptr;
}
vkDestroyCommandPool(vulkan_->GetDevice(), frameData_[i].cmdPool_, nullptr);
frameData_[i].push_->Destroy(vulkan_);
delete frameData_[i].push_;
}
delete drawPixelsTex_;
drawPixelsTex_ = nullptr;
vulkan_->Delete().QueueDeleteShaderModule(fsBasicTex_);
vulkan_->Delete().QueueDeleteShaderModule(vsBasicTex_);
if (fsBasicTex_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteShaderModule(fsBasicTex_);
if (vsBasicTex_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteShaderModule(vsBasicTex_);
vulkan_->Delete().QueueDeleteSampler(linearSampler_);
vulkan_->Delete().QueueDeleteSampler(nearestSampler_);
vulkan_->Delete().QueueDeletePipeline(pipelineBasicTex_);
if (pipelinePostShader_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeletePipeline(pipelinePostShader_);
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache2D_);
if (linearSampler_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteSampler(linearSampler_);
if (nearestSampler_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteSampler(nearestSampler_);
// pipelineBasicTex_ and pipelineBasicTex_ come from vulkan2D_.
if (pipelineCache2D_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache2D_);
}
void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth) {
@ -1514,10 +1539,20 @@ void FramebufferManagerVulkan::EndFrame() {
}
void FramebufferManagerVulkan::DeviceLost() {
vulkan2D_.DeviceLost();
DestroyAllFBOs(false);
DestroyDeviceObjects();
resized_ = false;
}
void FramebufferManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
vulkan2D_.DeviceRestore(vulkan_);
InitDeviceObjects();
}
std::vector<FramebufferInfo> FramebufferManagerVulkan::GetFramebufferList() {
std::vector<FramebufferInfo> list;

View File

@ -104,6 +104,7 @@ public:
void Resized();
void DeviceLost();
void DeviceRestore(VulkanContext *vulkan);
void CopyDisplayToOutput();
int GetLineWidth();
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old);
@ -174,6 +175,9 @@ private:
void PackFramebufferAsync_(VirtualFramebuffer *vfb);
void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h);
void InitDeviceObjects();
void DestroyDeviceObjects();
VulkanContext *vulkan_;
// The command buffer of the current framebuffer pass being rendered to.

View File

@ -494,6 +494,8 @@ void GPU_Vulkan::BeginHostFrame() {
if (resized_) {
CheckGPUFeatures();
// In case the GPU changed.
BuildReportingInfo();
UpdateCmdInfo();
drawEngine_.Resized();
textureCache_.NotifyConfigChanged();
@ -524,7 +526,6 @@ void GPU_Vulkan::EndHostFrame() {
}
// Needs to be called on GPU thread, not reporting thread.
// TODO
void GPU_Vulkan::BuildReportingInfo() {
const auto &props = vulkan_->GetPhysicalDeviceProperties();
const auto &features = vulkan_->GetFeaturesAvailable();
@ -1944,11 +1945,25 @@ void GPU_Vulkan::FastLoadBoneMatrix(u32 target) {
}
void GPU_Vulkan::DeviceLost() {
// TODO
framebufferManager_->DeviceLost();
drawEngine_.DeviceLost();
pipelineManager_->DeviceLost();
textureCache_.DeviceLost();
depalShaderCache_.Clear();
shaderManager_->ClearShaders();
}
void GPU_Vulkan::DeviceRestore() {
// TODO
vulkan_ = (VulkanContext *)PSP_CoreParameter().graphicsContext->GetAPIContext();
CheckGPUFeatures();
BuildReportingInfo();
UpdateCmdInfo();
framebufferManager_->DeviceRestore(vulkan_);
drawEngine_.DeviceRestore(vulkan_);
pipelineManager_->DeviceRestore(vulkan_);
textureCache_.DeviceRestore(vulkan_);
shaderManager_->DeviceRestore(vulkan_);
}
void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {

View File

@ -13,7 +13,8 @@ PipelineManagerVulkan::PipelineManagerVulkan(VulkanContext *vulkan) : vulkan_(vu
PipelineManagerVulkan::~PipelineManagerVulkan() {
Clear();
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
if (pipelineCache_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
}
void PipelineManagerVulkan::Clear() {
@ -27,6 +28,17 @@ void PipelineManagerVulkan::Clear() {
pipelines_.clear();
}
void PipelineManagerVulkan::DeviceLost() {
Clear();
if (pipelineCache_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
}
void PipelineManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
pipelineCache_ = vulkan->CreatePipelineCache();
}
struct DeclTypeInfo {
VkFormat type;
const char *name;

View File

@ -87,6 +87,9 @@ public:
void Clear();
void DeviceLost();
void DeviceRestore(VulkanContext *vulkan);
std::string DebugGetObjectString(std::string id, DebugShaderType type, DebugShaderStringType stringType);
std::vector<std::string> DebugGetObjectIDs(DebugShaderType type);

View File

@ -81,7 +81,7 @@ VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, ShaderID id, c
}
VulkanFragmentShader::~VulkanFragmentShader() {
if (module_) {
if (module_ != VK_NULL_HANDLE) {
vulkan_->Delete().QueueDeleteShaderModule(module_);
}
}
@ -134,7 +134,7 @@ VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, ShaderID id, const
}
VulkanVertexShader::~VulkanVertexShader() {
if (module_) {
if (module_ != VK_NULL_HANDLE) {
vulkan_->Delete().QueueDeleteShaderModule(module_);
}
}
@ -437,6 +437,11 @@ void ShaderManagerVulkan::BoneUpdateUniforms(int dirtyUniforms) {
}
}
void ShaderManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
}
void ShaderManagerVulkan::Clear() {
for (auto iter = fsCache_.begin(); iter != fsCache_.end(); ++iter) {
delete iter->second;

View File

@ -229,6 +229,8 @@ public:
ShaderManagerVulkan(VulkanContext *vulkan);
~ShaderManagerVulkan();
void DeviceRestore(VulkanContext *vulkan);
void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform);
void ClearShaders();
void DirtyShader();

View File

@ -129,6 +129,17 @@ VkSampler SamplerCache::GetOrCreateSampler(const SamplerCacheKey &key) {
return sampler;
}
void SamplerCache::DeviceLost() {
for (auto iter : cache_) {
vulkan_->Delete().QueueDeleteSampler(iter.second);
}
cache_.clear();
}
void SamplerCache::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
}
TextureCacheVulkan::TextureCacheVulkan(VulkanContext *vulkan)
: vulkan_(vulkan), samplerCache_(vulkan), secondCacheSizeEstimate_(0),
clearCacheNextFrame_(false), lowMemoryMode_(false), texelsScaledThisFrame_(0) {
@ -153,21 +164,45 @@ TextureCacheVulkan::~TextureCacheVulkan() {
}, allocator_);
}
void TextureCacheVulkan::DeviceLost() {
Clear(true);
if (allocator_) {
allocator_->Destroy();
// We have to delete on queue, so this can free its queued deletions.
vulkan_->Delete().QueueCallback([](void *ptr) {
auto allocator = static_cast<VulkanDeviceAllocator *>(ptr);
delete allocator;
}, allocator_);
allocator_ = nullptr;
}
samplerCache_.DeviceLost();
nextTexture_ = nullptr;
}
void TextureCacheVulkan::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
allocator_ = new VulkanDeviceAllocator(vulkan_, TEXCACHE_MIN_SLAB_SIZE, TEXCACHE_MAX_SLAB_SIZE);
samplerCache_.DeviceRestore(vulkan);
}
void TextureCacheVulkan::DownloadFramebufferForClut(u32 clutAddr, u32 bytes) {
}
void TextureCacheVulkan::Clear(bool delete_them) {
lastBoundTexture = nullptr;
if (delete_them) {
for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) {
DEBUG_LOG(G3D, "Deleting texture %p", iter->second.vkTex);
delete iter->second.vkTex;
}
for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) {
DEBUG_LOG(G3D, "Deleting texture %p", iter->second.vkTex);
delete iter->second.vkTex;
}
for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) {
DEBUG_LOG(G3D, "Deleting texture %p", iter->second.vkTex);
delete iter->second.vkTex;
}
for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) {
DEBUG_LOG(G3D, "Deleting texture %p", iter->second.vkTex);
delete iter->second.vkTex;
}
if (cache.size() + secondCache.size()) {
INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache.size() + secondCache.size()));
@ -1153,7 +1188,7 @@ bool TextureCacheVulkan::HandleTextureChange(TexCacheEntry *const entry, const c
return false;
}
void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry,VulkanPushBuffer *uploadBuffer) {
void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, VulkanPushBuffer *uploadBuffer) {
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;
// For the estimate, we assume cluts always point to 8888 for simplicity.

View File

@ -75,6 +75,9 @@ public:
~SamplerCache();
VkSampler GetOrCreateSampler(const SamplerCacheKey &key);
void DeviceLost();
void DeviceRestore(VulkanContext *vulkan);
private:
VulkanContext *vulkan_;
std::map<SamplerCacheKey, VkSampler> cache_;
@ -96,6 +99,9 @@ public:
void InvalidateAll(GPUInvalidationType type);
void ClearNextFrame();
void DeviceLost();
void DeviceRestore(VulkanContext *vulkan);
void SetFramebufferManager(FramebufferManagerVulkan *fbManager) {
framebufferManager_ = fbManager;
}

View File

@ -48,6 +48,40 @@ void VulkanFBO::Create(VulkanContext *vulkan, VkRenderPass rp_compatible, int wi
}
Vulkan2D::Vulkan2D(VulkanContext *vulkan) : vulkan_(vulkan) {
InitDeviceObjects();
}
Vulkan2D::~Vulkan2D() {
DestroyDeviceObjects();
}
void Vulkan2D::Shutdown() {
DestroyDeviceObjects();
}
void Vulkan2D::DestroyDeviceObjects() {
for (int i = 0; i < 2; i++) {
if (frameData_[i].descPool != VK_NULL_HANDLE) {
vulkan_->Delete().QueueDeleteDescriptorPool(frameData_[i].descPool);
}
}
for (auto it : pipelines_) {
vulkan_->Delete().QueueDeletePipeline(it.second);
}
pipelines_.clear();
VkDevice device = vulkan_->GetDevice();
if (descriptorSetLayout_ != VK_NULL_HANDLE) {
vkDestroyDescriptorSetLayout(device, descriptorSetLayout_, nullptr);
descriptorSetLayout_ = VK_NULL_HANDLE;
}
if (pipelineLayout_ != VK_NULL_HANDLE) {
vkDestroyPipelineLayout(device, pipelineLayout_, nullptr);
pipelineLayout_ = VK_NULL_HANDLE;
}
}
void Vulkan2D::InitDeviceObjects() {
// All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated.
VkDescriptorSetLayoutBinding bindings[2] = {};
bindings[0].descriptorCount = 1;
@ -96,13 +130,13 @@ Vulkan2D::Vulkan2D(VulkanContext *vulkan) : vulkan_(vulkan) {
assert(VK_SUCCESS == res);
}
Vulkan2D::~Vulkan2D() {
VkDevice device = vulkan_->GetDevice();
for (int i = 0; i < 2; i++) {
vulkan_->Delete().QueueDeleteDescriptorPool(frameData_[i].descPool);
}
vkDestroyDescriptorSetLayout(device, descriptorSetLayout_, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout_, nullptr);
void Vulkan2D::DeviceLost() {
DestroyDeviceObjects();
}
void Vulkan2D::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
InitDeviceObjects();
}
void Vulkan2D::BeginFrame() {
@ -324,4 +358,4 @@ VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits
return VK_NULL_HANDLE;
}
}
}
}

View File

@ -79,6 +79,10 @@ public:
Vulkan2D(VulkanContext *vulkan);
~Vulkan2D();
void DeviceLost();
void DeviceRestore(VulkanContext *vulkan);
void Shutdown();
VkPipeline GetPipeline(VkPipelineCache cache, VkRenderPass rp, VkShaderModule vs, VkShaderModule fs);
void BeginFrame();
@ -95,6 +99,9 @@ public:
};
private:
void InitDeviceObjects();
void DestroyDeviceObjects();
VulkanContext *vulkan_;
VkDescriptorSetLayout descriptorSetLayout_;
VkPipelineLayout pipelineLayout_;
@ -131,4 +138,4 @@ private:
};
VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code, std::string *error);
VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code, std::string *error);