diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index efe327c27..b641e4df9 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -71,6 +71,11 @@ static void display_vmus(); static void reset_vmus(); static void term_vmus(); +float gui_get_scaling() +{ + return scaling; +} + void gui_init() { if (inited) @@ -237,9 +242,9 @@ void ImGui_Impl_NewFrame() } static double last_render; -std::vector render_times; +std::vector render_times(100); -void gui_dosmth(int width, int height) +void gui_rendertick() { if (last_render == 0) { @@ -251,15 +256,11 @@ void gui_dosmth(int width, int height) if (render_times.size() > 100) render_times.erase(render_times.begin()); last_render = new_time; +} - ImGui_Impl_NewFrame(); - ImGui::NewFrame(); - +void gui_plot_render_time(int width, int height) +{ ImGui::PlotLines("Render Times", &render_times[0], render_times.size(), 0, "", 0.0, 1.0 / 30.0, ImVec2(300, 50)); - - // Render dear imgui into screen - ImGui::Render(); - ImGui_impl_RenderDrawData(ImGui::GetDrawData()); } // Helper to display a little (?) mark which shows a tooltip when hovered. @@ -1665,6 +1666,7 @@ void gui_display_osd() } if (settings.rend.FloatVMUs) display_vmus(); +// gui_plot_render_time(screen_width, screen_height); ImGui::Render(); ImGui_impl_RenderDrawData(ImGui::GetDrawData()); @@ -1713,8 +1715,9 @@ void gui_refresh_files() #define VMU_WIDTH (70 * 48 * scaling / 32) #define VMU_HEIGHT (70 * scaling) #define VMU_PADDING (8 * scaling) -static u32 vmu_lcd_data[8][48 * 32]; -static bool vmu_lcd_status[8]; +u32 vmu_lcd_data[8][48 * 32]; +bool vmu_lcd_status[8]; +bool vmu_lcd_changed[8]; static ImTextureID vmu_lcd_tex_ids[8]; void push_vmu_screen(int bus_id, int bus_port, u8* buffer) @@ -1726,6 +1729,7 @@ void push_vmu_screen(int bus_id, int bus_port, u8* buffer) for (int i = 0; i < ARRAY_SIZE(vmu_lcd_data[vmu_id]); i++, buffer++) *p++ = *buffer != 0 ? 0xFFFFFFFFu : 0xFF000000u; vmu_lcd_status[vmu_id] = true; + vmu_lcd_changed[vmu_id] = true; } static const int vmu_coords[8][2] = { @@ -1743,7 +1747,6 @@ static void display_vmus() { if (!game_started) return; - // TODO Vulkan if (!settings.pvr.IsOpenGL()) return; ImGui::SetNextWindowBgAlpha(0); @@ -1794,7 +1797,6 @@ static void reset_vmus() static void term_vmus() { - // TODO Vulkan if (!settings.pvr.IsOpenGL()) return; for (int i = 0; i < ARRAY_SIZE(vmu_lcd_status); i++) diff --git a/core/rend/gui.h b/core/rend/gui.h index bfa0c063a..a40d3c89c 100644 --- a/core/rend/gui.h +++ b/core/rend/gui.h @@ -17,6 +17,7 @@ along with reicast. If not, see . */ #pragma once +#include "types.h" void gui_init(); void gui_open_settings(); @@ -28,6 +29,9 @@ void gui_term(); void gui_refresh_files(); extern int screen_dpi; +extern u32 vmu_lcd_data[8][48 * 32]; +extern bool vmu_lcd_status[8]; +extern bool vmu_lcd_changed[8]; typedef enum { Closed, Commands, Settings, ClosedNoResume, Main, Onboarding, VJoyEdit, VJoyEditCommands } GuiState; extern GuiState gui_state; @@ -41,3 +45,4 @@ static inline bool gui_is_content_browser() { return gui_state == Main; } +float gui_get_scaling(); diff --git a/core/rend/gui_util.h b/core/rend/gui_util.h index ade64dfcd..5db77f25c 100644 --- a/core/rend/gui_util.h +++ b/core/rend/gui_util.h @@ -23,6 +23,7 @@ #include "vulkan/imgui_impl_vulkan.h" #include "gles/imgui_impl_opengl3.h" #include "vulkan/vulkan_context.h" +#include "gui.h" typedef void (*StringCallback)(bool cancelled, std::string selection); @@ -35,16 +36,19 @@ static inline void ImGui_impl_RenderDrawData(ImDrawData *draw_data, bool save_ba { VulkanContext *context = VulkanContext::Instance(); bool rendering = context->IsRendering(); + const std::vector *vmuCmdBuffers = nullptr; if (!rendering) { context->NewFrame(); + vmuCmdBuffers = context->PrepareVMUs(); context->BeginRenderPass(); context->PresentLastFrame(); + context->DrawVMUs(gui_get_scaling()); } // Record Imgui Draw Data and draw funcs into command buffer ImGui_ImplVulkan_RenderDrawData(draw_data, (VkCommandBuffer)context->GetCurrentCommandBuffer()); if (!rendering) - context->EndFrame(); + context->EndFrame(vmuCmdBuffers); } else #endif diff --git a/core/rend/vulkan/drawer.h b/core/rend/vulkan/drawer.h index f9ccb0fc5..1b8b98ad3 100644 --- a/core/rend/vulkan/drawer.h +++ b/core/rend/vulkan/drawer.h @@ -108,6 +108,11 @@ protected: void NewImage() { imageIndex = (imageIndex + 1) % GetContext()->GetSwapChainSize(); + if (perStripSorting != settings.rend.PerStripSorting) + { + perStripSorting = settings.rend.PerStripSorting; + pipelineManager->Reset(); + } } void Init(SamplerManager *samplerManager, PipelineManager *pipelineManager) @@ -174,6 +179,7 @@ private: std::vector> sortedPolys; std::vector> sortedIndexes; u32 sortedIndexCount = 0; + bool perStripSorting = false; }; class ScreenDrawer : public Drawer diff --git a/core/rend/vulkan/oit/oit_drawer.cpp b/core/rend/vulkan/oit/oit_drawer.cpp index 3dfc92044..86711991b 100644 --- a/core/rend/vulkan/oit/oit_drawer.cpp +++ b/core/rend/vulkan/oit/oit_drawer.cpp @@ -347,7 +347,7 @@ bool OITDrawer::Draw(const Texture *fogTexture) if (!oitBuffers->isFirstFrameAfterInit()) { // Tr modifier volumes - if (!GetContext()->GetVendorID() != VENDOR_QUALCOMM) // Adreno bug + if (GetContext()->GetVendorID() != VENDOR_QUALCOMM) // Adreno bug DrawModifierVolumes(cmdBuffer, previous_pass.mvo_tr_count, current_pass.mvo_tr_count - previous_pass.mvo_tr_count); vk::Pipeline pipeline = pipelineManager->GetFinalPipeline(current_pass.autosort); diff --git a/core/rend/vulkan/oit/oit_renderer.cpp b/core/rend/vulkan/oit/oit_renderer.cpp index af8556e4f..bcc0607f0 100644 --- a/core/rend/vulkan/oit/oit_renderer.cpp +++ b/core/rend/vulkan/oit/oit_renderer.cpp @@ -45,7 +45,6 @@ public: screenDrawer.Init(&samplerManager, &shaderManager, &oitBuffers); screenDrawer.SetCommandPool(&texCommandPool); - quadBuffer = std::unique_ptr(new QuadBuffer()); #ifdef __ANDROID__ if (!vjoyTexture) @@ -107,7 +106,6 @@ public: textureDrawer.Term(); oitBuffers.Term(); osdBuffer.reset(); - quadBuffer = nullptr; textureCache.Clear(); fogTexture = nullptr; texCommandPool.Term(); @@ -295,7 +293,6 @@ private: } OITBuffers oitBuffers; - std::unique_ptr quadBuffer; std::unique_ptr fogTexture; CommandPool texCommandPool; diff --git a/core/rend/vulkan/pipeline.h b/core/rend/vulkan/pipeline.h index a8d063a64..986da3e80 100644 --- a/core/rend/vulkan/pipeline.h +++ b/core/rend/vulkan/pipeline.h @@ -155,8 +155,7 @@ public: if (this->renderPass != renderPass) { this->renderPass = renderPass; - pipelines.clear(); - modVolPipelines.clear(); + Reset(); } } @@ -182,6 +181,13 @@ public: return *modVolPipelines[pipehash]; } + + void Reset() + { + pipelines.clear(); + modVolPipelines.clear(); + } + vk::PipelineLayout GetPipelineLayout() const { return *pipelineLayout; } vk::DescriptorSetLayout GetPerFrameDSLayout() const { return *perFrameLayout; } vk::DescriptorSetLayout GetPerPolyDSLayout() const { return *perPolyLayout; } diff --git a/core/rend/vulkan/quad.cpp b/core/rend/vulkan/quad.cpp index 473d818cc..a5379c122 100644 --- a/core/rend/vulkan/quad.cpp +++ b/core/rend/vulkan/quad.cpp @@ -128,9 +128,9 @@ void QuadPipeline::Init(ShaderManager *shaderManager, vk::RenderPass renderPass) pipelineLayout = GetContext()->GetDevice().createPipelineLayoutUnique( vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descSetLayout.get())); } - if (!sampler) + if (!linearSampler) { - sampler = GetContext()->GetDevice().createSamplerUnique( + linearSampler = GetContext()->GetDevice().createSamplerUnique( vk::SamplerCreateInfo(vk::SamplerCreateFlags(), vk::Filter::eLinear, vk::Filter::eLinear, vk::SamplerMipmapMode::eLinear, @@ -140,35 +140,50 @@ void QuadPipeline::Init(ShaderManager *shaderManager, vk::RenderPass renderPass) 16.0f, false, vk::CompareOp::eNever, 0.0f, 0.0f, vk::BorderColor::eFloatOpaqueBlack)); } + if (!nearestSampler) + { + nearestSampler = GetContext()->GetDevice().createSamplerUnique( + vk::SamplerCreateInfo(vk::SamplerCreateFlags(), + vk::Filter::eNearest, vk::Filter::eNearest, + vk::SamplerMipmapMode::eNearest, + vk::SamplerAddressMode::eClampToBorder, + vk::SamplerAddressMode::eClampToBorder, + vk::SamplerAddressMode::eClampToBorder, 0.0f, false, + 16.0f, false, vk::CompareOp::eNever, 0.0f, 0.0f, + vk::BorderColor::eFloatOpaqueBlack)); + } if (this->renderPass != renderPass) { this->renderPass = renderPass; pipeline.reset(); } - descriptorSets.resize(GetContext()->GetSwapChainSize()); } -void QuadPipeline::SetTexture(vk::ImageView imageView) +void QuadDrawer::Init(QuadPipeline *pipeline) { - vk::UniqueDescriptorSet &descriptorSet = descriptorSets[GetContext()->GetCurrentImageIndex()]; - if (!descriptorSet) + this->pipeline = pipeline; + buffer = std::unique_ptr(new QuadBuffer()); + descriptorSets.resize(VulkanContext::Instance()->GetSwapChainSize()); +} + +void QuadDrawer::Draw(vk::CommandBuffer commandBuffer, vk::ImageView imageView, QuadVertex vertices[], bool nearestFilter) +{ + VulkanContext *context = GetContext(); + auto &descSet = descriptorSets[context->GetCurrentImageIndex()]; + if (!descSet) { - descriptorSet = std::move( - GetContext()->GetDevice().allocateDescriptorSetsUnique( - vk::DescriptorSetAllocateInfo( - GetContext()->GetDescriptorPool(), 1, - &descSetLayout.get())).front()); + vk::DescriptorSetLayout layout = pipeline->GetDescSetLayout(); + descSet = std::move(context->GetDevice().allocateDescriptorSetsUnique( + vk::DescriptorSetAllocateInfo(context->GetDescriptorPool(), 1, &layout)).front()); } - vk::DescriptorImageInfo imageInfo(*sampler, imageView, vk::ImageLayout::eShaderReadOnlyOptimal); + vk::DescriptorImageInfo imageInfo(nearestFilter ? pipeline->GetNearestSampler() : pipeline->GetLinearSampler(), imageView, vk::ImageLayout::eShaderReadOnlyOptimal); std::vector writeDescriptorSets; writeDescriptorSets.push_back( - vk::WriteDescriptorSet(*descriptorSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, - nullptr, nullptr)); - GetContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr); -} + vk::WriteDescriptorSet(*descSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr)); + context->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr); + commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline->GetPipelineLayout(), 0, 1, &descSet.get(), 0, nullptr); -void QuadPipeline::BindDescriptorSets(vk::CommandBuffer cmdBuffer) -{ - cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *pipelineLayout, 0, 1, - &descriptorSets[GetContext()->GetCurrentImageIndex()].get(), 0, nullptr); + buffer->Update(vertices); + buffer->Bind(commandBuffer); + buffer->Draw(commandBuffer); } diff --git a/core/rend/vulkan/quad.h b/core/rend/vulkan/quad.h index cbcec1f7f..efaf70249 100644 --- a/core/rend/vulkan/quad.h +++ b/core/rend/vulkan/quad.h @@ -54,10 +54,10 @@ public: if (vertices == nullptr) { static QuadVertex defaultVtx[] = { - { { -1, -1, 0 }, { 0, 0 } }, - { { 1, -1, 0 }, { 1, 0 } }, - { { -1, 1, 0 }, { 0, 1 } }, - { { 1, 1, 0 }, { 1, 1 } }, + { { -1.f, -1.f, 0.f }, { 0.f, 0.f } }, + { { 1.f, -1.f, 0.f }, { 1.f, 0.f } }, + { { -1.f, 1.f, 0.f }, { 0.f, 1.f } }, + { { 1.f, 1.f, 0.f }, { 1.f, 1.f } }, }; vertices = defaultVtx; }; @@ -73,29 +73,42 @@ public: void Init(ShaderManager *shaderManager, vk::RenderPass renderPass); void Term() { pipeline.reset(); - sampler.reset(); - descriptorSets.clear(); + linearSampler.reset(); + nearestSampler.reset(); pipelineLayout.reset(); descSetLayout.reset(); } + void BindPipeline(vk::CommandBuffer commandBuffer) { commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, GetPipeline()); } + vk::DescriptorSetLayout GetDescSetLayout() const { return *descSetLayout; } + vk::PipelineLayout GetPipelineLayout() const { return *pipelineLayout; } + vk::Sampler GetLinearSampler() const { return *linearSampler; } + vk::Sampler GetNearestSampler() const { return *nearestSampler; } + +private: vk::Pipeline GetPipeline() { if (!pipeline) CreatePipeline(); return *pipeline; } - - void SetTexture(vk::ImageView imageView); - void BindDescriptorSets(vk::CommandBuffer cmdBuffer); - -private: void CreatePipeline(); vk::RenderPass renderPass; vk::UniquePipeline pipeline; - vk::UniqueSampler sampler; - std::vector descriptorSets; + vk::UniqueSampler linearSampler; + vk::UniqueSampler nearestSampler; vk::UniquePipelineLayout pipelineLayout; vk::UniqueDescriptorSetLayout descSetLayout; ShaderManager *shaderManager; }; + +class QuadDrawer +{ +public: + void Init(QuadPipeline *pipeline); + void Draw(vk::CommandBuffer commandBuffer, vk::ImageView imageView, QuadVertex vertices[] = nullptr, bool nearestFilter = false); +private: + QuadPipeline *pipeline = nullptr; + std::unique_ptr buffer; + std::vector descriptorSets; +}; diff --git a/core/rend/vulkan/texture.h b/core/rend/vulkan/texture.h index 3a8bcff82..4dfc76961 100644 --- a/core/rend/vulkan/texture.h +++ b/core/rend/vulkan/texture.h @@ -30,11 +30,6 @@ void setImageLayout(vk::CommandBuffer const& commandBuffer, vk::Image image, vk: struct Texture : BaseTextureCacheData { - ~Texture() override - { - imageView.reset(); - image.reset(); - } void UploadToGPU(int width, int height, u8 *data) override; u64 GetIntId() { return (u64)reinterpret_cast(this); } std::string GetId() override { char s[20]; sprintf(s, "%p", this); return s; } @@ -61,14 +56,13 @@ private: std::unique_ptr stagingBufferData; vk::CommandBuffer commandBuffer; - vk::UniqueDeviceMemory deviceMemory; - vk::UniqueImageView imageView; + Allocation allocation; vk::UniqueImage image; + vk::UniqueImageView imageView; vk::ImageView readOnlyImageView; vk::PhysicalDevice physicalDevice; vk::Device device; - Allocation allocation; friend class TextureDrawer; friend class OITTextureDrawer; @@ -125,13 +119,13 @@ private: vk::Extent2D extent; std::unique_ptr stagingBufferData; + Allocation allocation; + vk::UniqueImage image; vk::UniqueImageView imageView; vk::UniqueImageView stencilView; - vk::UniqueImage image; vk::PhysicalDevice physicalDevice; vk::Device device; - Allocation allocation; }; class TextureCache : public BaseTextureCache diff --git a/core/rend/vulkan/vmu.cpp b/core/rend/vulkan/vmu.cpp new file mode 100644 index 000000000..39182969d --- /dev/null +++ b/core/rend/vulkan/vmu.cpp @@ -0,0 +1,111 @@ +/* + Created on: Dec 13, 2019 + + Copyright 2019 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . +*/ +#include "vmu.h" +#include "texture.h" +#include "rend/gui.h" + +VulkanVMUs::~VulkanVMUs() +{ +} + +const std::vector* VulkanVMUs::PrepareVMUs(vk::CommandPool commandPool) +{ + VulkanContext *context = VulkanContext::Instance(); + commandBuffers.resize(context->GetSwapChainSize()); + commandBuffers[context->GetCurrentImageIndex()].clear(); + for (int i = 0; i < 8; i++) + { + std::unique_ptr& texture = vmuTextures[i]; + if (!vmu_lcd_status[i]) + { + texture.reset(); + continue; + } + bool update = vmu_lcd_changed[i]; + if (!texture) + { + texture = std::unique_ptr(new Texture()); + update = true; + } + if (!update) + continue; + + texture->tex_type = TextureType::_8888; + texture->SetDevice(context->GetDevice()); + texture->SetPhysicalDevice(context->GetPhysicalDevice()); + commandBuffers[context->GetCurrentImageIndex()].emplace_back(std::move( + VulkanContext::Instance()->GetDevice().allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool, vk::CommandBufferLevel::ePrimary, 1)) + .front())); + texture->SetCommandBuffer(*commandBuffers[context->GetCurrentImageIndex()].back()); + texture->UploadToGPU(48, 32, (u8*)vmu_lcd_data[i]); + texture->SetCommandBuffer(nullptr); + vmu_lcd_changed[i] = false; + } + return &commandBuffers[context->GetCurrentImageIndex()]; +} + +void VulkanVMUs::DrawVMUs(vk::Extent2D viewport, float scaling) +{ + f32 vmu_padding = 8.f * scaling; + f32 vmu_height = 70.f * scaling; + f32 vmu_width = 48.f / 32.f * vmu_height; + + VulkanContext *context = VulkanContext::Instance(); + vk::CommandBuffer commandBuffer = context->GetCurrentCommandBuffer(); + pipeline->BindPipeline(commandBuffer); + float blendConstants[4] = { 0.75f, 0.75f, 0.75f, 0.75f }; + commandBuffer.setBlendConstants(blendConstants); + QuadVertex vtx[] = { + { { -1.f, -1.f, 0.f }, { 0.f, 1.f } }, + { { 1.f, -1.f, 0.f }, { 1.f, 1.f } }, + { { -1.f, 1.f, 0.f }, { 0.f, 0.f } }, + { { 1.f, 1.f, 0.f }, { 1.f, 0.f } }, + }; + + for (int i = 0; i < 8; i++) + { + if (!vmuTextures[i]) + continue; + f32 x; + if (i & 2) + x = viewport.width - vmu_padding - vmu_width; + else + x = vmu_padding; + f32 y; + if (i & 4) + { + y = viewport.height - vmu_padding - vmu_height; + if (i & 1) + y -= vmu_padding + vmu_height; + } + else + { + y = vmu_padding; + if (i & 1) + y += vmu_padding + vmu_height; + } + vk::Viewport viewport(x, y, vmu_width, vmu_height); + commandBuffer.setViewport(0, 1, &viewport); + commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(x, y), vk::Extent2D(vmu_width, vmu_height))); + + drawers[i]->Draw(commandBuffer, vmuTextures[i]->GetImageView(), vtx, true); + } +} diff --git a/core/rend/vulkan/vmu.h b/core/rend/vulkan/vmu.h new file mode 100644 index 000000000..e7b0ba57a --- /dev/null +++ b/core/rend/vulkan/vmu.h @@ -0,0 +1,48 @@ +/* + Created on: Dec 13, 2019 + + Copyright 2019 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . +*/ +#pragma once +#include +#include +#include "quad.h" + +class Texture; + +class VulkanVMUs +{ +public: + ~VulkanVMUs(); + void Init(QuadPipeline *pipeline) { + this->pipeline = pipeline; + for (auto& drawer : drawers) + { + drawer = std::unique_ptr(new QuadDrawer()); + drawer->Init(pipeline); + } + } + const std::vector* PrepareVMUs(vk::CommandPool commandPool); + void DrawVMUs(vk::Extent2D viewport, float scaling); + +private: + std::array, 8> vmuTextures; + std::vector> commandBuffers; + std::array, 8> drawers; + QuadPipeline *pipeline = nullptr; +}; diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index fec633f7c..215b76953 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -29,6 +29,7 @@ #endif #include "compiler.h" #include "utils.h" +#include "texture.h" VulkanContext *VulkanContext::contextInstance; @@ -479,9 +480,9 @@ bool VulkanContext::InitDevice() } allocator.Init(physicalDevice, *device); - quadBuffer = std::unique_ptr(new QuadBuffer()); shaderManager = std::unique_ptr(new ShaderManager()); quadPipeline = std::unique_ptr(new QuadPipeline()); + quadDrawer = std::unique_ptr(new QuadDrawer()); CreateSwapChain(); @@ -648,6 +649,8 @@ void VulkanContext::CreateSwapChain() imageAcquiredSemaphores.push_back(device->createSemaphoreUnique(vk::SemaphoreCreateInfo())); } quadPipeline->Init(shaderManager.get(), *renderPass); + quadDrawer->Init(quadPipeline.get()); + vmus->Init(quadPipeline.get()); InitImgui(); @@ -702,6 +705,7 @@ bool VulkanContext::Init() vk::AndroidSurfaceCreateInfoKHR createInfo(vk::AndroidSurfaceCreateFlagsKHR(), (struct ANativeWindow*)window); surface = instance->createAndroidSurfaceKHRUnique(createInfo); #endif + vmus = std::unique_ptr(new VulkanVMUs()); return InitDevice(); } @@ -731,13 +735,18 @@ void VulkanContext::BeginRenderPass() vk::SubpassContents::eInline); } -void VulkanContext::EndFrame() +void VulkanContext::EndFrame(const std::vector *cmdBuffers) { vk::CommandBuffer commandBuffer = *commandBuffers[currentImage]; commandBuffer.endRenderPass(); commandBuffer.end(); vk::PipelineStageFlags wait_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput; - vk::SubmitInfo submitInfo(1, &(*imageAcquiredSemaphores[currentSemaphore]), &wait_stage, 1, &commandBuffer, 1, &(*renderCompleteSemaphores[currentSemaphore])); + std::vector allCmdBuffers; + if (cmdBuffers != nullptr) + allCmdBuffers = vk::uniqueToRaw(*cmdBuffers); + allCmdBuffers.push_back(commandBuffer); + vk::SubmitInfo submitInfo(1, &(*imageAcquiredSemaphores[currentSemaphore]), &wait_stage, allCmdBuffers.size(),allCmdBuffers.data(), + 1, &(*renderCompleteSemaphores[currentSemaphore])); graphicsQueue.submit(1, &submitInfo, *drawFences[currentImage]); verify(rendering); rendering = false; @@ -769,14 +778,9 @@ void VulkanContext::DrawFrame(vk::ImageView imageView, vk::Offset2D extent) { { -1, 1, 0 }, { 0 - marginWidth, 1 } }, { { 1, 1, 0 }, { 1 + marginWidth, 1 } }, }; - quadBuffer->Update(vtx); vk::CommandBuffer commandBuffer = GetCurrentCommandBuffer(); - vk::Pipeline pipeline = quadPipeline->GetPipeline(); - commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); - - quadPipeline->SetTexture(imageView); - quadPipeline->BindDescriptorSets(commandBuffer); + quadPipeline->BindPipeline(commandBuffer); float blendConstants[4] = { 1.0, 1.0, 1.0, 1.0 }; commandBuffer.setBlendConstants(blendConstants); @@ -784,8 +788,17 @@ void VulkanContext::DrawFrame(vk::ImageView imageView, vk::Offset2D extent) vk::Viewport viewport(0, 0, width, height); commandBuffer.setViewport(0, 1, &viewport); commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), vk::Extent2D(width, height))); - quadBuffer->Bind(commandBuffer); - quadBuffer->Draw(commandBuffer); + quadDrawer->Draw(commandBuffer, imageView, vtx); +} + +const std::vector *VulkanContext::PrepareVMUs() +{ + return vmus->PrepareVMUs(*commandPools[GetCurrentImageIndex()]); +} + + void VulkanContext::DrawVMUs(float scaling) +{ + vmus->DrawVMUs(vk::Extent2D(width, height), scaling); } extern Renderer *renderer; @@ -793,11 +806,17 @@ extern Renderer *renderer; void VulkanContext::PresentFrame(vk::ImageView imageView, vk::Offset2D extent) { NewFrame(); + const std::vector *vmuCmdBuffers = nullptr; + if (settings.rend.FloatVMUs) + vmuCmdBuffers = PrepareVMUs(); + BeginRenderPass(); DrawFrame(imageView, extent); + if (settings.rend.FloatVMUs) + DrawVMUs(gui_get_scaling()); renderer->DrawOSD(false); - EndFrame(); + EndFrame(vmuCmdBuffers); lastFrameView = imageView; lastFrameExtent = extent; @@ -828,12 +847,13 @@ void VulkanContext::Term() } } } + vmus.reset(); ShaderCompiler::Term(); swapChain.reset(); imageViews.clear(); framebuffers.clear(); renderPass.reset(); - quadBuffer.reset(); + quadDrawer.reset(); quadPipeline.reset(); shaderManager.reset(); descriptorPool.reset(); diff --git a/core/rend/vulkan/vulkan_context.h b/core/rend/vulkan/vulkan_context.h index 679d712b2..59785939b 100644 --- a/core/rend/vulkan/vulkan_context.h +++ b/core/rend/vulkan/vulkan_context.h @@ -23,6 +23,7 @@ #include "vmallocator.h" #include "quad.h" #include "rend/TexCache.h" +#include "vmu.h" extern int screen_width, screen_height; @@ -50,7 +51,7 @@ public: void SetWindowSize(u32 width, u32 height) { this->width = screen_width = width; this->height = screen_height = height; } void NewFrame(); void BeginRenderPass(); - void EndFrame(); + void EndFrame(const std::vector *cmdBuffers = nullptr); void Present(); void PresentFrame(vk::ImageView imageView, vk::Offset2D extent); void PresentLastFrame(); @@ -103,6 +104,8 @@ public: u32 GetMaxStorageBufferRange() const { return maxStorageBufferRange; } vk::DeviceSize GetMaxMemoryAllocationSize() const { return maxMemoryAllocationSize; } u32 GetVendorID() const { return vendorID; } + const std::vector *PrepareVMUs(); + void DrawVMUs(float scaling); private: vk::Format FindDepthFormat(); @@ -198,13 +201,15 @@ private: vk::UniquePipelineCache pipelineCache; - std::unique_ptr quadBuffer; std::unique_ptr quadPipeline; + std::unique_ptr quadDrawer; std::unique_ptr shaderManager; vk::ImageView lastFrameView; vk::Offset2D lastFrameExtent; + std::unique_ptr vmus; + #ifdef VK_DEBUG #ifndef __ANDROID__ vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger; diff --git a/core/rend/vulkan/vulkan_renderer.cpp b/core/rend/vulkan/vulkan_renderer.cpp index da0733539..f94ee339c 100644 --- a/core/rend/vulkan/vulkan_renderer.cpp +++ b/core/rend/vulkan/vulkan_renderer.cpp @@ -27,7 +27,6 @@ #include "shaders.h" #include "rend/gui.h" #include "rend/osd.h" -#include "quad.h" class VulkanRenderer : public Renderer { @@ -42,8 +41,6 @@ public: screenDrawer.Init(&samplerManager, &shaderManager); screenDrawer.SetCommandPool(&texCommandPool); - quadPipeline.Init(&shaderManager, screenDrawer.GetRenderPass()); - quadBuffer = std::unique_ptr(new QuadBuffer()); #ifdef __ANDROID__ if (!vjoyTexture) @@ -85,7 +82,6 @@ public: { texCommandPool.Init(); screenDrawer.Init(&samplerManager, &shaderManager); - quadPipeline.Init(&shaderManager, screenDrawer.GetRenderPass()); #ifdef __ANDROID__ osdPipeline.Init(&shaderManager, vjoyTexture->GetImageView(), GetContext()->GetRenderPass()); #endif @@ -95,8 +91,6 @@ public: { DEBUG_LOG(RENDERER, "VulkanRenderer::Term"); GetContext()->WaitIdle(); - quadBuffer = nullptr; - quadPipeline.Term(); osdBuffer.reset(); vjoyTexture.reset(); textureCache.Clear(); @@ -286,7 +280,6 @@ private: fogTexture->SetCommandBuffer(nullptr); } - std::unique_ptr quadBuffer; std::unique_ptr fogTexture; CommandPool texCommandPool; @@ -295,7 +288,6 @@ private: ScreenDrawer screenDrawer; TextureDrawer textureDrawer; std::vector> framebufferTextures; - QuadPipeline quadPipeline; OSDPipeline osdPipeline; std::unique_ptr vjoyTexture; std::unique_ptr osdBuffer;