mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-14 08:12:16 +00:00
Swapchain recreation and window resizing (#933)
* Always present acquired swapchain images
Always present acquired swapchain images in order to be able to acquire them again.
fix #865
* Recreate swapchain if window is resized
* Respect aspect ratio when blitting to frame
* Make SDL window resizable
* clang-format
* designator order (building with gcc)
Fix /shadPS4/src/video_core/renderer_vulkan/vk_instance.cpp:314:9: error: designator order for field ‘vk::PhysicalDeviceVulkan12Features::samplerMirrorClampToEdge’ does not match declaration order in ‘vk::PhysicalDeviceVulkan12Features’
* Clear frame before blitting
* clang-format
* Revert "designator order (building with gcc)"
There already is a PR opened for this.
This reverts commit 7f8ccf4b1e
.
This commit is contained in:
parent
e634461ebb
commit
a984d44fd3
4 changed files with 67 additions and 17 deletions
|
@ -36,6 +36,7 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
|
||||||
SDL_SetNumberProperty(props, "flags", SDL_WINDOW_VULKAN);
|
SDL_SetNumberProperty(props, "flags", SDL_WINDOW_VULKAN);
|
||||||
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, true);
|
||||||
window = SDL_CreateWindowWithProperties(props);
|
window = SDL_CreateWindowWithProperties(props);
|
||||||
SDL_DestroyProperties(props);
|
SDL_DestroyProperties(props);
|
||||||
if (window == nullptr) {
|
if (window == nullptr) {
|
||||||
|
|
|
@ -33,8 +33,8 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] vk::ImageBlit MakeImageBlit(s32 frame_width, s32 frame_height, s32 swapchain_width,
|
[[nodiscard]] vk::ImageBlit MakeImageBlit(s32 frame_width, s32 frame_height, s32 dst_width,
|
||||||
s32 swapchain_height) {
|
s32 dst_height, s32 offset_x, s32 offset_y) {
|
||||||
return vk::ImageBlit{
|
return vk::ImageBlit{
|
||||||
.srcSubresource = MakeImageSubresourceLayers(),
|
.srcSubresource = MakeImageSubresourceLayers(),
|
||||||
.srcOffsets =
|
.srcOffsets =
|
||||||
|
@ -54,19 +54,44 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for
|
||||||
.dstOffsets =
|
.dstOffsets =
|
||||||
std::array{
|
std::array{
|
||||||
vk::Offset3D{
|
vk::Offset3D{
|
||||||
.x = 0,
|
.x = offset_x,
|
||||||
.y = 0,
|
.y = offset_y,
|
||||||
.z = 0,
|
.z = 0,
|
||||||
},
|
},
|
||||||
vk::Offset3D{
|
vk::Offset3D{
|
||||||
.x = swapchain_width,
|
.x = offset_x + dst_width,
|
||||||
.y = swapchain_height,
|
.y = offset_y + dst_height,
|
||||||
.z = 1,
|
.z = 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] vk::ImageBlit MakeImageBlitStretch(s32 frame_width, s32 frame_height,
|
||||||
|
s32 swapchain_width, s32 swapchain_height) {
|
||||||
|
return MakeImageBlit(frame_width, frame_height, swapchain_width, swapchain_height, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] vk::ImageBlit MakeImageBlitFit(s32 frame_width, s32 frame_height, s32 swapchain_width,
|
||||||
|
s32 swapchain_height) {
|
||||||
|
float frame_aspect = static_cast<float>(frame_width) / frame_height;
|
||||||
|
float swapchain_aspect = static_cast<float>(swapchain_width) / swapchain_height;
|
||||||
|
|
||||||
|
s32 dst_width = swapchain_width;
|
||||||
|
s32 dst_height = swapchain_height;
|
||||||
|
|
||||||
|
if (frame_aspect > swapchain_aspect) {
|
||||||
|
dst_height = static_cast<s32>(swapchain_width / frame_aspect);
|
||||||
|
} else {
|
||||||
|
dst_width = static_cast<s32>(swapchain_height * frame_aspect);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 offset_x = (swapchain_width - dst_width) / 2;
|
||||||
|
s32 offset_y = (swapchain_height - dst_height) / 2;
|
||||||
|
|
||||||
|
return MakeImageBlit(frame_width, frame_height, dst_width, dst_height, offset_x, offset_y);
|
||||||
|
}
|
||||||
|
|
||||||
RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_)
|
RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_)
|
||||||
: window{window_}, liverpool{liverpool_},
|
: window{window_}, liverpool{liverpool_},
|
||||||
instance{window, Config::getGpuId(), Config::vkValidationEnabled(),
|
instance{window, Config::getGpuId(), Config::vkValidationEnabled(),
|
||||||
|
@ -234,11 +259,24 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop
|
||||||
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
||||||
{}, {}, pre_barrier);
|
{}, {}, pre_barrier);
|
||||||
|
|
||||||
|
// Clear the frame image before blitting to avoid artifacts.
|
||||||
|
const vk::ClearColorValue clear_color{std::array{0.0f, 0.0f, 0.0f, 1.0f}};
|
||||||
|
const vk::ImageSubresourceRange clear_range{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
|
};
|
||||||
|
cmdbuf.clearColorImage(frame->image, vk::ImageLayout::eTransferDstOptimal, clear_color,
|
||||||
|
clear_range);
|
||||||
|
|
||||||
// Post-processing (Anti-aliasing, FSR etc) goes here. For now just blit to the frame image.
|
// Post-processing (Anti-aliasing, FSR etc) goes here. For now just blit to the frame image.
|
||||||
cmdbuf.blitImage(
|
cmdbuf.blitImage(image.image, image.last_state.layout, frame->image,
|
||||||
image.image, image.last_state.layout, frame->image, vk::ImageLayout::eTransferDstOptimal,
|
vk::ImageLayout::eTransferDstOptimal,
|
||||||
MakeImageBlit(image.info.size.width, image.info.size.height, frame->width, frame->height),
|
MakeImageBlitFit(image.info.size.width, image.info.size.height, frame->width,
|
||||||
vk::Filter::eLinear);
|
frame->height),
|
||||||
|
vk::Filter::eLinear);
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier post_barrier{
|
const vk::ImageMemoryBarrier post_barrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
|
@ -269,6 +307,12 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::Present(Frame* frame) {
|
void RendererVulkan::Present(Frame* frame) {
|
||||||
|
// Recreate the swapchain if the window was resized.
|
||||||
|
if (window.getWidth() != swapchain.GetExtent().width ||
|
||||||
|
window.getHeight() != swapchain.GetExtent().height) {
|
||||||
|
swapchain.Recreate(window.getWidth(), window.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Core::NewFrame();
|
ImGui::Core::NewFrame();
|
||||||
|
|
||||||
swapchain.AcquireNextImage();
|
swapchain.AcquireNextImage();
|
||||||
|
@ -341,10 +385,11 @@ void RendererVulkan::Present(Frame* frame) {
|
||||||
vk::PipelineStageFlagBits::eTransfer,
|
vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
||||||
|
|
||||||
cmdbuf.blitImage(frame->image, vk::ImageLayout::eTransferSrcOptimal, swapchain_image,
|
cmdbuf.blitImage(
|
||||||
vk::ImageLayout::eTransferDstOptimal,
|
frame->image, vk::ImageLayout::eTransferSrcOptimal, swapchain_image,
|
||||||
MakeImageBlit(frame->width, frame->height, extent.width, extent.height),
|
vk::ImageLayout::eTransferDstOptimal,
|
||||||
vk::Filter::eLinear);
|
MakeImageBlitStretch(frame->width, frame->height, extent.width, extent.height),
|
||||||
|
vk::Filter::eLinear);
|
||||||
|
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
vk::PipelineStageFlagBits::eAllCommands,
|
||||||
|
|
|
@ -83,6 +83,10 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) {
|
||||||
RefreshSemaphores();
|
RefreshSemaphores();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Swapchain::Recreate(u32 width_, u32 height_) {
|
||||||
|
Create(width_, height_, surface);
|
||||||
|
}
|
||||||
|
|
||||||
bool Swapchain::AcquireNextImage() {
|
bool Swapchain::AcquireNextImage() {
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
vk::Result result =
|
vk::Result result =
|
||||||
|
@ -109,9 +113,6 @@ bool Swapchain::AcquireNextImage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swapchain::Present() {
|
void Swapchain::Present() {
|
||||||
if (needs_recreation) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const vk::PresentInfoKHR present_info = {
|
const vk::PresentInfoKHR present_info = {
|
||||||
.waitSemaphoreCount = 1,
|
.waitSemaphoreCount = 1,
|
||||||
|
|
|
@ -25,6 +25,9 @@ public:
|
||||||
/// Creates (or recreates) the swapchain with a given size.
|
/// Creates (or recreates) the swapchain with a given size.
|
||||||
void Create(u32 width, u32 height, vk::SurfaceKHR surface);
|
void Create(u32 width, u32 height, vk::SurfaceKHR surface);
|
||||||
|
|
||||||
|
/// Recreates the swapchain with a given size and current surface.
|
||||||
|
void Recreate(u32 width, u32 height);
|
||||||
|
|
||||||
/// Acquires the next image in the swapchain.
|
/// Acquires the next image in the swapchain.
|
||||||
bool AcquireNextImage();
|
bool AcquireNextImage();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue