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)); static_cast<Settings::GraphicsAPI>(sdl2_config->GetInteger("Renderer", "graphics_api", 2));
Settings::values.async_command_recording = Settings::values.async_command_recording =
sdl2_config->GetBoolean("Renderer", "async_command_recording", true); 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.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_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true);
Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true); Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true);

View File

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

View File

@@ -167,7 +167,8 @@ void RendererVulkan::PrepareRendertarget() {
LCD::Read(color_fill.raw, lcd_color_addr); LCD::Read(color_fill.raw, lcd_color_addr);
if (color_fill.is_enabled) { 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 { } else {
TextureInfo& texture = screen_infos[i].texture; TextureInfo& texture = screen_infos[i].texture;
if (texture.width != framebuffer.width || texture.height != framebuffer.height || if (texture.width != framebuffer.width || texture.height != framebuffer.height ||
@@ -197,7 +198,8 @@ void RendererVulkan::BeginRendering() {
present_textures[i] = vk::DescriptorImageInfo{ present_textures[i] = vk::DescriptorImageInfo{
.imageView = info.display_texture ? info.display_texture->image_view .imageView = info.display_texture ? info.display_texture->image_view
: info.texture.alloc.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]}; present_textures[3] = vk::DescriptorImageInfo{.sampler = present_samplers[current_sampler]};
@@ -295,41 +297,53 @@ void RendererVulkan::CompileShaders() {
void RendererVulkan::BuildLayouts() { void RendererVulkan::BuildLayouts() {
const std::array present_layout_bindings = { const std::array present_layout_bindings = {
vk::DescriptorSetLayoutBinding{.binding = 0, vk::DescriptorSetLayoutBinding{
.descriptorType = vk::DescriptorType::eSampledImage, .binding = 0,
.descriptorCount = 3, .descriptorType = vk::DescriptorType::eSampledImage,
.stageFlags = vk::ShaderStageFlagBits::eFragment}, .descriptorCount = 3,
vk::DescriptorSetLayoutBinding{.binding = 1, .stageFlags = vk::ShaderStageFlagBits::eFragment,
.descriptorType = vk::DescriptorType::eSampler, },
.descriptorCount = 1, vk::DescriptorSetLayoutBinding{
.stageFlags = vk::ShaderStageFlagBits::eFragment}}; .binding = 1,
.descriptorType = vk::DescriptorType::eSampler,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eFragment,
},
};
const vk::DescriptorSetLayoutCreateInfo present_layout_info = { const vk::DescriptorSetLayoutCreateInfo present_layout_info = {
.bindingCount = static_cast<u32>(present_layout_bindings.size()), .bindingCount = static_cast<u32>(present_layout_bindings.size()),
.pBindings = present_layout_bindings.data()}; .pBindings = present_layout_bindings.data(),
};
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info); present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info);
const std::array update_template_entries = { const std::array update_template_entries = {
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0, vk::DescriptorUpdateTemplateEntry{
.dstArrayElement = 0, .dstBinding = 0,
.descriptorCount = 3, .dstArrayElement = 0,
.descriptorType = vk::DescriptorType::eSampledImage, .descriptorCount = 3,
.offset = 0, .descriptorType = vk::DescriptorType::eSampledImage,
.stride = sizeof(vk::DescriptorImageInfo)}, .offset = 0,
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1, .stride = sizeof(vk::DescriptorImageInfo),
.dstArrayElement = 0, },
.descriptorCount = 1, vk::DescriptorUpdateTemplateEntry{
.descriptorType = vk::DescriptorType::eSampler, .dstBinding = 1,
.offset = 3 * sizeof(vk::DescriptorImageInfo), .dstArrayElement = 0,
.stride = 0}}; .descriptorCount = 1,
.descriptorType = vk::DescriptorType::eSampler,
.offset = 3 * sizeof(vk::DescriptorImageInfo),
.stride = 0,
},
};
const vk::DescriptorUpdateTemplateCreateInfo template_info = { const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()), .descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(), .pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = present_descriptor_layout}; .descriptorSetLayout = present_descriptor_layout,
};
present_update_template = device.createDescriptorUpdateTemplate(template_info); present_update_template = device.createDescriptorUpdateTemplate(template_info);
@@ -339,37 +353,49 @@ void RendererVulkan::BuildLayouts() {
.size = sizeof(PresentUniformData), .size = sizeof(PresentUniformData),
}; };
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1, const vk::PipelineLayoutCreateInfo layout_info = {
.pSetLayouts = &present_descriptor_layout, .setLayoutCount = 1,
.pushConstantRangeCount = 1, .pSetLayouts = &present_descriptor_layout,
.pPushConstantRanges = &push_range}; .pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range,
};
present_pipeline_layout = device.createPipelineLayout(layout_info); present_pipeline_layout = device.createPipelineLayout(layout_info);
} }
void RendererVulkan::BuildPipelines() { void RendererVulkan::BuildPipelines() {
const vk::VertexInputBindingDescription binding = {.binding = 0, const vk::VertexInputBindingDescription binding = {
.stride = sizeof(ScreenRectVertex), .binding = 0,
.inputRate = vk::VertexInputRate::eVertex}; .stride = sizeof(ScreenRectVertex),
.inputRate = vk::VertexInputRate::eVertex,
};
const std::array attributes = { const std::array attributes = {
vk::VertexInputAttributeDescription{.location = 0, vk::VertexInputAttributeDescription{
.binding = 0, .location = 0,
.format = vk::Format::eR32G32Sfloat, .binding = 0,
.offset = offsetof(ScreenRectVertex, position)}, .format = vk::Format::eR32G32Sfloat,
vk::VertexInputAttributeDescription{.location = 1, .offset = offsetof(ScreenRectVertex, position),
.binding = 0, },
.format = vk::Format::eR32G32Sfloat, vk::VertexInputAttributeDescription{
.offset = offsetof(ScreenRectVertex, tex_coord)}}; .location = 1,
.binding = 0,
.format = vk::Format::eR32G32Sfloat,
.offset = offsetof(ScreenRectVertex, tex_coord),
},
};
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = { const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
.vertexBindingDescriptionCount = 1, .vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &binding, .pVertexBindingDescriptions = &binding,
.vertexAttributeDescriptionCount = static_cast<u32>(attributes.size()), .vertexAttributeDescriptionCount = static_cast<u32>(attributes.size()),
.pVertexAttributeDescriptions = attributes.data()}; .pVertexAttributeDescriptions = attributes.data(),
};
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = { const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
.topology = vk::PrimitiveTopology::eTriangleStrip, .primitiveRestartEnable = false}; .topology = vk::PrimitiveTopology::eTriangleStrip,
.primitiveRestartEnable = false,
};
const vk::PipelineRasterizationStateCreateInfo raster_state = { const vk::PipelineRasterizationStateCreateInfo raster_state = {
.depthClampEnable = false, .depthClampEnable = false,
@@ -377,21 +403,26 @@ void RendererVulkan::BuildPipelines() {
.cullMode = vk::CullModeFlagBits::eNone, .cullMode = vk::CullModeFlagBits::eNone,
.frontFace = vk::FrontFace::eClockwise, .frontFace = vk::FrontFace::eClockwise,
.depthBiasEnable = false, .depthBiasEnable = false,
.lineWidth = 1.0f}; .lineWidth = 1.0f,
};
const vk::PipelineMultisampleStateCreateInfo multisampling = { const vk::PipelineMultisampleStateCreateInfo multisampling = {
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false}; .rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
const vk::PipelineColorBlendAttachmentState colorblend_attachment = { const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
.blendEnable = false, .blendEnable = false,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA}; vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
const vk::PipelineColorBlendStateCreateInfo color_blending = { const vk::PipelineColorBlendStateCreateInfo color_blending = {
.logicOpEnable = false, .logicOpEnable = false,
.attachmentCount = 1, .attachmentCount = 1,
.pAttachments = &colorblend_attachment, .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::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}}; const vk::Rect2D placeholder_scissor = vk::Rect2D{{0, 0}, {1, 1}};
@@ -402,27 +433,36 @@ void RendererVulkan::BuildPipelines() {
.pScissors = &placeholder_scissor, .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 = { const vk::PipelineDynamicStateCreateInfo dynamic_info = {
.dynamicStateCount = static_cast<u32>(dynamic_states.size()), .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
.pDynamicStates = dynamic_states.data()}; .pDynamicStates = dynamic_states.data(),
};
const vk::PipelineDepthStencilStateCreateInfo depth_info = {.depthTestEnable = false, const vk::PipelineDepthStencilStateCreateInfo depth_info = {
.depthWriteEnable = false, .depthTestEnable = false,
.depthCompareOp = .depthWriteEnable = false,
vk::CompareOp::eAlways, .depthCompareOp = vk::CompareOp::eAlways,
.depthBoundsTestEnable = false, .depthBoundsTestEnable = false,
.stencilTestEnable = false}; .stencilTestEnable = false,
};
for (u32 i = 0; i < PRESENT_PIPELINES; i++) { for (u32 i = 0; i < PRESENT_PIPELINES; i++) {
const std::array shader_stages = { const std::array shader_stages = {
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eVertex, vk::PipelineShaderStageCreateInfo{
.module = present_vertex_shader, .stage = vk::ShaderStageFlagBits::eVertex,
.pName = "main"}, .module = present_vertex_shader,
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eFragment, .pName = "main",
.module = present_shaders[i], },
.pName = "main"}, vk::PipelineShaderStageCreateInfo{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = present_shaders[i],
.pName = "main",
},
}; };
const vk::GraphicsPipelineCreateInfo pipeline_info = { const vk::GraphicsPipelineCreateInfo pipeline_info = {
@@ -437,7 +477,8 @@ void RendererVulkan::BuildPipelines() {
.pColorBlendState = &color_blending, .pColorBlendState = &color_blending,
.pDynamicState = &dynamic_info, .pDynamicState = &dynamic_info,
.layout = present_pipeline_layout, .layout = present_pipeline_layout,
.renderPass = renderpass_cache.GetPresentRenderpass()}; .renderPass = renderpass_cache.GetPresentRenderpass(),
};
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
if (const auto result = device.createGraphicsPipeline({}, pipeline_info); if (const auto result = device.createGraphicsPipeline({}, pipeline_info);
@@ -453,67 +494,80 @@ void RendererVulkan::BuildPipelines() {
void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture, void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture,
const GPU::Regs::FramebufferConfig& framebuffer) { const GPU::Regs::FramebufferConfig& framebuffer) {
TextureInfo old_texture = std::move(texture); TextureInfo old_texture = std::move(texture);
texture = TextureInfo{.alloc = runtime.Allocate( texture = TextureInfo{
framebuffer.width, framebuffer.height, .alloc =
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format), runtime.Allocate(framebuffer.width, framebuffer.height,
VideoCore::TextureType::Texture2D), VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format),
.width = framebuffer.width, VideoCore::TextureType::Texture2D),
.height = framebuffer.height, .width = framebuffer.width,
.format = framebuffer.color_format}; .height = framebuffer.height,
.format = framebuffer.color_format,
};
// Recyle the old texture after allocation to avoid having duplicates of the same allocation in // Recyle the old texture after allocation to avoid having duplicates of the same allocation in
// the recycler // the recycler
if (old_texture.width != 0 && old_texture.height != 0) { if (old_texture.width != 0 && old_texture.height != 0) {
const HostTextureTag tag = {.format = old_texture.alloc.format, const HostTextureTag tag = {
.width = old_texture.width, .format = old_texture.alloc.format,
.height = old_texture.height}; .width = old_texture.width,
.height = old_texture.height,
};
runtime.Recycle(tag, std::move(old_texture.alloc)); 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 = { 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(); renderpass_cache.ExitRenderpass();
scheduler.Record([image = texture.alloc.image, scheduler.Record([image = texture.alloc.image, clear_color](vk::CommandBuffer render_cmdbuf,
clear_color](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { vk::CommandBuffer) {
const vk::ImageSubresourceRange range = {.aspectMask = vk::ImageAspectFlagBits::eColor, const vk::ImageSubresourceRange range = {
.baseMipLevel = 0, .aspectMask = vk::ImageAspectFlagBits::eColor,
.levelCount = VK_REMAINING_MIP_LEVELS, .baseMipLevel = 0,
.baseArrayLayer = 0, .levelCount = VK_REMAINING_MIP_LEVELS,
.layerCount = VK_REMAINING_ARRAY_LAYERS}; .baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
};
const vk::ImageMemoryBarrier pre_barrier = { const vk::ImageMemoryBarrier pre_barrier = {
.srcAccessMask = vk::AccessFlagBits::eShaderRead | .srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
vk::AccessFlagBits::eTransferRead, .dstAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = vk::AccessFlagBits::eTransferWrite, .oldLayout = vk::ImageLayout::eGeneral,
.oldLayout = vk::ImageLayout::eGeneral, .newLayout = vk::ImageLayout::eTransferDstOptimal,
.newLayout = vk::ImageLayout::eTransferDstOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = image,
.image = image, .subresourceRange = range,
.subresourceRange = range
}; };
const vk::ImageMemoryBarrier post_barrier = { const vk::ImageMemoryBarrier post_barrier = {
.srcAccessMask = vk::AccessFlagBits::eTransferWrite, .srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
vk::AccessFlagBits::eTransferRead, .oldLayout = vk::ImageLayout::eTransferDstOptimal,
.oldLayout = vk::ImageLayout::eTransferDstOptimal, .newLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = image,
.image = image, .subresourceRange = range,
.subresourceRange = range
}; };
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier); 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, render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands,
@@ -873,14 +927,19 @@ void RendererVulkan::SwapBuffers() {
} while (swapchain.NeedsRecreation()); } while (swapchain.NeedsRecreation());
scheduler.Record([layout](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { scheduler.Record([layout](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
const vk::Viewport viewport = {.x = 0.0f, const vk::Viewport viewport = {
.y = 0.0f, .x = 0.0f,
.width = static_cast<float>(layout.width), .y = 0.0f,
.height = static_cast<float>(layout.height), .width = static_cast<float>(layout.width),
.minDepth = 0.0f, .height = static_cast<float>(layout.height),
.maxDepth = 1.0f}; .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.setViewport(0, viewport);
render_cmdbuf.setScissor(0, scissor); render_cmdbuf.setScissor(0, scissor);
@@ -888,20 +947,6 @@ void RendererVulkan::SwapBuffers() {
DrawScreens(layout, false); 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 image_acquired = swapchain.GetImageAcquiredSemaphore();
const vk::Semaphore present_ready = swapchain.GetPresentReadySemaphore(); const vk::Semaphore present_ready = swapchain.GetPresentReadySemaphore();
scheduler.Flush(present_ready, image_acquired); 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_blit_helper.h"
#include "video_core/renderer_vulkan/vk_descriptor_manager.h" #include "video_core/renderer_vulkan/vk_descriptor_manager.h"
#include "video_core/renderer_vulkan/vk_instance.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_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.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" #include "video_core/renderer_vulkan/vk_texture_runtime.h"
namespace Vulkan { namespace Vulkan {
BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler, DescriptorManager& desc_manager) BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler,
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} { DescriptorManager& desc_manager)
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} {
constexpr std::string_view cs_source = R"( constexpr std::string_view cs_source = R"(
#version 450 core #version 450 core
#extension GL_EXT_samplerless_texture_functions : require #extension GL_EXT_samplerless_texture_functions : require
@@ -36,77 +37,100 @@ imageStore(color, dst_coord, uvec4(value));
} }
)"; )";
compute_shader = 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 = { const std::array compute_layout_bindings = {
vk::DescriptorSetLayoutBinding{.binding = 0, vk::DescriptorSetLayoutBinding{
.descriptorType = vk::DescriptorType::eSampledImage, .binding = 0,
.descriptorCount = 1, .descriptorType = vk::DescriptorType::eSampledImage,
.stageFlags = vk::ShaderStageFlagBits::eCompute}, .descriptorCount = 1,
vk::DescriptorSetLayoutBinding{.binding = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute,
.descriptorType = vk::DescriptorType::eSampledImage, },
.descriptorCount = 1, vk::DescriptorSetLayoutBinding{
.stageFlags = vk::ShaderStageFlagBits::eCompute}, .binding = 1,
vk::DescriptorSetLayoutBinding{.binding = 2, .descriptorType = vk::DescriptorType::eSampledImage,
.descriptorType = vk::DescriptorType::eStorageImage, .descriptorCount = 1,
.descriptorCount = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute,
.stageFlags = vk::ShaderStageFlagBits::eCompute}}; },
vk::DescriptorSetLayoutBinding{
.binding = 2,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
};
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = { const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
.bindingCount = static_cast<u32>(compute_layout_bindings.size()), .bindingCount = static_cast<u32>(compute_layout_bindings.size()),
.pBindings = compute_layout_bindings.data()}; .pBindings = compute_layout_bindings.data(),
};
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info); descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
const std::array update_template_entries = { const std::array update_template_entries = {
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0, vk::DescriptorUpdateTemplateEntry{
.dstArrayElement = 0, .dstBinding = 0,
.descriptorCount = 1, .dstArrayElement = 0,
.descriptorType = vk::DescriptorType::eSampledImage, .descriptorCount = 1,
.offset = 0, .descriptorType = vk::DescriptorType::eSampledImage,
.stride = sizeof(vk::DescriptorImageInfo)}, .offset = 0,
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1, .stride = sizeof(vk::DescriptorImageInfo),
.dstArrayElement = 0, },
.descriptorCount = 1, vk::DescriptorUpdateTemplateEntry{
.descriptorType = vk::DescriptorType::eSampledImage, .dstBinding = 1,
.offset = sizeof(vk::DescriptorImageInfo), .dstArrayElement = 0,
.stride = 0}, .descriptorCount = 1,
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2, .descriptorType = vk::DescriptorType::eSampledImage,
.dstArrayElement = 0, .offset = sizeof(vk::DescriptorImageInfo),
.descriptorCount = 1, .stride = 0,
.descriptorType = vk::DescriptorType::eStorageImage, },
.offset = 2 * sizeof(vk::DescriptorImageInfo), vk::DescriptorUpdateTemplateEntry{
.stride = 0}}; .dstBinding = 2,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageImage,
.offset = 2 * sizeof(vk::DescriptorImageInfo),
.stride = 0,
},
};
const vk::DescriptorUpdateTemplateCreateInfo template_info = { const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()), .descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(), .pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_layout}; .descriptorSetLayout = descriptor_layout,
};
update_template = device.createDescriptorUpdateTemplate(template_info); update_template = device.createDescriptorUpdateTemplate(template_info);
const vk::PushConstantRange push_range = { const vk::PushConstantRange push_range = {
.stageFlags = vk::ShaderStageFlagBits::eCompute, .stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0, .offset = 0,
.size = sizeof(Common::Vec2i), .size = sizeof(Common::Vec2i),
}; };
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1, const vk::PipelineLayoutCreateInfo layout_info = {
.pSetLayouts = &descriptor_layout, .setLayoutCount = 1,
.pushConstantRangeCount = 1, .pSetLayouts = &descriptor_layout,
.pPushConstantRanges = &push_range}; .pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range,
};
compute_pipeline_layout = device.createPipelineLayout(layout_info); compute_pipeline_layout = device.createPipelineLayout(layout_info);
const vk::PipelineShaderStageCreateInfo compute_stage = { 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, const vk::ComputePipelineCreateInfo compute_info = {
.layout = compute_pipeline_layout}; .stage = compute_stage,
.layout = compute_pipeline_layout,
};
if (const auto result = device.createComputePipeline({}, compute_info); if (const auto result = device.createComputePipeline({}, compute_info);
result.result == vk::Result::eSuccess) { result.result == vk::Result::eSuccess) {
compute_pipeline = result.value; compute_pipeline = result.value;
} else { } else {
LOG_CRITICAL(Render_Vulkan, "D24S8 compute pipeline creation failed!"); LOG_CRITICAL(Render_Vulkan, "D24S8 compute pipeline creation failed!");
@@ -125,97 +149,103 @@ BlitHelper::~BlitHelper() {
void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest, void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) { const VideoCore::TextureBlit& blit) {
const std::array textures = { const std::array textures = {
vk::DescriptorImageInfo{.imageView = source.GetDepthView(), vk::DescriptorImageInfo{
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal}, .imageView = source.GetDepthView(),
vk::DescriptorImageInfo{.imageView = source.GetStencilView(), .imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal}, },
vk::DescriptorImageInfo{.imageView = dest.GetImageView(), vk::DescriptorImageInfo{
.imageLayout = vk::ImageLayout::eGeneral}}; .imageView = source.GetStencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = dest.GetImageView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
};
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout); vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]); device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
scheduler.Record([this, set, blit, scheduler.Record([this, set, blit, src_image = source.alloc.image,
src_image = source.alloc.image, dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { vk::CommandBuffer) {
const std::array pre_barriers = { const std::array pre_barriers = {
vk::ImageMemoryBarrier{ vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite | .srcAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead, vk::AccessFlagBits::eDepthStencilAttachmentRead,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral, .oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal, .newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image, .image = src_image,
.subresourceRange{ .subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth | .aspectMask =
vk::ImageAspectFlagBits::eStencil, vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0, .baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS, .levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0, .baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
},
}, },
vk::ImageMemoryBarrier{ },
.srcAccessMask = vk::AccessFlagBits::eNone, vk::ImageMemoryBarrier{
.dstAccessMask = vk::AccessFlagBits::eShaderWrite, .srcAccessMask = vk::AccessFlagBits::eNone,
.oldLayout = vk::ImageLayout::eUndefined, .dstAccessMask = vk::AccessFlagBits::eShaderWrite,
.newLayout = vk::ImageLayout::eGeneral, .oldLayout = vk::ImageLayout::eUndefined,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .newLayout = vk::ImageLayout::eGeneral,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.subresourceRange{ .image = dst_image,
.aspectMask = vk::ImageAspectFlagBits::eColor, .subresourceRange{
.baseMipLevel = 0, .aspectMask = vk::ImageAspectFlagBits::eColor,
.levelCount = VK_REMAINING_MIP_LEVELS, .baseMipLevel = 0,
.baseArrayLayer = 0, .levelCount = VK_REMAINING_MIP_LEVELS,
.layerCount = VK_REMAINING_ARRAY_LAYERS, .baseArrayLayer = 0,
}, .layerCount = VK_REMAINING_ARRAY_LAYERS,
} },
}; }};
const std::array post_barriers = { const std::array post_barriers = {
vk::ImageMemoryBarrier{ vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eShaderRead, .srcAccessMask = vk::AccessFlagBits::eShaderRead,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite | .dstAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite, vk::AccessFlagBits::eDepthStencilAttachmentWrite,
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal, .oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.newLayout = vk::ImageLayout::eGeneral, .newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image, .image = src_image,
.subresourceRange{ .subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth | .aspectMask =
vk::ImageAspectFlagBits::eStencil, vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0, .baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS, .levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0, .baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
},
}, },
vk::ImageMemoryBarrier{ },
.srcAccessMask = vk::AccessFlagBits::eShaderWrite, vk::ImageMemoryBarrier{
.dstAccessMask = vk::AccessFlagBits::eShaderRead, .srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral, .dstAccessMask = vk::AccessFlagBits::eShaderRead,
.newLayout = vk::ImageLayout::eGeneral, .oldLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .newLayout = vk::ImageLayout::eGeneral,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.subresourceRange{ .image = dst_image,
.aspectMask = vk::ImageAspectFlagBits::eColor, .subresourceRange{
.baseMipLevel = 0, .aspectMask = vk::ImageAspectFlagBits::eColor,
.levelCount = VK_REMAINING_MIP_LEVELS, .baseMipLevel = 0,
.baseArrayLayer = 0, .levelCount = VK_REMAINING_MIP_LEVELS,
.layerCount = VK_REMAINING_ARRAY_LAYERS, .baseArrayLayer = 0,
}, .layerCount = VK_REMAINING_ARRAY_LAYERS,
} },
}; }};
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eComputeShader,
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers); 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); render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
const auto src_offset = Common::MakeVec(blit.src_rect.left, blit.src_rect.bottom); 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 = { constexpr static std::array RASTERIZER_SETS = {
Bindings{// Utility set Bindings{
.bindings = {vk::DescriptorType::eUniformBuffer, vk::DescriptorType::eUniformBuffer, // Utility set
vk::DescriptorType::eUniformTexelBuffer, .bindings =
vk::DescriptorType::eUniformTexelBuffer, {
vk::DescriptorType::eUniformTexelBuffer}, vk::DescriptorType::eUniformBuffer,
.binding_count = 5}, vk::DescriptorType::eUniformBuffer,
Bindings{// Texture set vk::DescriptorType::eUniformTexelBuffer,
.bindings = {vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage, vk::DescriptorType::eUniformTexelBuffer,
vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage}, vk::DescriptorType::eUniformTexelBuffer,
.binding_count = 4}, },
Bindings{// Sampler set .binding_count = 5,
.bindings = {vk::DescriptorType::eSampler, vk::DescriptorType::eSampler, },
vk::DescriptorType::eSampler, vk::DescriptorType::eSampler}, Bindings{
.binding_count = 4}, // Texture set
Bindings{// Shadow set .bindings =
.bindings = {vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, {
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, vk::DescriptorType::eSampledImage,
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, vk::DescriptorType::eSampledImage,
vk::DescriptorType::eStorageImage}, vk::DescriptorType::eSampledImage,
.binding_count = 4}}; 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) { constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) {
vk::ShaderStageFlags flags; vk::ShaderStageFlags flags;
@@ -66,7 +97,7 @@ DescriptorManager::DescriptorManager(const Instance& instance, Scheduler& schedu
} }
DescriptorManager::~DescriptorManager() { DescriptorManager::~DescriptorManager() {
vk::Device device = instance.GetDevice(); const vk::Device device = instance.GetDevice();
device.destroyPipelineLayout(pipeline_layout); device.destroyPipelineLayout(pipeline_layout);
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) { for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
@@ -89,7 +120,7 @@ void DescriptorManager::BindDescriptorSets() {
descriptor_set_dirty.fill(true); 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; std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> bound_sets;
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) { for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
if (descriptor_set_dirty[i]) { if (descriptor_set_dirty[i]) {
@@ -116,51 +147,59 @@ void DescriptorManager::BuildLayouts() {
std::array<vk::DescriptorSetLayoutBinding, MAX_DESCRIPTORS> set_bindings; std::array<vk::DescriptorSetLayoutBinding, MAX_DESCRIPTORS> set_bindings;
std::array<vk::DescriptorUpdateTemplateEntry, MAX_DESCRIPTORS> update_entries; 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++) { for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
const auto& set = RASTERIZER_SETS[i]; const auto& set = RASTERIZER_SETS[i];
for (u32 j = 0; j < set.binding_count; j++) { for (u32 j = 0; j < set.binding_count; j++) {
vk::DescriptorType type = set.bindings[j]; const vk::DescriptorType type = set.bindings[j];
set_bindings[j] = vk::DescriptorSetLayoutBinding{.binding = j, set_bindings[j] = vk::DescriptorSetLayoutBinding{
.descriptorType = type, .binding = j,
.descriptorCount = 1, .descriptorType = type,
.stageFlags = ToVkStageFlags(type)}; .descriptorCount = 1,
.stageFlags = ToVkStageFlags(type),
};
update_entries[j] = update_entries[j] = vk::DescriptorUpdateTemplateEntry{
vk::DescriptorUpdateTemplateEntry{.dstBinding = j, .dstBinding = j,
.dstArrayElement = 0, .dstArrayElement = 0,
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = type, .descriptorType = type,
.offset = j * sizeof(DescriptorData), .offset = j * sizeof(DescriptorData),
.stride = 0}; .stride = 0,
};
} }
const vk::DescriptorSetLayoutCreateInfo layout_info = {.bindingCount = set.binding_count, const vk::DescriptorSetLayoutCreateInfo layout_info = {
.pBindings = set_bindings.data()}; .bindingCount = set.binding_count,
.pBindings = set_bindings.data(),
};
descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info); descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info);
const vk::DescriptorUpdateTemplateCreateInfo template_info = { const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = set.binding_count, .descriptorUpdateEntryCount = set.binding_count,
.pDescriptorUpdateEntries = update_entries.data(), .pDescriptorUpdateEntries = update_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_set_layouts[i]}; .descriptorSetLayout = descriptor_set_layouts[i],
};
update_templates[i] = device.createDescriptorUpdateTemplate(template_info); update_templates[i] = device.createDescriptorUpdateTemplate(template_info);
} }
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = MAX_DESCRIPTOR_SETS, const vk::PipelineLayoutCreateInfo layout_info = {
.pSetLayouts = descriptor_set_layouts.data(), .setLayoutCount = MAX_DESCRIPTOR_SETS,
.pushConstantRangeCount = 0, .pSetLayouts = descriptor_set_layouts.data(),
.pPushConstantRanges = nullptr}; .pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
pipeline_layout = device.createPipelineLayout(layout_info); pipeline_layout = device.createPipelineLayout(layout_info);
} }
vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) { vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) {
vk::Device device = instance.GetDevice(); const vk::Device device = instance.GetDevice();
const vk::DescriptorSetAllocateInfo alloc_info = { const vk::DescriptorSetAllocateInfo alloc_info = {
.descriptorPool = current_pool, .descriptorSetCount = 1, .pSetLayouts = &layout}; .descriptorPool = current_pool,
.descriptorSetCount = 1,
.pSetLayouts = &layout,
};
try { try {
return device.allocateDescriptorSets(alloc_info)[0]; 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_descriptor_manager.h"
#include "video_core/renderer_vulkan/vk_format_reinterpreter.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_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.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" #include "video_core/renderer_vulkan/vk_texture_runtime.h"
namespace Vulkan { namespace Vulkan {
D24S8toRGBA8::D24S8toRGBA8(const Instance& instance, Scheduler& scheduler, D24S8toRGBA8::D24S8toRGBA8(const Instance& instance, Scheduler& scheduler,
DescriptorManager& desc_manager, TextureRuntime& runtime) 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"( constexpr std::string_view cs_source = R"(
#version 450 core #version 450 core
#extension GL_EXT_samplerless_texture_functions : require #extension GL_EXT_samplerless_texture_functions : require
@@ -35,77 +36,98 @@ imageStore(color, tex_coord, vec4(components) / (exp2(8.0) - 1.0));
} }
)"; )";
compute_shader = 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 = { const std::array compute_layout_bindings = {
vk::DescriptorSetLayoutBinding{.binding = 0, vk::DescriptorSetLayoutBinding{
.descriptorType = vk::DescriptorType::eSampledImage, .binding = 0,
.descriptorCount = 1, .descriptorType = vk::DescriptorType::eSampledImage,
.stageFlags = vk::ShaderStageFlagBits::eCompute}, .descriptorCount = 1,
vk::DescriptorSetLayoutBinding{.binding = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute,
.descriptorType = vk::DescriptorType::eSampledImage, },
.descriptorCount = 1, vk::DescriptorSetLayoutBinding{
.stageFlags = vk::ShaderStageFlagBits::eCompute}, .binding = 1,
vk::DescriptorSetLayoutBinding{.binding = 2, .descriptorType = vk::DescriptorType::eSampledImage,
.descriptorType = vk::DescriptorType::eStorageImage, .descriptorCount = 1,
.descriptorCount = 1, .stageFlags = vk::ShaderStageFlagBits::eCompute,
.stageFlags = vk::ShaderStageFlagBits::eCompute}}; },
vk::DescriptorSetLayoutBinding{
.binding = 2,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
},
};
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = { const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
.bindingCount = static_cast<u32>(compute_layout_bindings.size()), .bindingCount = static_cast<u32>(compute_layout_bindings.size()),
.pBindings = compute_layout_bindings.data()}; .pBindings = compute_layout_bindings.data(),
};
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info); descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
const std::array update_template_entries = { const std::array update_template_entries = {
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0, vk::DescriptorUpdateTemplateEntry{
.dstArrayElement = 0, .dstBinding = 0,
.descriptorCount = 1, .dstArrayElement = 0,
.descriptorType = vk::DescriptorType::eSampledImage, .descriptorCount = 1,
.offset = 0, .descriptorType = vk::DescriptorType::eSampledImage,
.stride = sizeof(vk::DescriptorImageInfo)}, .offset = 0,
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1, .stride = sizeof(vk::DescriptorImageInfo),
.dstArrayElement = 0, },
.descriptorCount = 1, vk::DescriptorUpdateTemplateEntry{
.descriptorType = vk::DescriptorType::eSampledImage, .dstBinding = 1,
.offset = sizeof(vk::DescriptorImageInfo), .dstArrayElement = 0,
.stride = 0}, .descriptorCount = 1,
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2, .descriptorType = vk::DescriptorType::eSampledImage,
.dstArrayElement = 0, .offset = sizeof(vk::DescriptorImageInfo),
.descriptorCount = 1, },
.descriptorType = vk::DescriptorType::eStorageImage, vk::DescriptorUpdateTemplateEntry{
.offset = 2 * sizeof(vk::DescriptorImageInfo), .dstBinding = 2,
.stride = 0}}; .dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageImage,
.offset = 2 * sizeof(vk::DescriptorImageInfo),
},
};
const vk::DescriptorUpdateTemplateCreateInfo template_info = { const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()), .descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
.pDescriptorUpdateEntries = update_template_entries.data(), .pDescriptorUpdateEntries = update_template_entries.data(),
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = descriptor_layout}; .descriptorSetLayout = descriptor_layout,
};
update_template = device.createDescriptorUpdateTemplate(template_info); update_template = device.createDescriptorUpdateTemplate(template_info);
const vk::PushConstantRange push_range = { const vk::PushConstantRange push_range = {
.stageFlags = vk::ShaderStageFlagBits::eCompute, .stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0, .offset = 0,
.size = sizeof(Common::Vec2i), .size = sizeof(Common::Vec2i),
}; };
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1, const vk::PipelineLayoutCreateInfo layout_info = {
.pSetLayouts = &descriptor_layout, .setLayoutCount = 1,
.pushConstantRangeCount = 1, .pSetLayouts = &descriptor_layout,
.pPushConstantRanges = &push_range}; .pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range,
};
compute_pipeline_layout = device.createPipelineLayout(layout_info); compute_pipeline_layout = device.createPipelineLayout(layout_info);
const vk::PipelineShaderStageCreateInfo compute_stage = { 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, const vk::ComputePipelineCreateInfo compute_info = {
.layout = compute_pipeline_layout}; .stage = compute_stage,
.layout = compute_pipeline_layout,
};
if (const auto result = device.createComputePipeline({}, compute_info); if (const auto result = device.createComputePipeline({}, compute_info);
result.result == vk::Result::eSuccess) { result.result == vk::Result::eSuccess) {
compute_pipeline = result.value; compute_pipeline = result.value;
} else { } else {
LOG_CRITICAL(Render_Vulkan, "D24S8 compute pipeline creation failed!"); 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, void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surface& dest,
VideoCore::Rect2D dst_rect) { VideoCore::Rect2D dst_rect) {
const std::array textures = { const std::array textures = {
vk::DescriptorImageInfo{.imageView = source.GetDepthView(), vk::DescriptorImageInfo{
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal}, .imageView = source.GetDepthView(),
vk::DescriptorImageInfo{.imageView = source.GetStencilView(), .imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal}, },
vk::DescriptorImageInfo{.imageView = dest.GetImageView(), vk::DescriptorImageInfo{
.imageLayout = vk::ImageLayout::eGeneral}}; .imageView = source.GetStencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = dest.GetImageView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
};
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout); vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]); device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
runtime.GetRenderpassCache().ExitRenderpass(); runtime.GetRenderpassCache().ExitRenderpass();
scheduler.Record([this, set, src_rect, scheduler.Record([this, set, src_rect, src_image = source.alloc.image,
src_image = source.alloc.image, dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { vk::CommandBuffer) {
const vk::ImageMemoryBarrier pre_barrier = { const vk::ImageMemoryBarrier pre_barrier = {
.srcAccessMask = vk::AccessFlagBits::eShaderWrite | .srcAccessMask = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eDepthStencilAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite |
vk::AccessFlagBits::eDepthStencilAttachmentRead, vk::AccessFlagBits::eDepthStencilAttachmentRead,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite, .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
.oldLayout = vk::ImageLayout::eGeneral, .oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal, .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, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image, .image = src_image,
.subresourceRange{ .subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eDepth | .aspectMask =
vk::ImageAspectFlagBits::eStencil, vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0, .baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS, .levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0, .baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; },
const std::array post_barriers = { vk::ImageMemoryBarrier{
vk::ImageMemoryBarrier{ .srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.srcAccessMask = vk::AccessFlagBits::eShaderRead, .dstAccessMask = vk::AccessFlagBits::eShaderRead,
.dstAccessMask = vk::AccessFlagBits::eShaderWrite | .oldLayout = vk::ImageLayout::eGeneral,
vk::AccessFlagBits::eDepthStencilAttachmentWrite, .newLayout = vk::ImageLayout::eGeneral,
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.newLayout = vk::ImageLayout::eGeneral, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = dst_image,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .subresourceRange{
.image = src_image, .aspectMask = vk::ImageAspectFlagBits::eColor,
.subresourceRange{ .baseMipLevel = 0,
.aspectMask = vk::ImageAspectFlagBits::eDepth | .levelCount = VK_REMAINING_MIP_LEVELS,
vk::ImageAspectFlagBits::eStencil, .baseArrayLayer = 0,
.baseMipLevel = 0, .layerCount = VK_REMAINING_ARRAY_LAYERS,
.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, render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eComputeShader, vk::PipelineStageFlagBits::eComputeShader,
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier); 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); render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
const auto src_offset = Common::MakeVec(src_rect.left, src_rect.bottom); 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() { [[nodiscard]] vk::DebugUtilsMessengerCreateInfoEXT MakeDebugUtilsMessengerInfo() {
return {.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo | return vk::DebugUtilsMessengerCreateInfoEXT{
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError | .messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose, vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose,
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | .messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
.pfnUserCallback = DebugHandler}; vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
.pfnUserCallback = DebugHandler,
};
} }
std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) { 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) Instance::Instance(bool validation, bool dump_command_buffers)
: enable_validation{validation}, dump_command_buffers{dump_command_buffers} { : enable_validation{validation}, dump_command_buffers{dump_command_buffers} {
// Fetch instance independant function pointers
auto vkGetInstanceProcAddr = auto vkGetInstanceProcAddr =
dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
@@ -110,19 +111,16 @@ Instance::Instance(bool validation, bool dump_command_buffers)
// Use required platform-specific flags // Use required platform-specific flags
auto flags = GetInstanceFlags(); auto flags = GetInstanceFlags();
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra", const vk::ApplicationInfo application_info = {
.applicationVersion = VK_MAKE_VERSION(1, 0, 0), .pApplicationName = "Citra",
.pEngineName = "Citra Vulkan", .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.engineVersion = VK_MAKE_VERSION(1, 0, 0), .pEngineName = "Citra Vulkan",
.apiVersion = VK_API_VERSION_1_0}; .engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_API_VERSION_1_0,
};
std::array<const char*, 3> layers; std::array<const char*, 2> layers;
#ifdef ANDROID
u32 layer_count = 1;
layers[0] = "VK_LAYER_KHRONOS_timeline_semaphore";
#else
u32 layer_count = 0; u32 layer_count = 0;
#endif
if (enable_validation) { if (enable_validation) {
layers[layer_count++] = "VK_LAYER_KHRONOS_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 = { const vk::StructureChain instance_chain = {
vk::InstanceCreateInfo{.flags = flags, vk::InstanceCreateInfo{
.pApplicationInfo = &application_info, .flags = flags,
.enabledLayerCount = layer_count, .pApplicationInfo = &application_info,
.ppEnabledLayerNames = layers.data(), .enabledLayerCount = layer_count,
.enabledExtensionCount = static_cast<u32>(extensions.size()), .ppEnabledLayerNames = layers.data(),
.ppEnabledExtensionNames = extensions.data()}, .enabledExtensionCount = static_cast<u32>(extensions.size()),
MakeDebugUtilsMessengerInfo()}; .ppEnabledExtensionNames = extensions.data(),
},
};
instance = vk::createInstance(instance_chain.get()); 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) Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
: enable_validation{Settings::values.renderer_debug}, : enable_validation{Settings::values.renderer_debug},
dump_command_buffers{Settings::values.dump_command_buffers} { 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 // Fetch instance independant function pointers
auto vkGetInstanceProcAddr = auto vkGetInstanceProcAddr =
@@ -176,11 +176,13 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
return; return;
} }
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra", const vk::ApplicationInfo application_info = {
.applicationVersion = VK_MAKE_VERSION(1, 0, 0), .pApplicationName = "Citra",
.pEngineName = "Citra Vulkan", .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.engineVersion = VK_MAKE_VERSION(1, 0, 0), .pEngineName = "Citra Vulkan",
.apiVersion = available_version}; .engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = available_version,
};
std::array<const char*, 3> layers; std::array<const char*, 3> layers;
#ifdef ANDROID #ifdef ANDROID
@@ -198,13 +200,16 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
} }
const vk::StructureChain instance_chain = { const vk::StructureChain instance_chain = {
vk::InstanceCreateInfo{.flags = flags, vk::InstanceCreateInfo{
.pApplicationInfo = &application_info, .flags = flags,
.enabledLayerCount = layer_count, .pApplicationInfo = &application_info,
.ppEnabledLayerNames = layers.data(), .enabledLayerCount = layer_count,
.enabledExtensionCount = static_cast<u32>(extensions.size()), .ppEnabledLayerNames = layers.data(),
.ppEnabledExtensionNames = extensions.data()}, .enabledExtensionCount = static_cast<u32>(extensions.size()),
MakeDebugUtilsMessengerInfo()}; .ppEnabledExtensionNames = extensions.data(),
},
MakeDebugUtilsMessengerInfo(),
};
try { try {
instance = vk::createInstance(instance_chain.get()); instance = vk::createInstance(instance_chain.get());
@@ -335,13 +340,15 @@ void Instance::CreateFormatTable() {
} }
const u32 index = static_cast<u32>(pixel_format); const u32 index = static_cast<u32>(pixel_format);
format_table[index] = FormatTraits{.transfer_support = supports_transfer, format_table[index] = FormatTraits{
.blit_support = supports_blit, .transfer_support = supports_transfer,
.attachment_support = supports_attachment, .blit_support = supports_blit,
.storage_support = supports_storage, .attachment_support = supports_attachment,
.usage = best_usage, .storage_support = supports_storage,
.native = format, .usage = best_usage,
.fallback = fallback}; .native = format,
.fallback = fallback,
};
} }
} }
@@ -431,12 +438,17 @@ bool Instance::CreateDevice() {
static constexpr float queue_priorities[] = {1.0f}; static constexpr float queue_priorities[] = {1.0f};
const std::array queue_infos = { const std::array queue_infos = {
vk::DeviceQueueCreateInfo{.queueFamilyIndex = graphics_queue_family_index, vk::DeviceQueueCreateInfo{
.queueCount = 1, .queueFamilyIndex = graphics_queue_family_index,
.pQueuePriorities = queue_priorities}, .queueCount = 1,
vk::DeviceQueueCreateInfo{.queueFamilyIndex = present_queue_family_index, .pQueuePriorities = queue_priorities,
.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 u32 queue_count = graphics_queue_family_index != present_queue_family_index ? 2u : 1u;
const vk::StructureChain device_chain = { const vk::StructureChain device_chain = {
@@ -447,23 +459,25 @@ bool Instance::CreateDevice() {
.ppEnabledExtensionNames = enabled_extensions.data(), .ppEnabledExtensionNames = enabled_extensions.data(),
}, },
vk::PhysicalDeviceFeatures2{ vk::PhysicalDeviceFeatures2{
.features = {.robustBufferAccess = features.robustBufferAccess, .features =
.geometryShader = features.geometryShader, {
.dualSrcBlend = features.dualSrcBlend, .robustBufferAccess = features.robustBufferAccess,
.logicOp = features.logicOp, .geometryShader = features.geometryShader,
.depthClamp = features.depthClamp, .dualSrcBlend = features.dualSrcBlend,
.largePoints = features.largePoints, .logicOp = features.logicOp,
.samplerAnisotropy = features.samplerAnisotropy, .depthClamp = features.depthClamp,
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics, .largePoints = features.largePoints,
.shaderStorageImageMultisample = features.shaderStorageImageMultisample, .samplerAnisotropy = features.samplerAnisotropy,
.shaderClipDistance = features.shaderClipDistance}}, .fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
.shaderClipDistance = features.shaderClipDistance,
},
},
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(), feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(), feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(),
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(), feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>() feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()};
};
// Create logical device
try { try {
device = physical_device.createDevice(device_chain.get()); device = physical_device.createDevice(device_chain.get());
} catch (vk::ExtensionNotPresentError& err) { } catch (vk::ExtensionNotPresentError& err) {
@@ -484,13 +498,16 @@ bool Instance::CreateDevice() {
void Instance::CreateAllocator() { void Instance::CreateAllocator() {
const VmaVulkanFunctions functions = { const VmaVulkanFunctions functions = {
.vkGetInstanceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr, .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, const VmaAllocatorCreateInfo allocator_info = {
.device = device, .physicalDevice = physical_device,
.pVulkanFunctions = &functions, .device = device,
.instance = instance, .pVulkanFunctions = &functions,
.vulkanApiVersion = VK_API_VERSION_1_1}; .instance = instance,
.vulkanApiVersion = VK_API_VERSION_1_1,
};
if (VkResult result = vmaCreateAllocator(&allocator_info, &allocator); result != VK_SUCCESS) { if (VkResult result = vmaCreateAllocator(&allocator_info, &allocator); result != VK_SUCCESS) {
LOG_CRITICAL(Render_Vulkan, "Failed to initialize VMA with error {}", result); LOG_CRITICAL(Render_Vulkan, "Failed to initialize VMA with error {}", result);

View File

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

View File

@@ -4,10 +4,10 @@
#pragma once #pragma once
#include <atomic> #include <atomic>
#include <limits>
#include <deque> #include <deque>
#include <vector> #include <limits>
#include <thread> #include <thread>
#include <vector>
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/renderer_vulkan/vk_common.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) { vk::Format ToVkAttributeFormat(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
constexpr std::array attribute_formats = { static constexpr std::array attribute_formats = {
std::array{vk::Format::eR8Sint, vk::Format::eR8G8Sint, vk::Format::eR8G8B8Sint, std::array{
vk::Format::eR8G8B8A8Sint}, vk::Format::eR8Sint,
std::array{vk::Format::eR8Uint, vk::Format::eR8G8Uint, vk::Format::eR8G8B8Uint, vk::Format::eR8G8Sint,
vk::Format::eR8G8B8A8Uint}, vk::Format::eR8G8B8Sint,
std::array{vk::Format::eR16Sint, vk::Format::eR16G16Sint, vk::Format::eR16G16B16Sint, vk::Format::eR8G8B8A8Sint,
vk::Format::eR16G16B16A16Sint}, },
std::array{vk::Format::eR32Sfloat, vk::Format::eR32G32Sfloat, vk::Format::eR32G32B32Sfloat, std::array{
vk::Format::eR32G32B32A32Sfloat}}; 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); ASSERT(size <= 4);
return attribute_formats[static_cast<u32>(format)][size - 1]; 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(), const std::string cache_file_path = fmt::format("{}{:x}{:x}.bin", GetPipelineCacheDir(),
instance.GetVendorID(), instance.GetDeviceID()); 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; std::vector<u8> cache_data;
FileUtil::IOFile cache_file{cache_file_path, "r"}; 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) { void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view) {
const vk::DescriptorImageInfo image_info = { 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}); desc_manager.SetBinding(1, binding, DescriptorData{image_info});
} }
void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) { void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) {
const vk::DescriptorImageInfo image_info = {.imageView = image_view, const vk::DescriptorImageInfo image_info = {
.imageLayout = vk::ImageLayout::eGeneral}; .imageView = image_view,
.imageLayout = vk::ImageLayout::eGeneral,
};
desc_manager.SetBinding(3, binding, DescriptorData{image_info}); desc_manager.SetBinding(3, binding, DescriptorData{image_info});
} }
void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) { void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) {
const DescriptorData data = { 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); desc_manager.SetBinding(0, binding, data);
} }
void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) { 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); desc_manager.SetBinding(0, binding, data);
} }
void PipelineCache::BindSampler(u32 binding, vk::Sampler sampler) { 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); desc_manager.SetBinding(2, binding, data);
} }
@@ -411,18 +448,21 @@ void PipelineCache::ApplyDynamic(const PipelineInfo& info) {
} }
vk::Pipeline PipelineCache::BuildPipeline(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; u32 shader_count = 0;
std::array<vk::PipelineShaderStageCreateInfo, MAX_SHADER_STAGES> shader_stages; std::array<vk::PipelineShaderStageCreateInfo, MAX_SHADER_STAGES> shader_stages;
for (std::size_t i = 0; i < current_shaders.size(); i++) { 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) { if (!shader) {
continue; continue;
} }
shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{ 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, .binding = binding.binding,
.stride = binding.stride, .stride = binding.stride,
.inputRate = binding.fixed.Value() ? vk::VertexInputRate::eInstance .inputRate = binding.fixed.Value() ? vk::VertexInputRate::eInstance
: vk::VertexInputRate::eVertex}; : vk::VertexInputRate::eVertex,
};
} }
u32 emulated_attrib_count = 0; u32 emulated_attrib_count = 0;
@@ -453,7 +494,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.location = attrib.location, .location = attrib.location,
.binding = attrib.binding, .binding = attrib.binding,
.format = is_supported ? format : ToVkAttributeFormat(attrib.type, 2), .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 // 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 // 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, .location = location,
.binding = attrib.binding, .binding = attrib.binding,
.format = ToVkAttributeFormat(attrib.type, 1), .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(), .pVertexBindingDescriptions = bindings.data(),
.vertexAttributeDescriptionCount = .vertexAttributeDescriptionCount =
info.vertex_layout.attribute_count + emulated_attrib_count, info.vertex_layout.attribute_count + emulated_attrib_count,
.pVertexAttributeDescriptions = attributes.data()}; .pVertexAttributeDescriptions = attributes.data(),
};
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = { const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
.topology = PicaToVK::PrimitiveTopology(info.rasterization.topology), .topology = PicaToVK::PrimitiveTopology(info.rasterization.topology),
.primitiveRestartEnable = false}; .primitiveRestartEnable = false,
};
const vk::PipelineRasterizationStateCreateInfo raster_state = { const vk::PipelineRasterizationStateCreateInfo raster_state = {
.depthClampEnable = false, .depthClampEnable = false,
@@ -487,10 +532,13 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.cullMode = PicaToVK::CullMode(info.rasterization.cull_mode), .cullMode = PicaToVK::CullMode(info.rasterization.cull_mode),
.frontFace = PicaToVK::FrontFace(info.rasterization.cull_mode), .frontFace = PicaToVK::FrontFace(info.rasterization.cull_mode),
.depthBiasEnable = false, .depthBiasEnable = false,
.lineWidth = 1.0f}; .lineWidth = 1.0f,
};
const vk::PipelineMultisampleStateCreateInfo multisampling = { const vk::PipelineMultisampleStateCreateInfo multisampling = {
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false}; .rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
const vk::PipelineColorBlendAttachmentState colorblend_attachment = { const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
.blendEnable = info.blending.blend_enable.Value(), .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), .srcAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.src_alpha_blend_factor),
.dstAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.dst_alpha_blend_factor), .dstAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.dst_alpha_blend_factor),
.alphaBlendOp = PicaToVK::BlendEquation(info.blending.alpha_blend_eq), .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 = { const vk::PipelineColorBlendStateCreateInfo color_blending = {
.logicOpEnable = !info.blending.blend_enable.Value() && !instance.NeedsLogicOpEmulation(), .logicOpEnable = !info.blending.blend_enable.Value() && !instance.NeedsLogicOpEmulation(),
.logicOp = PicaToVK::LogicOp(info.blending.logic_op.Value()), .logicOp = PicaToVK::LogicOp(info.blending.logic_op.Value()),
.attachmentCount = 1, .attachmentCount = 1,
.pAttachments = &colorblend_attachment, .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 = { 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 = { const vk::PipelineViewportStateCreateInfo viewport_info = {
.viewportCount = 1, .viewportCount = 1,
@@ -542,13 +601,15 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
const vk::PipelineDynamicStateCreateInfo dynamic_info = { const vk::PipelineDynamicStateCreateInfo dynamic_info = {
.dynamicStateCount = extended_dynamic_states ? static_cast<u32>(dynamic_states.size()) : 6u, .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 = { const vk::StencilOpState stencil_op_state = {
.failOp = PicaToVK::StencilOp(info.depth_stencil.stencil_fail_op), .failOp = PicaToVK::StencilOp(info.depth_stencil.stencil_fail_op),
.passOp = PicaToVK::StencilOp(info.depth_stencil.stencil_pass_op), .passOp = PicaToVK::StencilOp(info.depth_stencil.stencil_pass_op),
.depthFailOp = PicaToVK::StencilOp(info.depth_stencil.stencil_depth_fail_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 = { const vk::PipelineDepthStencilStateCreateInfo depth_info = {
.depthTestEnable = static_cast<u32>(info.depth_stencil.depth_test_enable.Value()), .depthTestEnable = static_cast<u32>(info.depth_stencil.depth_test_enable.Value()),
@@ -557,7 +618,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.depthBoundsTestEnable = false, .depthBoundsTestEnable = false,
.stencilTestEnable = static_cast<u32>(info.depth_stencil.stencil_test_enable.Value()), .stencilTestEnable = static_cast<u32>(info.depth_stencil.stencil_test_enable.Value()),
.front = stencil_op_state, .front = stencil_op_state,
.back = stencil_op_state}; .back = stencil_op_state,
};
const vk::GraphicsPipelineCreateInfo pipeline_info = { const vk::GraphicsPipelineCreateInfo pipeline_info = {
.stageCount = shader_count, .stageCount = shader_count,
@@ -572,7 +634,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
.pDynamicState = &dynamic_info, .pDynamicState = &dynamic_info,
.layout = desc_manager.GetPipelineLayout(), .layout = desc_manager.GetPipelineLayout(),
.renderPass = .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); if (const auto result = device.createGraphicsPipeline(pipeline_cache, pipeline_info);
result.result == vk::Result::eSuccess) { 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 UNIFORM_BUFFER_SIZE = 16 * 1024 * 1024;
constexpr u32 TEXTURE_BUFFER_SIZE = 512 * 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, constexpr std::array TEXTURE_BUFFER_FORMATS = {
vk::Format::eR32G32B32A32Sfloat}; vk::Format::eR32G32Sfloat,
vk::Format::eR32G32B32A32Sfloat,
};
constexpr VideoCore::SurfaceParams NULL_PARAMS = {.width = 1, constexpr VideoCore::SurfaceParams NULL_PARAMS = {
.height = 1, .width = 1,
.stride = 1, .height = 1,
.texture_type = VideoCore::TextureType::Texture2D, .stride = 1,
.pixel_format = VideoCore::PixelFormat::RGBA8, .texture_type = VideoCore::TextureType::Texture2D,
.type = VideoCore::SurfaceType::Color}; .pixel_format = VideoCore::PixelFormat::RGBA8,
.type = VideoCore::SurfaceType::Color,
};
constexpr vk::ImageUsageFlags NULL_USAGE = vk::ImageUsageFlagBits::eSampled | constexpr vk::ImageUsageFlags NULL_USAGE = vk::ImageUsageFlagBits::eSampled |
vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferSrc |
@@ -85,7 +91,8 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan
.min_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear, .min_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
.mip_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear, .mip_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
.wrap_s = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder, .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); default_sampler = CreateSampler(default_sampler_info);
@@ -265,8 +272,8 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
SetupFixedAttribs(); SetupFixedAttribs();
// Bind the generated bindings // Bind the generated bindings
scheduler.Record([this, vertex_offsets = binding_offsets]( scheduler.Record([this, vertex_offsets = binding_offsets](vk::CommandBuffer render_cmdbuf,
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { vk::CommandBuffer) {
render_cmdbuf.bindVertexBuffers(0, vertex_buffers, vertex_offsets); render_cmdbuf.bindVertexBuffers(0, vertex_buffers, vertex_offsets);
}); });
} }
@@ -435,8 +442,8 @@ void RasterizerVulkan::SetupIndexArray() {
index_buffer.Commit(index_buffer_size); index_buffer.Commit(index_buffer_size);
scheduler.Record([this, index_offset = index_offset, index_type = index_type]( scheduler.Record([this, index_offset = index_offset,
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { index_type = index_type](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
render_cmdbuf.bindIndexBuffer(index_buffer.GetHandle(), index_offset, index_type); 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 // nothing. Always sample from the base level until mipmaps for texture cubes are
// implemented // implemented
const bool skip_mipmap = config.type == Pica::TexturingRegs::TextureConfig::TextureCube; const bool skip_mipmap = config.type == Pica::TexturingRegs::TextureConfig::TextureCube;
info = SamplerInfo{.mag_filter = config.mag_filter, info = SamplerInfo{
.min_filter = config.min_filter, .mag_filter = config.mag_filter,
.mip_filter = config.mip_filter, .min_filter = config.min_filter,
.wrap_s = config.wrap_s, .mip_filter = config.mip_filter,
.wrap_t = config.wrap_t, .wrap_s = config.wrap_s,
.border_color = config.border_color.raw, .wrap_t = config.wrap_t,
.lod_min = skip_mipmap ? 0.f : static_cast<float>(config.lod.min_level), .border_color = config.border_color.raw,
.lod_max = skip_mipmap ? 0.f : static_cast<float>(config.lod.max_level), .lod_min = skip_mipmap ? 0.f : static_cast<float>(config.lod.min_level),
.lod_bias = static_cast<float>(config.lod.bias)}; .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 // Search the cache and bind the appropriate sampler
if (auto it = samplers.find(info); it != samplers.end()) { 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, .renderpass = renderpass_cache.GetRenderpass(pipeline_info.color_attachment,
pipeline_info.depth_attachment, false), pipeline_info.depth_attachment, false),
.width = width, .width = width,
.height = height}; .height = height,
};
auto [it, new_framebuffer] = framebuffers.try_emplace(framebuffer_info, vk::Framebuffer{}); auto [it, new_framebuffer] = framebuffers.try_emplace(framebuffer_info, vk::Framebuffer{});
if (new_framebuffer) { if (new_framebuffer) {
@@ -721,9 +731,11 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
const RenderpassState renderpass_info = { const RenderpassState renderpass_info = {
.renderpass = framebuffer_info.renderpass, .renderpass = framebuffer_info.renderpass,
.framebuffer = it->second, .framebuffer = it->second,
.render_area = vk::Rect2D{.offset = {static_cast<s32>(draw_rect.left), .render_area =
static_cast<s32>(draw_rect.bottom)}, vk::Rect2D{
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()}}, .offset = {static_cast<s32>(draw_rect.left), static_cast<s32>(draw_rect.bottom)},
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()},
},
.clear = {}, .clear = {},
}; };
@@ -1086,8 +1098,11 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
const auto color = PicaToVK::ColorRGBA8(info.border_color); const auto color = PicaToVK::ColorRGBA8(info.border_color);
const vk::SamplerCustomBorderColorCreateInfoEXT border_color_info = { const vk::SamplerCustomBorderColorCreateInfoEXT border_color_info = {
.customBorderColor = .customBorderColor =
vk::ClearColorValue{.float32 = std::array{color[0], color[1], color[2], color[3]}}, vk::ClearColorValue{
.format = vk::Format::eUndefined}; .float32 = std::array{color[0], color[1], color[2], color[3]},
},
.format = vk::Format::eUndefined,
};
const vk::SamplerCreateInfo sampler_info = { const vk::SamplerCreateInfo sampler_info = {
.pNext = use_border_color ? &border_color_info : nullptr, .pNext = use_border_color ? &border_color_info : nullptr,
@@ -1105,7 +1120,8 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
.maxLod = info.lod_max, .maxLod = info.lod_max,
.borderColor = .borderColor =
use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack, use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack,
.unnormalizedCoordinates = false}; .unnormalizedCoordinates = false,
};
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
return device.createSampler(sampler_info); return device.createSampler(sampler_info);
@@ -1123,12 +1139,14 @@ vk::Framebuffer RasterizerVulkan::CreateFramebuffer(const FramebufferInfo& info)
attachments[attachment_count++] = info.depth; attachments[attachment_count++] = info.depth;
} }
const vk::FramebufferCreateInfo framebuffer_info = {.renderPass = info.renderpass, const vk::FramebufferCreateInfo framebuffer_info = {
.attachmentCount = attachment_count, .renderPass = info.renderpass,
.pAttachments = attachments.data(), .attachmentCount = attachment_count,
.width = info.width, .pAttachments = attachments.data(),
.height = info.height, .width = info.width,
.layers = 1}; .height = info.height,
.layers = 1,
};
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
return device.createFramebuffer(framebuffer_info); return device.createFramebuffer(framebuffer_info);

View File

@@ -61,12 +61,12 @@ RenderpassCache::RenderpassCache(const Instance& instance, Scheduler& scheduler)
continue; continue;
} }
cached_renderpasses[color][depth][0] = CreateRenderPass( cached_renderpasses[color][depth][0] =
color_format, depth_format, vk::AttachmentLoadOp::eLoad, CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eLoad,
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
cached_renderpasses[color][depth][1] = CreateRenderPass( cached_renderpasses[color][depth][1] =
color_format, depth_format, vk::AttachmentLoadOp::eClear, CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eClear,
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
} }
} }
} }
@@ -100,11 +100,13 @@ void RenderpassCache::EnterRenderpass(const RenderpassState& state) {
render_cmdbuf.endRenderPass(); render_cmdbuf.endRenderPass();
} }
const vk::RenderPassBeginInfo renderpass_begin_info = {.renderPass = state.renderpass, const vk::RenderPassBeginInfo renderpass_begin_info = {
.framebuffer = state.framebuffer, .renderPass = state.renderpass,
.renderArea = state.render_area, .framebuffer = state.framebuffer,
.clearValueCount = 1, .renderArea = state.render_area,
.pClearValues = &state.clear}; .clearValueCount = 1,
.pClearValues = &state.clear,
};
render_cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline); 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{}; vk::AttachmentReference depth_attachment_ref{};
if (color != vk::Format::eUndefined) { if (color != vk::Format::eUndefined) {
attachments[attachment_count] = attachments[attachment_count] = vk::AttachmentDescription{
vk::AttachmentDescription{.format = color, .format = color,
.loadOp = load_op, .loadOp = load_op,
.storeOp = vk::AttachmentStoreOp::eStore, .storeOp = vk::AttachmentStoreOp::eStore,
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare, .stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare, .stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
.initialLayout = initial_layout, .initialLayout = initial_layout,
.finalLayout = final_layout}; .finalLayout = final_layout,
};
color_attachment_ref = vk::AttachmentReference{ color_attachment_ref = vk::AttachmentReference{
.attachment = attachment_count++, .layout = vk::ImageLayout::eGeneral}; .attachment = attachment_count++,
.layout = vk::ImageLayout::eGeneral,
};
use_color = true; use_color = true;
} }
@@ -183,34 +188,38 @@ vk::RenderPass RenderpassCache::CreateRenderPass(vk::Format color, vk::Format de
.stencilLoadOp = load_op, .stencilLoadOp = load_op,
.stencilStoreOp = vk::AttachmentStoreOp::eStore, .stencilStoreOp = vk::AttachmentStoreOp::eStore,
.initialLayout = vk::ImageLayout::eGeneral, .initialLayout = vk::ImageLayout::eGeneral,
.finalLayout = vk::ImageLayout::eGeneral}; .finalLayout = vk::ImageLayout::eGeneral,
};
depth_attachment_ref = depth_attachment_ref = vk::AttachmentReference{
vk::AttachmentReference{.attachment = attachment_count++, .attachment = attachment_count++,
.layout = vk::ImageLayout::eGeneral}; .layout = vk::ImageLayout::eGeneral,
};
use_depth = true; use_depth = true;
} }
// We also require only one subpass // We also require only one subpass
const vk::SubpassDescription subpass = {.pipelineBindPoint = vk::PipelineBindPoint::eGraphics, const vk::SubpassDescription subpass = {
.inputAttachmentCount = 0, .pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
.pInputAttachments = nullptr, .inputAttachmentCount = 0,
.colorAttachmentCount = use_color ? 1u : 0u, .pInputAttachments = nullptr,
.pColorAttachments = &color_attachment_ref, .colorAttachmentCount = use_color ? 1u : 0u,
.pResolveAttachments = 0, .pColorAttachments = &color_attachment_ref,
.pDepthStencilAttachment = .pResolveAttachments = 0,
use_depth ? &depth_attachment_ref : nullptr}; .pDepthStencilAttachment = use_depth ? &depth_attachment_ref : nullptr,
};
const vk::RenderPassCreateInfo renderpass_info = {.attachmentCount = attachment_count, const vk::RenderPassCreateInfo renderpass_info = {
.pAttachments = attachments.data(), .attachmentCount = attachment_count,
.subpassCount = 1, .pAttachments = attachments.data(),
.pSubpasses = &subpass, .subpassCount = 1,
.dependencyCount = 0, .pSubpasses = &subpass,
.pDependencies = nullptr}; .dependencyCount = 0,
.pDependencies = nullptr,
};
// Create the renderpass const vk::Device device = instance.GetDevice();
vk::Device device = instance.GetDevice();
return device.createRenderPass(renderpass_info); 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 = { const vk::CommandPoolCreateInfo pool_create_info = {
.flags = vk::CommandPoolCreateFlagBits::eTransient | .flags = vk::CommandPoolCreateFlagBits::eTransient |
vk::CommandPoolCreateFlagBits::eResetCommandBuffer, vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
.queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex()}; .queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex(),
};
vk::Device device = instance.GetDevice(); vk::Device device = instance.GetDevice();
pool.handle = device.createCommandPool(pool_create_info); 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 = { const vk::CommandBufferAllocateInfo buffer_alloc_info = {
.commandPool = pool.handle, .commandPool = pool.handle,
.level = vk::CommandBufferLevel::ePrimary, .level = vk::CommandBufferLevel::ePrimary,
.commandBufferCount = COMMAND_BUFFER_POOL_SIZE}; .commandBufferCount = COMMAND_BUFFER_POOL_SIZE,
};
auto buffers = device.allocateCommandBuffers(buffer_alloc_info); auto buffers = device.allocateCommandBuffers(buffer_alloc_info);
std::copy(buffers.begin(), buffers.end(), pool.cmdbufs.begin()); 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(); vk::DescriptorPool& pool = pools.emplace_back();
// Choose a sane pool size good for most games // Choose a sane pool size good for most games
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = { static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {{
{{vk::DescriptorType::eUniformBuffer, 4096}, {vk::DescriptorType::eUniformBuffer, 4096},
{vk::DescriptorType::eSampledImage, 4096}, {vk::DescriptorType::eSampledImage, 4096},
{vk::DescriptorType::eSampler, 4096}, {vk::DescriptorType::eSampler, 4096},
{vk::DescriptorType::eUniformTexelBuffer, 2048}, {vk::DescriptorType::eUniformTexelBuffer, 2048},
{vk::DescriptorType::eStorageImage, 1024}}}; {vk::DescriptorType::eStorageImage, 1024},
}};
const vk::DescriptorPoolCreateInfo descriptor_pool_info = { const vk::DescriptorPoolCreateInfo descriptor_pool_info = {
.maxSets = 8192, .maxSets = 8192,
.poolSizeCount = static_cast<u32>(pool_sizes.size()), .poolSizeCount = static_cast<u32>(pool_sizes.size()),
.pPoolSizes = pool_sizes.data()}; .pPoolSizes = pool_sizes.data(),
};
pool = instance.GetDevice().createDescriptorPool(descriptor_pool_info); 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(); renderer.FlushBuffers();
renderpass_cache.ExitRenderpass(); renderpass_cache.ExitRenderpass();
Record([signal_semaphore, wait_semaphore, Record([signal_semaphore, wait_semaphore, handle, signal_value,
handle, signal_value, this](vk::CommandBuffer render_cmdbuf, this](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer upload_cmdbuf) {
vk::CommandBuffer upload_cmdbuf) {
MICROPROFILE_SCOPE(Vulkan_Submit); MICROPROFILE_SCOPE(Vulkan_Submit);
upload_cmdbuf.end(); upload_cmdbuf.end();
render_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); 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 slot = static_cast<u32>(slot_semantic);
const u32 attrib = config.semantic_maps[slot].attribute_index; const u32 attrib = config.semantic_maps[slot].attribute_index;
const u32 comp = config.semantic_maps[slot].component_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 += " normquat = GetVertexQuaternion();\n";
out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " + out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " +
semantic(VSOutputAttributes::COLOR_G) + ", " + semantic(VSOutputAttributes::COLOR_B) + semantic(VSOutputAttributes::COLOR_G) + ", " +
", " + semantic(VSOutputAttributes::COLOR_A) + ");\n"; semantic(VSOutputAttributes::COLOR_B) + ", " +
semantic(VSOutputAttributes::COLOR_A) + ");\n";
out += " primary_color = min(abs(vtx_color), vec4(1.0));\n\n"; out += " primary_color = min(abs(vtx_color), vec4(1.0));\n\n";
out += " texcoord0 = vec2(" + semantic(VSOutputAttributes::TEXCOORD0_U) + ", " + out += " texcoord0 = vec2(" + semantic(VSOutputAttributes::TEXCOORD0_U) + ", " +

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff