mirror of
https://github.com/libretro/ppsspp.git
synced 2024-12-04 23:16:41 +00:00
Merge pull request #9041 from unknownbrackets/vulkan
WIP: Progress toward device restore on Vulkan
This commit is contained in:
commit
405ac4f2cc
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user