mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-22 14:31:39 +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
c8d29aa1ec
commit
0bca802cb8
|
@ -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_HEIGHT_NUMBER, height);
|
||||
SDL_SetNumberProperty(props, "flags", SDL_WINDOW_VULKAN);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, true);
|
||||
window = SDL_CreateWindowWithProperties(props);
|
||||
SDL_DestroyProperties(props);
|
||||
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,
|
||||
s32 swapchain_height) {
|
||||
[[nodiscard]] vk::ImageBlit MakeImageBlit(s32 frame_width, s32 frame_height, s32 dst_width,
|
||||
s32 dst_height, s32 offset_x, s32 offset_y) {
|
||||
return vk::ImageBlit{
|
||||
.srcSubresource = MakeImageSubresourceLayers(),
|
||||
.srcOffsets =
|
||||
|
@ -54,19 +54,44 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for
|
|||
.dstOffsets =
|
||||
std::array{
|
||||
vk::Offset3D{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.x = offset_x,
|
||||
.y = offset_y,
|
||||
.z = 0,
|
||||
},
|
||||
vk::Offset3D{
|
||||
.x = swapchain_width,
|
||||
.y = swapchain_height,
|
||||
.x = offset_x + dst_width,
|
||||
.y = offset_y + dst_height,
|
||||
.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_)
|
||||
: window{window_}, liverpool{liverpool_},
|
||||
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,
|
||||
{}, {}, 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.
|
||||
cmdbuf.blitImage(
|
||||
image.image, image.last_state.layout, frame->image, vk::ImageLayout::eTransferDstOptimal,
|
||||
MakeImageBlit(image.info.size.width, image.info.size.height, frame->width, frame->height),
|
||||
vk::Filter::eLinear);
|
||||
cmdbuf.blitImage(image.image, image.last_state.layout, frame->image,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
MakeImageBlitFit(image.info.size.width, image.info.size.height, frame->width,
|
||||
frame->height),
|
||||
vk::Filter::eLinear);
|
||||
|
||||
const vk::ImageMemoryBarrier post_barrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
|
@ -269,6 +307,12 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop
|
|||
}
|
||||
|
||||
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();
|
||||
|
||||
swapchain.AcquireNextImage();
|
||||
|
@ -341,10 +385,11 @@ void RendererVulkan::Present(Frame* frame) {
|
|||
vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
||||
|
||||
cmdbuf.blitImage(frame->image, vk::ImageLayout::eTransferSrcOptimal, swapchain_image,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
MakeImageBlit(frame->width, frame->height, extent.width, extent.height),
|
||||
vk::Filter::eLinear);
|
||||
cmdbuf.blitImage(
|
||||
frame->image, vk::ImageLayout::eTransferSrcOptimal, swapchain_image,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
MakeImageBlitStretch(frame->width, frame->height, extent.width, extent.height),
|
||||
vk::Filter::eLinear);
|
||||
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||
vk::PipelineStageFlagBits::eAllCommands,
|
||||
|
|
|
@ -83,6 +83,10 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) {
|
|||
RefreshSemaphores();
|
||||
}
|
||||
|
||||
void Swapchain::Recreate(u32 width_, u32 height_) {
|
||||
Create(width_, height_, surface);
|
||||
}
|
||||
|
||||
bool Swapchain::AcquireNextImage() {
|
||||
vk::Device device = instance.GetDevice();
|
||||
vk::Result result =
|
||||
|
@ -109,9 +113,6 @@ bool Swapchain::AcquireNextImage() {
|
|||
}
|
||||
|
||||
void Swapchain::Present() {
|
||||
if (needs_recreation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const vk::PresentInfoKHR present_info = {
|
||||
.waitSemaphoreCount = 1,
|
||||
|
|
|
@ -25,6 +25,9 @@ public:
|
|||
/// Creates (or recreates) the swapchain with a given size.
|
||||
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.
|
||||
bool AcquireNextImage();
|
||||
|
||||
|
|
Loading…
Reference in a new issue