renderer_vulkan: Properly format structs

This commit is contained in:
GPUCode
2022-12-29 20:11:57 +02:00
parent 98e0ecf6a7
commit d3392ae0b1
19 changed files with 1492 additions and 1139 deletions

View File

@@ -118,7 +118,8 @@ void Config::ReadValues() {
static_cast<Settings::GraphicsAPI>(sdl2_config->GetInteger("Renderer", "graphics_api", 2));
Settings::values.async_command_recording =
sdl2_config->GetBoolean("Renderer", "async_command_recording", true);
Settings::values.spirv_shader_gen = sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
Settings::values.spirv_shader_gen =
sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "renderer_debug", false);
Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true);
Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true);

View File

@@ -19,13 +19,13 @@
static bool IsPortraitMode() {
return JNI_FALSE != IDCache::GetEnvForThread()->CallStaticBooleanMethod(
IDCache::GetNativeLibraryClass(), IDCache::GetIsPortraitMode());
IDCache::GetNativeLibraryClass(), IDCache::GetIsPortraitMode());
}
static void UpdateLandscapeScreenLayout() {
Settings::values.layout_option =
static_cast<Settings::LayoutOption>(IDCache::GetEnvForThread()->CallStaticIntMethod(
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
static_cast<Settings::LayoutOption>(IDCache::GetEnvForThread()->CallStaticIntMethod(
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
}
void EmuWindow_Android_Vulkan::OnSurfaceChanged(ANativeWindow* surface) {

View File

@@ -167,7 +167,8 @@ void RendererVulkan::PrepareRendertarget() {
LCD::Read(color_fill.raw, lcd_color_addr);
if (color_fill.is_enabled) {
LoadColorToActiveVkTexture(color_fill.color_r, color_fill.color_g, color_fill.color_b, screen_infos[i].texture);
LoadColorToActiveVkTexture(color_fill.color_r, color_fill.color_g, color_fill.color_b,
screen_infos[i].texture);
} else {
TextureInfo& texture = screen_infos[i].texture;
if (texture.width != framebuffer.width || texture.height != framebuffer.height ||
@@ -197,7 +198,8 @@ void RendererVulkan::BeginRendering() {
present_textures[i] = vk::DescriptorImageInfo{
.imageView = info.display_texture ? info.display_texture->image_view
: info.texture.alloc.image_view,
.imageLayout = vk::ImageLayout::eGeneral};
.imageLayout = vk::ImageLayout::eGeneral,
};
}
present_textures[3] = vk::DescriptorImageInfo{.sampler = present_samplers[current_sampler]};
@@ -295,41 +297,53 @@ void RendererVulkan::CompileShaders() {
void RendererVulkan::BuildLayouts() {
const std::array present_layout_bindings = {
vk::DescriptorSetLayoutBinding{.binding = 0,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 3,
.stageFlags = vk::ShaderStageFlagBits::eFragment},
vk::DescriptorSetLayoutBinding{.binding = 1,
.descriptorType = vk::DescriptorType::eSampler,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eFragment}};
vk::DescriptorSetLayoutBinding{
.binding = 0,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 3,
.stageFlags = vk::ShaderStageFlagBits::eFragment,
},
vk::DescriptorSetLayoutBinding{
.binding = 1,
.descriptorType = vk::DescriptorType::eSampler,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eFragment,
},
};
const vk::DescriptorSetLayoutCreateInfo present_layout_info = {
.bindingCount = static_cast<u32>(present_layout_bindings.size()),
.pBindings = present_layout_bindings.data()};
.pBindings = present_layout_bindings.data(),
};
vk::Device device = instance.GetDevice();
present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info);
const std::array update_template_entries = {
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 3,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = 0,
.stride = sizeof(vk::DescriptorImageInfo)},
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampler,
.offset = 3 * sizeof(vk::DescriptorImageInfo),
.stride = 0}};
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 3,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = 0,
.stride = sizeof(vk::DescriptorImageInfo),
},
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampler,
.offset = 3 * sizeof(vk::DescriptorImageInfo),
.stride = 0,
},
};
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = present_descriptor_layout};
.descriptorSetLayout = present_descriptor_layout,
};
present_update_template = device.createDescriptorUpdateTemplate(template_info);
@@ -339,37 +353,49 @@ void RendererVulkan::BuildLayouts() {
.size = sizeof(PresentUniformData),
};
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
.pSetLayouts = &present_descriptor_layout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range};
const vk::PipelineLayoutCreateInfo layout_info = {
.setLayoutCount = 1,
.pSetLayouts = &present_descriptor_layout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range,
};
present_pipeline_layout = device.createPipelineLayout(layout_info);
}
void RendererVulkan::BuildPipelines() {
const vk::VertexInputBindingDescription binding = {.binding = 0,
.stride = sizeof(ScreenRectVertex),
.inputRate = vk::VertexInputRate::eVertex};
const vk::VertexInputBindingDescription binding = {
.binding = 0,
.stride = sizeof(ScreenRectVertex),
.inputRate = vk::VertexInputRate::eVertex,
};
const std::array attributes = {
vk::VertexInputAttributeDescription{.location = 0,
.binding = 0,
.format = vk::Format::eR32G32Sfloat,
.offset = offsetof(ScreenRectVertex, position)},
vk::VertexInputAttributeDescription{.location = 1,
.binding = 0,
.format = vk::Format::eR32G32Sfloat,
.offset = offsetof(ScreenRectVertex, tex_coord)}};
vk::VertexInputAttributeDescription{
.location = 0,
.binding = 0,
.format = vk::Format::eR32G32Sfloat,
.offset = offsetof(ScreenRectVertex, position),
},
vk::VertexInputAttributeDescription{
.location = 1,
.binding = 0,
.format = vk::Format::eR32G32Sfloat,
.offset = offsetof(ScreenRectVertex, tex_coord),
},
};
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &binding,
.vertexAttributeDescriptionCount = static_cast<u32>(attributes.size()),
.pVertexAttributeDescriptions = attributes.data()};
.pVertexAttributeDescriptions = attributes.data(),
};
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
.topology = vk::PrimitiveTopology::eTriangleStrip, .primitiveRestartEnable = false};
.topology = vk::PrimitiveTopology::eTriangleStrip,
.primitiveRestartEnable = false,
};
const vk::PipelineRasterizationStateCreateInfo raster_state = {
.depthClampEnable = false,
@@ -377,21 +403,26 @@ void RendererVulkan::BuildPipelines() {
.cullMode = vk::CullModeFlagBits::eNone,
.frontFace = vk::FrontFace::eClockwise,
.depthBiasEnable = false,
.lineWidth = 1.0f};
.lineWidth = 1.0f,
};
const vk::PipelineMultisampleStateCreateInfo multisampling = {
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false};
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
.blendEnable = false,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA};
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
const vk::PipelineColorBlendStateCreateInfo color_blending = {
.logicOpEnable = false,
.attachmentCount = 1,
.pAttachments = &colorblend_attachment,
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f}};
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
};
const vk::Viewport placeholder_viewport = vk::Viewport{0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
const vk::Rect2D placeholder_scissor = vk::Rect2D{{0, 0}, {1, 1}};
@@ -402,27 +433,36 @@ void RendererVulkan::BuildPipelines() {
.pScissors = &placeholder_scissor,
};
const std::array dynamic_states = {vk::DynamicState::eViewport, vk::DynamicState::eScissor};
const std::array dynamic_states = {
vk::DynamicState::eViewport,
vk::DynamicState::eScissor,
};
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
.pDynamicStates = dynamic_states.data()};
.pDynamicStates = dynamic_states.data(),
};
const vk::PipelineDepthStencilStateCreateInfo depth_info = {.depthTestEnable = false,
.depthWriteEnable = false,
.depthCompareOp =
vk::CompareOp::eAlways,
.depthBoundsTestEnable = false,
.stencilTestEnable = false};
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
.depthTestEnable = false,
.depthWriteEnable = false,
.depthCompareOp = vk::CompareOp::eAlways,
.depthBoundsTestEnable = false,
.stencilTestEnable = false,
};
for (u32 i = 0; i < PRESENT_PIPELINES; i++) {
const std::array shader_stages = {
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eVertex,
.module = present_vertex_shader,
.pName = "main"},
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eFragment,
.module = present_shaders[i],
.pName = "main"},
vk::PipelineShaderStageCreateInfo{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = present_vertex_shader,
.pName = "main",
},
vk::PipelineShaderStageCreateInfo{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = present_shaders[i],
.pName = "main",
},
};
const vk::GraphicsPipelineCreateInfo pipeline_info = {
@@ -437,7 +477,8 @@ void RendererVulkan::BuildPipelines() {
.pColorBlendState = &color_blending,
.pDynamicState = &dynamic_info,
.layout = present_pipeline_layout,
.renderPass = renderpass_cache.GetPresentRenderpass()};
.renderPass = renderpass_cache.GetPresentRenderpass(),
};
vk::Device device = instance.GetDevice();
if (const auto result = device.createGraphicsPipeline({}, pipeline_info);
@@ -453,67 +494,80 @@ void RendererVulkan::BuildPipelines() {
void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture,
const GPU::Regs::FramebufferConfig& framebuffer) {
TextureInfo old_texture = std::move(texture);
texture = TextureInfo{.alloc = runtime.Allocate(
framebuffer.width, framebuffer.height,
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format),
VideoCore::TextureType::Texture2D),
.width = framebuffer.width,
.height = framebuffer.height,
.format = framebuffer.color_format};
texture = TextureInfo{
.alloc =
runtime.Allocate(framebuffer.width, framebuffer.height,
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format),
VideoCore::TextureType::Texture2D),
.width = framebuffer.width,
.height = framebuffer.height,
.format = framebuffer.color_format,
};
// Recyle the old texture after allocation to avoid having duplicates of the same allocation in
// the recycler
if (old_texture.width != 0 && old_texture.height != 0) {
const HostTextureTag tag = {.format = old_texture.alloc.format,
.width = old_texture.width,
.height = old_texture.height};
const HostTextureTag tag = {
.format = old_texture.alloc.format,
.width = old_texture.width,
.height = old_texture.height,
};
runtime.Recycle(tag, std::move(old_texture.alloc));
}
}
void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture) {
void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b,
const TextureInfo& texture) {
const vk::ClearColorValue clear_color = {
.float32 = std::array{color_r / 255.0f, color_g / 255.0f, color_b / 255.0f, 1.0f}};
.float32 =
std::array{
color_r / 255.0f,
color_g / 255.0f,
color_b / 255.0f,
1.0f,
},
};
renderpass_cache.ExitRenderpass();
scheduler.Record([image = texture.alloc.image,
clear_color](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
const vk::ImageSubresourceRange range = {.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS};
scheduler.Record([image = texture.alloc.image, clear_color](vk::CommandBuffer render_cmdbuf,
vk::CommandBuffer) {
const vk::ImageSubresourceRange range = {
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
};
const vk::ImageMemoryBarrier pre_barrier = {
.srcAccessMask = vk::AccessFlagBits::eShaderRead |
vk::AccessFlagBits::eTransferRead,
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange = range
.srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange = range,
};
const vk::ImageMemoryBarrier post_barrier = {
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead |
vk::AccessFlagBits::eTransferRead,
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange = range
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange = range,
};
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
render_cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear_color, range);
render_cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear_color,
range);
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eAllCommands,
@@ -873,14 +927,19 @@ void RendererVulkan::SwapBuffers() {
} while (swapchain.NeedsRecreation());
scheduler.Record([layout](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
const vk::Viewport viewport = {.x = 0.0f,
.y = 0.0f,
.width = static_cast<float>(layout.width),
.height = static_cast<float>(layout.height),
.minDepth = 0.0f,
.maxDepth = 1.0f};
const vk::Viewport viewport = {
.x = 0.0f,
.y = 0.0f,
.width = static_cast<float>(layout.width),
.height = static_cast<float>(layout.height),
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
const vk::Rect2D scissor = {.offset = {0, 0}, .extent = {layout.width, layout.height}};
const vk::Rect2D scissor = {
.offset = {0, 0},
.extent = {layout.width, layout.height},
};
render_cmdbuf.setViewport(0, viewport);
render_cmdbuf.setScissor(0, scissor);
@@ -888,20 +947,6 @@ void RendererVulkan::SwapBuffers() {
DrawScreens(layout, false);
/*renderpass_cache.ExitRenderpass();
scheduler.Record([](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
const vk::MemoryBarrier memory_write_barrier = {
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
};
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands,
vk::DependencyFlagBits::eByRegion,
memory_write_barrier, {}, {});
});*/
const vk::Semaphore image_acquired = swapchain.GetImageAcquiredSemaphore();
const vk::Semaphore present_ready = swapchain.GetPresentReadySemaphore();
scheduler.Flush(present_ready, image_acquired);

View File

@@ -6,15 +6,16 @@
#include "video_core/renderer_vulkan/vk_blit_helper.h"
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
namespace Vulkan {
BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler, DescriptorManager& desc_manager)
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} {
BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler,
DescriptorManager& desc_manager)
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} {
constexpr std::string_view cs_source = R"(
#version 450 core
#extension GL_EXT_samplerless_texture_functions : require
@@ -36,77 +37,100 @@ imageStore(color, dst_coord, uvec4(value));
}
)";
compute_shader =
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
const std::array compute_layout_bindings = {
vk::DescriptorSetLayoutBinding{.binding = 0,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute},
vk::DescriptorSetLayoutBinding{.binding = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute},
vk::DescriptorSetLayoutBinding{.binding = 2,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute}};
vk::DescriptorSetLayoutBinding{
.binding = 0,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
vk::DescriptorSetLayoutBinding{
.binding = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
vk::DescriptorSetLayoutBinding{
.binding = 2,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
};
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
.pBindings = compute_layout_bindings.data()};
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
.pBindings = compute_layout_bindings.data(),
};
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
const std::array update_template_entries = {
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = 0,
.stride = sizeof(vk::DescriptorImageInfo)},
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = sizeof(vk::DescriptorImageInfo),
.stride = 0},
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageImage,
.offset = 2 * sizeof(vk::DescriptorImageInfo),
.stride = 0}};
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = 0,
.stride = sizeof(vk::DescriptorImageInfo),
},
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = sizeof(vk::DescriptorImageInfo),
.stride = 0,
},
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageImage,
.offset = 2 * sizeof(vk::DescriptorImageInfo),
.stride = 0,
},
};
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_layout};
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_layout,
};
update_template = device.createDescriptorUpdateTemplate(template_info);
const vk::PushConstantRange push_range = {
.stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0,
.size = sizeof(Common::Vec2i),
.stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0,
.size = sizeof(Common::Vec2i),
};
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
.pSetLayouts = &descriptor_layout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range};
const vk::PipelineLayoutCreateInfo layout_info = {
.setLayoutCount = 1,
.pSetLayouts = &descriptor_layout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range,
};
compute_pipeline_layout = device.createPipelineLayout(layout_info);
const vk::PipelineShaderStageCreateInfo compute_stage = {
.stage = vk::ShaderStageFlagBits::eCompute, .module = compute_shader, .pName = "main"};
.stage = vk::ShaderStageFlagBits::eCompute,
.module = compute_shader,
.pName = "main",
};
const vk::ComputePipelineCreateInfo compute_info = {.stage = compute_stage,
.layout = compute_pipeline_layout};
const vk::ComputePipelineCreateInfo compute_info = {
.stage = compute_stage,
.layout = compute_pipeline_layout,
};
if (const auto result = device.createComputePipeline({}, compute_info);
result.result == vk::Result::eSuccess) {
result.result == vk::Result::eSuccess) {
compute_pipeline = result.value;
} else {
LOG_CRITICAL(Render_Vulkan, "D24S8 compute pipeline creation failed!");
@@ -125,97 +149,103 @@ BlitHelper::~BlitHelper() {
void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) {
const std::array textures = {
vk::DescriptorImageInfo{.imageView = source.GetDepthView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
vk::DescriptorImageInfo{.imageView = source.GetStencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
vk::DescriptorImageInfo{.imageView = dest.GetImageView(),
.imageLayout = vk::ImageLayout::eGeneral}};
vk::DescriptorImageInfo{
.imageView = source.GetDepthView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = source.GetStencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = dest.GetImageView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
};
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
scheduler.Record([this, set, blit,
src_image = source.alloc.image,
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
scheduler.Record([this, set, blit, src_image = source.alloc.image,
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
vk::CommandBuffer) {
const std::array pre_barriers = {
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth |
vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask =
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eNone,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
}
};
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eNone,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
}};
const std::array post_barriers = {
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth |
vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask =
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
}
};
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
}};
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eComputeShader,
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout, 0, set, {});
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout,
0, set, {});
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
const auto src_offset = Common::MakeVec(blit.src_rect.left, blit.src_rect.bottom);

View File

@@ -15,26 +15,57 @@ struct Bindings {
};
constexpr static std::array RASTERIZER_SETS = {
Bindings{// Utility set
.bindings = {vk::DescriptorType::eUniformBuffer, vk::DescriptorType::eUniformBuffer,
vk::DescriptorType::eUniformTexelBuffer,
vk::DescriptorType::eUniformTexelBuffer,
vk::DescriptorType::eUniformTexelBuffer},
.binding_count = 5},
Bindings{// Texture set
.bindings = {vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage,
vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage},
.binding_count = 4},
Bindings{// Sampler set
.bindings = {vk::DescriptorType::eSampler, vk::DescriptorType::eSampler,
vk::DescriptorType::eSampler, vk::DescriptorType::eSampler},
.binding_count = 4},
Bindings{// Shadow set
.bindings = {vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage},
.binding_count = 4}};
Bindings{
// Utility set
.bindings =
{
vk::DescriptorType::eUniformBuffer,
vk::DescriptorType::eUniformBuffer,
vk::DescriptorType::eUniformTexelBuffer,
vk::DescriptorType::eUniformTexelBuffer,
vk::DescriptorType::eUniformTexelBuffer,
},
.binding_count = 5,
},
Bindings{
// Texture set
.bindings =
{
vk::DescriptorType::eSampledImage,
vk::DescriptorType::eSampledImage,
vk::DescriptorType::eSampledImage,
vk::DescriptorType::eSampledImage,
},
.binding_count = 4,
},
Bindings{
// Sampler set
.bindings =
{
vk::DescriptorType::eSampler,
vk::DescriptorType::eSampler,
vk::DescriptorType::eSampler,
vk::DescriptorType::eSampler,
},
.binding_count = 4,
},
Bindings{
// Shadow set
.bindings =
{
vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage,
vk::DescriptorType::eStorageImage,
},
.binding_count = 4, // TODO: Combine cube faces to a single storage image
// some android devices only expose up to four storage
// slots per pipeline
},
};
constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) {
vk::ShaderStageFlags flags;
@@ -66,7 +97,7 @@ DescriptorManager::DescriptorManager(const Instance& instance, Scheduler& schedu
}
DescriptorManager::~DescriptorManager() {
vk::Device device = instance.GetDevice();
const vk::Device device = instance.GetDevice();
device.destroyPipelineLayout(pipeline_layout);
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
@@ -89,7 +120,7 @@ void DescriptorManager::BindDescriptorSets() {
descriptor_set_dirty.fill(true);
}
vk::Device device = instance.GetDevice();
const vk::Device device = instance.GetDevice();
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> bound_sets;
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
if (descriptor_set_dirty[i]) {
@@ -116,51 +147,59 @@ void DescriptorManager::BuildLayouts() {
std::array<vk::DescriptorSetLayoutBinding, MAX_DESCRIPTORS> set_bindings;
std::array<vk::DescriptorUpdateTemplateEntry, MAX_DESCRIPTORS> update_entries;
vk::Device device = instance.GetDevice();
const vk::Device device = instance.GetDevice();
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
const auto& set = RASTERIZER_SETS[i];
for (u32 j = 0; j < set.binding_count; j++) {
vk::DescriptorType type = set.bindings[j];
set_bindings[j] = vk::DescriptorSetLayoutBinding{.binding = j,
.descriptorType = type,
.descriptorCount = 1,
.stageFlags = ToVkStageFlags(type)};
const vk::DescriptorType type = set.bindings[j];
set_bindings[j] = vk::DescriptorSetLayoutBinding{
.binding = j,
.descriptorType = type,
.descriptorCount = 1,
.stageFlags = ToVkStageFlags(type),
};
update_entries[j] =
vk::DescriptorUpdateTemplateEntry{.dstBinding = j,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = type,
.offset = j * sizeof(DescriptorData),
.stride = 0};
update_entries[j] = vk::DescriptorUpdateTemplateEntry{
.dstBinding = j,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = type,
.offset = j * sizeof(DescriptorData),
.stride = 0,
};
}
const vk::DescriptorSetLayoutCreateInfo layout_info = {.bindingCount = set.binding_count,
.pBindings = set_bindings.data()};
const vk::DescriptorSetLayoutCreateInfo layout_info = {
.bindingCount = set.binding_count,
.pBindings = set_bindings.data(),
};
descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info);
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = set.binding_count,
.pDescriptorUpdateEntries = update_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_set_layouts[i]};
.descriptorSetLayout = descriptor_set_layouts[i],
};
update_templates[i] = device.createDescriptorUpdateTemplate(template_info);
}
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = MAX_DESCRIPTOR_SETS,
.pSetLayouts = descriptor_set_layouts.data(),
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr};
const vk::PipelineLayoutCreateInfo layout_info = {
.setLayoutCount = MAX_DESCRIPTOR_SETS,
.pSetLayouts = descriptor_set_layouts.data(),
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
pipeline_layout = device.createPipelineLayout(layout_info);
}
vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) {
vk::Device device = instance.GetDevice();
const vk::Device device = instance.GetDevice();
const vk::DescriptorSetAllocateInfo alloc_info = {
.descriptorPool = current_pool, .descriptorSetCount = 1, .pSetLayouts = &layout};
.descriptorPool = current_pool,
.descriptorSetCount = 1,
.pSetLayouts = &layout,
};
try {
return device.allocateDescriptorSets(alloc_info)[0];

View File

@@ -4,16 +4,17 @@
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
#include "video_core/renderer_vulkan/vk_format_reinterpreter.h"
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
namespace Vulkan {
D24S8toRGBA8::D24S8toRGBA8(const Instance& instance, Scheduler& scheduler,
DescriptorManager& desc_manager, TextureRuntime& runtime)
: FormatReinterpreterBase{instance, scheduler, desc_manager, runtime}, device{instance.GetDevice()} {
: FormatReinterpreterBase{instance, scheduler, desc_manager, runtime},
device{instance.GetDevice()} {
constexpr std::string_view cs_source = R"(
#version 450 core
#extension GL_EXT_samplerless_texture_functions : require
@@ -35,77 +36,98 @@ imageStore(color, tex_coord, vec4(components) / (exp2(8.0) - 1.0));
}
)";
compute_shader =
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
const std::array compute_layout_bindings = {
vk::DescriptorSetLayoutBinding{.binding = 0,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute},
vk::DescriptorSetLayoutBinding{.binding = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute},
vk::DescriptorSetLayoutBinding{.binding = 2,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute}};
vk::DescriptorSetLayoutBinding{
.binding = 0,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
vk::DescriptorSetLayoutBinding{
.binding = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
vk::DescriptorSetLayoutBinding{
.binding = 2,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
};
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
.pBindings = compute_layout_bindings.data()};
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
.pBindings = compute_layout_bindings.data(),
};
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
const std::array update_template_entries = {
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = 0,
.stride = sizeof(vk::DescriptorImageInfo)},
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = sizeof(vk::DescriptorImageInfo),
.stride = 0},
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageImage,
.offset = 2 * sizeof(vk::DescriptorImageInfo),
.stride = 0}};
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = 0,
.stride = sizeof(vk::DescriptorImageInfo),
},
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampledImage,
.offset = sizeof(vk::DescriptorImageInfo),
},
vk::DescriptorUpdateTemplateEntry{
.dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageImage,
.offset = 2 * sizeof(vk::DescriptorImageInfo),
},
};
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_layout};
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_layout,
};
update_template = device.createDescriptorUpdateTemplate(template_info);
const vk::PushConstantRange push_range = {
.stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0,
.size = sizeof(Common::Vec2i),
.stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0,
.size = sizeof(Common::Vec2i),
};
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
.pSetLayouts = &descriptor_layout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range};
const vk::PipelineLayoutCreateInfo layout_info = {
.setLayoutCount = 1,
.pSetLayouts = &descriptor_layout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range,
};
compute_pipeline_layout = device.createPipelineLayout(layout_info);
const vk::PipelineShaderStageCreateInfo compute_stage = {
.stage = vk::ShaderStageFlagBits::eCompute, .module = compute_shader, .pName = "main"};
.stage = vk::ShaderStageFlagBits::eCompute,
.module = compute_shader,
.pName = "main",
};
const vk::ComputePipelineCreateInfo compute_info = {.stage = compute_stage,
.layout = compute_pipeline_layout};
const vk::ComputePipelineCreateInfo compute_info = {
.stage = compute_stage,
.layout = compute_pipeline_layout,
};
if (const auto result = device.createComputePipeline({}, compute_info);
result.result == vk::Result::eSuccess) {
result.result == vk::Result::eSuccess) {
compute_pipeline = result.value;
} else {
LOG_CRITICAL(Render_Vulkan, "D24S8 compute pipeline creation failed!");
@@ -124,80 +146,87 @@ D24S8toRGBA8::~D24S8toRGBA8() {
void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surface& dest,
VideoCore::Rect2D dst_rect) {
const std::array textures = {
vk::DescriptorImageInfo{.imageView = source.GetDepthView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
vk::DescriptorImageInfo{.imageView = source.GetStencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
vk::DescriptorImageInfo{.imageView = dest.GetImageView(),
.imageLayout = vk::ImageLayout::eGeneral}};
vk::DescriptorImageInfo{
.imageView = source.GetDepthView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = source.GetStencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = dest.GetImageView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
};
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
runtime.GetRenderpassCache().ExitRenderpass();
scheduler.Record([this, set, src_rect,
src_image = source.alloc.image,
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
scheduler.Record([this, set, src_rect, src_image = source.alloc.image,
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
vk::CommandBuffer) {
const vk::ImageMemoryBarrier pre_barrier = {
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
const std::array post_barriers = {
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth |
vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
.aspectMask =
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
const std::array post_barriers = {
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth |
vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
}
};
}};
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eComputeShader,
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout, 0, set, {});
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout,
0, set, {});
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
const auto src_offset = Common::MakeVec(src_rect.left, src_rect.bottom);

View File

@@ -76,15 +76,17 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) {
}
[[nodiscard]] vk::DebugUtilsMessengerCreateInfoEXT MakeDebugUtilsMessengerInfo() {
return {.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose,
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.pfnUserCallback = DebugHandler};
return vk::DebugUtilsMessengerCreateInfoEXT{
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose,
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.pfnUserCallback = DebugHandler,
};
}
std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
@@ -99,7 +101,6 @@ std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
Instance::Instance(bool validation, bool dump_command_buffers)
: enable_validation{validation}, dump_command_buffers{dump_command_buffers} {
// Fetch instance independant function pointers
auto vkGetInstanceProcAddr =
dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
@@ -110,19 +111,16 @@ Instance::Instance(bool validation, bool dump_command_buffers)
// Use required platform-specific flags
auto flags = GetInstanceFlags();
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "Citra Vulkan",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_API_VERSION_1_0};
const vk::ApplicationInfo application_info = {
.pApplicationName = "Citra",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "Citra Vulkan",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_API_VERSION_1_0,
};
std::array<const char*, 3> layers;
#ifdef ANDROID
u32 layer_count = 1;
layers[0] = "VK_LAYER_KHRONOS_timeline_semaphore";
#else
std::array<const char*, 2> layers;
u32 layer_count = 0;
#endif
if (enable_validation) {
layers[layer_count++] = "VK_LAYER_KHRONOS_validation";
@@ -132,13 +130,15 @@ Instance::Instance(bool validation, bool dump_command_buffers)
}
const vk::StructureChain instance_chain = {
vk::InstanceCreateInfo{.flags = flags,
.pApplicationInfo = &application_info,
.enabledLayerCount = layer_count,
.ppEnabledLayerNames = layers.data(),
.enabledExtensionCount = static_cast<u32>(extensions.size()),
.ppEnabledExtensionNames = extensions.data()},
MakeDebugUtilsMessengerInfo()};
vk::InstanceCreateInfo{
.flags = flags,
.pApplicationInfo = &application_info,
.enabledLayerCount = layer_count,
.ppEnabledLayerNames = layers.data(),
.enabledExtensionCount = static_cast<u32>(extensions.size()),
.ppEnabledExtensionNames = extensions.data(),
},
};
instance = vk::createInstance(instance_chain.get());
@@ -156,7 +156,7 @@ Instance::Instance(bool validation, bool dump_command_buffers)
Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
: enable_validation{Settings::values.renderer_debug},
dump_command_buffers{Settings::values.dump_command_buffers} {
auto window_info = window.GetWindowInfo();
const Frontend::EmuWindow::WindowSystemInfo window_info = window.GetWindowInfo();
// Fetch instance independant function pointers
auto vkGetInstanceProcAddr =
@@ -176,11 +176,13 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
return;
}
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "Citra Vulkan",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = available_version};
const vk::ApplicationInfo application_info = {
.pApplicationName = "Citra",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "Citra Vulkan",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = available_version,
};
std::array<const char*, 3> layers;
#ifdef ANDROID
@@ -198,13 +200,16 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
}
const vk::StructureChain instance_chain = {
vk::InstanceCreateInfo{.flags = flags,
.pApplicationInfo = &application_info,
.enabledLayerCount = layer_count,
.ppEnabledLayerNames = layers.data(),
.enabledExtensionCount = static_cast<u32>(extensions.size()),
.ppEnabledExtensionNames = extensions.data()},
MakeDebugUtilsMessengerInfo()};
vk::InstanceCreateInfo{
.flags = flags,
.pApplicationInfo = &application_info,
.enabledLayerCount = layer_count,
.ppEnabledLayerNames = layers.data(),
.enabledExtensionCount = static_cast<u32>(extensions.size()),
.ppEnabledExtensionNames = extensions.data(),
},
MakeDebugUtilsMessengerInfo(),
};
try {
instance = vk::createInstance(instance_chain.get());
@@ -335,13 +340,15 @@ void Instance::CreateFormatTable() {
}
const u32 index = static_cast<u32>(pixel_format);
format_table[index] = FormatTraits{.transfer_support = supports_transfer,
.blit_support = supports_blit,
.attachment_support = supports_attachment,
.storage_support = supports_storage,
.usage = best_usage,
.native = format,
.fallback = fallback};
format_table[index] = FormatTraits{
.transfer_support = supports_transfer,
.blit_support = supports_blit,
.attachment_support = supports_attachment,
.storage_support = supports_storage,
.usage = best_usage,
.native = format,
.fallback = fallback,
};
}
}
@@ -431,12 +438,17 @@ bool Instance::CreateDevice() {
static constexpr float queue_priorities[] = {1.0f};
const std::array queue_infos = {
vk::DeviceQueueCreateInfo{.queueFamilyIndex = graphics_queue_family_index,
.queueCount = 1,
.pQueuePriorities = queue_priorities},
vk::DeviceQueueCreateInfo{.queueFamilyIndex = present_queue_family_index,
.queueCount = 1,
.pQueuePriorities = queue_priorities}};
vk::DeviceQueueCreateInfo{
.queueFamilyIndex = graphics_queue_family_index,
.queueCount = 1,
.pQueuePriorities = queue_priorities,
},
vk::DeviceQueueCreateInfo{
.queueFamilyIndex = present_queue_family_index,
.queueCount = 1,
.pQueuePriorities = queue_priorities,
},
};
const u32 queue_count = graphics_queue_family_index != present_queue_family_index ? 2u : 1u;
const vk::StructureChain device_chain = {
@@ -447,23 +459,25 @@ bool Instance::CreateDevice() {
.ppEnabledExtensionNames = enabled_extensions.data(),
},
vk::PhysicalDeviceFeatures2{
.features = {.robustBufferAccess = features.robustBufferAccess,
.geometryShader = features.geometryShader,
.dualSrcBlend = features.dualSrcBlend,
.logicOp = features.logicOp,
.depthClamp = features.depthClamp,
.largePoints = features.largePoints,
.samplerAnisotropy = features.samplerAnisotropy,
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
.shaderClipDistance = features.shaderClipDistance}},
.features =
{
.robustBufferAccess = features.robustBufferAccess,
.geometryShader = features.geometryShader,
.dualSrcBlend = features.dualSrcBlend,
.logicOp = features.logicOp,
.depthClamp = features.depthClamp,
.largePoints = features.largePoints,
.samplerAnisotropy = features.samplerAnisotropy,
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
.shaderClipDistance = features.shaderClipDistance,
},
},
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(),
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()
};
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()};
// Create logical device
try {
device = physical_device.createDevice(device_chain.get());
} catch (vk::ExtensionNotPresentError& err) {
@@ -484,13 +498,16 @@ bool Instance::CreateDevice() {
void Instance::CreateAllocator() {
const VmaVulkanFunctions functions = {
.vkGetInstanceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr,
.vkGetDeviceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr};
.vkGetDeviceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr,
};
const VmaAllocatorCreateInfo allocator_info = {.physicalDevice = physical_device,
.device = device,
.pVulkanFunctions = &functions,
.instance = instance,
.vulkanApiVersion = VK_API_VERSION_1_1};
const VmaAllocatorCreateInfo allocator_info = {
.physicalDevice = physical_device,
.device = device,
.pVulkanFunctions = &functions,
.instance = instance,
.vulkanApiVersion = VK_API_VERSION_1_1,
};
if (VkResult result = vmaCreateAllocator(&allocator_info, &allocator); result != VK_SUCCESS) {
LOG_CRITICAL(Render_Vulkan, "Failed to initialize VMA with error {}", result);

View File

@@ -7,12 +7,13 @@
namespace Vulkan {
MasterSemaphore::MasterSemaphore(const Instance& instance) : device{instance.GetDevice()} {
const vk::StructureChain semaphore_chain = {vk::SemaphoreCreateInfo{},
vk::SemaphoreTypeCreateInfoKHR{
.semaphoreType = vk::SemaphoreType::eTimeline,
.initialValue = 0,
}};
const vk::StructureChain semaphore_chain = {
vk::SemaphoreCreateInfo{},
vk::SemaphoreTypeCreateInfoKHR{
.semaphoreType = vk::SemaphoreType::eTimeline,
.initialValue = 0,
},
};
semaphore = device.createSemaphore(semaphore_chain.get());
}

View File

@@ -4,10 +4,10 @@
#pragma once
#include <atomic>
#include <limits>
#include <deque>
#include <vector>
#include <limits>
#include <thread>
#include <vector>
#include "common/common_types.h"
#include "video_core/renderer_vulkan/vk_common.h"

View File

@@ -32,15 +32,32 @@ u32 AttribBytes(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
}
vk::Format ToVkAttributeFormat(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
constexpr std::array attribute_formats = {
std::array{vk::Format::eR8Sint, vk::Format::eR8G8Sint, vk::Format::eR8G8B8Sint,
vk::Format::eR8G8B8A8Sint},
std::array{vk::Format::eR8Uint, vk::Format::eR8G8Uint, vk::Format::eR8G8B8Uint,
vk::Format::eR8G8B8A8Uint},
std::array{vk::Format::eR16Sint, vk::Format::eR16G16Sint, vk::Format::eR16G16B16Sint,
vk::Format::eR16G16B16A16Sint},
std::array{vk::Format::eR32Sfloat, vk::Format::eR32G32Sfloat, vk::Format::eR32G32B32Sfloat,
vk::Format::eR32G32B32A32Sfloat}};
static constexpr std::array attribute_formats = {
std::array{
vk::Format::eR8Sint,
vk::Format::eR8G8Sint,
vk::Format::eR8G8B8Sint,
vk::Format::eR8G8B8A8Sint,
},
std::array{
vk::Format::eR8Uint,
vk::Format::eR8G8Uint,
vk::Format::eR8G8B8Uint,
vk::Format::eR8G8B8A8Uint,
},
std::array{
vk::Format::eR16Sint,
vk::Format::eR16G16Sint,
vk::Format::eR16G16B16Sint,
vk::Format::eR16G16B16A16Sint,
},
std::array{
vk::Format::eR32Sfloat,
vk::Format::eR32G32Sfloat,
vk::Format::eR32G32B32Sfloat,
vk::Format::eR32G32B32A32Sfloat,
},
};
ASSERT(size <= 4);
return attribute_formats[static_cast<u32>(format)][size - 1];
@@ -126,7 +143,10 @@ void PipelineCache::LoadDiskCache() {
const std::string cache_file_path = fmt::format("{}{:x}{:x}.bin", GetPipelineCacheDir(),
instance.GetVendorID(), instance.GetDeviceID());
vk::PipelineCacheCreateInfo cache_info = {.initialDataSize = 0, .pInitialData = nullptr};
vk::PipelineCacheCreateInfo cache_info = {
.initialDataSize = 0,
.pInitialData = nullptr,
};
std::vector<u8> cache_data;
FileUtil::IOFile cache_file{cache_file_path, "r"};
@@ -289,29 +309,46 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view) {
const vk::DescriptorImageInfo image_info = {
.imageView = image_view, .imageLayout = vk::ImageLayout::eGeneral};
.imageView = image_view,
.imageLayout = vk::ImageLayout::eGeneral,
};
desc_manager.SetBinding(1, binding, DescriptorData{image_info});
}
void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) {
const vk::DescriptorImageInfo image_info = {.imageView = image_view,
.imageLayout = vk::ImageLayout::eGeneral};
const vk::DescriptorImageInfo image_info = {
.imageView = image_view,
.imageLayout = vk::ImageLayout::eGeneral,
};
desc_manager.SetBinding(3, binding, DescriptorData{image_info});
}
void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) {
const DescriptorData data = {
.buffer_info = vk::DescriptorBufferInfo{.buffer = buffer, .offset = offset, .range = size}};
.buffer_info =
vk::DescriptorBufferInfo{
.buffer = buffer,
.offset = offset,
.range = size,
},
};
desc_manager.SetBinding(0, binding, data);
}
void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) {
const DescriptorData data = {.buffer_view = buffer_view};
const DescriptorData data = {
.buffer_view = buffer_view,
};
desc_manager.SetBinding(0, binding, data);
}
void PipelineCache::BindSampler(u32 binding, vk::Sampler sampler) {
const DescriptorData data = {.image_info = vk::DescriptorImageInfo{.sampler = sampler}};
const DescriptorData data = {
.image_info =
vk::DescriptorImageInfo{
.sampler = sampler,
},
};
desc_manager.SetBinding(2, binding, data);
}
@@ -411,18 +448,21 @@ void PipelineCache::ApplyDynamic(const PipelineInfo& info) {
}
vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
vk::Device device = instance.GetDevice();
const vk::Device device = instance.GetDevice();
u32 shader_count = 0;
std::array<vk::PipelineShaderStageCreateInfo, MAX_SHADER_STAGES> shader_stages;
for (std::size_t i = 0; i < current_shaders.size(); i++) {
vk::ShaderModule shader = current_shaders[i];
const vk::ShaderModule shader = current_shaders[i];
if (!shader) {
continue;
}
shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{
.stage = ToVkShaderStage(i), .module = shader, .pName = "main"};
.stage = ToVkShaderStage(i),
.module = shader,
.pName = "main",
};
}
/**
@@ -438,7 +478,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.binding = binding.binding,
.stride = binding.stride,
.inputRate = binding.fixed.Value() ? vk::VertexInputRate::eInstance
: vk::VertexInputRate::eVertex};
: vk::VertexInputRate::eVertex,
};
}
u32 emulated_attrib_count = 0;
@@ -453,7 +494,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.location = attrib.location,
.binding = attrib.binding,
.format = is_supported ? format : ToVkAttributeFormat(attrib.type, 2),
.offset = attrib.offset};
.offset = attrib.offset,
};
// When the requested 3-component vertex format is unsupported by the hardware
// is it emulated by breaking it into a vec2 + vec1. These are combined to a vec3
@@ -466,7 +508,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.location = location,
.binding = attrib.binding,
.format = ToVkAttributeFormat(attrib.type, 1),
.offset = attrib.offset + AttribBytes(attrib.type, 2)};
.offset = attrib.offset + AttribBytes(attrib.type, 2),
};
}
}
@@ -475,11 +518,13 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.pVertexBindingDescriptions = bindings.data(),
.vertexAttributeDescriptionCount =
info.vertex_layout.attribute_count + emulated_attrib_count,
.pVertexAttributeDescriptions = attributes.data()};
.pVertexAttributeDescriptions = attributes.data(),
};
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
.topology = PicaToVK::PrimitiveTopology(info.rasterization.topology),
.primitiveRestartEnable = false};
.primitiveRestartEnable = false,
};
const vk::PipelineRasterizationStateCreateInfo raster_state = {
.depthClampEnable = false,
@@ -487,10 +532,13 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.cullMode = PicaToVK::CullMode(info.rasterization.cull_mode),
.frontFace = PicaToVK::FrontFace(info.rasterization.cull_mode),
.depthBiasEnable = false,
.lineWidth = 1.0f};
.lineWidth = 1.0f,
};
const vk::PipelineMultisampleStateCreateInfo multisampling = {
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false};
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
.blendEnable = info.blending.blend_enable.Value(),
@@ -500,19 +548,30 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.srcAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.src_alpha_blend_factor),
.dstAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.dst_alpha_blend_factor),
.alphaBlendOp = PicaToVK::BlendEquation(info.blending.alpha_blend_eq),
.colorWriteMask = static_cast<vk::ColorComponentFlags>(info.blending.color_write_mask)};
.colorWriteMask = static_cast<vk::ColorComponentFlags>(info.blending.color_write_mask),
};
const vk::PipelineColorBlendStateCreateInfo color_blending = {
.logicOpEnable = !info.blending.blend_enable.Value() && !instance.NeedsLogicOpEmulation(),
.logicOp = PicaToVK::LogicOp(info.blending.logic_op.Value()),
.attachmentCount = 1,
.pAttachments = &colorblend_attachment,
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f}};
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
};
const vk::Viewport viewport = {
.x = 0.0f, .y = 0.0f, .width = 1.0f, .height = 1.0f, .minDepth = 0.0f, .maxDepth = 1.0f};
.x = 0.0f,
.y = 0.0f,
.width = 1.0f,
.height = 1.0f,
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
const vk::Rect2D scissor = {.offset = {0, 0}, .extent = {1, 1}};
const vk::Rect2D scissor = {
.offset = {0, 0},
.extent = {1, 1},
};
const vk::PipelineViewportStateCreateInfo viewport_info = {
.viewportCount = 1,
@@ -542,13 +601,15 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
.dynamicStateCount = extended_dynamic_states ? static_cast<u32>(dynamic_states.size()) : 6u,
.pDynamicStates = dynamic_states.data()};
.pDynamicStates = dynamic_states.data(),
};
const vk::StencilOpState stencil_op_state = {
.failOp = PicaToVK::StencilOp(info.depth_stencil.stencil_fail_op),
.passOp = PicaToVK::StencilOp(info.depth_stencil.stencil_pass_op),
.depthFailOp = PicaToVK::StencilOp(info.depth_stencil.stencil_depth_fail_op),
.compareOp = PicaToVK::CompareFunc(info.depth_stencil.stencil_compare_op)};
.compareOp = PicaToVK::CompareFunc(info.depth_stencil.stencil_compare_op),
};
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
.depthTestEnable = static_cast<u32>(info.depth_stencil.depth_test_enable.Value()),
@@ -557,7 +618,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.depthBoundsTestEnable = false,
.stencilTestEnable = static_cast<u32>(info.depth_stencil.stencil_test_enable.Value()),
.front = stencil_op_state,
.back = stencil_op_state};
.back = stencil_op_state,
};
const vk::GraphicsPipelineCreateInfo pipeline_info = {
.stageCount = shader_count,
@@ -572,7 +634,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.pDynamicState = &dynamic_info,
.layout = desc_manager.GetPipelineLayout(),
.renderPass =
renderpass_cache.GetRenderpass(info.color_attachment, info.depth_attachment, false)};
renderpass_cache.GetRenderpass(info.color_attachment, info.depth_attachment, false),
};
if (const auto result = device.createGraphicsPipeline(pipeline_cache, pipeline_info);
result.result == vk::Result::eSuccess) {

View File

@@ -26,17 +26,23 @@ constexpr u32 INDEX_BUFFER_SIZE = 16 * 1024 * 1024;
constexpr u32 UNIFORM_BUFFER_SIZE = 16 * 1024 * 1024;
constexpr u32 TEXTURE_BUFFER_SIZE = 512 * 1024;
constexpr std::array TEXTURE_BUFFER_LF_FORMATS = {vk::Format::eR32G32Sfloat};
constexpr std::array TEXTURE_BUFFER_LF_FORMATS = {
vk::Format::eR32G32Sfloat,
};
constexpr std::array TEXTURE_BUFFER_FORMATS = {vk::Format::eR32G32Sfloat,
vk::Format::eR32G32B32A32Sfloat};
constexpr std::array TEXTURE_BUFFER_FORMATS = {
vk::Format::eR32G32Sfloat,
vk::Format::eR32G32B32A32Sfloat,
};
constexpr VideoCore::SurfaceParams NULL_PARAMS = {.width = 1,
.height = 1,
.stride = 1,
.texture_type = VideoCore::TextureType::Texture2D,
.pixel_format = VideoCore::PixelFormat::RGBA8,
.type = VideoCore::SurfaceType::Color};
constexpr VideoCore::SurfaceParams NULL_PARAMS = {
.width = 1,
.height = 1,
.stride = 1,
.texture_type = VideoCore::TextureType::Texture2D,
.pixel_format = VideoCore::PixelFormat::RGBA8,
.type = VideoCore::SurfaceType::Color,
};
constexpr vk::ImageUsageFlags NULL_USAGE = vk::ImageUsageFlagBits::eSampled |
vk::ImageUsageFlagBits::eTransferSrc |
@@ -85,7 +91,8 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan
.min_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
.mip_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
.wrap_s = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder,
.wrap_t = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder};
.wrap_t = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder,
};
default_sampler = CreateSampler(default_sampler_info);
@@ -265,8 +272,8 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
SetupFixedAttribs();
// Bind the generated bindings
scheduler.Record([this, vertex_offsets = binding_offsets](
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
scheduler.Record([this, vertex_offsets = binding_offsets](vk::CommandBuffer render_cmdbuf,
vk::CommandBuffer) {
render_cmdbuf.bindVertexBuffers(0, vertex_buffers, vertex_offsets);
});
}
@@ -435,8 +442,8 @@ void RasterizerVulkan::SetupIndexArray() {
index_buffer.Commit(index_buffer_size);
scheduler.Record([this, index_offset = index_offset, index_type = index_type](
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
scheduler.Record([this, index_offset = index_offset,
index_type = index_type](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
render_cmdbuf.bindIndexBuffer(index_buffer.GetHandle(), index_offset, index_type);
});
}
@@ -548,15 +555,17 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
// nothing. Always sample from the base level until mipmaps for texture cubes are
// implemented
const bool skip_mipmap = config.type == Pica::TexturingRegs::TextureConfig::TextureCube;
info = SamplerInfo{.mag_filter = config.mag_filter,
.min_filter = config.min_filter,
.mip_filter = config.mip_filter,
.wrap_s = config.wrap_s,
.wrap_t = config.wrap_t,
.border_color = config.border_color.raw,
.lod_min = skip_mipmap ? 0.f : static_cast<float>(config.lod.min_level),
.lod_max = skip_mipmap ? 0.f : static_cast<float>(config.lod.max_level),
.lod_bias = static_cast<float>(config.lod.bias)};
info = SamplerInfo{
.mag_filter = config.mag_filter,
.min_filter = config.min_filter,
.mip_filter = config.mip_filter,
.wrap_s = config.wrap_s,
.wrap_t = config.wrap_t,
.border_color = config.border_color.raw,
.lod_min = skip_mipmap ? 0.f : static_cast<float>(config.lod.min_level),
.lod_max = skip_mipmap ? 0.f : static_cast<float>(config.lod.max_level),
.lod_bias = static_cast<float>(config.lod.bias),
};
// Search the cache and bind the appropriate sampler
if (auto it = samplers.find(info); it != samplers.end()) {
@@ -711,7 +720,8 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
.renderpass = renderpass_cache.GetRenderpass(pipeline_info.color_attachment,
pipeline_info.depth_attachment, false),
.width = width,
.height = height};
.height = height,
};
auto [it, new_framebuffer] = framebuffers.try_emplace(framebuffer_info, vk::Framebuffer{});
if (new_framebuffer) {
@@ -721,9 +731,11 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
const RenderpassState renderpass_info = {
.renderpass = framebuffer_info.renderpass,
.framebuffer = it->second,
.render_area = vk::Rect2D{.offset = {static_cast<s32>(draw_rect.left),
static_cast<s32>(draw_rect.bottom)},
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()}},
.render_area =
vk::Rect2D{
.offset = {static_cast<s32>(draw_rect.left), static_cast<s32>(draw_rect.bottom)},
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()},
},
.clear = {},
};
@@ -1086,8 +1098,11 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
const auto color = PicaToVK::ColorRGBA8(info.border_color);
const vk::SamplerCustomBorderColorCreateInfoEXT border_color_info = {
.customBorderColor =
vk::ClearColorValue{.float32 = std::array{color[0], color[1], color[2], color[3]}},
.format = vk::Format::eUndefined};
vk::ClearColorValue{
.float32 = std::array{color[0], color[1], color[2], color[3]},
},
.format = vk::Format::eUndefined,
};
const vk::SamplerCreateInfo sampler_info = {
.pNext = use_border_color ? &border_color_info : nullptr,
@@ -1105,7 +1120,8 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
.maxLod = info.lod_max,
.borderColor =
use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack,
.unnormalizedCoordinates = false};
.unnormalizedCoordinates = false,
};
vk::Device device = instance.GetDevice();
return device.createSampler(sampler_info);
@@ -1123,12 +1139,14 @@ vk::Framebuffer RasterizerVulkan::CreateFramebuffer(const FramebufferInfo& info)
attachments[attachment_count++] = info.depth;
}
const vk::FramebufferCreateInfo framebuffer_info = {.renderPass = info.renderpass,
.attachmentCount = attachment_count,
.pAttachments = attachments.data(),
.width = info.width,
.height = info.height,
.layers = 1};
const vk::FramebufferCreateInfo framebuffer_info = {
.renderPass = info.renderpass,
.attachmentCount = attachment_count,
.pAttachments = attachments.data(),
.width = info.width,
.height = info.height,
.layers = 1,
};
vk::Device device = instance.GetDevice();
return device.createFramebuffer(framebuffer_info);

View File

@@ -61,12 +61,12 @@ RenderpassCache::RenderpassCache(const Instance& instance, Scheduler& scheduler)
continue;
}
cached_renderpasses[color][depth][0] = CreateRenderPass(
color_format, depth_format, vk::AttachmentLoadOp::eLoad,
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
cached_renderpasses[color][depth][1] = CreateRenderPass(
color_format, depth_format, vk::AttachmentLoadOp::eClear,
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
cached_renderpasses[color][depth][0] =
CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eLoad,
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
cached_renderpasses[color][depth][1] =
CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eClear,
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
}
}
}
@@ -100,11 +100,13 @@ void RenderpassCache::EnterRenderpass(const RenderpassState& state) {
render_cmdbuf.endRenderPass();
}
const vk::RenderPassBeginInfo renderpass_begin_info = {.renderPass = state.renderpass,
.framebuffer = state.framebuffer,
.renderArea = state.render_area,
.clearValueCount = 1,
.pClearValues = &state.clear};
const vk::RenderPassBeginInfo renderpass_begin_info = {
.renderPass = state.renderpass,
.framebuffer = state.framebuffer,
.renderArea = state.render_area,
.clearValueCount = 1,
.pClearValues = &state.clear,
};
render_cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
});
@@ -160,17 +162,20 @@ vk::RenderPass RenderpassCache::CreateRenderPass(vk::Format color, vk::Format de
vk::AttachmentReference depth_attachment_ref{};
if (color != vk::Format::eUndefined) {
attachments[attachment_count] =
vk::AttachmentDescription{.format = color,
.loadOp = load_op,
.storeOp = vk::AttachmentStoreOp::eStore,
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
.initialLayout = initial_layout,
.finalLayout = final_layout};
attachments[attachment_count] = vk::AttachmentDescription{
.format = color,
.loadOp = load_op,
.storeOp = vk::AttachmentStoreOp::eStore,
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
.initialLayout = initial_layout,
.finalLayout = final_layout,
};
color_attachment_ref = vk::AttachmentReference{
.attachment = attachment_count++, .layout = vk::ImageLayout::eGeneral};
.attachment = attachment_count++,
.layout = vk::ImageLayout::eGeneral,
};
use_color = true;
}
@@ -183,34 +188,38 @@ vk::RenderPass RenderpassCache::CreateRenderPass(vk::Format color, vk::Format de
.stencilLoadOp = load_op,
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
.initialLayout = vk::ImageLayout::eGeneral,
.finalLayout = vk::ImageLayout::eGeneral};
.finalLayout = vk::ImageLayout::eGeneral,
};
depth_attachment_ref =
vk::AttachmentReference{.attachment = attachment_count++,
.layout = vk::ImageLayout::eGeneral};
depth_attachment_ref = vk::AttachmentReference{
.attachment = attachment_count++,
.layout = vk::ImageLayout::eGeneral,
};
use_depth = true;
}
// We also require only one subpass
const vk::SubpassDescription subpass = {.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
.inputAttachmentCount = 0,
.pInputAttachments = nullptr,
.colorAttachmentCount = use_color ? 1u : 0u,
.pColorAttachments = &color_attachment_ref,
.pResolveAttachments = 0,
.pDepthStencilAttachment =
use_depth ? &depth_attachment_ref : nullptr};
const vk::SubpassDescription subpass = {
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
.inputAttachmentCount = 0,
.pInputAttachments = nullptr,
.colorAttachmentCount = use_color ? 1u : 0u,
.pColorAttachments = &color_attachment_ref,
.pResolveAttachments = 0,
.pDepthStencilAttachment = use_depth ? &depth_attachment_ref : nullptr,
};
const vk::RenderPassCreateInfo renderpass_info = {.attachmentCount = attachment_count,
.pAttachments = attachments.data(),
.subpassCount = 1,
.pSubpasses = &subpass,
.dependencyCount = 0,
.pDependencies = nullptr};
const vk::RenderPassCreateInfo renderpass_info = {
.attachmentCount = attachment_count,
.pAttachments = attachments.data(),
.subpassCount = 1,
.pSubpasses = &subpass,
.dependencyCount = 0,
.pDependencies = nullptr,
};
// Create the renderpass
vk::Device device = instance.GetDevice();
const vk::Device device = instance.GetDevice();
return device.createRenderPass(renderpass_info);
}

View File

@@ -86,7 +86,8 @@ void CommandPool::Allocate(std::size_t begin, std::size_t end) {
const vk::CommandPoolCreateInfo pool_create_info = {
.flags = vk::CommandPoolCreateFlagBits::eTransient |
vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
.queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex()};
.queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex(),
};
vk::Device device = instance.GetDevice();
pool.handle = device.createCommandPool(pool_create_info);
@@ -94,7 +95,8 @@ void CommandPool::Allocate(std::size_t begin, std::size_t end) {
const vk::CommandBufferAllocateInfo buffer_alloc_info = {
.commandPool = pool.handle,
.level = vk::CommandBufferLevel::ePrimary,
.commandBufferCount = COMMAND_BUFFER_POOL_SIZE};
.commandBufferCount = COMMAND_BUFFER_POOL_SIZE,
};
auto buffers = device.allocateCommandBuffers(buffer_alloc_info);
std::copy(buffers.begin(), buffers.end(), pool.cmdbufs.begin());
@@ -126,17 +128,19 @@ void DescriptorPool::Allocate(std::size_t begin, std::size_t end) {
vk::DescriptorPool& pool = pools.emplace_back();
// Choose a sane pool size good for most games
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {
{{vk::DescriptorType::eUniformBuffer, 4096},
{vk::DescriptorType::eSampledImage, 4096},
{vk::DescriptorType::eSampler, 4096},
{vk::DescriptorType::eUniformTexelBuffer, 2048},
{vk::DescriptorType::eStorageImage, 1024}}};
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {{
{vk::DescriptorType::eUniformBuffer, 4096},
{vk::DescriptorType::eSampledImage, 4096},
{vk::DescriptorType::eSampler, 4096},
{vk::DescriptorType::eUniformTexelBuffer, 2048},
{vk::DescriptorType::eStorageImage, 1024},
}};
const vk::DescriptorPoolCreateInfo descriptor_pool_info = {
.maxSets = 8192,
.poolSizeCount = static_cast<u32>(pool_sizes.size()),
.pPoolSizes = pool_sizes.data()};
.pPoolSizes = pool_sizes.data(),
};
pool = instance.GetDevice().createDescriptorPool(descriptor_pool_info);
}

View File

@@ -139,9 +139,8 @@ void Scheduler::SubmitExecution(vk::Semaphore signal_semaphore, vk::Semaphore wa
renderer.FlushBuffers();
renderpass_cache.ExitRenderpass();
Record([signal_semaphore, wait_semaphore,
handle, signal_value, this](vk::CommandBuffer render_cmdbuf,
vk::CommandBuffer upload_cmdbuf) {
Record([signal_semaphore, wait_semaphore, handle, signal_value,
this](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer upload_cmdbuf) {
MICROPROFILE_SCOPE(Vulkan_Submit);
upload_cmdbuf.end();
render_cmdbuf.end();

View File

@@ -1768,7 +1768,8 @@ layout (set = 0, binding = 0, std140) uniform vs_config {
out += fmt::format("vec4 vs_out_attr{};\n", i);
}
const auto semantic = [&config = config.state](VSOutputAttributes::Semantic slot_semantic) -> std::string {
const auto semantic =
[&config = config.state](VSOutputAttributes::Semantic slot_semantic) -> std::string {
const u32 slot = static_cast<u32>(slot_semantic);
const u32 attrib = config.semantic_maps[slot].attribute_index;
const u32 comp = config.semantic_maps[slot].component_index;
@@ -1795,8 +1796,9 @@ layout (set = 0, binding = 0, std140) uniform vs_config {
out += " normquat = GetVertexQuaternion();\n";
out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " +
semantic(VSOutputAttributes::COLOR_G) + ", " + semantic(VSOutputAttributes::COLOR_B) +
", " + semantic(VSOutputAttributes::COLOR_A) + ");\n";
semantic(VSOutputAttributes::COLOR_G) + ", " +
semantic(VSOutputAttributes::COLOR_B) + ", " +
semantic(VSOutputAttributes::COLOR_A) + ");\n";
out += " primary_color = min(abs(vtx_color), vec4(1.0));\n\n";
out += " texcoord0 = vec2(" + semantic(VSOutputAttributes::TEXCOORD0_U) + ", " +

View File

@@ -150,8 +150,8 @@ struct PicaFSConfig : Common::HashableStruct<PicaFSConfigState> {
* PICA vertex/geometry shader.
*/
struct PicaShaderConfigCommon {
void Init(const Pica::RasterizerRegs& rasterizer,
const Pica::ShaderRegs& regs, Pica::Shader::ShaderSetup& setup);
void Init(const Pica::RasterizerRegs& rasterizer, const Pica::ShaderRegs& regs,
Pica::Shader::ShaderSetup& setup);
u64 program_hash;
u64 swizzle_hash;
@@ -183,8 +183,8 @@ struct PicaShaderConfigCommon {
* shader.
*/
struct PicaVSConfig : Common::HashableStruct<PicaShaderConfigCommon> {
explicit PicaVSConfig(const Pica::RasterizerRegs& rasterizer,
const Pica::ShaderRegs& regs, Pica::Shader::ShaderSetup& setup) {
explicit PicaVSConfig(const Pica::RasterizerRegs& rasterizer, const Pica::ShaderRegs& regs,
Pica::Shader::ShaderSetup& setup) {
state.Init(rasterizer, regs, setup);
}
explicit PicaVSConfig(const PicaShaderConfigCommon& conf) {

View File

@@ -59,9 +59,10 @@ StagingBuffer::StagingBuffer(const Instance& instance, u32 size, bool readback)
const VmaAllocationCreateFlags flags =
readback ? VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
const VmaAllocationCreateInfo alloc_create_info = {.flags =
flags | VMA_ALLOCATION_CREATE_MAPPED_BIT,
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST};
const VmaAllocationCreateInfo alloc_create_info = {
.flags = flags | VMA_ALLOCATION_CREATE_MAPPED_BIT,
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
};
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
@@ -88,11 +89,15 @@ StreamBuffer::StreamBuffer(const Instance& instance, Scheduler& scheduler, u32 s
bool readback)
: instance{instance}, scheduler{scheduler}, staging{instance, size, readback}, usage{usage},
total_size{size}, bucket_size{size / BUCKET_COUNT}, readback{readback} {
const vk::BufferCreateInfo buffer_info = {
.size = total_size, .usage = usage | vk::BufferUsageFlagBits::eTransferDst};
const VmaAllocationCreateInfo alloc_create_info = {.usage =
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE};
const vk::BufferCreateInfo buffer_info = {
.size = total_size,
.usage = usage | vk::BufferUsageFlagBits::eTransferDst,
};
const VmaAllocationCreateInfo alloc_create_info = {
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
};
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
@@ -109,7 +114,11 @@ StreamBuffer::StreamBuffer(const Instance& instance, Scheduler& scheduler, u32 s
vk::Device device = instance.GetDevice();
for (std::size_t i = 0; i < view_formats.size(); i++) {
const vk::BufferViewCreateInfo view_info = {
.buffer = gpu_buffer, .format = view_formats[i], .offset = 0, .range = total_size};
.buffer = gpu_buffer,
.format = view_formats[i],
.offset = 0,
.range = total_size,
};
views[i] = device.createBufferView(view_info);
}
@@ -171,7 +180,10 @@ void StreamBuffer::Flush() {
scheduler.Record([this, flush_start, flush_size](vk::CommandBuffer,
vk::CommandBuffer upload_cmdbuf) {
const vk::BufferCopy copy_region = {
.srcOffset = flush_start, .dstOffset = flush_start, .size = flush_size};
.srcOffset = flush_start,
.dstOffset = flush_start,
.size = flush_size,
};
upload_cmdbuf.copyBuffer(staging.buffer, gpu_buffer, copy_region);
@@ -182,7 +194,8 @@ void StreamBuffer::Flush() {
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = gpu_buffer,
.offset = flush_start,
.size = flush_size};
.size = flush_size,
};
upload_cmdbuf.pipelineBarrier(
vk::PipelineStageFlagBits::eTransfer, MakePipelineStage(usage),

View File

@@ -69,7 +69,8 @@ void Swapchain::Create() {
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eInherit,
.presentMode = present_mode,
.clipped = true,
.oldSwapchain = swapchain};
.oldSwapchain = swapchain,
};
vk::Device device = instance.GetDevice();
vk::SwapchainKHR new_swapchain = device.createSwapchainKHR(swapchain_info);
@@ -111,11 +112,14 @@ void Swapchain::AcquireNextImage() {
MICROPROFILE_DEFINE(Vulkan_Present, "Vulkan", "Swapchain Present", MP_RGB(66, 185, 245));
void Swapchain::Present() {
scheduler.Record([this, index = image_index](vk::CommandBuffer, vk::CommandBuffer) {
const vk::PresentInfoKHR present_info = {.waitSemaphoreCount = 1,
.pWaitSemaphores = &present_ready[index],
.swapchainCount = 1,
.pSwapchains = &swapchain,
.pImageIndices = &index};
const vk::PresentInfoKHR present_info = {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &present_ready[index],
.swapchainCount = 1,
.pSwapchains = &swapchain,
.pImageIndices = &index,
};
MICROPROFILE_SCOPE(Vulkan_Present);
vk::Queue present_queue = instance.GetPresentQueue();
try {
@@ -135,8 +139,8 @@ void Swapchain::FindPresentFormat() {
const std::vector<vk::SurfaceFormatKHR> formats =
instance.GetPhysicalDevice().getSurfaceFormatsKHR(surface);
// If there is a single undefined surface format, the device doesn't care, so we'll just use
// RGBA
// If there is a single undefined surface format, the device doesn't care, so we'll just use
// RGBA
if (formats[0].format == vk::Format::eUndefined) {
surface_format.format = vk::Format::eR8G8B8A8Unorm;
surface_format.colorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
@@ -233,11 +237,15 @@ void Swapchain::SetupImages() {
.image = image,
.viewType = vk::ImageViewType::e2D,
.format = surface_format.format,
.subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1}};
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
image_views.push_back(device.createImageView(view_info));
@@ -247,7 +255,8 @@ void Swapchain::SetupImages() {
.pAttachments = &image_views.back(),
.width = extent.width,
.height = extent.height,
.layers = 1};
.layers = 1,
};
framebuffers.push_back(device.createFramebuffer(framebuffer_info));
}

File diff suppressed because it is too large Load Diff