Permalink
Browse files

Merge pull request #10079 from hrydgard/vulkan-android-fixes

Vulkan lost-device fixes
  • Loading branch information...
hrydgard committed Nov 10, 2017
2 parents 6ae8b36 + 3e7d913 commit f014735ebfb7466b7bc167d41070360d52b4522a
@@ -65,6 +65,16 @@ std::string VulkanVendorString(uint32_t vendorId) {
}
}
const char *PresentModeString(VkPresentModeKHR presentMode) {
switch (presentMode) {
case VK_PRESENT_MODE_IMMEDIATE_KHR: return "IMMEDIATE";
case VK_PRESENT_MODE_MAILBOX_KHR: return "MAILBOX";
case VK_PRESENT_MODE_FIFO_KHR: return "FIFO";
case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "FIFO_RELAXED";
default: return "UNKNOWN";
}
}
VulkanContext::VulkanContext() {
if (!VulkanLoad()) {
init_error_ = "Failed to load Vulkan driver library";
@@ -165,8 +175,13 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32
}
VulkanContext::~VulkanContext() {
assert(instance_ == VK_NULL_HANDLE);
}
void VulkanContext::DestroyInstance() {
vkDestroyInstance(instance_, nullptr);
VulkanFree();
instance_ = VK_NULL_HANDLE;
}
void VulkanContext::BeginFrame() {
@@ -214,6 +229,7 @@ bool VulkanContext::InitObjects() {
}
void VulkanContext::DestroyObjects() {
ILOG("VulkanContext::DestroyObjects (including swapchain)");
if (swapchain_ != VK_NULL_HANDLE)
vkDestroySwapchainKHR(device_, swapchain_, nullptr);
swapchain_ = VK_NULL_HANDLE;
@@ -580,12 +596,15 @@ void VulkanContext::InitSurfaceAndroid(ANativeWindow *wnd, int width, int height
void VulkanContext::ReinitSurfaceAndroid(int width, int height) {
if (surface_ != VK_NULL_HANDLE) {
ILOG("Destroying Android Vulkan surface (%d, %d)", width_, height_);
vkDestroySurfaceKHR(instance_, surface_, nullptr);
surface_ = VK_NULL_HANDLE;
}
VkResult U_ASSERT_ONLY res;
ILOG("Creating Android Vulkan surface (%d, %d)", width, height);
VkAndroidSurfaceCreateInfoKHR android = { VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR };
android.flags = 0;
android.window = native_window;
@@ -710,7 +729,7 @@ bool VulkanContext::InitSwapchain() {
// to fall back in a sensible way.
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
for (size_t i = 0; i < presentModeCount; i++) {
ILOG("Supported present mode: %d", presentModes[i]);
ILOG("Supported present mode: %d (%s)", presentModes[i], PresentModeString(presentModes[i]));
}
for (size_t i = 0; i < presentModeCount; i++) {
if (swapchainPresentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) {
@@ -734,7 +753,7 @@ bool VulkanContext::InitSwapchain() {
// HACK
swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
#endif
ILOG("Chosen present mode: %d", swapchainPresentMode);
ILOG("Chosen present mode: %d (%s)", swapchainPresentMode, PresentModeString(swapchainPresentMode));
delete[] presentModes;
// Determine the number of VkImage's to use in the swap chain (we desire to
// own only 1 image at a time, besides the images being displayed and
@@ -797,6 +816,7 @@ VkFence VulkanContext::CreateFence(bool presignalled) {
}
void VulkanContext::DestroyDevice() {
ILOG("VulkanContext::DestroyDevice (performing deletes)");
// If there happen to be any pending deletes, now is a good time.
for (int i = 0; i < ARRAY_SIZE(frame_); i++) {
frame_[i].deleteList.PerformDeletes(device_);
@@ -962,3 +982,103 @@ const char *VulkanResultToString(VkResult res) {
return "VK_ERROR_...(unknown)";
}
}
void VulkanDeleteList::Take(VulkanDeleteList &del) {
assert(cmdPools_.size() == 0);
assert(descPools_.size() == 0);
assert(modules_.size() == 0);
assert(buffers_.size() == 0);
assert(bufferViews_.size() == 0);
assert(images_.size() == 0);
assert(imageViews_.size() == 0);
assert(deviceMemory_.size() == 0);
assert(samplers_.size() == 0);
assert(pipelines_.size() == 0);
assert(pipelineCaches_.size() == 0);
assert(renderPasses_.size() == 0);
assert(framebuffers_.size() == 0);
assert(callbacks_.size() == 0);
cmdPools_ = std::move(del.cmdPools_);
descPools_ = std::move(del.descPools_);
modules_ = std::move(del.modules_);
buffers_ = std::move(del.buffers_);
bufferViews_ = std::move(del.bufferViews_);
images_ = std::move(del.images_);
imageViews_ = std::move(del.imageViews_);
deviceMemory_ = std::move(del.deviceMemory_);
samplers_ = std::move(del.samplers_);
pipelines_ = std::move(del.pipelines_);
pipelineCaches_ = std::move(del.pipelineCaches_);
renderPasses_ = std::move(del.renderPasses_);
framebuffers_ = std::move(del.framebuffers_);
pipelineLayouts_ = std::move(del.pipelineLayouts_);
descSetLayouts_ = std::move(del.descSetLayouts_);
callbacks_ = std::move(del.callbacks_);
}
void VulkanDeleteList::PerformDeletes(VkDevice device) {
for (auto &cmdPool : cmdPools_) {
vkDestroyCommandPool(device, cmdPool, nullptr);
}
cmdPools_.clear();
for (auto &descPool : descPools_) {
vkDestroyDescriptorPool(device, descPool, nullptr);
}
descPools_.clear();
for (auto &module : modules_) {
vkDestroyShaderModule(device, module, nullptr);
}
modules_.clear();
for (auto &buf : buffers_) {
vkDestroyBuffer(device, buf, nullptr);
}
buffers_.clear();
for (auto &bufView : bufferViews_) {
vkDestroyBufferView(device, bufView, nullptr);
}
bufferViews_.clear();
for (auto &image : images_) {
vkDestroyImage(device, image, nullptr);
}
images_.clear();
for (auto &imageView : imageViews_) {
vkDestroyImageView(device, imageView, nullptr);
}
imageViews_.clear();
for (auto &mem : deviceMemory_) {
vkFreeMemory(device, mem, nullptr);
}
deviceMemory_.clear();
for (auto &sampler : samplers_) {
vkDestroySampler(device, sampler, nullptr);
}
samplers_.clear();
for (auto &pipeline : pipelines_) {
vkDestroyPipeline(device, pipeline, nullptr);
}
pipelines_.clear();
for (auto &pcache : pipelineCaches_) {
vkDestroyPipelineCache(device, pcache, nullptr);
}
pipelineCaches_.clear();
for (auto &renderPass : renderPasses_) {
vkDestroyRenderPass(device, renderPass, nullptr);
}
renderPasses_.clear();
for (auto &framebuffer : framebuffers_) {
vkDestroyFramebuffer(device, framebuffer, nullptr);
}
framebuffers_.clear();
for (auto &pipeLayout : pipelineLayouts_) {
vkDestroyPipelineLayout(device, pipeLayout, nullptr);
}
pipelineLayouts_.clear();
for (auto &descSetLayout : descSetLayouts_) {
vkDestroyDescriptorSetLayout(device, descSetLayout, nullptr);
}
descSetLayouts_.clear();
for (auto &callback : callbacks_) {
callback.func(callback.userdata);
}
callbacks_.clear();
}
@@ -71,6 +71,7 @@ class VulkanDeleteList {
};
public:
// NOTE: These all take reference handles so they can zero the input value.
void QueueDeleteCommandPool(VkCommandPool &pool) { cmdPools_.push_back(pool); pool = VK_NULL_HANDLE; }
void QueueDeleteDescriptorPool(VkDescriptorPool &pool) { descPools_.push_back(pool); pool = VK_NULL_HANDLE; }
void QueueDeleteShaderModule(VkShaderModule &module) { modules_.push_back(module); module = VK_NULL_HANDLE; }
@@ -88,105 +89,8 @@ class VulkanDeleteList {
void QueueDeleteDescriptorSetLayout(VkDescriptorSetLayout &descSetLayout) { descSetLayouts_.push_back(descSetLayout); descSetLayout = VK_NULL_HANDLE; }
void QueueCallback(void(*func)(void *userdata), void *userdata) { callbacks_.push_back(Callback(func, userdata)); }
void Take(VulkanDeleteList &del) {
assert(cmdPools_.size() == 0);
assert(descPools_.size() == 0);
assert(modules_.size() == 0);
assert(buffers_.size() == 0);
assert(bufferViews_.size() == 0);
assert(images_.size() == 0);
assert(imageViews_.size() == 0);
assert(deviceMemory_.size() == 0);
assert(samplers_.size() == 0);
assert(pipelines_.size() == 0);
assert(pipelineCaches_.size() == 0);
assert(renderPasses_.size() == 0);
assert(framebuffers_.size() == 0);
assert(callbacks_.size() == 0);
cmdPools_ = std::move(del.cmdPools_);
descPools_ = std::move(del.descPools_);
modules_ = std::move(del.modules_);
buffers_ = std::move(del.buffers_);
bufferViews_ = std::move(del.bufferViews_);
images_ = std::move(del.images_);
imageViews_ = std::move(del.imageViews_);
deviceMemory_ = std::move(del.deviceMemory_);
samplers_ = std::move(del.samplers_);
pipelines_ = std::move(del.pipelines_);
pipelineCaches_ = std::move(del.pipelineCaches_);
renderPasses_ = std::move(del.renderPasses_);
framebuffers_ = std::move(del.framebuffers_);
pipelineLayouts_ = std::move(del.pipelineLayouts_);
descSetLayouts_ = std::move(del.descSetLayouts_);
callbacks_ = std::move(del.callbacks_);
}
void PerformDeletes(VkDevice device) {
for (auto &cmdPool : cmdPools_) {
vkDestroyCommandPool(device, cmdPool, nullptr);
}
cmdPools_.clear();
for (auto &descPool : descPools_) {
vkDestroyDescriptorPool(device, descPool, nullptr);
}
descPools_.clear();
for (auto &module : modules_) {
vkDestroyShaderModule(device, module, nullptr);
}
modules_.clear();
for (auto &buf : buffers_) {
vkDestroyBuffer(device, buf, nullptr);
}
buffers_.clear();
for (auto &bufView : bufferViews_) {
vkDestroyBufferView(device, bufView, nullptr);
}
bufferViews_.clear();
for (auto &image : images_) {
vkDestroyImage(device, image, nullptr);
}
images_.clear();
for (auto &imageView : imageViews_) {
vkDestroyImageView(device, imageView, nullptr);
}
imageViews_.clear();
for (auto &mem : deviceMemory_) {
vkFreeMemory(device, mem, nullptr);
}
deviceMemory_.clear();
for (auto &sampler : samplers_) {
vkDestroySampler(device, sampler, nullptr);
}
samplers_.clear();
for (auto &pipeline : pipelines_) {
vkDestroyPipeline(device, pipeline, nullptr);
}
pipelines_.clear();
for (auto &pcache : pipelineCaches_) {
vkDestroyPipelineCache(device, pcache, nullptr);
}
pipelineCaches_.clear();
for (auto &renderPass : renderPasses_) {
vkDestroyRenderPass(device, renderPass, nullptr);
}
renderPasses_.clear();
for (auto &framebuffer : framebuffers_) {
vkDestroyFramebuffer(device, framebuffer, nullptr);
}
framebuffers_.clear();
for (auto &pipeLayout : pipelineLayouts_) {
vkDestroyPipelineLayout(device, pipeLayout, nullptr);
}
pipelineLayouts_.clear();
for (auto &descSetLayout : descSetLayouts_) {
vkDestroyDescriptorSetLayout(device, descSetLayout, nullptr);
}
descSetLayouts_.clear();
for (auto &callback : callbacks_) {
callback.func(callback.userdata);
}
callbacks_.clear();
}
void Take(VulkanDeleteList &del);
void PerformDeletes(VkDevice device);
private:
std::vector<VkCommandPool> cmdPools_;
@@ -214,7 +118,8 @@ class VulkanContext {
~VulkanContext();
VkResult CreateInstance(const char *app_name, int app_ver, uint32_t flags);
void DestroyInstance();
int GetBestPhysicalDevice();
void ChooseDevice(int physical_device);
bool EnableDeviceExtension(const char *extension);
@@ -78,7 +78,6 @@ void VulkanPushBuffer::Destroy(VulkanContext *vulkan) {
vulkan->Delete().QueueDeleteBuffer(info.buffer);
vulkan->Delete().QueueDeleteDeviceMemory(info.deviceMemory);
}
buffers_.clear();
}
View
@@ -172,7 +172,7 @@ bool UpdateScreenScale(int width, int height) {
dp_yres = new_dp_yres;
pixel_xres = width;
pixel_yres = height;
INFO_LOG(SYSTEM, "pixel_res: %dx%d", pixel_xres, pixel_yres);
INFO_LOG(SYSTEM, "pixel_res: %dx%d. Calling NativeResized()", pixel_xres, pixel_yres);
NativeResized();
return true;
}
@@ -137,13 +137,6 @@ void SoftwareTransform(
bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0;
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
// TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts.
#if defined(MOBILE_DEVICE)
if (vertexCount > 0x10000/3)
vertexCount = 0x10000/3;
#endif
float uscale = 1.0f;
float vscale = 1.0f;
if (throughmode) {
@@ -701,8 +701,15 @@ void DrawEngineGLES::DoFlush() {
params.allowSeparateAlphaClear = true;
int maxIndex = indexGen.MaxIndex();
int vertexCount = indexGen.VertexCount();
// TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts.
#if defined(MOBILE_DEVICE)
if (vertexCount > 0x10000 / 3)
vertexCount = 0x10000 / 3;
#endif
SoftwareTransform(
prim, indexGen.VertexCount(),
prim, vertexCount,
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
maxIndex, drawBuffer, numTrans, drawIndexed, &params, &result);
ApplyDrawStateLate();
@@ -60,14 +60,26 @@ static VkFormat GetClutDestFormat(GEPaletteFormat format, VkComponentMapping *co
DepalShaderCacheVulkan::DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan)
: draw_(draw), vulkan_(vulkan) {
std::string errors;
vshader_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_VERTEX_BIT, depal_vs, &errors);
assert(vshader_ != VK_NULL_HANDLE);
DeviceRestore(draw, vulkan);
}
DepalShaderCacheVulkan::~DepalShaderCacheVulkan() {
DeviceLost();
}
void DepalShaderCacheVulkan::DeviceLost() {
Clear();
vulkan_->Delete().QueueDeleteShaderModule(vshader_);
draw_ = nullptr;
vulkan_ = nullptr;
}
void DepalShaderCacheVulkan::DeviceRestore(Draw::DrawContext *draw, VulkanContext *vulkan) {
draw_ = draw;
vulkan_ = vulkan;
std::string errors;
vshader_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_VERTEX_BIT, depal_vs, &errors);
assert(vshader_ != VK_NULL_HANDLE);
}
DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat) {
@@ -52,6 +52,8 @@ class DepalShaderCacheVulkan : public DepalShaderCacheCommon {
public:
DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan);
~DepalShaderCacheVulkan();
void DeviceLost();
void DeviceRestore(Draw::DrawContext *draw, VulkanContext *vulkan);
// This also uploads the palette and binds the correct texture.
DepalShaderVulkan *GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat);
Oops, something went wrong.

0 comments on commit f014735

Please sign in to comment.