22 changed files with 662 additions and 952 deletions
-
3src/video_core/CMakeLists.txt
-
1src/video_core/engines/maxwell_dma.h
-
12src/video_core/host_shaders/opengl_present_scaleforce.frag
-
12src/video_core/host_shaders/present_bicubic.frag
-
12src/video_core/host_shaders/present_gaussian.frag
-
2src/video_core/host_shaders/vulkan_present.frag
-
33src/video_core/host_shaders/vulkan_present.vert
-
1src/video_core/host_shaders/vulkan_present_scaleforce_fp16.frag
-
2src/video_core/host_shaders/vulkan_present_scaleforce_fp32.frag
-
34src/video_core/renderer_vulkan/present/filters.cpp
-
24src/video_core/renderer_vulkan/present/filters.h
-
336src/video_core/renderer_vulkan/present/layer.cpp
-
92src/video_core/renderer_vulkan/present/layer.h
-
34src/video_core/renderer_vulkan/present/present_push_constants.h
-
31src/video_core/renderer_vulkan/present/util.cpp
-
6src/video_core/renderer_vulkan/present/util.h
-
503src/video_core/renderer_vulkan/present/window_adapt_pass.cpp
-
29src/video_core/renderer_vulkan/present/window_adapt_pass.h
-
8src/video_core/renderer_vulkan/renderer_vulkan.cpp
-
2src/video_core/renderer_vulkan/renderer_vulkan.h
-
378src/video_core/renderer_vulkan/vk_blit_screen.cpp
-
59src/video_core/renderer_vulkan/vk_blit_screen.h
@ -0,0 +1,336 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
||||
|
#include "video_core/renderer_vulkan/vk_rasterizer.h"
|
||||
|
|
||||
|
#include "common/settings.h"
|
||||
|
#include "video_core/framebuffer_config.h"
|
||||
|
#include "video_core/renderer_vulkan/present/fsr.h"
|
||||
|
#include "video_core/renderer_vulkan/present/fxaa.h"
|
||||
|
#include "video_core/renderer_vulkan/present/layer.h"
|
||||
|
#include "video_core/renderer_vulkan/present/present_push_constants.h"
|
||||
|
#include "video_core/renderer_vulkan/present/smaa.h"
|
||||
|
#include "video_core/renderer_vulkan/present/util.h"
|
||||
|
#include "video_core/renderer_vulkan/vk_blit_screen.h"
|
||||
|
#include "video_core/textures/decoders.h"
|
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
namespace { |
||||
|
|
||||
|
u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) { |
||||
|
using namespace VideoCore::Surface; |
||||
|
return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)); |
||||
|
} |
||||
|
|
||||
|
std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) { |
||||
|
return static_cast<std::size_t>(framebuffer.stride) * |
||||
|
static_cast<std::size_t>(framebuffer.height) * GetBytesPerPixel(framebuffer); |
||||
|
} |
||||
|
|
||||
|
VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { |
||||
|
switch (framebuffer.pixel_format) { |
||||
|
case Service::android::PixelFormat::Rgba8888: |
||||
|
case Service::android::PixelFormat::Rgbx8888: |
||||
|
return VK_FORMAT_A8B8G8R8_UNORM_PACK32; |
||||
|
case Service::android::PixelFormat::Rgb565: |
||||
|
return VK_FORMAT_R5G6B5_UNORM_PACK16; |
||||
|
case Service::android::PixelFormat::Bgra8888: |
||||
|
return VK_FORMAT_B8G8R8A8_UNORM; |
||||
|
default: |
||||
|
UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", |
||||
|
static_cast<u32>(framebuffer.pixel_format)); |
||||
|
return VK_FORMAT_A8B8G8R8_UNORM_PACK32; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} // Anonymous namespace
|
||||
|
|
||||
|
Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, |
||||
|
Tegra::MaxwellDeviceMemoryManager& device_memory_, size_t image_count_, |
||||
|
VkExtent2D output_size, VkDescriptorSetLayout layout) |
||||
|
: device(device_), memory_allocator(memory_allocator_), scheduler(scheduler_), |
||||
|
device_memory(device_memory_), image_count(image_count_) { |
||||
|
CreateDescriptorPool(); |
||||
|
CreateDescriptorSets(layout); |
||||
|
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { |
||||
|
CreateFSR(output_size); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Layer::~Layer() { |
||||
|
ReleaseRawImages(); |
||||
|
} |
||||
|
|
||||
|
void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, |
||||
|
VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer, |
||||
|
VkSampler sampler, size_t image_index, |
||||
|
const Tegra::FramebufferConfig& framebuffer, |
||||
|
const Layout::FramebufferLayout& layout) { |
||||
|
const auto texture_info = rasterizer.AccelerateDisplay( |
||||
|
framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride); |
||||
|
const u32 texture_width = texture_info ? texture_info->width : framebuffer.width; |
||||
|
const u32 texture_height = texture_info ? texture_info->height : framebuffer.height; |
||||
|
const u32 scaled_width = texture_info ? texture_info->scaled_width : texture_width; |
||||
|
const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height; |
||||
|
const bool use_accelerated = texture_info.has_value(); |
||||
|
|
||||
|
RefreshResources(framebuffer); |
||||
|
SetAntiAliasPass(); |
||||
|
|
||||
|
// Finish any pending renderpass
|
||||
|
scheduler.RequestOutsideRenderPassOperationContext(); |
||||
|
scheduler.Wait(resource_ticks[image_index]); |
||||
|
SCOPE_EXIT({ resource_ticks[image_index] = scheduler.CurrentTick(); }); |
||||
|
|
||||
|
if (!use_accelerated) { |
||||
|
UpdateRawImage(framebuffer, image_index); |
||||
|
} |
||||
|
|
||||
|
VkImage source_image = texture_info ? texture_info->image : *raw_images[image_index]; |
||||
|
VkImageView source_image_view = |
||||
|
texture_info ? texture_info->image_view : *raw_image_views[image_index]; |
||||
|
|
||||
|
anti_alias->Draw(scheduler, image_index, &source_image, &source_image_view); |
||||
|
|
||||
|
auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); |
||||
|
const VkExtent2D render_extent{ |
||||
|
.width = scaled_width, |
||||
|
.height = scaled_height, |
||||
|
}; |
||||
|
|
||||
|
if (fsr) { |
||||
|
source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, |
||||
|
render_extent, crop_rect); |
||||
|
crop_rect = {0, 0, 1, 1}; |
||||
|
} |
||||
|
|
||||
|
SetMatrixData(*out_push_constants, layout); |
||||
|
SetVertexData(*out_push_constants, layout, crop_rect); |
||||
|
|
||||
|
UpdateDescriptorSet(source_image_view, sampler, image_index); |
||||
|
*out_descriptor_set = descriptor_sets[image_index]; |
||||
|
} |
||||
|
|
||||
|
void Layer::CreateDescriptorPool() { |
||||
|
descriptor_pool = CreateWrappedDescriptorPool(device, image_count, image_count); |
||||
|
} |
||||
|
|
||||
|
void Layer::CreateDescriptorSets(VkDescriptorSetLayout layout) { |
||||
|
const std::vector layouts(image_count, layout); |
||||
|
descriptor_sets = CreateWrappedDescriptorSets(descriptor_pool, layouts); |
||||
|
} |
||||
|
|
||||
|
void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { |
||||
|
const VkBufferCreateInfo ci{ |
||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
||||
|
.pNext = nullptr, |
||||
|
.flags = 0, |
||||
|
.size = CalculateBufferSize(framebuffer), |
||||
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | |
||||
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, |
||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
||||
|
.queueFamilyIndexCount = 0, |
||||
|
.pQueueFamilyIndices = nullptr, |
||||
|
}; |
||||
|
|
||||
|
buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload); |
||||
|
} |
||||
|
|
||||
|
void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { |
||||
|
const auto format = GetFormat(framebuffer); |
||||
|
resource_ticks.resize(image_count); |
||||
|
raw_images.resize(image_count); |
||||
|
raw_image_views.resize(image_count); |
||||
|
|
||||
|
for (size_t i = 0; i < image_count; ++i) { |
||||
|
raw_images[i] = |
||||
|
CreateWrappedImage(memory_allocator, {framebuffer.width, framebuffer.height}, format); |
||||
|
raw_image_views[i] = CreateWrappedImageView(device, raw_images[i], format); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Layer::CreateFSR(VkExtent2D output_size) { |
||||
|
fsr = std::make_unique<FSR>(device, memory_allocator, image_count, output_size); |
||||
|
} |
||||
|
|
||||
|
void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { |
||||
|
if (framebuffer.width == raw_width && framebuffer.height == raw_height && |
||||
|
framebuffer.pixel_format == pixel_format && !raw_images.empty()) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
raw_width = framebuffer.width; |
||||
|
raw_height = framebuffer.height; |
||||
|
pixel_format = framebuffer.pixel_format; |
||||
|
anti_alias.reset(); |
||||
|
|
||||
|
ReleaseRawImages(); |
||||
|
CreateStagingBuffer(framebuffer); |
||||
|
CreateRawImages(framebuffer); |
||||
|
} |
||||
|
|
||||
|
void Layer::SetAntiAliasPass() { |
||||
|
if (anti_alias && anti_alias_setting == Settings::values.anti_aliasing.GetValue()) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
anti_alias_setting = Settings::values.anti_aliasing.GetValue(); |
||||
|
|
||||
|
const VkExtent2D render_area{ |
||||
|
.width = Settings::values.resolution_info.ScaleUp(raw_width), |
||||
|
.height = Settings::values.resolution_info.ScaleUp(raw_height), |
||||
|
}; |
||||
|
|
||||
|
switch (anti_alias_setting) { |
||||
|
case Settings::AntiAliasing::Fxaa: |
||||
|
anti_alias = std::make_unique<FXAA>(device, memory_allocator, image_count, render_area); |
||||
|
break; |
||||
|
case Settings::AntiAliasing::Smaa: |
||||
|
anti_alias = std::make_unique<SMAA>(device, memory_allocator, image_count, render_area); |
||||
|
break; |
||||
|
default: |
||||
|
anti_alias = std::make_unique<NoAA>(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Layer::ReleaseRawImages() { |
||||
|
for (const u64 tick : resource_ticks) { |
||||
|
scheduler.Wait(tick); |
||||
|
} |
||||
|
raw_images.clear(); |
||||
|
buffer.reset(); |
||||
|
} |
||||
|
|
||||
|
u64 Layer::CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const { |
||||
|
return GetSizeInBytes(framebuffer) * image_count; |
||||
|
} |
||||
|
|
||||
|
u64 Layer::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, |
||||
|
size_t image_index) const { |
||||
|
return GetSizeInBytes(framebuffer) * image_index; |
||||
|
} |
||||
|
|
||||
|
void Layer::SetMatrixData(PresentPushConstants& data, |
||||
|
const Layout::FramebufferLayout& layout) const { |
||||
|
data.modelview_matrix = |
||||
|
MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height)); |
||||
|
} |
||||
|
|
||||
|
void Layer::SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout, |
||||
|
const Common::Rectangle<f32>& crop) const { |
||||
|
// Map the coordinates to the screen.
|
||||
|
const auto& screen = layout.screen; |
||||
|
const auto x = static_cast<f32>(screen.left); |
||||
|
const auto y = static_cast<f32>(screen.top); |
||||
|
const auto w = static_cast<f32>(screen.GetWidth()); |
||||
|
const auto h = static_cast<f32>(screen.GetHeight()); |
||||
|
|
||||
|
data.vertices[0] = ScreenRectVertex(x, y, crop.left, crop.top); |
||||
|
data.vertices[1] = ScreenRectVertex(x + w, y, crop.right, crop.top); |
||||
|
data.vertices[2] = ScreenRectVertex(x, y + h, crop.left, crop.bottom); |
||||
|
data.vertices[3] = ScreenRectVertex(x + w, y + h, crop.right, crop.bottom); |
||||
|
} |
||||
|
|
||||
|
void Layer::UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index) { |
||||
|
const VkDescriptorImageInfo image_info{ |
||||
|
.sampler = sampler, |
||||
|
.imageView = image_view, |
||||
|
.imageLayout = VK_IMAGE_LAYOUT_GENERAL, |
||||
|
}; |
||||
|
|
||||
|
const VkWriteDescriptorSet sampler_write{ |
||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
||||
|
.pNext = nullptr, |
||||
|
.dstSet = descriptor_sets[image_index], |
||||
|
.dstBinding = 0, |
||||
|
.dstArrayElement = 0, |
||||
|
.descriptorCount = 1, |
||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |
||||
|
.pImageInfo = &image_info, |
||||
|
.pBufferInfo = nullptr, |
||||
|
.pTexelBufferView = nullptr, |
||||
|
}; |
||||
|
|
||||
|
device.GetLogical().UpdateDescriptorSets(std::array{sampler_write}, {}); |
||||
|
} |
||||
|
|
||||
|
void Layer::UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t image_index) { |
||||
|
const std::span<u8> mapped_span = buffer.Mapped(); |
||||
|
|
||||
|
const u64 image_offset = GetRawImageOffset(framebuffer, image_index); |
||||
|
|
||||
|
const DAddr framebuffer_addr = framebuffer.address + framebuffer.offset; |
||||
|
const u8* const host_ptr = device_memory.GetPointer<u8>(framebuffer_addr); |
||||
|
|
||||
|
// TODO(Rodrigo): Read this from HLE
|
||||
|
constexpr u32 block_height_log2 = 4; |
||||
|
const u32 bytes_per_pixel = GetBytesPerPixel(framebuffer); |
||||
|
const u64 linear_size{GetSizeInBytes(framebuffer)}; |
||||
|
const u64 tiled_size{Tegra::Texture::CalculateSize( |
||||
|
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; |
||||
|
Tegra::Texture::UnswizzleTexture( |
||||
|
mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size), |
||||
|
bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0); |
||||
|
|
||||
|
const VkBufferImageCopy copy{ |
||||
|
.bufferOffset = image_offset, |
||||
|
.bufferRowLength = 0, |
||||
|
.bufferImageHeight = 0, |
||||
|
.imageSubresource = |
||||
|
{ |
||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, |
||||
|
.mipLevel = 0, |
||||
|
.baseArrayLayer = 0, |
||||
|
.layerCount = 1, |
||||
|
}, |
||||
|
.imageOffset = {.x = 0, .y = 0, .z = 0}, |
||||
|
.imageExtent = |
||||
|
{ |
||||
|
.width = framebuffer.width, |
||||
|
.height = framebuffer.height, |
||||
|
.depth = 1, |
||||
|
}, |
||||
|
}; |
||||
|
scheduler.Record([this, copy, index = image_index](vk::CommandBuffer cmdbuf) { |
||||
|
const VkImage image = *raw_images[index]; |
||||
|
const VkImageMemoryBarrier base_barrier{ |
||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, |
||||
|
.pNext = nullptr, |
||||
|
.srcAccessMask = 0, |
||||
|
.dstAccessMask = 0, |
||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, |
||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL, |
||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, |
||||
|
.image = image, |
||||
|
.subresourceRange{ |
||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, |
||||
|
.baseMipLevel = 0, |
||||
|
.levelCount = 1, |
||||
|
.baseArrayLayer = 0, |
||||
|
.layerCount = 1, |
||||
|
}, |
||||
|
}; |
||||
|
VkImageMemoryBarrier read_barrier = base_barrier; |
||||
|
read_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
||||
|
read_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
||||
|
read_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
||||
|
|
||||
|
VkImageMemoryBarrier write_barrier = base_barrier; |
||||
|
write_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
||||
|
write_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; |
||||
|
write_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
||||
|
|
||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, |
||||
|
read_barrier); |
||||
|
cmdbuf.CopyBufferToImage(*buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy); |
||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, |
||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | |
||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, |
||||
|
0, write_barrier); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} // namespace Vulkan
|
||||
@ -0,0 +1,92 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "common/math_util.h" |
||||
|
#include "video_core/host1x/gpu_device_memory_manager.h" |
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h" |
||||
|
|
||||
|
namespace Layout { |
||||
|
struct FramebufferLayout; |
||||
|
} |
||||
|
|
||||
|
namespace Tegra { |
||||
|
struct FramebufferConfig; |
||||
|
} |
||||
|
|
||||
|
namespace Service::android { |
||||
|
enum class PixelFormat : u32; |
||||
|
} |
||||
|
|
||||
|
namespace Settings { |
||||
|
enum class AntiAliasing : u32; |
||||
|
} |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
class AntiAliasPass; |
||||
|
class Device; |
||||
|
class FSR; |
||||
|
class MemoryAllocator; |
||||
|
struct PresentPushConstants; |
||||
|
class RasterizerVulkan; |
||||
|
class Scheduler; |
||||
|
|
||||
|
class Layer final { |
||||
|
public: |
||||
|
explicit Layer(const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler, |
||||
|
Tegra::MaxwellDeviceMemoryManager& device_memory, size_t image_count, |
||||
|
VkExtent2D output_size, VkDescriptorSetLayout layout); |
||||
|
~Layer(); |
||||
|
|
||||
|
void ConfigureDraw(PresentPushConstants* out_push_constants, |
||||
|
VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer, |
||||
|
VkSampler sampler, size_t image_index, |
||||
|
const Tegra::FramebufferConfig& framebuffer, |
||||
|
const Layout::FramebufferLayout& layout); |
||||
|
|
||||
|
private: |
||||
|
void CreateDescriptorPool(); |
||||
|
void CreateDescriptorSets(VkDescriptorSetLayout layout); |
||||
|
void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer); |
||||
|
void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); |
||||
|
void CreateFSR(VkExtent2D output_size); |
||||
|
|
||||
|
void RefreshResources(const Tegra::FramebufferConfig& framebuffer); |
||||
|
void SetAntiAliasPass(); |
||||
|
void ReleaseRawImages(); |
||||
|
|
||||
|
u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; |
||||
|
u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, size_t image_index) const; |
||||
|
|
||||
|
void SetMatrixData(PresentPushConstants& data, const Layout::FramebufferLayout& layout) const; |
||||
|
void SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout, |
||||
|
const Common::Rectangle<f32>& crop) const; |
||||
|
void UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index); |
||||
|
void UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t image_index); |
||||
|
|
||||
|
private: |
||||
|
const Device& device; |
||||
|
MemoryAllocator& memory_allocator; |
||||
|
Scheduler& scheduler; |
||||
|
Tegra::MaxwellDeviceMemoryManager& device_memory; |
||||
|
const size_t image_count{}; |
||||
|
vk::DescriptorPool descriptor_pool{}; |
||||
|
vk::DescriptorSets descriptor_sets{}; |
||||
|
|
||||
|
vk::Buffer buffer{}; |
||||
|
std::vector<vk::Image> raw_images{}; |
||||
|
std::vector<vk::ImageView> raw_image_views{}; |
||||
|
u32 raw_width{}; |
||||
|
u32 raw_height{}; |
||||
|
Service::android::PixelFormat pixel_format{}; |
||||
|
|
||||
|
Settings::AntiAliasing anti_alias_setting{}; |
||||
|
std::unique_ptr<AntiAliasPass> anti_alias{}; |
||||
|
|
||||
|
std::unique_ptr<FSR> fsr{}; |
||||
|
std::vector<u64> resource_ticks{}; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Vulkan |
||||
@ -0,0 +1,34 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
struct ScreenRectVertex { |
||||
|
ScreenRectVertex() = default; |
||||
|
explicit ScreenRectVertex(f32 x, f32 y, f32 u, f32 v) : position{{x, y}}, tex_coord{{u, v}} {} |
||||
|
|
||||
|
std::array<f32, 2> position; |
||||
|
std::array<f32, 2> tex_coord; |
||||
|
}; |
||||
|
|
||||
|
static inline std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) { |
||||
|
// clang-format off |
||||
|
return { 2.f / width, 0.f, 0.f, 0.f, |
||||
|
0.f, 2.f / height, 0.f, 0.f, |
||||
|
0.f, 0.f, 1.f, 0.f, |
||||
|
-1.f, -1.f, 0.f, 1.f}; |
||||
|
// clang-format on |
||||
|
} |
||||
|
|
||||
|
struct PresentPushConstants { |
||||
|
std::array<f32, 4 * 4> modelview_matrix; |
||||
|
std::array<ScreenRectVertex, 4> vertices; |
||||
|
}; |
||||
|
|
||||
|
static_assert(sizeof(PresentPushConstants) <= 128, "Push constants are too large"); |
||||
|
|
||||
|
} // namespace Vulkan |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue