mirror of
https://github.com/PabloMK7/citra.git
synced 2025-12-17 20:58:47 +00:00
Merge branch 'master' into vk-fixes
This commit is contained in:
commit
2fe2dd1482
35 changed files with 445 additions and 185 deletions
|
|
@ -148,8 +148,6 @@ inline GLenum BlendFunc(Pica::FramebufferRegs::BlendFactor factor) {
|
|||
// Range check table for input
|
||||
if (index >= blend_func_table.size()) {
|
||||
LOG_CRITICAL(Render_OpenGL, "Unknown blend factor {}", index);
|
||||
UNREACHABLE();
|
||||
|
||||
return GL_ONE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,10 @@ inline vk::BlendFactor BlendFunc(Pica::FramebufferRegs::BlendFactor factor) {
|
|||
}};
|
||||
|
||||
const auto index = static_cast<std::size_t>(factor);
|
||||
ASSERT_MSG(index < blend_func_table.size(), "Unknown blend factor {}", index);
|
||||
if (index >= blend_func_table.size()) {
|
||||
LOG_CRITICAL(Render_Vulkan, "Unknown blend factor {}", index);
|
||||
return vk::BlendFactor::eOne;
|
||||
}
|
||||
return blend_func_table[index];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <span>
|
||||
#include <boost/container/static_vector.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/settings.h"
|
||||
|
|
@ -153,6 +154,12 @@ Instance::Instance(Core::TelemetrySession& telemetry, Frontend::EmuWindow& windo
|
|||
physical_device = physical_devices[physical_device_index];
|
||||
available_extensions = GetSupportedExtensions(physical_device);
|
||||
properties = physical_device.getProperties();
|
||||
if (properties.apiVersion < TargetVulkanApiVersion) {
|
||||
throw std::runtime_error(fmt::format(
|
||||
"Vulkan {}.{} is required, but only {}.{} is supported by device!",
|
||||
VK_VERSION_MAJOR(TargetVulkanApiVersion), VK_VERSION_MINOR(TargetVulkanApiVersion),
|
||||
VK_VERSION_MAJOR(properties.apiVersion), VK_VERSION_MINOR(properties.apiVersion)));
|
||||
}
|
||||
|
||||
CollectTelemetryParameters(telemetry);
|
||||
CreateDevice();
|
||||
|
|
@ -629,7 +636,7 @@ void Instance::CreateAllocator() {
|
|||
.device = *device,
|
||||
.pVulkanFunctions = &functions,
|
||||
.instance = *instance,
|
||||
.vulkanApiVersion = properties.apiVersion,
|
||||
.vulkanApiVersion = TargetVulkanApiVersion,
|
||||
};
|
||||
|
||||
const VkResult result = vmaCreateAllocator(&allocator_info, &allocator);
|
||||
|
|
@ -670,7 +677,7 @@ void Instance::CollectToolingInfo() {
|
|||
if (!tooling_info) {
|
||||
return;
|
||||
}
|
||||
const auto tools = physical_device.getToolProperties();
|
||||
const auto tools = physical_device.getToolPropertiesEXT();
|
||||
for (const vk::PhysicalDeviceToolProperties& tool : tools) {
|
||||
const std::string_view name = tool.name;
|
||||
LOG_INFO(Render_Vulkan, "Attached debugging tool: {}", name);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
#include <boost/container/static_vector.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
|
|
@ -291,13 +292,14 @@ vk::UniqueInstance CreateInstance(const Common::DynamicLibrary& library,
|
|||
}
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||
|
||||
if (!VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion) {
|
||||
throw std::runtime_error("Vulkan 1.0 is not supported, 1.1 is required!");
|
||||
}
|
||||
|
||||
const u32 available_version = vk::enumerateInstanceVersion();
|
||||
if (available_version < VK_API_VERSION_1_1) {
|
||||
throw std::runtime_error("Vulkan 1.0 is not supported, 1.1 is required!");
|
||||
const u32 available_version = VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion
|
||||
? vk::enumerateInstanceVersion()
|
||||
: VK_API_VERSION_1_0;
|
||||
if (available_version < TargetVulkanApiVersion) {
|
||||
throw std::runtime_error(fmt::format(
|
||||
"Vulkan {}.{} is required, but only {}.{} is supported by instance!",
|
||||
VK_VERSION_MAJOR(TargetVulkanApiVersion), VK_VERSION_MINOR(TargetVulkanApiVersion),
|
||||
VK_VERSION_MAJOR(available_version), VK_VERSION_MINOR(available_version)));
|
||||
}
|
||||
|
||||
const auto extensions = GetInstanceExtensions(window_type, enable_validation);
|
||||
|
|
@ -307,7 +309,7 @@ vk::UniqueInstance CreateInstance(const Common::DynamicLibrary& library,
|
|||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.pEngineName = "Citra Vulkan",
|
||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.apiVersion = VK_API_VERSION_1_3,
|
||||
.apiVersion = TargetVulkanApiVersion,
|
||||
};
|
||||
|
||||
boost::container::static_vector<const char*, 2> layers;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ enum class WindowSystemType : u8;
|
|||
|
||||
namespace Vulkan {
|
||||
|
||||
constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_1;
|
||||
|
||||
using DebugCallback =
|
||||
std::variant<vk::UniqueDebugUtilsMessengerEXT, vk::UniqueDebugReportCallbackEXT>;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
||||
#include "common/literals.h"
|
||||
#include "common/microprofile.h"
|
||||
|
|
@ -118,9 +119,9 @@ u32 UnpackDepthStencil(const VideoCore::StagingData& data, vk::Format dest) {
|
|||
}
|
||||
|
||||
boost::container::small_vector<vk::ImageMemoryBarrier, 3> MakeInitBarriers(
|
||||
vk::ImageAspectFlags aspect, std::span<const vk::Image> images, std::size_t num_images) {
|
||||
vk::ImageAspectFlags aspect, std::span<const vk::Image> images) {
|
||||
boost::container::small_vector<vk::ImageMemoryBarrier, 3> barriers;
|
||||
for (std::size_t i = 0; i < num_images; i++) {
|
||||
for (const vk::Image& image : images) {
|
||||
barriers.push_back(vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||
.dstAccessMask = vk::AccessFlagBits::eNone,
|
||||
|
|
@ -128,7 +129,7 @@ boost::container::small_vector<vk::ImageMemoryBarrier, 3> MakeInitBarriers(
|
|||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = images[i],
|
||||
.image = image,
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect,
|
||||
.baseMipLevel = 0,
|
||||
|
|
@ -218,11 +219,10 @@ Handle MakeHandle(const Instance* instance, u32 width, u32 height, u32 levels, T
|
|||
}
|
||||
|
||||
vk::UniqueFramebuffer MakeFramebuffer(vk::Device device, vk::RenderPass render_pass, u32 width,
|
||||
u32 height, std::span<const vk::ImageView> attachments,
|
||||
u32 num_attachments) {
|
||||
u32 height, std::span<const vk::ImageView> attachments) {
|
||||
const vk::FramebufferCreateInfo framebuffer_info = {
|
||||
.renderPass = render_pass,
|
||||
.attachmentCount = num_attachments,
|
||||
.attachmentCount = static_cast<u32>(attachments.size()),
|
||||
.pAttachments = attachments.data(),
|
||||
.width = width,
|
||||
.height = height,
|
||||
|
|
@ -710,8 +710,7 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceParams& param
|
|||
ASSERT_MSG(format != vk::Format::eUndefined && levels >= 1,
|
||||
"Image allocation parameters are invalid");
|
||||
|
||||
u32 num_images = 0;
|
||||
std::array<vk::Image, 3> raw_images;
|
||||
boost::container::static_vector<vk::Image, 3> raw_images;
|
||||
|
||||
vk::ImageCreateFlags flags{};
|
||||
if (texture_type == VideoCore::TextureType::CubeMap) {
|
||||
|
|
@ -724,18 +723,18 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceParams& param
|
|||
const bool need_format_list = is_mutable && instance->IsImageFormatListSupported();
|
||||
handles[0] = MakeHandle(instance, width, height, levels, texture_type, format, traits.usage,
|
||||
flags, traits.aspect, need_format_list, DebugName(false));
|
||||
raw_images[num_images++] = handles[0].image;
|
||||
raw_images.emplace_back(handles[0].image);
|
||||
|
||||
if (res_scale != 1) {
|
||||
handles[1] =
|
||||
MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, format,
|
||||
traits.usage, flags, traits.aspect, need_format_list, DebugName(true));
|
||||
raw_images[num_images++] = handles[1].image;
|
||||
raw_images.emplace_back(handles[1].image);
|
||||
}
|
||||
|
||||
runtime->render_manager.EndRendering();
|
||||
scheduler->Record([raw_images, num_images, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
|
||||
const auto barriers = MakeInitBarriers(aspect, raw_images, num_images);
|
||||
scheduler->Record([raw_images, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
|
||||
const auto barriers = MakeInitBarriers(aspect, raw_images);
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, barriers);
|
||||
|
|
@ -753,8 +752,7 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceBase& surface
|
|||
const bool has_normal = mat && mat->Map(MapType::Normal);
|
||||
const vk::Format format = traits.native;
|
||||
|
||||
u32 num_images = 0;
|
||||
std::array<vk::Image, 2> raw_images;
|
||||
boost::container::static_vector<vk::Image, 2> raw_images;
|
||||
|
||||
vk::ImageCreateFlags flags{};
|
||||
if (texture_type == VideoCore::TextureType::CubeMap) {
|
||||
|
|
@ -764,23 +762,23 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceBase& surface
|
|||
const std::string debug_name = DebugName(false, true);
|
||||
handles[0] = MakeHandle(instance, mat->width, mat->height, levels, texture_type, format,
|
||||
traits.usage, flags, traits.aspect, false, debug_name);
|
||||
raw_images[num_images++] = handles[0].image;
|
||||
raw_images.emplace_back(handles[0].image);
|
||||
|
||||
if (res_scale != 1) {
|
||||
handles[1] = MakeHandle(instance, mat->width, mat->height, levels, texture_type,
|
||||
vk::Format::eR8G8B8A8Unorm, traits.usage, flags, traits.aspect,
|
||||
false, debug_name);
|
||||
raw_images[num_images++] = handles[1].image;
|
||||
raw_images.emplace_back(handles[1].image);
|
||||
}
|
||||
if (has_normal) {
|
||||
handles[2] = MakeHandle(instance, mat->width, mat->height, levels, texture_type, format,
|
||||
traits.usage, flags, traits.aspect, false, debug_name);
|
||||
raw_images[num_images++] = handles[2].image;
|
||||
raw_images.emplace_back(handles[2].image);
|
||||
}
|
||||
|
||||
runtime->render_manager.EndRendering();
|
||||
scheduler->Record([raw_images, num_images, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
|
||||
const auto barriers = MakeInitBarriers(aspect, raw_images, num_images);
|
||||
scheduler->Record([raw_images, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
|
||||
const auto barriers = MakeInitBarriers(aspect, raw_images);
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, barriers);
|
||||
|
|
@ -817,11 +815,10 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload,
|
|||
|
||||
scheduler->Record([buffer = runtime->upload_buffer.Handle(), format = traits.native, params,
|
||||
staging, upload](vk::CommandBuffer cmdbuf) {
|
||||
u32 num_copies = 1;
|
||||
std::array<vk::BufferImageCopy, 2> buffer_image_copies;
|
||||
boost::container::static_vector<vk::BufferImageCopy, 2> buffer_image_copies;
|
||||
|
||||
const auto rect = upload.texture_rect;
|
||||
buffer_image_copies[0] = vk::BufferImageCopy{
|
||||
buffer_image_copies.emplace_back(vk::BufferImageCopy{
|
||||
.bufferOffset = upload.buffer_offset,
|
||||
.bufferRowLength = rect.GetWidth(),
|
||||
.bufferImageHeight = rect.GetHeight(),
|
||||
|
|
@ -833,15 +830,16 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload,
|
|||
},
|
||||
.imageOffset = {static_cast<s32>(rect.left), static_cast<s32>(rect.bottom), 0},
|
||||
.imageExtent = {rect.GetWidth(), rect.GetHeight(), 1},
|
||||
};
|
||||
});
|
||||
|
||||
if (params.aspect & vk::ImageAspectFlagBits::eStencil) {
|
||||
buffer_image_copies[0].imageSubresource.aspectMask = vk::ImageAspectFlagBits::eDepth;
|
||||
vk::BufferImageCopy& stencil_copy = buffer_image_copies[1];
|
||||
|
||||
vk::BufferImageCopy& stencil_copy =
|
||||
buffer_image_copies.emplace_back(buffer_image_copies[0]);
|
||||
stencil_copy = buffer_image_copies[0];
|
||||
stencil_copy.bufferOffset += UnpackDepthStencil(staging, format);
|
||||
stencil_copy.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eStencil;
|
||||
num_copies++;
|
||||
}
|
||||
|
||||
const vk::ImageMemoryBarrier read_barrier = {
|
||||
|
|
@ -869,7 +867,7 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload,
|
|||
vk::DependencyFlagBits::eByRegion, {}, {}, read_barrier);
|
||||
|
||||
cmdbuf.copyBufferToImage(buffer, params.src_image, vk::ImageLayout::eTransferDstOptimal,
|
||||
num_copies, buffer_image_copies.data());
|
||||
buffer_image_copies);
|
||||
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, params.pipeline_flags,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, write_barrier);
|
||||
|
|
@ -1077,7 +1075,7 @@ void Surface::ScaleUp(u32 new_scale) {
|
|||
runtime->render_manager.EndRendering();
|
||||
scheduler->Record(
|
||||
[raw_images = std::array{Image()}, aspect = traits.aspect](vk::CommandBuffer cmdbuf) {
|
||||
const auto barriers = MakeInitBarriers(aspect, raw_images, raw_images.size());
|
||||
const auto barriers = MakeInitBarriers(aspect, raw_images);
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::PipelineStageFlagBits::eTopOfPipe,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, barriers);
|
||||
|
|
@ -1343,7 +1341,7 @@ vk::Framebuffer Surface::Framebuffer() noexcept {
|
|||
runtime->render_manager.GetRenderpass(color_format, depth_format, false);
|
||||
const auto attachments = std::array{ImageView()};
|
||||
framebuffers[index] = MakeFramebuffer(instance->GetDevice(), render_pass, GetScaledWidth(),
|
||||
GetScaledHeight(), attachments, 1);
|
||||
GetScaledHeight(), attachments);
|
||||
return framebuffers[index].get();
|
||||
}
|
||||
|
||||
|
|
@ -1473,17 +1471,16 @@ Framebuffer::Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferPa
|
|||
image_views[index] = shadow_rendering ? surface->StorageView() : surface->FramebufferView();
|
||||
};
|
||||
|
||||
u32 num_attachments = 0;
|
||||
std::array<vk::ImageView, 2> attachments;
|
||||
boost::container::static_vector<vk::ImageView, 2> attachments;
|
||||
|
||||
if (color) {
|
||||
prepare(0, color);
|
||||
attachments[num_attachments++] = image_views[0];
|
||||
attachments.emplace_back(image_views[0]);
|
||||
}
|
||||
|
||||
if (depth) {
|
||||
prepare(1, depth);
|
||||
attachments[num_attachments++] = image_views[1];
|
||||
attachments.emplace_back(image_views[1]);
|
||||
}
|
||||
|
||||
const vk::Device device = runtime.GetInstance().GetDevice();
|
||||
|
|
@ -1491,11 +1488,10 @@ Framebuffer::Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferPa
|
|||
render_pass =
|
||||
render_manager.GetRenderpass(PixelFormat::Invalid, PixelFormat::Invalid, false);
|
||||
framebuffer = MakeFramebuffer(device, render_pass, color->GetScaledWidth(),
|
||||
color->GetScaledHeight(), {}, 0);
|
||||
color->GetScaledHeight(), {});
|
||||
} else {
|
||||
render_pass = render_manager.GetRenderpass(formats[0], formats[1], false);
|
||||
framebuffer =
|
||||
MakeFramebuffer(device, render_pass, width, height, attachments, num_attachments);
|
||||
framebuffer = MakeFramebuffer(device, render_pass, width, height, attachments);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue