renderer_vulkan: Properly format structs
This commit is contained in:
@@ -118,7 +118,8 @@ void Config::ReadValues() {
|
||||
static_cast<Settings::GraphicsAPI>(sdl2_config->GetInteger("Renderer", "graphics_api", 2));
|
||||
Settings::values.async_command_recording =
|
||||
sdl2_config->GetBoolean("Renderer", "async_command_recording", true);
|
||||
Settings::values.spirv_shader_gen = sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
|
||||
Settings::values.spirv_shader_gen =
|
||||
sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
|
||||
Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "renderer_debug", false);
|
||||
Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true);
|
||||
Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true);
|
||||
|
@@ -19,13 +19,13 @@
|
||||
|
||||
static bool IsPortraitMode() {
|
||||
return JNI_FALSE != IDCache::GetEnvForThread()->CallStaticBooleanMethod(
|
||||
IDCache::GetNativeLibraryClass(), IDCache::GetIsPortraitMode());
|
||||
IDCache::GetNativeLibraryClass(), IDCache::GetIsPortraitMode());
|
||||
}
|
||||
|
||||
static void UpdateLandscapeScreenLayout() {
|
||||
Settings::values.layout_option =
|
||||
static_cast<Settings::LayoutOption>(IDCache::GetEnvForThread()->CallStaticIntMethod(
|
||||
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
|
||||
static_cast<Settings::LayoutOption>(IDCache::GetEnvForThread()->CallStaticIntMethod(
|
||||
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
|
||||
}
|
||||
|
||||
void EmuWindow_Android_Vulkan::OnSurfaceChanged(ANativeWindow* surface) {
|
||||
|
@@ -167,7 +167,8 @@ void RendererVulkan::PrepareRendertarget() {
|
||||
LCD::Read(color_fill.raw, lcd_color_addr);
|
||||
|
||||
if (color_fill.is_enabled) {
|
||||
LoadColorToActiveVkTexture(color_fill.color_r, color_fill.color_g, color_fill.color_b, screen_infos[i].texture);
|
||||
LoadColorToActiveVkTexture(color_fill.color_r, color_fill.color_g, color_fill.color_b,
|
||||
screen_infos[i].texture);
|
||||
} else {
|
||||
TextureInfo& texture = screen_infos[i].texture;
|
||||
if (texture.width != framebuffer.width || texture.height != framebuffer.height ||
|
||||
@@ -197,7 +198,8 @@ void RendererVulkan::BeginRendering() {
|
||||
present_textures[i] = vk::DescriptorImageInfo{
|
||||
.imageView = info.display_texture ? info.display_texture->image_view
|
||||
: info.texture.alloc.image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral};
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
}
|
||||
|
||||
present_textures[3] = vk::DescriptorImageInfo{.sampler = present_samplers[current_sampler]};
|
||||
@@ -295,41 +297,53 @@ void RendererVulkan::CompileShaders() {
|
||||
|
||||
void RendererVulkan::BuildLayouts() {
|
||||
const std::array present_layout_bindings = {
|
||||
vk::DescriptorSetLayoutBinding{.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 3,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment},
|
||||
vk::DescriptorSetLayoutBinding{.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment}};
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 3,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||
},
|
||||
};
|
||||
|
||||
const vk::DescriptorSetLayoutCreateInfo present_layout_info = {
|
||||
.bindingCount = static_cast<u32>(present_layout_bindings.size()),
|
||||
.pBindings = present_layout_bindings.data()};
|
||||
.pBindings = present_layout_bindings.data(),
|
||||
};
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info);
|
||||
|
||||
const std::array update_template_entries = {
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 3,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo)},
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
.offset = 3 * sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0}};
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 3,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo),
|
||||
},
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
.offset = 3 * sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0,
|
||||
},
|
||||
};
|
||||
|
||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||
.descriptorSetLayout = present_descriptor_layout};
|
||||
.descriptorSetLayout = present_descriptor_layout,
|
||||
};
|
||||
|
||||
present_update_template = device.createDescriptorUpdateTemplate(template_info);
|
||||
|
||||
@@ -339,37 +353,49 @@ void RendererVulkan::BuildLayouts() {
|
||||
.size = sizeof(PresentUniformData),
|
||||
};
|
||||
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
|
||||
.pSetLayouts = &present_descriptor_layout,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &push_range};
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &present_descriptor_layout,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &push_range,
|
||||
};
|
||||
|
||||
present_pipeline_layout = device.createPipelineLayout(layout_info);
|
||||
}
|
||||
|
||||
void RendererVulkan::BuildPipelines() {
|
||||
const vk::VertexInputBindingDescription binding = {.binding = 0,
|
||||
.stride = sizeof(ScreenRectVertex),
|
||||
.inputRate = vk::VertexInputRate::eVertex};
|
||||
const vk::VertexInputBindingDescription binding = {
|
||||
.binding = 0,
|
||||
.stride = sizeof(ScreenRectVertex),
|
||||
.inputRate = vk::VertexInputRate::eVertex,
|
||||
};
|
||||
|
||||
const std::array attributes = {
|
||||
vk::VertexInputAttributeDescription{.location = 0,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32Sfloat,
|
||||
.offset = offsetof(ScreenRectVertex, position)},
|
||||
vk::VertexInputAttributeDescription{.location = 1,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32Sfloat,
|
||||
.offset = offsetof(ScreenRectVertex, tex_coord)}};
|
||||
vk::VertexInputAttributeDescription{
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32Sfloat,
|
||||
.offset = offsetof(ScreenRectVertex, position),
|
||||
},
|
||||
vk::VertexInputAttributeDescription{
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32Sfloat,
|
||||
.offset = offsetof(ScreenRectVertex, tex_coord),
|
||||
},
|
||||
};
|
||||
|
||||
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
|
||||
.vertexBindingDescriptionCount = 1,
|
||||
.pVertexBindingDescriptions = &binding,
|
||||
.vertexAttributeDescriptionCount = static_cast<u32>(attributes.size()),
|
||||
.pVertexAttributeDescriptions = attributes.data()};
|
||||
.pVertexAttributeDescriptions = attributes.data(),
|
||||
};
|
||||
|
||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||
.topology = vk::PrimitiveTopology::eTriangleStrip, .primitiveRestartEnable = false};
|
||||
.topology = vk::PrimitiveTopology::eTriangleStrip,
|
||||
.primitiveRestartEnable = false,
|
||||
};
|
||||
|
||||
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
||||
.depthClampEnable = false,
|
||||
@@ -377,21 +403,26 @@ void RendererVulkan::BuildPipelines() {
|
||||
.cullMode = vk::CullModeFlagBits::eNone,
|
||||
.frontFace = vk::FrontFace::eClockwise,
|
||||
.depthBiasEnable = false,
|
||||
.lineWidth = 1.0f};
|
||||
.lineWidth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
||||
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false};
|
||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||
.sampleShadingEnable = false,
|
||||
};
|
||||
|
||||
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
||||
.blendEnable = false,
|
||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
||||
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA};
|
||||
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||
};
|
||||
|
||||
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
||||
.logicOpEnable = false,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &colorblend_attachment,
|
||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f}};
|
||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
||||
};
|
||||
|
||||
const vk::Viewport placeholder_viewport = vk::Viewport{0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
|
||||
const vk::Rect2D placeholder_scissor = vk::Rect2D{{0, 0}, {1, 1}};
|
||||
@@ -402,27 +433,36 @@ void RendererVulkan::BuildPipelines() {
|
||||
.pScissors = &placeholder_scissor,
|
||||
};
|
||||
|
||||
const std::array dynamic_states = {vk::DynamicState::eViewport, vk::DynamicState::eScissor};
|
||||
const std::array dynamic_states = {
|
||||
vk::DynamicState::eViewport,
|
||||
vk::DynamicState::eScissor,
|
||||
};
|
||||
|
||||
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
|
||||
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
|
||||
.pDynamicStates = dynamic_states.data()};
|
||||
.pDynamicStates = dynamic_states.data(),
|
||||
};
|
||||
|
||||
const vk::PipelineDepthStencilStateCreateInfo depth_info = {.depthTestEnable = false,
|
||||
.depthWriteEnable = false,
|
||||
.depthCompareOp =
|
||||
vk::CompareOp::eAlways,
|
||||
.depthBoundsTestEnable = false,
|
||||
.stencilTestEnable = false};
|
||||
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
|
||||
.depthTestEnable = false,
|
||||
.depthWriteEnable = false,
|
||||
.depthCompareOp = vk::CompareOp::eAlways,
|
||||
.depthBoundsTestEnable = false,
|
||||
.stencilTestEnable = false,
|
||||
};
|
||||
|
||||
for (u32 i = 0; i < PRESENT_PIPELINES; i++) {
|
||||
const std::array shader_stages = {
|
||||
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eVertex,
|
||||
.module = present_vertex_shader,
|
||||
.pName = "main"},
|
||||
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eFragment,
|
||||
.module = present_shaders[i],
|
||||
.pName = "main"},
|
||||
vk::PipelineShaderStageCreateInfo{
|
||||
.stage = vk::ShaderStageFlagBits::eVertex,
|
||||
.module = present_vertex_shader,
|
||||
.pName = "main",
|
||||
},
|
||||
vk::PipelineShaderStageCreateInfo{
|
||||
.stage = vk::ShaderStageFlagBits::eFragment,
|
||||
.module = present_shaders[i],
|
||||
.pName = "main",
|
||||
},
|
||||
};
|
||||
|
||||
const vk::GraphicsPipelineCreateInfo pipeline_info = {
|
||||
@@ -437,7 +477,8 @@ void RendererVulkan::BuildPipelines() {
|
||||
.pColorBlendState = &color_blending,
|
||||
.pDynamicState = &dynamic_info,
|
||||
.layout = present_pipeline_layout,
|
||||
.renderPass = renderpass_cache.GetPresentRenderpass()};
|
||||
.renderPass = renderpass_cache.GetPresentRenderpass(),
|
||||
};
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
if (const auto result = device.createGraphicsPipeline({}, pipeline_info);
|
||||
@@ -453,67 +494,80 @@ void RendererVulkan::BuildPipelines() {
|
||||
void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture,
|
||||
const GPU::Regs::FramebufferConfig& framebuffer) {
|
||||
TextureInfo old_texture = std::move(texture);
|
||||
texture = TextureInfo{.alloc = runtime.Allocate(
|
||||
framebuffer.width, framebuffer.height,
|
||||
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format),
|
||||
VideoCore::TextureType::Texture2D),
|
||||
.width = framebuffer.width,
|
||||
.height = framebuffer.height,
|
||||
.format = framebuffer.color_format};
|
||||
texture = TextureInfo{
|
||||
.alloc =
|
||||
runtime.Allocate(framebuffer.width, framebuffer.height,
|
||||
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format),
|
||||
VideoCore::TextureType::Texture2D),
|
||||
.width = framebuffer.width,
|
||||
.height = framebuffer.height,
|
||||
.format = framebuffer.color_format,
|
||||
};
|
||||
|
||||
// Recyle the old texture after allocation to avoid having duplicates of the same allocation in
|
||||
// the recycler
|
||||
if (old_texture.width != 0 && old_texture.height != 0) {
|
||||
const HostTextureTag tag = {.format = old_texture.alloc.format,
|
||||
.width = old_texture.width,
|
||||
.height = old_texture.height};
|
||||
const HostTextureTag tag = {
|
||||
.format = old_texture.alloc.format,
|
||||
.width = old_texture.width,
|
||||
.height = old_texture.height,
|
||||
};
|
||||
|
||||
runtime.Recycle(tag, std::move(old_texture.alloc));
|
||||
}
|
||||
}
|
||||
|
||||
void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture) {
|
||||
void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b,
|
||||
const TextureInfo& texture) {
|
||||
const vk::ClearColorValue clear_color = {
|
||||
.float32 = std::array{color_r / 255.0f, color_g / 255.0f, color_b / 255.0f, 1.0f}};
|
||||
.float32 =
|
||||
std::array{
|
||||
color_r / 255.0f,
|
||||
color_g / 255.0f,
|
||||
color_b / 255.0f,
|
||||
1.0f,
|
||||
},
|
||||
};
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
scheduler.Record([image = texture.alloc.image,
|
||||
clear_color](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
const vk::ImageSubresourceRange range = {.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS};
|
||||
scheduler.Record([image = texture.alloc.image, clear_color](vk::CommandBuffer render_cmdbuf,
|
||||
vk::CommandBuffer) {
|
||||
const vk::ImageSubresourceRange range = {
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
};
|
||||
|
||||
const vk::ImageMemoryBarrier pre_barrier = {
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead |
|
||||
vk::AccessFlagBits::eTransferRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange = range
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange = range,
|
||||
};
|
||||
|
||||
const vk::ImageMemoryBarrier post_barrier = {
|
||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead |
|
||||
vk::AccessFlagBits::eTransferRead,
|
||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange = range
|
||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
|
||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange = range,
|
||||
};
|
||||
|
||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||
vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
|
||||
|
||||
render_cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear_color, range);
|
||||
render_cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear_color,
|
||||
range);
|
||||
|
||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::PipelineStageFlagBits::eAllCommands,
|
||||
@@ -873,14 +927,19 @@ void RendererVulkan::SwapBuffers() {
|
||||
} while (swapchain.NeedsRecreation());
|
||||
|
||||
scheduler.Record([layout](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
const vk::Viewport viewport = {.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(layout.width),
|
||||
.height = static_cast<float>(layout.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f};
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(layout.width),
|
||||
.height = static_cast<float>(layout.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::Rect2D scissor = {.offset = {0, 0}, .extent = {layout.width, layout.height}};
|
||||
const vk::Rect2D scissor = {
|
||||
.offset = {0, 0},
|
||||
.extent = {layout.width, layout.height},
|
||||
};
|
||||
|
||||
render_cmdbuf.setViewport(0, viewport);
|
||||
render_cmdbuf.setScissor(0, scissor);
|
||||
@@ -888,20 +947,6 @@ void RendererVulkan::SwapBuffers() {
|
||||
|
||||
DrawScreens(layout, false);
|
||||
|
||||
/*renderpass_cache.ExitRenderpass();
|
||||
|
||||
scheduler.Record([](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
const vk::MemoryBarrier memory_write_barrier = {
|
||||
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
|
||||
};
|
||||
|
||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||
vk::PipelineStageFlagBits::eAllCommands,
|
||||
vk::DependencyFlagBits::eByRegion,
|
||||
memory_write_barrier, {}, {});
|
||||
});*/
|
||||
|
||||
const vk::Semaphore image_acquired = swapchain.GetImageAcquiredSemaphore();
|
||||
const vk::Semaphore present_ready = swapchain.GetPresentReadySemaphore();
|
||||
scheduler.Flush(present_ready, image_acquired);
|
||||
|
@@ -6,15 +6,16 @@
|
||||
#include "video_core/renderer_vulkan/vk_blit_helper.h"
|
||||
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler, DescriptorManager& desc_manager)
|
||||
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} {
|
||||
BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler,
|
||||
DescriptorManager& desc_manager)
|
||||
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} {
|
||||
constexpr std::string_view cs_source = R"(
|
||||
#version 450 core
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
@@ -36,77 +37,100 @@ imageStore(color, dst_coord, uvec4(value));
|
||||
}
|
||||
)";
|
||||
compute_shader =
|
||||
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
||||
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
||||
|
||||
const std::array compute_layout_bindings = {
|
||||
vk::DescriptorSetLayoutBinding{.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
||||
vk::DescriptorSetLayoutBinding{.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
||||
vk::DescriptorSetLayoutBinding{.binding = 2,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute}};
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 2,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
},
|
||||
};
|
||||
|
||||
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
|
||||
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
||||
.pBindings = compute_layout_bindings.data()};
|
||||
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
||||
.pBindings = compute_layout_bindings.data(),
|
||||
};
|
||||
|
||||
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
|
||||
|
||||
const std::array update_template_entries = {
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo)},
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0},
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0}};
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo),
|
||||
},
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0,
|
||||
},
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 2,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0,
|
||||
},
|
||||
};
|
||||
|
||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||
.descriptorSetLayout = descriptor_layout};
|
||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||
.descriptorSetLayout = descriptor_layout,
|
||||
};
|
||||
|
||||
update_template = device.createDescriptorUpdateTemplate(template_info);
|
||||
|
||||
const vk::PushConstantRange push_range = {
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
.offset = 0,
|
||||
.size = sizeof(Common::Vec2i),
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
.offset = 0,
|
||||
.size = sizeof(Common::Vec2i),
|
||||
};
|
||||
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
|
||||
.pSetLayouts = &descriptor_layout,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &push_range};
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &descriptor_layout,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &push_range,
|
||||
};
|
||||
|
||||
compute_pipeline_layout = device.createPipelineLayout(layout_info);
|
||||
|
||||
const vk::PipelineShaderStageCreateInfo compute_stage = {
|
||||
.stage = vk::ShaderStageFlagBits::eCompute, .module = compute_shader, .pName = "main"};
|
||||
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||
.module = compute_shader,
|
||||
.pName = "main",
|
||||
};
|
||||
|
||||
const vk::ComputePipelineCreateInfo compute_info = {.stage = compute_stage,
|
||||
.layout = compute_pipeline_layout};
|
||||
const vk::ComputePipelineCreateInfo compute_info = {
|
||||
.stage = compute_stage,
|
||||
.layout = compute_pipeline_layout,
|
||||
};
|
||||
|
||||
if (const auto result = device.createComputePipeline({}, compute_info);
|
||||
result.result == vk::Result::eSuccess) {
|
||||
result.result == vk::Result::eSuccess) {
|
||||
compute_pipeline = result.value;
|
||||
} else {
|
||||
LOG_CRITICAL(Render_Vulkan, "D24S8 compute pipeline creation failed!");
|
||||
@@ -125,97 +149,103 @@ BlitHelper::~BlitHelper() {
|
||||
void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
||||
const VideoCore::TextureBlit& blit) {
|
||||
const std::array textures = {
|
||||
vk::DescriptorImageInfo{.imageView = source.GetDepthView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
||||
vk::DescriptorImageInfo{.imageView = source.GetStencilView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
||||
vk::DescriptorImageInfo{.imageView = dest.GetImageView(),
|
||||
.imageLayout = vk::ImageLayout::eGeneral}};
|
||||
vk::DescriptorImageInfo{
|
||||
.imageView = source.GetDepthView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
},
|
||||
vk::DescriptorImageInfo{
|
||||
.imageView = source.GetStencilView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
},
|
||||
vk::DescriptorImageInfo{
|
||||
.imageView = dest.GetImageView(),
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
},
|
||||
};
|
||||
|
||||
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
|
||||
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
|
||||
|
||||
scheduler.Record([this, set, blit,
|
||||
src_image = source.alloc.image,
|
||||
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
scheduler.Record([this, set, blit, src_image = source.alloc.image,
|
||||
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
|
||||
vk::CommandBuffer) {
|
||||
const std::array pre_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = src_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
||||
vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = src_image,
|
||||
.subresourceRange{
|
||||
.aspectMask =
|
||||
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eUndefined,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eUndefined,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
}};
|
||||
const std::array post_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = src_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
||||
vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = src_image,
|
||||
.subresourceRange{
|
||||
.aspectMask =
|
||||
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
}};
|
||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||
vk::PipelineStageFlagBits::eComputeShader,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
||||
|
||||
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout, 0, set, {});
|
||||
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout,
|
||||
0, set, {});
|
||||
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
|
||||
|
||||
const auto src_offset = Common::MakeVec(blit.src_rect.left, blit.src_rect.bottom);
|
||||
|
@@ -15,26 +15,57 @@ struct Bindings {
|
||||
};
|
||||
|
||||
constexpr static std::array RASTERIZER_SETS = {
|
||||
Bindings{// Utility set
|
||||
.bindings = {vk::DescriptorType::eUniformBuffer, vk::DescriptorType::eUniformBuffer,
|
||||
vk::DescriptorType::eUniformTexelBuffer,
|
||||
vk::DescriptorType::eUniformTexelBuffer,
|
||||
vk::DescriptorType::eUniformTexelBuffer},
|
||||
.binding_count = 5},
|
||||
Bindings{// Texture set
|
||||
.bindings = {vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage,
|
||||
vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage},
|
||||
.binding_count = 4},
|
||||
Bindings{// Sampler set
|
||||
.bindings = {vk::DescriptorType::eSampler, vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eSampler, vk::DescriptorType::eSampler},
|
||||
.binding_count = 4},
|
||||
Bindings{// Shadow set
|
||||
.bindings = {vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage},
|
||||
.binding_count = 4}};
|
||||
Bindings{
|
||||
// Utility set
|
||||
.bindings =
|
||||
{
|
||||
vk::DescriptorType::eUniformBuffer,
|
||||
vk::DescriptorType::eUniformBuffer,
|
||||
vk::DescriptorType::eUniformTexelBuffer,
|
||||
vk::DescriptorType::eUniformTexelBuffer,
|
||||
vk::DescriptorType::eUniformTexelBuffer,
|
||||
},
|
||||
.binding_count = 5,
|
||||
},
|
||||
Bindings{
|
||||
// Texture set
|
||||
.bindings =
|
||||
{
|
||||
vk::DescriptorType::eSampledImage,
|
||||
vk::DescriptorType::eSampledImage,
|
||||
vk::DescriptorType::eSampledImage,
|
||||
vk::DescriptorType::eSampledImage,
|
||||
},
|
||||
.binding_count = 4,
|
||||
},
|
||||
Bindings{
|
||||
// Sampler set
|
||||
.bindings =
|
||||
{
|
||||
vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eSampler,
|
||||
},
|
||||
.binding_count = 4,
|
||||
},
|
||||
Bindings{
|
||||
// Shadow set
|
||||
.bindings =
|
||||
{
|
||||
vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage,
|
||||
vk::DescriptorType::eStorageImage,
|
||||
},
|
||||
.binding_count = 4, // TODO: Combine cube faces to a single storage image
|
||||
// some android devices only expose up to four storage
|
||||
// slots per pipeline
|
||||
},
|
||||
};
|
||||
|
||||
constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) {
|
||||
vk::ShaderStageFlags flags;
|
||||
@@ -66,7 +97,7 @@ DescriptorManager::DescriptorManager(const Instance& instance, Scheduler& schedu
|
||||
}
|
||||
|
||||
DescriptorManager::~DescriptorManager() {
|
||||
vk::Device device = instance.GetDevice();
|
||||
const vk::Device device = instance.GetDevice();
|
||||
device.destroyPipelineLayout(pipeline_layout);
|
||||
|
||||
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||
@@ -89,7 +120,7 @@ void DescriptorManager::BindDescriptorSets() {
|
||||
descriptor_set_dirty.fill(true);
|
||||
}
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
const vk::Device device = instance.GetDevice();
|
||||
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> bound_sets;
|
||||
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||
if (descriptor_set_dirty[i]) {
|
||||
@@ -116,51 +147,59 @@ void DescriptorManager::BuildLayouts() {
|
||||
std::array<vk::DescriptorSetLayoutBinding, MAX_DESCRIPTORS> set_bindings;
|
||||
std::array<vk::DescriptorUpdateTemplateEntry, MAX_DESCRIPTORS> update_entries;
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
const vk::Device device = instance.GetDevice();
|
||||
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||
const auto& set = RASTERIZER_SETS[i];
|
||||
for (u32 j = 0; j < set.binding_count; j++) {
|
||||
vk::DescriptorType type = set.bindings[j];
|
||||
set_bindings[j] = vk::DescriptorSetLayoutBinding{.binding = j,
|
||||
.descriptorType = type,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = ToVkStageFlags(type)};
|
||||
const vk::DescriptorType type = set.bindings[j];
|
||||
set_bindings[j] = vk::DescriptorSetLayoutBinding{
|
||||
.binding = j,
|
||||
.descriptorType = type,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = ToVkStageFlags(type),
|
||||
};
|
||||
|
||||
update_entries[j] =
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = j,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = type,
|
||||
.offset = j * sizeof(DescriptorData),
|
||||
.stride = 0};
|
||||
update_entries[j] = vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = j,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = type,
|
||||
.offset = j * sizeof(DescriptorData),
|
||||
.stride = 0,
|
||||
};
|
||||
}
|
||||
|
||||
const vk::DescriptorSetLayoutCreateInfo layout_info = {.bindingCount = set.binding_count,
|
||||
.pBindings = set_bindings.data()};
|
||||
const vk::DescriptorSetLayoutCreateInfo layout_info = {
|
||||
.bindingCount = set.binding_count,
|
||||
.pBindings = set_bindings.data(),
|
||||
};
|
||||
descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info);
|
||||
|
||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||
.descriptorUpdateEntryCount = set.binding_count,
|
||||
.pDescriptorUpdateEntries = update_entries.data(),
|
||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||
.descriptorSetLayout = descriptor_set_layouts[i]};
|
||||
|
||||
.descriptorSetLayout = descriptor_set_layouts[i],
|
||||
};
|
||||
update_templates[i] = device.createDescriptorUpdateTemplate(template_info);
|
||||
}
|
||||
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = MAX_DESCRIPTOR_SETS,
|
||||
.pSetLayouts = descriptor_set_layouts.data(),
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr};
|
||||
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||
.setLayoutCount = MAX_DESCRIPTOR_SETS,
|
||||
.pSetLayouts = descriptor_set_layouts.data(),
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr,
|
||||
};
|
||||
pipeline_layout = device.createPipelineLayout(layout_info);
|
||||
}
|
||||
|
||||
vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) {
|
||||
vk::Device device = instance.GetDevice();
|
||||
|
||||
const vk::Device device = instance.GetDevice();
|
||||
const vk::DescriptorSetAllocateInfo alloc_info = {
|
||||
.descriptorPool = current_pool, .descriptorSetCount = 1, .pSetLayouts = &layout};
|
||||
.descriptorPool = current_pool,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &layout,
|
||||
};
|
||||
|
||||
try {
|
||||
return device.allocateDescriptorSets(alloc_info)[0];
|
||||
|
@@ -4,16 +4,17 @@
|
||||
|
||||
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
|
||||
#include "video_core/renderer_vulkan/vk_format_reinterpreter.h"
|
||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
D24S8toRGBA8::D24S8toRGBA8(const Instance& instance, Scheduler& scheduler,
|
||||
DescriptorManager& desc_manager, TextureRuntime& runtime)
|
||||
: FormatReinterpreterBase{instance, scheduler, desc_manager, runtime}, device{instance.GetDevice()} {
|
||||
: FormatReinterpreterBase{instance, scheduler, desc_manager, runtime},
|
||||
device{instance.GetDevice()} {
|
||||
constexpr std::string_view cs_source = R"(
|
||||
#version 450 core
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
@@ -35,77 +36,98 @@ imageStore(color, tex_coord, vec4(components) / (exp2(8.0) - 1.0));
|
||||
}
|
||||
)";
|
||||
compute_shader =
|
||||
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
||||
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
||||
|
||||
const std::array compute_layout_bindings = {
|
||||
vk::DescriptorSetLayoutBinding{.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
||||
vk::DescriptorSetLayoutBinding{.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
||||
vk::DescriptorSetLayoutBinding{.binding = 2,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute}};
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 2,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
},
|
||||
};
|
||||
|
||||
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
|
||||
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
||||
.pBindings = compute_layout_bindings.data()};
|
||||
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
||||
.pBindings = compute_layout_bindings.data(),
|
||||
};
|
||||
|
||||
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
|
||||
|
||||
const std::array update_template_entries = {
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo)},
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0},
|
||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0}};
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo),
|
||||
},
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = sizeof(vk::DescriptorImageInfo),
|
||||
},
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 2,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
||||
},
|
||||
};
|
||||
|
||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||
.descriptorSetLayout = descriptor_layout};
|
||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||
.descriptorSetLayout = descriptor_layout,
|
||||
};
|
||||
|
||||
update_template = device.createDescriptorUpdateTemplate(template_info);
|
||||
|
||||
const vk::PushConstantRange push_range = {
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
.offset = 0,
|
||||
.size = sizeof(Common::Vec2i),
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
.offset = 0,
|
||||
.size = sizeof(Common::Vec2i),
|
||||
};
|
||||
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
|
||||
.pSetLayouts = &descriptor_layout,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &push_range};
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &descriptor_layout,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &push_range,
|
||||
};
|
||||
|
||||
compute_pipeline_layout = device.createPipelineLayout(layout_info);
|
||||
|
||||
const vk::PipelineShaderStageCreateInfo compute_stage = {
|
||||
.stage = vk::ShaderStageFlagBits::eCompute, .module = compute_shader, .pName = "main"};
|
||||
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||
.module = compute_shader,
|
||||
.pName = "main",
|
||||
};
|
||||
|
||||
const vk::ComputePipelineCreateInfo compute_info = {.stage = compute_stage,
|
||||
.layout = compute_pipeline_layout};
|
||||
const vk::ComputePipelineCreateInfo compute_info = {
|
||||
.stage = compute_stage,
|
||||
.layout = compute_pipeline_layout,
|
||||
};
|
||||
|
||||
if (const auto result = device.createComputePipeline({}, compute_info);
|
||||
result.result == vk::Result::eSuccess) {
|
||||
result.result == vk::Result::eSuccess) {
|
||||
compute_pipeline = result.value;
|
||||
} else {
|
||||
LOG_CRITICAL(Render_Vulkan, "D24S8 compute pipeline creation failed!");
|
||||
@@ -124,80 +146,87 @@ D24S8toRGBA8::~D24S8toRGBA8() {
|
||||
void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surface& dest,
|
||||
VideoCore::Rect2D dst_rect) {
|
||||
const std::array textures = {
|
||||
vk::DescriptorImageInfo{.imageView = source.GetDepthView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
||||
vk::DescriptorImageInfo{.imageView = source.GetStencilView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
||||
vk::DescriptorImageInfo{.imageView = dest.GetImageView(),
|
||||
.imageLayout = vk::ImageLayout::eGeneral}};
|
||||
vk::DescriptorImageInfo{
|
||||
.imageView = source.GetDepthView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
},
|
||||
vk::DescriptorImageInfo{
|
||||
.imageView = source.GetStencilView(),
|
||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
},
|
||||
vk::DescriptorImageInfo{
|
||||
.imageView = dest.GetImageView(),
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
},
|
||||
};
|
||||
|
||||
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
|
||||
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
|
||||
|
||||
runtime.GetRenderpassCache().ExitRenderpass();
|
||||
scheduler.Record([this, set, src_rect,
|
||||
src_image = source.alloc.image,
|
||||
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
scheduler.Record([this, set, src_rect, src_image = source.alloc.image,
|
||||
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
|
||||
vk::CommandBuffer) {
|
||||
const vk::ImageMemoryBarrier pre_barrier = {
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = src_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
const std::array post_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = src_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
||||
vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
.aspectMask =
|
||||
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
const std::array post_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||
.oldLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = src_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
||||
vk::ImageAspectFlagBits::eStencil,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dst_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||
vk::PipelineStageFlagBits::eComputeShader,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
|
||||
|
||||
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout, 0, set, {});
|
||||
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout,
|
||||
0, set, {});
|
||||
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
|
||||
|
||||
const auto src_offset = Common::MakeVec(src_rect.left, src_rect.bottom);
|
||||
|
@@ -76,15 +76,17 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) {
|
||||
}
|
||||
|
||||
[[nodiscard]] vk::DebugUtilsMessengerCreateInfoEXT MakeDebugUtilsMessengerInfo() {
|
||||
return {.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose,
|
||||
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
|
||||
.pfnUserCallback = DebugHandler};
|
||||
return vk::DebugUtilsMessengerCreateInfoEXT{
|
||||
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose,
|
||||
.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
|
||||
.pfnUserCallback = DebugHandler,
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
|
||||
@@ -99,7 +101,6 @@ std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
|
||||
|
||||
Instance::Instance(bool validation, bool dump_command_buffers)
|
||||
: enable_validation{validation}, dump_command_buffers{dump_command_buffers} {
|
||||
// Fetch instance independant function pointers
|
||||
auto vkGetInstanceProcAddr =
|
||||
dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||
@@ -110,19 +111,16 @@ Instance::Instance(bool validation, bool dump_command_buffers)
|
||||
// Use required platform-specific flags
|
||||
auto flags = GetInstanceFlags();
|
||||
|
||||
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra",
|
||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.pEngineName = "Citra Vulkan",
|
||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.apiVersion = VK_API_VERSION_1_0};
|
||||
const vk::ApplicationInfo application_info = {
|
||||
.pApplicationName = "Citra",
|
||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.pEngineName = "Citra Vulkan",
|
||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.apiVersion = VK_API_VERSION_1_0,
|
||||
};
|
||||
|
||||
std::array<const char*, 3> layers;
|
||||
#ifdef ANDROID
|
||||
u32 layer_count = 1;
|
||||
layers[0] = "VK_LAYER_KHRONOS_timeline_semaphore";
|
||||
#else
|
||||
std::array<const char*, 2> layers;
|
||||
u32 layer_count = 0;
|
||||
#endif
|
||||
|
||||
if (enable_validation) {
|
||||
layers[layer_count++] = "VK_LAYER_KHRONOS_validation";
|
||||
@@ -132,13 +130,15 @@ Instance::Instance(bool validation, bool dump_command_buffers)
|
||||
}
|
||||
|
||||
const vk::StructureChain instance_chain = {
|
||||
vk::InstanceCreateInfo{.flags = flags,
|
||||
.pApplicationInfo = &application_info,
|
||||
.enabledLayerCount = layer_count,
|
||||
.ppEnabledLayerNames = layers.data(),
|
||||
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
||||
.ppEnabledExtensionNames = extensions.data()},
|
||||
MakeDebugUtilsMessengerInfo()};
|
||||
vk::InstanceCreateInfo{
|
||||
.flags = flags,
|
||||
.pApplicationInfo = &application_info,
|
||||
.enabledLayerCount = layer_count,
|
||||
.ppEnabledLayerNames = layers.data(),
|
||||
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
||||
.ppEnabledExtensionNames = extensions.data(),
|
||||
},
|
||||
};
|
||||
|
||||
instance = vk::createInstance(instance_chain.get());
|
||||
|
||||
@@ -156,7 +156,7 @@ Instance::Instance(bool validation, bool dump_command_buffers)
|
||||
Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
||||
: enable_validation{Settings::values.renderer_debug},
|
||||
dump_command_buffers{Settings::values.dump_command_buffers} {
|
||||
auto window_info = window.GetWindowInfo();
|
||||
const Frontend::EmuWindow::WindowSystemInfo window_info = window.GetWindowInfo();
|
||||
|
||||
// Fetch instance independant function pointers
|
||||
auto vkGetInstanceProcAddr =
|
||||
@@ -176,11 +176,13 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
||||
return;
|
||||
}
|
||||
|
||||
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra",
|
||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.pEngineName = "Citra Vulkan",
|
||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.apiVersion = available_version};
|
||||
const vk::ApplicationInfo application_info = {
|
||||
.pApplicationName = "Citra",
|
||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.pEngineName = "Citra Vulkan",
|
||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.apiVersion = available_version,
|
||||
};
|
||||
|
||||
std::array<const char*, 3> layers;
|
||||
#ifdef ANDROID
|
||||
@@ -198,13 +200,16 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
||||
}
|
||||
|
||||
const vk::StructureChain instance_chain = {
|
||||
vk::InstanceCreateInfo{.flags = flags,
|
||||
.pApplicationInfo = &application_info,
|
||||
.enabledLayerCount = layer_count,
|
||||
.ppEnabledLayerNames = layers.data(),
|
||||
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
||||
.ppEnabledExtensionNames = extensions.data()},
|
||||
MakeDebugUtilsMessengerInfo()};
|
||||
vk::InstanceCreateInfo{
|
||||
.flags = flags,
|
||||
.pApplicationInfo = &application_info,
|
||||
.enabledLayerCount = layer_count,
|
||||
.ppEnabledLayerNames = layers.data(),
|
||||
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
||||
.ppEnabledExtensionNames = extensions.data(),
|
||||
},
|
||||
MakeDebugUtilsMessengerInfo(),
|
||||
};
|
||||
|
||||
try {
|
||||
instance = vk::createInstance(instance_chain.get());
|
||||
@@ -335,13 +340,15 @@ void Instance::CreateFormatTable() {
|
||||
}
|
||||
|
||||
const u32 index = static_cast<u32>(pixel_format);
|
||||
format_table[index] = FormatTraits{.transfer_support = supports_transfer,
|
||||
.blit_support = supports_blit,
|
||||
.attachment_support = supports_attachment,
|
||||
.storage_support = supports_storage,
|
||||
.usage = best_usage,
|
||||
.native = format,
|
||||
.fallback = fallback};
|
||||
format_table[index] = FormatTraits{
|
||||
.transfer_support = supports_transfer,
|
||||
.blit_support = supports_blit,
|
||||
.attachment_support = supports_attachment,
|
||||
.storage_support = supports_storage,
|
||||
.usage = best_usage,
|
||||
.native = format,
|
||||
.fallback = fallback,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,12 +438,17 @@ bool Instance::CreateDevice() {
|
||||
static constexpr float queue_priorities[] = {1.0f};
|
||||
|
||||
const std::array queue_infos = {
|
||||
vk::DeviceQueueCreateInfo{.queueFamilyIndex = graphics_queue_family_index,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = queue_priorities},
|
||||
vk::DeviceQueueCreateInfo{.queueFamilyIndex = present_queue_family_index,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = queue_priorities}};
|
||||
vk::DeviceQueueCreateInfo{
|
||||
.queueFamilyIndex = graphics_queue_family_index,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = queue_priorities,
|
||||
},
|
||||
vk::DeviceQueueCreateInfo{
|
||||
.queueFamilyIndex = present_queue_family_index,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = queue_priorities,
|
||||
},
|
||||
};
|
||||
|
||||
const u32 queue_count = graphics_queue_family_index != present_queue_family_index ? 2u : 1u;
|
||||
const vk::StructureChain device_chain = {
|
||||
@@ -447,23 +459,25 @@ bool Instance::CreateDevice() {
|
||||
.ppEnabledExtensionNames = enabled_extensions.data(),
|
||||
},
|
||||
vk::PhysicalDeviceFeatures2{
|
||||
.features = {.robustBufferAccess = features.robustBufferAccess,
|
||||
.geometryShader = features.geometryShader,
|
||||
.dualSrcBlend = features.dualSrcBlend,
|
||||
.logicOp = features.logicOp,
|
||||
.depthClamp = features.depthClamp,
|
||||
.largePoints = features.largePoints,
|
||||
.samplerAnisotropy = features.samplerAnisotropy,
|
||||
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
|
||||
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
|
||||
.shaderClipDistance = features.shaderClipDistance}},
|
||||
.features =
|
||||
{
|
||||
.robustBufferAccess = features.robustBufferAccess,
|
||||
.geometryShader = features.geometryShader,
|
||||
.dualSrcBlend = features.dualSrcBlend,
|
||||
.logicOp = features.logicOp,
|
||||
.depthClamp = features.depthClamp,
|
||||
.largePoints = features.largePoints,
|
||||
.samplerAnisotropy = features.samplerAnisotropy,
|
||||
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
|
||||
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
|
||||
.shaderClipDistance = features.shaderClipDistance,
|
||||
},
|
||||
},
|
||||
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
|
||||
feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(),
|
||||
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
|
||||
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()
|
||||
};
|
||||
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()};
|
||||
|
||||
// Create logical device
|
||||
try {
|
||||
device = physical_device.createDevice(device_chain.get());
|
||||
} catch (vk::ExtensionNotPresentError& err) {
|
||||
@@ -484,13 +498,16 @@ bool Instance::CreateDevice() {
|
||||
void Instance::CreateAllocator() {
|
||||
const VmaVulkanFunctions functions = {
|
||||
.vkGetInstanceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr,
|
||||
.vkGetDeviceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr};
|
||||
.vkGetDeviceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr,
|
||||
};
|
||||
|
||||
const VmaAllocatorCreateInfo allocator_info = {.physicalDevice = physical_device,
|
||||
.device = device,
|
||||
.pVulkanFunctions = &functions,
|
||||
.instance = instance,
|
||||
.vulkanApiVersion = VK_API_VERSION_1_1};
|
||||
const VmaAllocatorCreateInfo allocator_info = {
|
||||
.physicalDevice = physical_device,
|
||||
.device = device,
|
||||
.pVulkanFunctions = &functions,
|
||||
.instance = instance,
|
||||
.vulkanApiVersion = VK_API_VERSION_1_1,
|
||||
};
|
||||
|
||||
if (VkResult result = vmaCreateAllocator(&allocator_info, &allocator); result != VK_SUCCESS) {
|
||||
LOG_CRITICAL(Render_Vulkan, "Failed to initialize VMA with error {}", result);
|
||||
|
@@ -7,12 +7,13 @@
|
||||
namespace Vulkan {
|
||||
|
||||
MasterSemaphore::MasterSemaphore(const Instance& instance) : device{instance.GetDevice()} {
|
||||
const vk::StructureChain semaphore_chain = {vk::SemaphoreCreateInfo{},
|
||||
vk::SemaphoreTypeCreateInfoKHR{
|
||||
.semaphoreType = vk::SemaphoreType::eTimeline,
|
||||
.initialValue = 0,
|
||||
}};
|
||||
|
||||
const vk::StructureChain semaphore_chain = {
|
||||
vk::SemaphoreCreateInfo{},
|
||||
vk::SemaphoreTypeCreateInfoKHR{
|
||||
.semaphoreType = vk::SemaphoreType::eTimeline,
|
||||
.initialValue = 0,
|
||||
},
|
||||
};
|
||||
semaphore = device.createSemaphore(semaphore_chain.get());
|
||||
}
|
||||
|
||||
|
@@ -4,10 +4,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/renderer_vulkan/vk_common.h"
|
||||
|
||||
|
@@ -32,15 +32,32 @@ u32 AttribBytes(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
|
||||
}
|
||||
|
||||
vk::Format ToVkAttributeFormat(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
|
||||
constexpr std::array attribute_formats = {
|
||||
std::array{vk::Format::eR8Sint, vk::Format::eR8G8Sint, vk::Format::eR8G8B8Sint,
|
||||
vk::Format::eR8G8B8A8Sint},
|
||||
std::array{vk::Format::eR8Uint, vk::Format::eR8G8Uint, vk::Format::eR8G8B8Uint,
|
||||
vk::Format::eR8G8B8A8Uint},
|
||||
std::array{vk::Format::eR16Sint, vk::Format::eR16G16Sint, vk::Format::eR16G16B16Sint,
|
||||
vk::Format::eR16G16B16A16Sint},
|
||||
std::array{vk::Format::eR32Sfloat, vk::Format::eR32G32Sfloat, vk::Format::eR32G32B32Sfloat,
|
||||
vk::Format::eR32G32B32A32Sfloat}};
|
||||
static constexpr std::array attribute_formats = {
|
||||
std::array{
|
||||
vk::Format::eR8Sint,
|
||||
vk::Format::eR8G8Sint,
|
||||
vk::Format::eR8G8B8Sint,
|
||||
vk::Format::eR8G8B8A8Sint,
|
||||
},
|
||||
std::array{
|
||||
vk::Format::eR8Uint,
|
||||
vk::Format::eR8G8Uint,
|
||||
vk::Format::eR8G8B8Uint,
|
||||
vk::Format::eR8G8B8A8Uint,
|
||||
},
|
||||
std::array{
|
||||
vk::Format::eR16Sint,
|
||||
vk::Format::eR16G16Sint,
|
||||
vk::Format::eR16G16B16Sint,
|
||||
vk::Format::eR16G16B16A16Sint,
|
||||
},
|
||||
std::array{
|
||||
vk::Format::eR32Sfloat,
|
||||
vk::Format::eR32G32Sfloat,
|
||||
vk::Format::eR32G32B32Sfloat,
|
||||
vk::Format::eR32G32B32A32Sfloat,
|
||||
},
|
||||
};
|
||||
|
||||
ASSERT(size <= 4);
|
||||
return attribute_formats[static_cast<u32>(format)][size - 1];
|
||||
@@ -126,7 +143,10 @@ void PipelineCache::LoadDiskCache() {
|
||||
|
||||
const std::string cache_file_path = fmt::format("{}{:x}{:x}.bin", GetPipelineCacheDir(),
|
||||
instance.GetVendorID(), instance.GetDeviceID());
|
||||
vk::PipelineCacheCreateInfo cache_info = {.initialDataSize = 0, .pInitialData = nullptr};
|
||||
vk::PipelineCacheCreateInfo cache_info = {
|
||||
.initialDataSize = 0,
|
||||
.pInitialData = nullptr,
|
||||
};
|
||||
|
||||
std::vector<u8> cache_data;
|
||||
FileUtil::IOFile cache_file{cache_file_path, "r"};
|
||||
@@ -289,29 +309,46 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
|
||||
|
||||
void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view) {
|
||||
const vk::DescriptorImageInfo image_info = {
|
||||
.imageView = image_view, .imageLayout = vk::ImageLayout::eGeneral};
|
||||
.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
desc_manager.SetBinding(1, binding, DescriptorData{image_info});
|
||||
}
|
||||
|
||||
void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) {
|
||||
const vk::DescriptorImageInfo image_info = {.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral};
|
||||
const vk::DescriptorImageInfo image_info = {
|
||||
.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
desc_manager.SetBinding(3, binding, DescriptorData{image_info});
|
||||
}
|
||||
|
||||
void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) {
|
||||
const DescriptorData data = {
|
||||
.buffer_info = vk::DescriptorBufferInfo{.buffer = buffer, .offset = offset, .range = size}};
|
||||
.buffer_info =
|
||||
vk::DescriptorBufferInfo{
|
||||
.buffer = buffer,
|
||||
.offset = offset,
|
||||
.range = size,
|
||||
},
|
||||
};
|
||||
desc_manager.SetBinding(0, binding, data);
|
||||
}
|
||||
|
||||
void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) {
|
||||
const DescriptorData data = {.buffer_view = buffer_view};
|
||||
const DescriptorData data = {
|
||||
.buffer_view = buffer_view,
|
||||
};
|
||||
desc_manager.SetBinding(0, binding, data);
|
||||
}
|
||||
|
||||
void PipelineCache::BindSampler(u32 binding, vk::Sampler sampler) {
|
||||
const DescriptorData data = {.image_info = vk::DescriptorImageInfo{.sampler = sampler}};
|
||||
const DescriptorData data = {
|
||||
.image_info =
|
||||
vk::DescriptorImageInfo{
|
||||
.sampler = sampler,
|
||||
},
|
||||
};
|
||||
desc_manager.SetBinding(2, binding, data);
|
||||
}
|
||||
|
||||
@@ -411,18 +448,21 @@ void PipelineCache::ApplyDynamic(const PipelineInfo& info) {
|
||||
}
|
||||
|
||||
vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
vk::Device device = instance.GetDevice();
|
||||
const vk::Device device = instance.GetDevice();
|
||||
|
||||
u32 shader_count = 0;
|
||||
std::array<vk::PipelineShaderStageCreateInfo, MAX_SHADER_STAGES> shader_stages;
|
||||
for (std::size_t i = 0; i < current_shaders.size(); i++) {
|
||||
vk::ShaderModule shader = current_shaders[i];
|
||||
const vk::ShaderModule shader = current_shaders[i];
|
||||
if (!shader) {
|
||||
continue;
|
||||
}
|
||||
|
||||
shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{
|
||||
.stage = ToVkShaderStage(i), .module = shader, .pName = "main"};
|
||||
.stage = ToVkShaderStage(i),
|
||||
.module = shader,
|
||||
.pName = "main",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -438,7 +478,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.binding = binding.binding,
|
||||
.stride = binding.stride,
|
||||
.inputRate = binding.fixed.Value() ? vk::VertexInputRate::eInstance
|
||||
: vk::VertexInputRate::eVertex};
|
||||
: vk::VertexInputRate::eVertex,
|
||||
};
|
||||
}
|
||||
|
||||
u32 emulated_attrib_count = 0;
|
||||
@@ -453,7 +494,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.location = attrib.location,
|
||||
.binding = attrib.binding,
|
||||
.format = is_supported ? format : ToVkAttributeFormat(attrib.type, 2),
|
||||
.offset = attrib.offset};
|
||||
.offset = attrib.offset,
|
||||
};
|
||||
|
||||
// When the requested 3-component vertex format is unsupported by the hardware
|
||||
// is it emulated by breaking it into a vec2 + vec1. These are combined to a vec3
|
||||
@@ -466,7 +508,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.location = location,
|
||||
.binding = attrib.binding,
|
||||
.format = ToVkAttributeFormat(attrib.type, 1),
|
||||
.offset = attrib.offset + AttribBytes(attrib.type, 2)};
|
||||
.offset = attrib.offset + AttribBytes(attrib.type, 2),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,11 +518,13 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.pVertexBindingDescriptions = bindings.data(),
|
||||
.vertexAttributeDescriptionCount =
|
||||
info.vertex_layout.attribute_count + emulated_attrib_count,
|
||||
.pVertexAttributeDescriptions = attributes.data()};
|
||||
.pVertexAttributeDescriptions = attributes.data(),
|
||||
};
|
||||
|
||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||
.topology = PicaToVK::PrimitiveTopology(info.rasterization.topology),
|
||||
.primitiveRestartEnable = false};
|
||||
.primitiveRestartEnable = false,
|
||||
};
|
||||
|
||||
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
||||
.depthClampEnable = false,
|
||||
@@ -487,10 +532,13 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.cullMode = PicaToVK::CullMode(info.rasterization.cull_mode),
|
||||
.frontFace = PicaToVK::FrontFace(info.rasterization.cull_mode),
|
||||
.depthBiasEnable = false,
|
||||
.lineWidth = 1.0f};
|
||||
.lineWidth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
||||
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false};
|
||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||
.sampleShadingEnable = false,
|
||||
};
|
||||
|
||||
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
||||
.blendEnable = info.blending.blend_enable.Value(),
|
||||
@@ -500,19 +548,30 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.srcAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.src_alpha_blend_factor),
|
||||
.dstAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.dst_alpha_blend_factor),
|
||||
.alphaBlendOp = PicaToVK::BlendEquation(info.blending.alpha_blend_eq),
|
||||
.colorWriteMask = static_cast<vk::ColorComponentFlags>(info.blending.color_write_mask)};
|
||||
.colorWriteMask = static_cast<vk::ColorComponentFlags>(info.blending.color_write_mask),
|
||||
};
|
||||
|
||||
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
||||
.logicOpEnable = !info.blending.blend_enable.Value() && !instance.NeedsLogicOpEmulation(),
|
||||
.logicOp = PicaToVK::LogicOp(info.blending.logic_op.Value()),
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &colorblend_attachment,
|
||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f}};
|
||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
||||
};
|
||||
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f, .y = 0.0f, .width = 1.0f, .height = 1.0f, .minDepth = 0.0f, .maxDepth = 1.0f};
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = 1.0f,
|
||||
.height = 1.0f,
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::Rect2D scissor = {.offset = {0, 0}, .extent = {1, 1}};
|
||||
const vk::Rect2D scissor = {
|
||||
.offset = {0, 0},
|
||||
.extent = {1, 1},
|
||||
};
|
||||
|
||||
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
||||
.viewportCount = 1,
|
||||
@@ -542,13 +601,15 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
|
||||
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
|
||||
.dynamicStateCount = extended_dynamic_states ? static_cast<u32>(dynamic_states.size()) : 6u,
|
||||
.pDynamicStates = dynamic_states.data()};
|
||||
.pDynamicStates = dynamic_states.data(),
|
||||
};
|
||||
|
||||
const vk::StencilOpState stencil_op_state = {
|
||||
.failOp = PicaToVK::StencilOp(info.depth_stencil.stencil_fail_op),
|
||||
.passOp = PicaToVK::StencilOp(info.depth_stencil.stencil_pass_op),
|
||||
.depthFailOp = PicaToVK::StencilOp(info.depth_stencil.stencil_depth_fail_op),
|
||||
.compareOp = PicaToVK::CompareFunc(info.depth_stencil.stencil_compare_op)};
|
||||
.compareOp = PicaToVK::CompareFunc(info.depth_stencil.stencil_compare_op),
|
||||
};
|
||||
|
||||
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
|
||||
.depthTestEnable = static_cast<u32>(info.depth_stencil.depth_test_enable.Value()),
|
||||
@@ -557,7 +618,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.depthBoundsTestEnable = false,
|
||||
.stencilTestEnable = static_cast<u32>(info.depth_stencil.stencil_test_enable.Value()),
|
||||
.front = stencil_op_state,
|
||||
.back = stencil_op_state};
|
||||
.back = stencil_op_state,
|
||||
};
|
||||
|
||||
const vk::GraphicsPipelineCreateInfo pipeline_info = {
|
||||
.stageCount = shader_count,
|
||||
@@ -572,7 +634,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||
.pDynamicState = &dynamic_info,
|
||||
.layout = desc_manager.GetPipelineLayout(),
|
||||
.renderPass =
|
||||
renderpass_cache.GetRenderpass(info.color_attachment, info.depth_attachment, false)};
|
||||
renderpass_cache.GetRenderpass(info.color_attachment, info.depth_attachment, false),
|
||||
};
|
||||
|
||||
if (const auto result = device.createGraphicsPipeline(pipeline_cache, pipeline_info);
|
||||
result.result == vk::Result::eSuccess) {
|
||||
|
@@ -26,17 +26,23 @@ constexpr u32 INDEX_BUFFER_SIZE = 16 * 1024 * 1024;
|
||||
constexpr u32 UNIFORM_BUFFER_SIZE = 16 * 1024 * 1024;
|
||||
constexpr u32 TEXTURE_BUFFER_SIZE = 512 * 1024;
|
||||
|
||||
constexpr std::array TEXTURE_BUFFER_LF_FORMATS = {vk::Format::eR32G32Sfloat};
|
||||
constexpr std::array TEXTURE_BUFFER_LF_FORMATS = {
|
||||
vk::Format::eR32G32Sfloat,
|
||||
};
|
||||
|
||||
constexpr std::array TEXTURE_BUFFER_FORMATS = {vk::Format::eR32G32Sfloat,
|
||||
vk::Format::eR32G32B32A32Sfloat};
|
||||
constexpr std::array TEXTURE_BUFFER_FORMATS = {
|
||||
vk::Format::eR32G32Sfloat,
|
||||
vk::Format::eR32G32B32A32Sfloat,
|
||||
};
|
||||
|
||||
constexpr VideoCore::SurfaceParams NULL_PARAMS = {.width = 1,
|
||||
.height = 1,
|
||||
.stride = 1,
|
||||
.texture_type = VideoCore::TextureType::Texture2D,
|
||||
.pixel_format = VideoCore::PixelFormat::RGBA8,
|
||||
.type = VideoCore::SurfaceType::Color};
|
||||
constexpr VideoCore::SurfaceParams NULL_PARAMS = {
|
||||
.width = 1,
|
||||
.height = 1,
|
||||
.stride = 1,
|
||||
.texture_type = VideoCore::TextureType::Texture2D,
|
||||
.pixel_format = VideoCore::PixelFormat::RGBA8,
|
||||
.type = VideoCore::SurfaceType::Color,
|
||||
};
|
||||
|
||||
constexpr vk::ImageUsageFlags NULL_USAGE = vk::ImageUsageFlagBits::eSampled |
|
||||
vk::ImageUsageFlagBits::eTransferSrc |
|
||||
@@ -85,7 +91,8 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan
|
||||
.min_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
|
||||
.mip_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
|
||||
.wrap_s = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder,
|
||||
.wrap_t = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder};
|
||||
.wrap_t = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder,
|
||||
};
|
||||
|
||||
default_sampler = CreateSampler(default_sampler_info);
|
||||
|
||||
@@ -265,8 +272,8 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
|
||||
SetupFixedAttribs();
|
||||
|
||||
// Bind the generated bindings
|
||||
scheduler.Record([this, vertex_offsets = binding_offsets](
|
||||
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
scheduler.Record([this, vertex_offsets = binding_offsets](vk::CommandBuffer render_cmdbuf,
|
||||
vk::CommandBuffer) {
|
||||
render_cmdbuf.bindVertexBuffers(0, vertex_buffers, vertex_offsets);
|
||||
});
|
||||
}
|
||||
@@ -435,8 +442,8 @@ void RasterizerVulkan::SetupIndexArray() {
|
||||
|
||||
index_buffer.Commit(index_buffer_size);
|
||||
|
||||
scheduler.Record([this, index_offset = index_offset, index_type = index_type](
|
||||
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
scheduler.Record([this, index_offset = index_offset,
|
||||
index_type = index_type](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||
render_cmdbuf.bindIndexBuffer(index_buffer.GetHandle(), index_offset, index_type);
|
||||
});
|
||||
}
|
||||
@@ -548,15 +555,17 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
||||
// nothing. Always sample from the base level until mipmaps for texture cubes are
|
||||
// implemented
|
||||
const bool skip_mipmap = config.type == Pica::TexturingRegs::TextureConfig::TextureCube;
|
||||
info = SamplerInfo{.mag_filter = config.mag_filter,
|
||||
.min_filter = config.min_filter,
|
||||
.mip_filter = config.mip_filter,
|
||||
.wrap_s = config.wrap_s,
|
||||
.wrap_t = config.wrap_t,
|
||||
.border_color = config.border_color.raw,
|
||||
.lod_min = skip_mipmap ? 0.f : static_cast<float>(config.lod.min_level),
|
||||
.lod_max = skip_mipmap ? 0.f : static_cast<float>(config.lod.max_level),
|
||||
.lod_bias = static_cast<float>(config.lod.bias)};
|
||||
info = SamplerInfo{
|
||||
.mag_filter = config.mag_filter,
|
||||
.min_filter = config.min_filter,
|
||||
.mip_filter = config.mip_filter,
|
||||
.wrap_s = config.wrap_s,
|
||||
.wrap_t = config.wrap_t,
|
||||
.border_color = config.border_color.raw,
|
||||
.lod_min = skip_mipmap ? 0.f : static_cast<float>(config.lod.min_level),
|
||||
.lod_max = skip_mipmap ? 0.f : static_cast<float>(config.lod.max_level),
|
||||
.lod_bias = static_cast<float>(config.lod.bias),
|
||||
};
|
||||
|
||||
// Search the cache and bind the appropriate sampler
|
||||
if (auto it = samplers.find(info); it != samplers.end()) {
|
||||
@@ -711,7 +720,8 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
||||
.renderpass = renderpass_cache.GetRenderpass(pipeline_info.color_attachment,
|
||||
pipeline_info.depth_attachment, false),
|
||||
.width = width,
|
||||
.height = height};
|
||||
.height = height,
|
||||
};
|
||||
|
||||
auto [it, new_framebuffer] = framebuffers.try_emplace(framebuffer_info, vk::Framebuffer{});
|
||||
if (new_framebuffer) {
|
||||
@@ -721,9 +731,11 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
||||
const RenderpassState renderpass_info = {
|
||||
.renderpass = framebuffer_info.renderpass,
|
||||
.framebuffer = it->second,
|
||||
.render_area = vk::Rect2D{.offset = {static_cast<s32>(draw_rect.left),
|
||||
static_cast<s32>(draw_rect.bottom)},
|
||||
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()}},
|
||||
.render_area =
|
||||
vk::Rect2D{
|
||||
.offset = {static_cast<s32>(draw_rect.left), static_cast<s32>(draw_rect.bottom)},
|
||||
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()},
|
||||
},
|
||||
.clear = {},
|
||||
};
|
||||
|
||||
@@ -1086,8 +1098,11 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
|
||||
const auto color = PicaToVK::ColorRGBA8(info.border_color);
|
||||
const vk::SamplerCustomBorderColorCreateInfoEXT border_color_info = {
|
||||
.customBorderColor =
|
||||
vk::ClearColorValue{.float32 = std::array{color[0], color[1], color[2], color[3]}},
|
||||
.format = vk::Format::eUndefined};
|
||||
vk::ClearColorValue{
|
||||
.float32 = std::array{color[0], color[1], color[2], color[3]},
|
||||
},
|
||||
.format = vk::Format::eUndefined,
|
||||
};
|
||||
|
||||
const vk::SamplerCreateInfo sampler_info = {
|
||||
.pNext = use_border_color ? &border_color_info : nullptr,
|
||||
@@ -1105,7 +1120,8 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
|
||||
.maxLod = info.lod_max,
|
||||
.borderColor =
|
||||
use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack,
|
||||
.unnormalizedCoordinates = false};
|
||||
.unnormalizedCoordinates = false,
|
||||
};
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
return device.createSampler(sampler_info);
|
||||
@@ -1123,12 +1139,14 @@ vk::Framebuffer RasterizerVulkan::CreateFramebuffer(const FramebufferInfo& info)
|
||||
attachments[attachment_count++] = info.depth;
|
||||
}
|
||||
|
||||
const vk::FramebufferCreateInfo framebuffer_info = {.renderPass = info.renderpass,
|
||||
.attachmentCount = attachment_count,
|
||||
.pAttachments = attachments.data(),
|
||||
.width = info.width,
|
||||
.height = info.height,
|
||||
.layers = 1};
|
||||
const vk::FramebufferCreateInfo framebuffer_info = {
|
||||
.renderPass = info.renderpass,
|
||||
.attachmentCount = attachment_count,
|
||||
.pAttachments = attachments.data(),
|
||||
.width = info.width,
|
||||
.height = info.height,
|
||||
.layers = 1,
|
||||
};
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
return device.createFramebuffer(framebuffer_info);
|
||||
|
@@ -61,12 +61,12 @@ RenderpassCache::RenderpassCache(const Instance& instance, Scheduler& scheduler)
|
||||
continue;
|
||||
}
|
||||
|
||||
cached_renderpasses[color][depth][0] = CreateRenderPass(
|
||||
color_format, depth_format, vk::AttachmentLoadOp::eLoad,
|
||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||
cached_renderpasses[color][depth][1] = CreateRenderPass(
|
||||
color_format, depth_format, vk::AttachmentLoadOp::eClear,
|
||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||
cached_renderpasses[color][depth][0] =
|
||||
CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eLoad,
|
||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||
cached_renderpasses[color][depth][1] =
|
||||
CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eClear,
|
||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,11 +100,13 @@ void RenderpassCache::EnterRenderpass(const RenderpassState& state) {
|
||||
render_cmdbuf.endRenderPass();
|
||||
}
|
||||
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {.renderPass = state.renderpass,
|
||||
.framebuffer = state.framebuffer,
|
||||
.renderArea = state.render_area,
|
||||
.clearValueCount = 1,
|
||||
.pClearValues = &state.clear};
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = state.renderpass,
|
||||
.framebuffer = state.framebuffer,
|
||||
.renderArea = state.render_area,
|
||||
.clearValueCount = 1,
|
||||
.pClearValues = &state.clear,
|
||||
};
|
||||
|
||||
render_cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||
});
|
||||
@@ -160,17 +162,20 @@ vk::RenderPass RenderpassCache::CreateRenderPass(vk::Format color, vk::Format de
|
||||
vk::AttachmentReference depth_attachment_ref{};
|
||||
|
||||
if (color != vk::Format::eUndefined) {
|
||||
attachments[attachment_count] =
|
||||
vk::AttachmentDescription{.format = color,
|
||||
.loadOp = load_op,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||
.initialLayout = initial_layout,
|
||||
.finalLayout = final_layout};
|
||||
attachments[attachment_count] = vk::AttachmentDescription{
|
||||
.format = color,
|
||||
.loadOp = load_op,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||
.initialLayout = initial_layout,
|
||||
.finalLayout = final_layout,
|
||||
};
|
||||
|
||||
color_attachment_ref = vk::AttachmentReference{
|
||||
.attachment = attachment_count++, .layout = vk::ImageLayout::eGeneral};
|
||||
.attachment = attachment_count++,
|
||||
.layout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
|
||||
use_color = true;
|
||||
}
|
||||
@@ -183,34 +188,38 @@ vk::RenderPass RenderpassCache::CreateRenderPass(vk::Format color, vk::Format de
|
||||
.stencilLoadOp = load_op,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
||||
.initialLayout = vk::ImageLayout::eGeneral,
|
||||
.finalLayout = vk::ImageLayout::eGeneral};
|
||||
.finalLayout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
|
||||
depth_attachment_ref =
|
||||
vk::AttachmentReference{.attachment = attachment_count++,
|
||||
.layout = vk::ImageLayout::eGeneral};
|
||||
depth_attachment_ref = vk::AttachmentReference{
|
||||
.attachment = attachment_count++,
|
||||
.layout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
|
||||
use_depth = true;
|
||||
}
|
||||
|
||||
// We also require only one subpass
|
||||
const vk::SubpassDescription subpass = {.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||
.inputAttachmentCount = 0,
|
||||
.pInputAttachments = nullptr,
|
||||
.colorAttachmentCount = use_color ? 1u : 0u,
|
||||
.pColorAttachments = &color_attachment_ref,
|
||||
.pResolveAttachments = 0,
|
||||
.pDepthStencilAttachment =
|
||||
use_depth ? &depth_attachment_ref : nullptr};
|
||||
const vk::SubpassDescription subpass = {
|
||||
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||
.inputAttachmentCount = 0,
|
||||
.pInputAttachments = nullptr,
|
||||
.colorAttachmentCount = use_color ? 1u : 0u,
|
||||
.pColorAttachments = &color_attachment_ref,
|
||||
.pResolveAttachments = 0,
|
||||
.pDepthStencilAttachment = use_depth ? &depth_attachment_ref : nullptr,
|
||||
};
|
||||
|
||||
const vk::RenderPassCreateInfo renderpass_info = {.attachmentCount = attachment_count,
|
||||
.pAttachments = attachments.data(),
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass,
|
||||
.dependencyCount = 0,
|
||||
.pDependencies = nullptr};
|
||||
const vk::RenderPassCreateInfo renderpass_info = {
|
||||
.attachmentCount = attachment_count,
|
||||
.pAttachments = attachments.data(),
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass,
|
||||
.dependencyCount = 0,
|
||||
.pDependencies = nullptr,
|
||||
};
|
||||
|
||||
// Create the renderpass
|
||||
vk::Device device = instance.GetDevice();
|
||||
const vk::Device device = instance.GetDevice();
|
||||
return device.createRenderPass(renderpass_info);
|
||||
}
|
||||
|
||||
|
@@ -86,7 +86,8 @@ void CommandPool::Allocate(std::size_t begin, std::size_t end) {
|
||||
const vk::CommandPoolCreateInfo pool_create_info = {
|
||||
.flags = vk::CommandPoolCreateFlagBits::eTransient |
|
||||
vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
|
||||
.queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex()};
|
||||
.queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex(),
|
||||
};
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
pool.handle = device.createCommandPool(pool_create_info);
|
||||
@@ -94,7 +95,8 @@ void CommandPool::Allocate(std::size_t begin, std::size_t end) {
|
||||
const vk::CommandBufferAllocateInfo buffer_alloc_info = {
|
||||
.commandPool = pool.handle,
|
||||
.level = vk::CommandBufferLevel::ePrimary,
|
||||
.commandBufferCount = COMMAND_BUFFER_POOL_SIZE};
|
||||
.commandBufferCount = COMMAND_BUFFER_POOL_SIZE,
|
||||
};
|
||||
|
||||
auto buffers = device.allocateCommandBuffers(buffer_alloc_info);
|
||||
std::copy(buffers.begin(), buffers.end(), pool.cmdbufs.begin());
|
||||
@@ -126,17 +128,19 @@ void DescriptorPool::Allocate(std::size_t begin, std::size_t end) {
|
||||
vk::DescriptorPool& pool = pools.emplace_back();
|
||||
|
||||
// Choose a sane pool size good for most games
|
||||
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {
|
||||
{{vk::DescriptorType::eUniformBuffer, 4096},
|
||||
{vk::DescriptorType::eSampledImage, 4096},
|
||||
{vk::DescriptorType::eSampler, 4096},
|
||||
{vk::DescriptorType::eUniformTexelBuffer, 2048},
|
||||
{vk::DescriptorType::eStorageImage, 1024}}};
|
||||
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {{
|
||||
{vk::DescriptorType::eUniformBuffer, 4096},
|
||||
{vk::DescriptorType::eSampledImage, 4096},
|
||||
{vk::DescriptorType::eSampler, 4096},
|
||||
{vk::DescriptorType::eUniformTexelBuffer, 2048},
|
||||
{vk::DescriptorType::eStorageImage, 1024},
|
||||
}};
|
||||
|
||||
const vk::DescriptorPoolCreateInfo descriptor_pool_info = {
|
||||
.maxSets = 8192,
|
||||
.poolSizeCount = static_cast<u32>(pool_sizes.size()),
|
||||
.pPoolSizes = pool_sizes.data()};
|
||||
.pPoolSizes = pool_sizes.data(),
|
||||
};
|
||||
|
||||
pool = instance.GetDevice().createDescriptorPool(descriptor_pool_info);
|
||||
}
|
||||
|
@@ -139,9 +139,8 @@ void Scheduler::SubmitExecution(vk::Semaphore signal_semaphore, vk::Semaphore wa
|
||||
renderer.FlushBuffers();
|
||||
|
||||
renderpass_cache.ExitRenderpass();
|
||||
Record([signal_semaphore, wait_semaphore,
|
||||
handle, signal_value, this](vk::CommandBuffer render_cmdbuf,
|
||||
vk::CommandBuffer upload_cmdbuf) {
|
||||
Record([signal_semaphore, wait_semaphore, handle, signal_value,
|
||||
this](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer upload_cmdbuf) {
|
||||
MICROPROFILE_SCOPE(Vulkan_Submit);
|
||||
upload_cmdbuf.end();
|
||||
render_cmdbuf.end();
|
||||
|
@@ -1768,7 +1768,8 @@ layout (set = 0, binding = 0, std140) uniform vs_config {
|
||||
out += fmt::format("vec4 vs_out_attr{};\n", i);
|
||||
}
|
||||
|
||||
const auto semantic = [&config = config.state](VSOutputAttributes::Semantic slot_semantic) -> std::string {
|
||||
const auto semantic =
|
||||
[&config = config.state](VSOutputAttributes::Semantic slot_semantic) -> std::string {
|
||||
const u32 slot = static_cast<u32>(slot_semantic);
|
||||
const u32 attrib = config.semantic_maps[slot].attribute_index;
|
||||
const u32 comp = config.semantic_maps[slot].component_index;
|
||||
@@ -1795,8 +1796,9 @@ layout (set = 0, binding = 0, std140) uniform vs_config {
|
||||
out += " normquat = GetVertexQuaternion();\n";
|
||||
|
||||
out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " +
|
||||
semantic(VSOutputAttributes::COLOR_G) + ", " + semantic(VSOutputAttributes::COLOR_B) +
|
||||
", " + semantic(VSOutputAttributes::COLOR_A) + ");\n";
|
||||
semantic(VSOutputAttributes::COLOR_G) + ", " +
|
||||
semantic(VSOutputAttributes::COLOR_B) + ", " +
|
||||
semantic(VSOutputAttributes::COLOR_A) + ");\n";
|
||||
out += " primary_color = min(abs(vtx_color), vec4(1.0));\n\n";
|
||||
|
||||
out += " texcoord0 = vec2(" + semantic(VSOutputAttributes::TEXCOORD0_U) + ", " +
|
||||
|
@@ -150,8 +150,8 @@ struct PicaFSConfig : Common::HashableStruct<PicaFSConfigState> {
|
||||
* PICA vertex/geometry shader.
|
||||
*/
|
||||
struct PicaShaderConfigCommon {
|
||||
void Init(const Pica::RasterizerRegs& rasterizer,
|
||||
const Pica::ShaderRegs& regs, Pica::Shader::ShaderSetup& setup);
|
||||
void Init(const Pica::RasterizerRegs& rasterizer, const Pica::ShaderRegs& regs,
|
||||
Pica::Shader::ShaderSetup& setup);
|
||||
|
||||
u64 program_hash;
|
||||
u64 swizzle_hash;
|
||||
@@ -183,8 +183,8 @@ struct PicaShaderConfigCommon {
|
||||
* shader.
|
||||
*/
|
||||
struct PicaVSConfig : Common::HashableStruct<PicaShaderConfigCommon> {
|
||||
explicit PicaVSConfig(const Pica::RasterizerRegs& rasterizer,
|
||||
const Pica::ShaderRegs& regs, Pica::Shader::ShaderSetup& setup) {
|
||||
explicit PicaVSConfig(const Pica::RasterizerRegs& rasterizer, const Pica::ShaderRegs& regs,
|
||||
Pica::Shader::ShaderSetup& setup) {
|
||||
state.Init(rasterizer, regs, setup);
|
||||
}
|
||||
explicit PicaVSConfig(const PicaShaderConfigCommon& conf) {
|
||||
|
@@ -59,9 +59,10 @@ StagingBuffer::StagingBuffer(const Instance& instance, u32 size, bool readback)
|
||||
const VmaAllocationCreateFlags flags =
|
||||
readback ? VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
|
||||
: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||
const VmaAllocationCreateInfo alloc_create_info = {.flags =
|
||||
flags | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST};
|
||||
const VmaAllocationCreateInfo alloc_create_info = {
|
||||
.flags = flags | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
};
|
||||
|
||||
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
|
||||
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
|
||||
@@ -88,11 +89,15 @@ StreamBuffer::StreamBuffer(const Instance& instance, Scheduler& scheduler, u32 s
|
||||
bool readback)
|
||||
: instance{instance}, scheduler{scheduler}, staging{instance, size, readback}, usage{usage},
|
||||
total_size{size}, bucket_size{size / BUCKET_COUNT}, readback{readback} {
|
||||
const vk::BufferCreateInfo buffer_info = {
|
||||
.size = total_size, .usage = usage | vk::BufferUsageFlagBits::eTransferDst};
|
||||
|
||||
const VmaAllocationCreateInfo alloc_create_info = {.usage =
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE};
|
||||
const vk::BufferCreateInfo buffer_info = {
|
||||
.size = total_size,
|
||||
.usage = usage | vk::BufferUsageFlagBits::eTransferDst,
|
||||
};
|
||||
|
||||
const VmaAllocationCreateInfo alloc_create_info = {
|
||||
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||
};
|
||||
|
||||
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
|
||||
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
|
||||
@@ -109,7 +114,11 @@ StreamBuffer::StreamBuffer(const Instance& instance, Scheduler& scheduler, u32 s
|
||||
vk::Device device = instance.GetDevice();
|
||||
for (std::size_t i = 0; i < view_formats.size(); i++) {
|
||||
const vk::BufferViewCreateInfo view_info = {
|
||||
.buffer = gpu_buffer, .format = view_formats[i], .offset = 0, .range = total_size};
|
||||
.buffer = gpu_buffer,
|
||||
.format = view_formats[i],
|
||||
.offset = 0,
|
||||
.range = total_size,
|
||||
};
|
||||
|
||||
views[i] = device.createBufferView(view_info);
|
||||
}
|
||||
@@ -171,7 +180,10 @@ void StreamBuffer::Flush() {
|
||||
scheduler.Record([this, flush_start, flush_size](vk::CommandBuffer,
|
||||
vk::CommandBuffer upload_cmdbuf) {
|
||||
const vk::BufferCopy copy_region = {
|
||||
.srcOffset = flush_start, .dstOffset = flush_start, .size = flush_size};
|
||||
.srcOffset = flush_start,
|
||||
.dstOffset = flush_start,
|
||||
.size = flush_size,
|
||||
};
|
||||
|
||||
upload_cmdbuf.copyBuffer(staging.buffer, gpu_buffer, copy_region);
|
||||
|
||||
@@ -182,7 +194,8 @@ void StreamBuffer::Flush() {
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.buffer = gpu_buffer,
|
||||
.offset = flush_start,
|
||||
.size = flush_size};
|
||||
.size = flush_size,
|
||||
};
|
||||
|
||||
upload_cmdbuf.pipelineBarrier(
|
||||
vk::PipelineStageFlagBits::eTransfer, MakePipelineStage(usage),
|
||||
|
@@ -69,7 +69,8 @@ void Swapchain::Create() {
|
||||
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eInherit,
|
||||
.presentMode = present_mode,
|
||||
.clipped = true,
|
||||
.oldSwapchain = swapchain};
|
||||
.oldSwapchain = swapchain,
|
||||
};
|
||||
|
||||
vk::Device device = instance.GetDevice();
|
||||
vk::SwapchainKHR new_swapchain = device.createSwapchainKHR(swapchain_info);
|
||||
@@ -111,11 +112,14 @@ void Swapchain::AcquireNextImage() {
|
||||
MICROPROFILE_DEFINE(Vulkan_Present, "Vulkan", "Swapchain Present", MP_RGB(66, 185, 245));
|
||||
void Swapchain::Present() {
|
||||
scheduler.Record([this, index = image_index](vk::CommandBuffer, vk::CommandBuffer) {
|
||||
const vk::PresentInfoKHR present_info = {.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &present_ready[index],
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &swapchain,
|
||||
.pImageIndices = &index};
|
||||
const vk::PresentInfoKHR present_info = {
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &present_ready[index],
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &swapchain,
|
||||
.pImageIndices = &index,
|
||||
};
|
||||
|
||||
MICROPROFILE_SCOPE(Vulkan_Present);
|
||||
vk::Queue present_queue = instance.GetPresentQueue();
|
||||
try {
|
||||
@@ -135,8 +139,8 @@ void Swapchain::FindPresentFormat() {
|
||||
const std::vector<vk::SurfaceFormatKHR> formats =
|
||||
instance.GetPhysicalDevice().getSurfaceFormatsKHR(surface);
|
||||
|
||||
// If there is a single undefined surface format, the device doesn't care, so we'll just use
|
||||
// RGBA
|
||||
// If there is a single undefined surface format, the device doesn't care, so we'll just use
|
||||
// RGBA
|
||||
if (formats[0].format == vk::Format::eUndefined) {
|
||||
surface_format.format = vk::Format::eR8G8B8A8Unorm;
|
||||
surface_format.colorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
|
||||
@@ -233,11 +237,15 @@ void Swapchain::SetupImages() {
|
||||
.image = image,
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = surface_format.format,
|
||||
.subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1}};
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
image_views.push_back(device.createImageView(view_info));
|
||||
|
||||
@@ -247,7 +255,8 @@ void Swapchain::SetupImages() {
|
||||
.pAttachments = &image_views.back(),
|
||||
.width = extent.width,
|
||||
.height = extent.height,
|
||||
.layers = 1};
|
||||
.layers = 1,
|
||||
};
|
||||
|
||||
framebuffers.push_back(device.createFramebuffer(framebuffer_info));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user