vulkan: VMU display
Reset pipeline when switching per-triangle/per-strip Adreno workaround test typo clean up
This commit is contained in:
parent
be50fca2d6
commit
d49373b0f9
|
@ -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<float> render_times;
|
||||
std::vector<float> 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++)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
along with reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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();
|
||||
|
|
|
@ -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<vk::UniqueCommandBuffer> *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
|
||||
|
|
|
@ -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<std::vector<SortTrigDrawParam>> sortedPolys;
|
||||
std::vector<std::vector<u32>> sortedIndexes;
|
||||
u32 sortedIndexCount = 0;
|
||||
bool perStripSorting = false;
|
||||
};
|
||||
|
||||
class ScreenDrawer : public Drawer
|
||||
|
|
|
@ -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<true>(cmdBuffer, previous_pass.mvo_tr_count, current_pass.mvo_tr_count - previous_pass.mvo_tr_count);
|
||||
|
||||
vk::Pipeline pipeline = pipelineManager->GetFinalPipeline(current_pass.autosort);
|
||||
|
|
|
@ -45,7 +45,6 @@ public:
|
|||
|
||||
screenDrawer.Init(&samplerManager, &shaderManager, &oitBuffers);
|
||||
screenDrawer.SetCommandPool(&texCommandPool);
|
||||
quadBuffer = std::unique_ptr<QuadBuffer>(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> quadBuffer;
|
||||
std::unique_ptr<Texture> fogTexture;
|
||||
CommandPool texCommandPool;
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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<QuadBuffer>(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<vk::WriteDescriptorSet> 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);
|
||||
}
|
||||
|
|
|
@ -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<vk::UniqueDescriptorSet> 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<QuadBuffer> buffer;
|
||||
std::vector<vk::UniqueDescriptorSet> descriptorSets;
|
||||
};
|
||||
|
|
|
@ -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<uintptr_t>(this); }
|
||||
std::string GetId() override { char s[20]; sprintf(s, "%p", this); return s; }
|
||||
|
@ -61,14 +56,13 @@ private:
|
|||
std::unique_ptr<BufferData> 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<BufferData> 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<Texture>
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "vmu.h"
|
||||
#include "texture.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
VulkanVMUs::~VulkanVMUs()
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<vk::UniqueCommandBuffer>* 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>& texture = vmuTextures[i];
|
||||
if (!vmu_lcd_status[i])
|
||||
{
|
||||
texture.reset();
|
||||
continue;
|
||||
}
|
||||
bool update = vmu_lcd_changed[i];
|
||||
if (!texture)
|
||||
{
|
||||
texture = std::unique_ptr<Texture>(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);
|
||||
}
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include "quad.h"
|
||||
|
||||
class Texture;
|
||||
|
||||
class VulkanVMUs
|
||||
{
|
||||
public:
|
||||
~VulkanVMUs();
|
||||
void Init(QuadPipeline *pipeline) {
|
||||
this->pipeline = pipeline;
|
||||
for (auto& drawer : drawers)
|
||||
{
|
||||
drawer = std::unique_ptr<QuadDrawer>(new QuadDrawer());
|
||||
drawer->Init(pipeline);
|
||||
}
|
||||
}
|
||||
const std::vector<vk::UniqueCommandBuffer>* PrepareVMUs(vk::CommandPool commandPool);
|
||||
void DrawVMUs(vk::Extent2D viewport, float scaling);
|
||||
|
||||
private:
|
||||
std::array<std::unique_ptr<Texture>, 8> vmuTextures;
|
||||
std::vector<std::vector<vk::UniqueCommandBuffer>> commandBuffers;
|
||||
std::array<std::unique_ptr<QuadDrawer>, 8> drawers;
|
||||
QuadPipeline *pipeline = nullptr;
|
||||
};
|
|
@ -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<QuadBuffer>(new QuadBuffer());
|
||||
shaderManager = std::unique_ptr<ShaderManager>(new ShaderManager());
|
||||
quadPipeline = std::unique_ptr<QuadPipeline>(new QuadPipeline());
|
||||
quadDrawer = std::unique_ptr<QuadDrawer>(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<VulkanVMUs>(new VulkanVMUs());
|
||||
|
||||
return InitDevice();
|
||||
}
|
||||
|
@ -731,13 +735,18 @@ void VulkanContext::BeginRenderPass()
|
|||
vk::SubpassContents::eInline);
|
||||
}
|
||||
|
||||
void VulkanContext::EndFrame()
|
||||
void VulkanContext::EndFrame(const std::vector<vk::UniqueCommandBuffer> *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<vk::CommandBuffer> 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<vk::UniqueCommandBuffer> *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<vk::UniqueCommandBuffer> *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();
|
||||
|
|
|
@ -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<vk::UniqueCommandBuffer> *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<vk::UniqueCommandBuffer> *PrepareVMUs();
|
||||
void DrawVMUs(float scaling);
|
||||
|
||||
private:
|
||||
vk::Format FindDepthFormat();
|
||||
|
@ -198,13 +201,15 @@ private:
|
|||
|
||||
vk::UniquePipelineCache pipelineCache;
|
||||
|
||||
std::unique_ptr<QuadBuffer> quadBuffer;
|
||||
std::unique_ptr<QuadPipeline> quadPipeline;
|
||||
std::unique_ptr<QuadDrawer> quadDrawer;
|
||||
std::unique_ptr<ShaderManager> shaderManager;
|
||||
|
||||
vk::ImageView lastFrameView;
|
||||
vk::Offset2D lastFrameExtent;
|
||||
|
||||
std::unique_ptr<VulkanVMUs> vmus;
|
||||
|
||||
#ifdef VK_DEBUG
|
||||
#ifndef __ANDROID__
|
||||
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger;
|
||||
|
|
|
@ -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<QuadBuffer>(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> quadBuffer;
|
||||
std::unique_ptr<Texture> fogTexture;
|
||||
CommandPool texCommandPool;
|
||||
|
||||
|
@ -295,7 +288,6 @@ private:
|
|||
ScreenDrawer screenDrawer;
|
||||
TextureDrawer textureDrawer;
|
||||
std::vector<std::unique_ptr<Texture>> framebufferTextures;
|
||||
QuadPipeline quadPipeline;
|
||||
OSDPipeline osdPipeline;
|
||||
std::unique_ptr<Texture> vjoyTexture;
|
||||
std::unique_ptr<BufferData> osdBuffer;
|
||||
|
|
Loading…
Reference in New Issue