mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-19 00:50:38 +00:00
Render without rendering (#2152)
* presenter: render the game inside a ImGui window * presenter: render the previous frame to keep the render rendering * swapchain: fix swapchain image view format not being converted to unorm * devtools: fix frame graph timing
This commit is contained in:
parent
440a693fae
commit
56a6c95730
19 changed files with 306 additions and 110 deletions
|
@ -30,6 +30,12 @@ extern void assert_fail_debug_msg(const char* msg);
|
|||
#define IM_VEC4_CLASS_EXTRA \
|
||||
constexpr ImVec4(float _v) : x(_v), y(_v), z(_v), w(_v) {}
|
||||
|
||||
namespace ImGui {
|
||||
struct Texture;
|
||||
}
|
||||
#define ImTextureID ImTextureID
|
||||
using ImTextureID = ::ImGui::Texture*;
|
||||
|
||||
#ifdef IMGUI_USE_WCHAR32
|
||||
#error "This project uses 16 bits wchar standard like Orbis"
|
||||
#endif
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "common/config.h"
|
||||
#include "common/path_util.h"
|
||||
#include "core/debug_state.h"
|
||||
#include "core/devtools/layer.h"
|
||||
#include "imgui/imgui_layer.h"
|
||||
#include "imgui_core.h"
|
||||
|
@ -167,7 +168,7 @@ bool ProcessEvent(SDL_Event* event) {
|
|||
}
|
||||
}
|
||||
|
||||
void NewFrame() {
|
||||
ImGuiID NewFrame(bool is_reusing_frame) {
|
||||
{
|
||||
std::scoped_lock lock{change_layers_mutex};
|
||||
while (!change_layers.empty()) {
|
||||
|
@ -182,17 +183,24 @@ void NewFrame() {
|
|||
}
|
||||
}
|
||||
|
||||
Sdl::NewFrame();
|
||||
Sdl::NewFrame(is_reusing_frame);
|
||||
ImGui::NewFrame();
|
||||
|
||||
DockSpaceOverViewport(0, GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
ImGuiWindowFlags flags = ImGuiDockNodeFlags_PassthruCentralNode;
|
||||
if (!DebugState.ShowingDebugMenuBar()) {
|
||||
flags |= ImGuiDockNodeFlags_NoTabBar;
|
||||
}
|
||||
ImGuiID dockId = DockSpaceOverViewport(0, GetMainViewport(), flags);
|
||||
|
||||
for (auto* layer : layers) {
|
||||
layer->Draw();
|
||||
}
|
||||
|
||||
return dockId;
|
||||
}
|
||||
|
||||
void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) {
|
||||
void Render(const vk::CommandBuffer& cmdbuf, const vk::ImageView& image_view,
|
||||
const vk::Extent2D& extent) {
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = GetDrawData();
|
||||
if (draw_data->CmdListsCount == 0) {
|
||||
|
@ -207,16 +215,16 @@ void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) {
|
|||
|
||||
vk::RenderingAttachmentInfo color_attachments[1]{
|
||||
{
|
||||
.imageView = frame->image_view,
|
||||
.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||
.loadOp = vk::AttachmentLoadOp::eLoad,
|
||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
},
|
||||
};
|
||||
vk::RenderingInfo render_info{};
|
||||
render_info.renderArea = vk::Rect2D{
|
||||
.offset = {0, 0},
|
||||
.extent = {frame->width, frame->height},
|
||||
.extent = extent,
|
||||
};
|
||||
render_info.layerCount = 1;
|
||||
render_info.colorAttachmentCount = 1;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
#include "vulkan/vulkan_handles.hpp"
|
||||
|
||||
|
@ -24,8 +26,9 @@ void Shutdown(const vk::Device& device);
|
|||
|
||||
bool ProcessEvent(SDL_Event* event);
|
||||
|
||||
void NewFrame();
|
||||
ImGuiID NewFrame(bool is_reusing_frame = false);
|
||||
|
||||
void Render(const vk::CommandBuffer& cmdbuf, Vulkan::Frame* frame);
|
||||
void Render(const vk::CommandBuffer& cmdbuf, const vk::ImageView& image_view,
|
||||
const vk::Extent2D& extent);
|
||||
|
||||
} // namespace ImGui::Core
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <imgui.h>
|
||||
#include "common/config.h"
|
||||
#include "core/debug_state.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
|
||||
// SDL
|
||||
|
@ -26,6 +27,7 @@ struct SdlData {
|
|||
SDL_Window* window{};
|
||||
SDL_WindowID window_id{};
|
||||
Uint64 time{};
|
||||
Uint64 nonReusedtime{};
|
||||
const char* clipboard_text_data{};
|
||||
|
||||
// IME handling
|
||||
|
@ -785,7 +787,7 @@ static void UpdateGamepads() {
|
|||
+thumb_dead_zone, +32767);
|
||||
}
|
||||
|
||||
void NewFrame() {
|
||||
void NewFrame(bool is_reusing_frame) {
|
||||
SdlData* bd = GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
@ -798,9 +800,26 @@ void NewFrame() {
|
|||
if (current_time <= bd->time)
|
||||
current_time = bd->time + 1;
|
||||
io.DeltaTime = bd->time > 0 ? (float)((double)(current_time - bd->time) / (double)frequency)
|
||||
: (float)(1.0f / 60.0f);
|
||||
: 1.0f / 60.0f;
|
||||
bd->time = current_time;
|
||||
|
||||
if (!is_reusing_frame) {
|
||||
if (current_time <= bd->nonReusedtime)
|
||||
current_time = bd->nonReusedtime + 1;
|
||||
float deltaTime =
|
||||
bd->nonReusedtime > 0
|
||||
? (float)((double)(current_time - bd->nonReusedtime) / (double)frequency)
|
||||
: 1.0f / 60.0f;
|
||||
bd->nonReusedtime = current_time;
|
||||
DebugState.FrameDeltaTime = deltaTime;
|
||||
float distribution = 0.016f / deltaTime / 10.0f;
|
||||
if (distribution > 1.0f) {
|
||||
distribution = 1.0f;
|
||||
}
|
||||
DebugState.Framerate =
|
||||
deltaTime * distribution + DebugState.Framerate * (1.0f - distribution);
|
||||
}
|
||||
|
||||
if (bd->mouse_pending_leave_frame && bd->mouse_pending_leave_frame >= ImGui::GetFrameCount() &&
|
||||
bd->mouse_buttons_down == 0) {
|
||||
bd->mouse_window_id = 0;
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace ImGui::Sdl {
|
|||
|
||||
bool Init(SDL_Window* window);
|
||||
void Shutdown();
|
||||
void NewFrame();
|
||||
void NewFrame(bool is_reusing);
|
||||
bool ProcessEvent(const SDL_Event* event);
|
||||
void OnResize();
|
||||
|
||||
|
|
|
@ -57,11 +57,12 @@ struct VkData {
|
|||
vk::DeviceMemory font_memory{};
|
||||
vk::Image font_image{};
|
||||
vk::ImageView font_view{};
|
||||
vk::DescriptorSet font_descriptor_set{};
|
||||
ImTextureID font_texture{};
|
||||
vk::CommandBuffer font_command_buffer{};
|
||||
|
||||
// Render buffers
|
||||
WindowRenderBuffers render_buffers{};
|
||||
bool enabled_blending{true};
|
||||
|
||||
VkData(const InitInfo init_info) : init_info(init_info) {
|
||||
render_buffers.count = init_info.image_count;
|
||||
|
@ -252,8 +253,8 @@ void UploadTextureData::Destroy() {
|
|||
const InitInfo& v = bd->init_info;
|
||||
|
||||
CheckVkErr(v.device.waitIdle());
|
||||
RemoveTexture(descriptor_set);
|
||||
descriptor_set = VK_NULL_HANDLE;
|
||||
RemoveTexture(im_texture);
|
||||
im_texture = nullptr;
|
||||
|
||||
v.device.destroyImageView(image_view, v.allocator);
|
||||
image_view = VK_NULL_HANDLE;
|
||||
|
@ -264,8 +265,8 @@ void UploadTextureData::Destroy() {
|
|||
}
|
||||
|
||||
// Register a texture
|
||||
vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout,
|
||||
vk::Sampler sampler) {
|
||||
ImTextureID AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout,
|
||||
vk::Sampler sampler) {
|
||||
VkData* bd = GetBackendData();
|
||||
const InitInfo& v = bd->init_info;
|
||||
|
||||
|
@ -303,7 +304,9 @@ vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_lay
|
|||
};
|
||||
v.device.updateDescriptorSets({write_desc}, {});
|
||||
}
|
||||
return descriptor_set;
|
||||
return new Texture{
|
||||
.descriptor_set = descriptor_set,
|
||||
};
|
||||
}
|
||||
UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height,
|
||||
size_t size) {
|
||||
|
@ -370,7 +373,7 @@ UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width,
|
|||
}
|
||||
|
||||
// Create descriptor set (ImTextureID)
|
||||
info.descriptor_set = AddTexture(info.image_view, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
info.im_texture = AddTexture(info.image_view, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
// Create Upload Buffer
|
||||
{
|
||||
|
@ -464,10 +467,12 @@ UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width,
|
|||
return info;
|
||||
}
|
||||
|
||||
void RemoveTexture(vk::DescriptorSet descriptor_set) {
|
||||
void RemoveTexture(ImTextureID texture) {
|
||||
IM_ASSERT(texture != nullptr);
|
||||
VkData* bd = GetBackendData();
|
||||
const InitInfo& v = bd->init_info;
|
||||
v.device.freeDescriptorSets(bd->descriptor_pool, {descriptor_set});
|
||||
v.device.freeDescriptorSets(bd->descriptor_pool, {texture->descriptor_set});
|
||||
delete texture;
|
||||
}
|
||||
|
||||
static void CreateOrResizeBuffer(RenderBuffer& rb, size_t new_size, vk::BufferUsageFlagBits usage) {
|
||||
|
@ -679,15 +684,11 @@ void RenderDrawData(ImDrawData& draw_data, vk::CommandBuffer command_buffer,
|
|||
command_buffer.setScissor(0, 1, &scissor);
|
||||
|
||||
// Bind DescriptorSet with font or user texture
|
||||
vk::DescriptorSet desc_set[1]{(VkDescriptorSet)pcmd->TextureId};
|
||||
if (sizeof(ImTextureID) < sizeof(ImU64)) {
|
||||
// We don't support texture switches if ImTextureID hasn't been redefined to be
|
||||
// 64-bit. Do a flaky check that other textures haven't been used.
|
||||
IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->font_descriptor_set);
|
||||
desc_set[0] = bd->font_descriptor_set;
|
||||
}
|
||||
vk::DescriptorSet desc_set[1]{pcmd->TextureId->descriptor_set};
|
||||
command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
bd->pipeline_layout, 0, {desc_set}, {});
|
||||
command_buffer.setColorBlendEnableEXT(
|
||||
0, {pcmd->TextureId->disable_blend ? vk::False : vk::True});
|
||||
|
||||
// Draw
|
||||
command_buffer.drawIndexed(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset,
|
||||
|
@ -709,7 +710,7 @@ static bool CreateFontsTexture() {
|
|||
const InitInfo& v = bd->init_info;
|
||||
|
||||
// Destroy existing texture (if any)
|
||||
if (bd->font_view || bd->font_image || bd->font_memory || bd->font_descriptor_set) {
|
||||
if (bd->font_view || bd->font_image || bd->font_memory || bd->font_texture) {
|
||||
CheckVkErr(v.queue.waitIdle());
|
||||
DestroyFontsTexture();
|
||||
}
|
||||
|
@ -782,7 +783,7 @@ static bool CreateFontsTexture() {
|
|||
}
|
||||
|
||||
// Create the Descriptor Set:
|
||||
bd->font_descriptor_set = AddTexture(bd->font_view, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
bd->font_texture = AddTexture(bd->font_view, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
// Create the Upload Buffer:
|
||||
vk::DeviceMemory upload_buffer_memory{};
|
||||
|
@ -874,7 +875,7 @@ static bool CreateFontsTexture() {
|
|||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID(bd->font_descriptor_set);
|
||||
io.Fonts->SetTexID(bd->font_texture);
|
||||
|
||||
// End command buffer
|
||||
vk::SubmitInfo end_info = {};
|
||||
|
@ -898,9 +899,9 @@ static void DestroyFontsTexture() {
|
|||
VkData* bd = GetBackendData();
|
||||
const InitInfo& v = bd->init_info;
|
||||
|
||||
if (bd->font_descriptor_set) {
|
||||
RemoveTexture(bd->font_descriptor_set);
|
||||
bd->font_descriptor_set = VK_NULL_HANDLE;
|
||||
if (bd->font_texture) {
|
||||
RemoveTexture(bd->font_texture);
|
||||
bd->font_texture = nullptr;
|
||||
io.Fonts->SetTexID(nullptr);
|
||||
}
|
||||
|
||||
|
@ -1057,9 +1058,10 @@ static void CreatePipeline(vk::Device device, const vk::AllocationCallbacks* all
|
|||
.pAttachments = color_attachment,
|
||||
};
|
||||
|
||||
vk::DynamicState dynamic_states[2]{
|
||||
vk::DynamicState dynamic_states[3]{
|
||||
vk::DynamicState::eViewport,
|
||||
vk::DynamicState::eScissor,
|
||||
vk::DynamicState::eColorBlendEnableEXT,
|
||||
};
|
||||
vk::PipelineDynamicStateCreateInfo dynamic_state{
|
||||
.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states),
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
|
||||
struct ImDrawData;
|
||||
|
||||
namespace ImGui {
|
||||
struct Texture {
|
||||
vk::DescriptorSet descriptor_set{nullptr};
|
||||
bool disable_blend{false};
|
||||
};
|
||||
} // namespace ImGui
|
||||
|
||||
namespace ImGui::Vulkan {
|
||||
|
||||
struct InitInfo {
|
||||
|
@ -34,29 +41,32 @@ struct InitInfo {
|
|||
struct UploadTextureData {
|
||||
vk::Image image;
|
||||
vk::ImageView image_view;
|
||||
vk::DescriptorSet descriptor_set;
|
||||
vk::DeviceMemory image_memory;
|
||||
|
||||
vk::CommandBuffer command_buffer; // Submit to the queue
|
||||
vk::Buffer upload_buffer;
|
||||
vk::DeviceMemory upload_buffer_memory;
|
||||
|
||||
ImTextureID im_texture;
|
||||
|
||||
void Upload();
|
||||
|
||||
void Destroy();
|
||||
};
|
||||
|
||||
vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout,
|
||||
vk::Sampler sampler = VK_NULL_HANDLE);
|
||||
ImTextureID AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout,
|
||||
vk::Sampler sampler = VK_NULL_HANDLE);
|
||||
|
||||
UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height,
|
||||
size_t size);
|
||||
|
||||
void RemoveTexture(vk::DescriptorSet descriptor_set);
|
||||
void RemoveTexture(ImTextureID descriptor_set);
|
||||
|
||||
bool Init(InitInfo info);
|
||||
void Shutdown();
|
||||
void RenderDrawData(ImDrawData& draw_data, vk::CommandBuffer command_buffer,
|
||||
vk::Pipeline pipeline = VK_NULL_HANDLE);
|
||||
|
||||
void SetBlendEnabled(bool enabled);
|
||||
|
||||
} // namespace ImGui::Vulkan
|
|
@ -4,6 +4,7 @@
|
|||
#include <deque>
|
||||
#include <utility>
|
||||
|
||||
#include <imgui.h>
|
||||
#include "common/assert.h"
|
||||
#include "common/config.h"
|
||||
#include "common/io_file.h"
|
||||
|
@ -123,7 +124,7 @@ static std::deque<UploadJob> g_upload_list;
|
|||
namespace Core::TextureManager {
|
||||
|
||||
Inner::~Inner() {
|
||||
if (upload_data.descriptor_set != nullptr) {
|
||||
if (upload_data.im_texture != nullptr) {
|
||||
std::unique_lock lk{g_upload_mtx};
|
||||
g_upload_list.emplace_back(UploadJob{
|
||||
.data = this->upload_data,
|
||||
|
@ -239,7 +240,7 @@ void Submit() {
|
|||
}
|
||||
if (upload.core != nullptr) {
|
||||
upload.core->upload_data.Upload();
|
||||
upload.core->texture_id = upload.core->upload_data.descriptor_set;
|
||||
upload.core->texture_id = upload.core->upload_data.im_texture;
|
||||
if (upload.core->count.fetch_sub(1) == 1) {
|
||||
delete upload.core;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue