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));
|
static_cast<Settings::GraphicsAPI>(sdl2_config->GetInteger("Renderer", "graphics_api", 2));
|
||||||
Settings::values.async_command_recording =
|
Settings::values.async_command_recording =
|
||||||
sdl2_config->GetBoolean("Renderer", "async_command_recording", true);
|
sdl2_config->GetBoolean("Renderer", "async_command_recording", true);
|
||||||
Settings::values.spirv_shader_gen = sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
|
Settings::values.spirv_shader_gen =
|
||||||
|
sdl2_config->GetBoolean("Renderer", "spirv_shader_gen", true);
|
||||||
Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "renderer_debug", false);
|
Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "renderer_debug", false);
|
||||||
Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true);
|
Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true);
|
||||||
Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true);
|
Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true);
|
||||||
|
@@ -167,7 +167,8 @@ void RendererVulkan::PrepareRendertarget() {
|
|||||||
LCD::Read(color_fill.raw, lcd_color_addr);
|
LCD::Read(color_fill.raw, lcd_color_addr);
|
||||||
|
|
||||||
if (color_fill.is_enabled) {
|
if (color_fill.is_enabled) {
|
||||||
LoadColorToActiveVkTexture(color_fill.color_r, color_fill.color_g, color_fill.color_b, screen_infos[i].texture);
|
LoadColorToActiveVkTexture(color_fill.color_r, color_fill.color_g, color_fill.color_b,
|
||||||
|
screen_infos[i].texture);
|
||||||
} else {
|
} else {
|
||||||
TextureInfo& texture = screen_infos[i].texture;
|
TextureInfo& texture = screen_infos[i].texture;
|
||||||
if (texture.width != framebuffer.width || texture.height != framebuffer.height ||
|
if (texture.width != framebuffer.width || texture.height != framebuffer.height ||
|
||||||
@@ -197,7 +198,8 @@ void RendererVulkan::BeginRendering() {
|
|||||||
present_textures[i] = vk::DescriptorImageInfo{
|
present_textures[i] = vk::DescriptorImageInfo{
|
||||||
.imageView = info.display_texture ? info.display_texture->image_view
|
.imageView = info.display_texture ? info.display_texture->image_view
|
||||||
: info.texture.alloc.image_view,
|
: info.texture.alloc.image_view,
|
||||||
.imageLayout = vk::ImageLayout::eGeneral};
|
.imageLayout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
present_textures[3] = vk::DescriptorImageInfo{.sampler = present_samplers[current_sampler]};
|
present_textures[3] = vk::DescriptorImageInfo{.sampler = present_samplers[current_sampler]};
|
||||||
@@ -295,41 +297,53 @@ void RendererVulkan::CompileShaders() {
|
|||||||
|
|
||||||
void RendererVulkan::BuildLayouts() {
|
void RendererVulkan::BuildLayouts() {
|
||||||
const std::array present_layout_bindings = {
|
const std::array present_layout_bindings = {
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 0,
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 0,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.descriptorCount = 3,
|
.descriptorCount = 3,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eFragment},
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 1,
|
},
|
||||||
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampler,
|
.descriptorType = vk::DescriptorType::eSampler,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eFragment}};
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::DescriptorSetLayoutCreateInfo present_layout_info = {
|
const vk::DescriptorSetLayoutCreateInfo present_layout_info = {
|
||||||
.bindingCount = static_cast<u32>(present_layout_bindings.size()),
|
.bindingCount = static_cast<u32>(present_layout_bindings.size()),
|
||||||
.pBindings = present_layout_bindings.data()};
|
.pBindings = present_layout_bindings.data(),
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info);
|
present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info);
|
||||||
|
|
||||||
const std::array update_template_entries = {
|
const std::array update_template_entries = {
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 0,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 3,
|
.descriptorCount = 3,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.stride = sizeof(vk::DescriptorImageInfo)},
|
.stride = sizeof(vk::DescriptorImageInfo),
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
|
},
|
||||||
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 1,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampler,
|
.descriptorType = vk::DescriptorType::eSampler,
|
||||||
.offset = 3 * sizeof(vk::DescriptorImageInfo),
|
.offset = 3 * sizeof(vk::DescriptorImageInfo),
|
||||||
.stride = 0}};
|
.stride = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||||
.descriptorSetLayout = present_descriptor_layout};
|
.descriptorSetLayout = present_descriptor_layout,
|
||||||
|
};
|
||||||
|
|
||||||
present_update_template = device.createDescriptorUpdateTemplate(template_info);
|
present_update_template = device.createDescriptorUpdateTemplate(template_info);
|
||||||
|
|
||||||
@@ -339,37 +353,49 @@ void RendererVulkan::BuildLayouts() {
|
|||||||
.size = sizeof(PresentUniformData),
|
.size = sizeof(PresentUniformData),
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
|
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||||
|
.setLayoutCount = 1,
|
||||||
.pSetLayouts = &present_descriptor_layout,
|
.pSetLayouts = &present_descriptor_layout,
|
||||||
.pushConstantRangeCount = 1,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = &push_range};
|
.pPushConstantRanges = &push_range,
|
||||||
|
};
|
||||||
|
|
||||||
present_pipeline_layout = device.createPipelineLayout(layout_info);
|
present_pipeline_layout = device.createPipelineLayout(layout_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::BuildPipelines() {
|
void RendererVulkan::BuildPipelines() {
|
||||||
const vk::VertexInputBindingDescription binding = {.binding = 0,
|
const vk::VertexInputBindingDescription binding = {
|
||||||
|
.binding = 0,
|
||||||
.stride = sizeof(ScreenRectVertex),
|
.stride = sizeof(ScreenRectVertex),
|
||||||
.inputRate = vk::VertexInputRate::eVertex};
|
.inputRate = vk::VertexInputRate::eVertex,
|
||||||
|
};
|
||||||
|
|
||||||
const std::array attributes = {
|
const std::array attributes = {
|
||||||
vk::VertexInputAttributeDescription{.location = 0,
|
vk::VertexInputAttributeDescription{
|
||||||
|
.location = 0,
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.format = vk::Format::eR32G32Sfloat,
|
.format = vk::Format::eR32G32Sfloat,
|
||||||
.offset = offsetof(ScreenRectVertex, position)},
|
.offset = offsetof(ScreenRectVertex, position),
|
||||||
vk::VertexInputAttributeDescription{.location = 1,
|
},
|
||||||
|
vk::VertexInputAttributeDescription{
|
||||||
|
.location = 1,
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.format = vk::Format::eR32G32Sfloat,
|
.format = vk::Format::eR32G32Sfloat,
|
||||||
.offset = offsetof(ScreenRectVertex, tex_coord)}};
|
.offset = offsetof(ScreenRectVertex, tex_coord),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
|
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
|
||||||
.vertexBindingDescriptionCount = 1,
|
.vertexBindingDescriptionCount = 1,
|
||||||
.pVertexBindingDescriptions = &binding,
|
.pVertexBindingDescriptions = &binding,
|
||||||
.vertexAttributeDescriptionCount = static_cast<u32>(attributes.size()),
|
.vertexAttributeDescriptionCount = static_cast<u32>(attributes.size()),
|
||||||
.pVertexAttributeDescriptions = attributes.data()};
|
.pVertexAttributeDescriptions = attributes.data(),
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||||
.topology = vk::PrimitiveTopology::eTriangleStrip, .primitiveRestartEnable = false};
|
.topology = vk::PrimitiveTopology::eTriangleStrip,
|
||||||
|
.primitiveRestartEnable = false,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
||||||
.depthClampEnable = false,
|
.depthClampEnable = false,
|
||||||
@@ -377,21 +403,26 @@ void RendererVulkan::BuildPipelines() {
|
|||||||
.cullMode = vk::CullModeFlagBits::eNone,
|
.cullMode = vk::CullModeFlagBits::eNone,
|
||||||
.frontFace = vk::FrontFace::eClockwise,
|
.frontFace = vk::FrontFace::eClockwise,
|
||||||
.depthBiasEnable = false,
|
.depthBiasEnable = false,
|
||||||
.lineWidth = 1.0f};
|
.lineWidth = 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
||||||
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false};
|
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||||
|
.sampleShadingEnable = false,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
||||||
.blendEnable = false,
|
.blendEnable = false,
|
||||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
||||||
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA};
|
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
||||||
.logicOpEnable = false,
|
.logicOpEnable = false,
|
||||||
.attachmentCount = 1,
|
.attachmentCount = 1,
|
||||||
.pAttachments = &colorblend_attachment,
|
.pAttachments = &colorblend_attachment,
|
||||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f}};
|
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::Viewport placeholder_viewport = vk::Viewport{0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
|
const vk::Viewport placeholder_viewport = vk::Viewport{0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
|
||||||
const vk::Rect2D placeholder_scissor = vk::Rect2D{{0, 0}, {1, 1}};
|
const vk::Rect2D placeholder_scissor = vk::Rect2D{{0, 0}, {1, 1}};
|
||||||
@@ -402,27 +433,36 @@ void RendererVulkan::BuildPipelines() {
|
|||||||
.pScissors = &placeholder_scissor,
|
.pScissors = &placeholder_scissor,
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::array dynamic_states = {vk::DynamicState::eViewport, vk::DynamicState::eScissor};
|
const std::array dynamic_states = {
|
||||||
|
vk::DynamicState::eViewport,
|
||||||
|
vk::DynamicState::eScissor,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
|
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
|
||||||
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
|
.dynamicStateCount = static_cast<u32>(dynamic_states.size()),
|
||||||
.pDynamicStates = dynamic_states.data()};
|
.pDynamicStates = dynamic_states.data(),
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineDepthStencilStateCreateInfo depth_info = {.depthTestEnable = false,
|
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
|
||||||
|
.depthTestEnable = false,
|
||||||
.depthWriteEnable = false,
|
.depthWriteEnable = false,
|
||||||
.depthCompareOp =
|
.depthCompareOp = vk::CompareOp::eAlways,
|
||||||
vk::CompareOp::eAlways,
|
|
||||||
.depthBoundsTestEnable = false,
|
.depthBoundsTestEnable = false,
|
||||||
.stencilTestEnable = false};
|
.stencilTestEnable = false,
|
||||||
|
};
|
||||||
|
|
||||||
for (u32 i = 0; i < PRESENT_PIPELINES; i++) {
|
for (u32 i = 0; i < PRESENT_PIPELINES; i++) {
|
||||||
const std::array shader_stages = {
|
const std::array shader_stages = {
|
||||||
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eVertex,
|
vk::PipelineShaderStageCreateInfo{
|
||||||
|
.stage = vk::ShaderStageFlagBits::eVertex,
|
||||||
.module = present_vertex_shader,
|
.module = present_vertex_shader,
|
||||||
.pName = "main"},
|
.pName = "main",
|
||||||
vk::PipelineShaderStageCreateInfo{.stage = vk::ShaderStageFlagBits::eFragment,
|
},
|
||||||
|
vk::PipelineShaderStageCreateInfo{
|
||||||
|
.stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
.module = present_shaders[i],
|
.module = present_shaders[i],
|
||||||
.pName = "main"},
|
.pName = "main",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::GraphicsPipelineCreateInfo pipeline_info = {
|
const vk::GraphicsPipelineCreateInfo pipeline_info = {
|
||||||
@@ -437,7 +477,8 @@ void RendererVulkan::BuildPipelines() {
|
|||||||
.pColorBlendState = &color_blending,
|
.pColorBlendState = &color_blending,
|
||||||
.pDynamicState = &dynamic_info,
|
.pDynamicState = &dynamic_info,
|
||||||
.layout = present_pipeline_layout,
|
.layout = present_pipeline_layout,
|
||||||
.renderPass = renderpass_cache.GetPresentRenderpass()};
|
.renderPass = renderpass_cache.GetPresentRenderpass(),
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
if (const auto result = device.createGraphicsPipeline({}, pipeline_info);
|
if (const auto result = device.createGraphicsPipeline({}, pipeline_info);
|
||||||
@@ -453,67 +494,80 @@ void RendererVulkan::BuildPipelines() {
|
|||||||
void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture,
|
void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture,
|
||||||
const GPU::Regs::FramebufferConfig& framebuffer) {
|
const GPU::Regs::FramebufferConfig& framebuffer) {
|
||||||
TextureInfo old_texture = std::move(texture);
|
TextureInfo old_texture = std::move(texture);
|
||||||
texture = TextureInfo{.alloc = runtime.Allocate(
|
texture = TextureInfo{
|
||||||
framebuffer.width, framebuffer.height,
|
.alloc =
|
||||||
|
runtime.Allocate(framebuffer.width, framebuffer.height,
|
||||||
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format),
|
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format),
|
||||||
VideoCore::TextureType::Texture2D),
|
VideoCore::TextureType::Texture2D),
|
||||||
.width = framebuffer.width,
|
.width = framebuffer.width,
|
||||||
.height = framebuffer.height,
|
.height = framebuffer.height,
|
||||||
.format = framebuffer.color_format};
|
.format = framebuffer.color_format,
|
||||||
|
};
|
||||||
|
|
||||||
// Recyle the old texture after allocation to avoid having duplicates of the same allocation in
|
// Recyle the old texture after allocation to avoid having duplicates of the same allocation in
|
||||||
// the recycler
|
// the recycler
|
||||||
if (old_texture.width != 0 && old_texture.height != 0) {
|
if (old_texture.width != 0 && old_texture.height != 0) {
|
||||||
const HostTextureTag tag = {.format = old_texture.alloc.format,
|
const HostTextureTag tag = {
|
||||||
|
.format = old_texture.alloc.format,
|
||||||
.width = old_texture.width,
|
.width = old_texture.width,
|
||||||
.height = old_texture.height};
|
.height = old_texture.height,
|
||||||
|
};
|
||||||
|
|
||||||
runtime.Recycle(tag, std::move(old_texture.alloc));
|
runtime.Recycle(tag, std::move(old_texture.alloc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture) {
|
void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b,
|
||||||
|
const TextureInfo& texture) {
|
||||||
const vk::ClearColorValue clear_color = {
|
const vk::ClearColorValue clear_color = {
|
||||||
.float32 = std::array{color_r / 255.0f, color_g / 255.0f, color_b / 255.0f, 1.0f}};
|
.float32 =
|
||||||
|
std::array{
|
||||||
|
color_r / 255.0f,
|
||||||
|
color_g / 255.0f,
|
||||||
|
color_b / 255.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
renderpass_cache.ExitRenderpass();
|
renderpass_cache.ExitRenderpass();
|
||||||
scheduler.Record([image = texture.alloc.image,
|
scheduler.Record([image = texture.alloc.image, clear_color](vk::CommandBuffer render_cmdbuf,
|
||||||
clear_color](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
vk::CommandBuffer) {
|
||||||
const vk::ImageSubresourceRange range = {.aspectMask = vk::ImageAspectFlagBits::eColor,
|
const vk::ImageSubresourceRange range = {
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS};
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier pre_barrier = {
|
const vk::ImageMemoryBarrier pre_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead |
|
.srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
|
||||||
vk::AccessFlagBits::eTransferRead,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
.oldLayout = vk::ImageLayout::eGeneral,
|
.oldLayout = vk::ImageLayout::eGeneral,
|
||||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = range
|
.subresourceRange = range,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier post_barrier = {
|
const vk::ImageMemoryBarrier post_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead |
|
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
|
||||||
vk::AccessFlagBits::eTransferRead,
|
|
||||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.newLayout = vk::ImageLayout::eGeneral,
|
.newLayout = vk::ImageLayout::eGeneral,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = range
|
.subresourceRange = range,
|
||||||
};
|
};
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::PipelineStageFlagBits::eTransfer,
|
vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
|
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
|
||||||
|
|
||||||
render_cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear_color, range);
|
render_cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear_color,
|
||||||
|
range);
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
vk::PipelineStageFlagBits::eAllCommands,
|
||||||
@@ -873,14 +927,19 @@ void RendererVulkan::SwapBuffers() {
|
|||||||
} while (swapchain.NeedsRecreation());
|
} while (swapchain.NeedsRecreation());
|
||||||
|
|
||||||
scheduler.Record([layout](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
scheduler.Record([layout](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
const vk::Viewport viewport = {.x = 0.0f,
|
const vk::Viewport viewport = {
|
||||||
|
.x = 0.0f,
|
||||||
.y = 0.0f,
|
.y = 0.0f,
|
||||||
.width = static_cast<float>(layout.width),
|
.width = static_cast<float>(layout.width),
|
||||||
.height = static_cast<float>(layout.height),
|
.height = static_cast<float>(layout.height),
|
||||||
.minDepth = 0.0f,
|
.minDepth = 0.0f,
|
||||||
.maxDepth = 1.0f};
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::Rect2D scissor = {.offset = {0, 0}, .extent = {layout.width, layout.height}};
|
const vk::Rect2D scissor = {
|
||||||
|
.offset = {0, 0},
|
||||||
|
.extent = {layout.width, layout.height},
|
||||||
|
};
|
||||||
|
|
||||||
render_cmdbuf.setViewport(0, viewport);
|
render_cmdbuf.setViewport(0, viewport);
|
||||||
render_cmdbuf.setScissor(0, scissor);
|
render_cmdbuf.setScissor(0, scissor);
|
||||||
@@ -888,20 +947,6 @@ void RendererVulkan::SwapBuffers() {
|
|||||||
|
|
||||||
DrawScreens(layout, false);
|
DrawScreens(layout, false);
|
||||||
|
|
||||||
/*renderpass_cache.ExitRenderpass();
|
|
||||||
|
|
||||||
scheduler.Record([](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
|
||||||
const vk::MemoryBarrier memory_write_barrier = {
|
|
||||||
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
|
|
||||||
};
|
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
|
||||||
vk::DependencyFlagBits::eByRegion,
|
|
||||||
memory_write_barrier, {}, {});
|
|
||||||
});*/
|
|
||||||
|
|
||||||
const vk::Semaphore image_acquired = swapchain.GetImageAcquiredSemaphore();
|
const vk::Semaphore image_acquired = swapchain.GetImageAcquiredSemaphore();
|
||||||
const vk::Semaphore present_ready = swapchain.GetPresentReadySemaphore();
|
const vk::Semaphore present_ready = swapchain.GetPresentReadySemaphore();
|
||||||
scheduler.Flush(present_ready, image_acquired);
|
scheduler.Flush(present_ready, image_acquired);
|
||||||
|
@@ -6,14 +6,15 @@
|
|||||||
#include "video_core/renderer_vulkan/vk_blit_helper.h"
|
#include "video_core/renderer_vulkan/vk_blit_helper.h"
|
||||||
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
|
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
|
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler, DescriptorManager& desc_manager)
|
BlitHelper::BlitHelper(const Instance& instance, Scheduler& scheduler,
|
||||||
|
DescriptorManager& desc_manager)
|
||||||
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} {
|
: scheduler{scheduler}, desc_manager{desc_manager}, device{instance.GetDevice()} {
|
||||||
constexpr std::string_view cs_source = R"(
|
constexpr std::string_view cs_source = R"(
|
||||||
#version 450 core
|
#version 450 core
|
||||||
@@ -39,50 +40,66 @@ imageStore(color, dst_coord, uvec4(value));
|
|||||||
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
||||||
|
|
||||||
const std::array compute_layout_bindings = {
|
const std::array compute_layout_bindings = {
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 0,
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 0,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 1,
|
},
|
||||||
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 2,
|
},
|
||||||
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 2,
|
||||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute}};
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
|
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
|
||||||
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
||||||
.pBindings = compute_layout_bindings.data()};
|
.pBindings = compute_layout_bindings.data(),
|
||||||
|
};
|
||||||
|
|
||||||
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
|
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
|
||||||
|
|
||||||
const std::array update_template_entries = {
|
const std::array update_template_entries = {
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 0,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.stride = sizeof(vk::DescriptorImageInfo)},
|
.stride = sizeof(vk::DescriptorImageInfo),
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
|
},
|
||||||
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 1,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.offset = sizeof(vk::DescriptorImageInfo),
|
.offset = sizeof(vk::DescriptorImageInfo),
|
||||||
.stride = 0},
|
.stride = 0,
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2,
|
},
|
||||||
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 2,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||||
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
||||||
.stride = 0}};
|
.stride = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||||
.descriptorSetLayout = descriptor_layout};
|
.descriptorSetLayout = descriptor_layout,
|
||||||
|
};
|
||||||
|
|
||||||
update_template = device.createDescriptorUpdateTemplate(template_info);
|
update_template = device.createDescriptorUpdateTemplate(template_info);
|
||||||
|
|
||||||
@@ -92,18 +109,25 @@ imageStore(color, dst_coord, uvec4(value));
|
|||||||
.size = sizeof(Common::Vec2i),
|
.size = sizeof(Common::Vec2i),
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
|
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||||
|
.setLayoutCount = 1,
|
||||||
.pSetLayouts = &descriptor_layout,
|
.pSetLayouts = &descriptor_layout,
|
||||||
.pushConstantRangeCount = 1,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = &push_range};
|
.pPushConstantRanges = &push_range,
|
||||||
|
};
|
||||||
|
|
||||||
compute_pipeline_layout = device.createPipelineLayout(layout_info);
|
compute_pipeline_layout = device.createPipelineLayout(layout_info);
|
||||||
|
|
||||||
const vk::PipelineShaderStageCreateInfo compute_stage = {
|
const vk::PipelineShaderStageCreateInfo compute_stage = {
|
||||||
.stage = vk::ShaderStageFlagBits::eCompute, .module = compute_shader, .pName = "main"};
|
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
.module = compute_shader,
|
||||||
|
.pName = "main",
|
||||||
|
};
|
||||||
|
|
||||||
const vk::ComputePipelineCreateInfo compute_info = {.stage = compute_stage,
|
const vk::ComputePipelineCreateInfo compute_info = {
|
||||||
.layout = compute_pipeline_layout};
|
.stage = compute_stage,
|
||||||
|
.layout = compute_pipeline_layout,
|
||||||
|
};
|
||||||
|
|
||||||
if (const auto result = device.createComputePipeline({}, compute_info);
|
if (const auto result = device.createComputePipeline({}, compute_info);
|
||||||
result.result == vk::Result::eSuccess) {
|
result.result == vk::Result::eSuccess) {
|
||||||
@@ -125,19 +149,26 @@ BlitHelper::~BlitHelper() {
|
|||||||
void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
||||||
const VideoCore::TextureBlit& blit) {
|
const VideoCore::TextureBlit& blit) {
|
||||||
const std::array textures = {
|
const std::array textures = {
|
||||||
vk::DescriptorImageInfo{.imageView = source.GetDepthView(),
|
vk::DescriptorImageInfo{
|
||||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
.imageView = source.GetDepthView(),
|
||||||
vk::DescriptorImageInfo{.imageView = source.GetStencilView(),
|
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
},
|
||||||
vk::DescriptorImageInfo{.imageView = dest.GetImageView(),
|
vk::DescriptorImageInfo{
|
||||||
.imageLayout = vk::ImageLayout::eGeneral}};
|
.imageView = source.GetStencilView(),
|
||||||
|
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||||
|
},
|
||||||
|
vk::DescriptorImageInfo{
|
||||||
|
.imageView = dest.GetImageView(),
|
||||||
|
.imageLayout = vk::ImageLayout::eGeneral,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
|
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
|
||||||
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
|
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
|
||||||
|
|
||||||
scheduler.Record([this, set, blit,
|
scheduler.Record([this, set, blit, src_image = source.alloc.image,
|
||||||
src_image = source.alloc.image,
|
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
|
||||||
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
vk::CommandBuffer) {
|
||||||
const std::array pre_barriers = {
|
const std::array pre_barriers = {
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||||
@@ -150,8 +181,8 @@ void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
|||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = src_image,
|
.image = src_image,
|
||||||
.subresourceRange{
|
.subresourceRange{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
.aspectMask =
|
||||||
vk::ImageAspectFlagBits::eStencil,
|
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
@@ -173,8 +204,7 @@ void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
|||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
}
|
}};
|
||||||
};
|
|
||||||
const std::array post_barriers = {
|
const std::array post_barriers = {
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
|
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||||
@@ -186,8 +216,8 @@ void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
|||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = src_image,
|
.image = src_image,
|
||||||
.subresourceRange{
|
.subresourceRange{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
.aspectMask =
|
||||||
vk::ImageAspectFlagBits::eStencil,
|
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
@@ -209,13 +239,13 @@ void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
|
|||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
}
|
}};
|
||||||
};
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::PipelineStageFlagBits::eComputeShader,
|
vk::PipelineStageFlagBits::eComputeShader,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
||||||
|
|
||||||
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout, 0, set, {});
|
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout,
|
||||||
|
0, set, {});
|
||||||
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
|
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
|
||||||
|
|
||||||
const auto src_offset = Common::MakeVec(blit.src_rect.left, blit.src_rect.bottom);
|
const auto src_offset = Common::MakeVec(blit.src_rect.left, blit.src_rect.bottom);
|
||||||
|
@@ -15,26 +15,57 @@ struct Bindings {
|
|||||||
};
|
};
|
||||||
|
|
||||||
constexpr static std::array RASTERIZER_SETS = {
|
constexpr static std::array RASTERIZER_SETS = {
|
||||||
Bindings{// Utility set
|
Bindings{
|
||||||
.bindings = {vk::DescriptorType::eUniformBuffer, vk::DescriptorType::eUniformBuffer,
|
// Utility set
|
||||||
|
.bindings =
|
||||||
|
{
|
||||||
|
vk::DescriptorType::eUniformBuffer,
|
||||||
|
vk::DescriptorType::eUniformBuffer,
|
||||||
vk::DescriptorType::eUniformTexelBuffer,
|
vk::DescriptorType::eUniformTexelBuffer,
|
||||||
vk::DescriptorType::eUniformTexelBuffer,
|
vk::DescriptorType::eUniformTexelBuffer,
|
||||||
vk::DescriptorType::eUniformTexelBuffer},
|
vk::DescriptorType::eUniformTexelBuffer,
|
||||||
.binding_count = 5},
|
},
|
||||||
Bindings{// Texture set
|
.binding_count = 5,
|
||||||
.bindings = {vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage,
|
},
|
||||||
vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage},
|
Bindings{
|
||||||
.binding_count = 4},
|
// Texture set
|
||||||
Bindings{// Sampler set
|
.bindings =
|
||||||
.bindings = {vk::DescriptorType::eSampler, vk::DescriptorType::eSampler,
|
{
|
||||||
vk::DescriptorType::eSampler, vk::DescriptorType::eSampler},
|
vk::DescriptorType::eSampledImage,
|
||||||
.binding_count = 4},
|
vk::DescriptorType::eSampledImage,
|
||||||
Bindings{// Shadow set
|
vk::DescriptorType::eSampledImage,
|
||||||
.bindings = {vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
|
vk::DescriptorType::eSampledImage,
|
||||||
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
|
},
|
||||||
vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage,
|
.binding_count = 4,
|
||||||
vk::DescriptorType::eStorageImage},
|
},
|
||||||
.binding_count = 4}};
|
Bindings{
|
||||||
|
// Sampler set
|
||||||
|
.bindings =
|
||||||
|
{
|
||||||
|
vk::DescriptorType::eSampler,
|
||||||
|
vk::DescriptorType::eSampler,
|
||||||
|
vk::DescriptorType::eSampler,
|
||||||
|
vk::DescriptorType::eSampler,
|
||||||
|
},
|
||||||
|
.binding_count = 4,
|
||||||
|
},
|
||||||
|
Bindings{
|
||||||
|
// Shadow set
|
||||||
|
.bindings =
|
||||||
|
{
|
||||||
|
vk::DescriptorType::eStorageImage,
|
||||||
|
vk::DescriptorType::eStorageImage,
|
||||||
|
vk::DescriptorType::eStorageImage,
|
||||||
|
vk::DescriptorType::eStorageImage,
|
||||||
|
vk::DescriptorType::eStorageImage,
|
||||||
|
vk::DescriptorType::eStorageImage,
|
||||||
|
vk::DescriptorType::eStorageImage,
|
||||||
|
},
|
||||||
|
.binding_count = 4, // TODO: Combine cube faces to a single storage image
|
||||||
|
// some android devices only expose up to four storage
|
||||||
|
// slots per pipeline
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) {
|
constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) {
|
||||||
vk::ShaderStageFlags flags;
|
vk::ShaderStageFlags flags;
|
||||||
@@ -66,7 +97,7 @@ DescriptorManager::DescriptorManager(const Instance& instance, Scheduler& schedu
|
|||||||
}
|
}
|
||||||
|
|
||||||
DescriptorManager::~DescriptorManager() {
|
DescriptorManager::~DescriptorManager() {
|
||||||
vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
device.destroyPipelineLayout(pipeline_layout);
|
device.destroyPipelineLayout(pipeline_layout);
|
||||||
|
|
||||||
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||||
@@ -89,7 +120,7 @@ void DescriptorManager::BindDescriptorSets() {
|
|||||||
descriptor_set_dirty.fill(true);
|
descriptor_set_dirty.fill(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> bound_sets;
|
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> bound_sets;
|
||||||
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||||
if (descriptor_set_dirty[i]) {
|
if (descriptor_set_dirty[i]) {
|
||||||
@@ -116,51 +147,59 @@ void DescriptorManager::BuildLayouts() {
|
|||||||
std::array<vk::DescriptorSetLayoutBinding, MAX_DESCRIPTORS> set_bindings;
|
std::array<vk::DescriptorSetLayoutBinding, MAX_DESCRIPTORS> set_bindings;
|
||||||
std::array<vk::DescriptorUpdateTemplateEntry, MAX_DESCRIPTORS> update_entries;
|
std::array<vk::DescriptorUpdateTemplateEntry, MAX_DESCRIPTORS> update_entries;
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||||
const auto& set = RASTERIZER_SETS[i];
|
const auto& set = RASTERIZER_SETS[i];
|
||||||
for (u32 j = 0; j < set.binding_count; j++) {
|
for (u32 j = 0; j < set.binding_count; j++) {
|
||||||
vk::DescriptorType type = set.bindings[j];
|
const vk::DescriptorType type = set.bindings[j];
|
||||||
set_bindings[j] = vk::DescriptorSetLayoutBinding{.binding = j,
|
set_bindings[j] = vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = j,
|
||||||
.descriptorType = type,
|
.descriptorType = type,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = ToVkStageFlags(type)};
|
.stageFlags = ToVkStageFlags(type),
|
||||||
|
};
|
||||||
|
|
||||||
update_entries[j] =
|
update_entries[j] = vk::DescriptorUpdateTemplateEntry{
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = j,
|
.dstBinding = j,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = type,
|
.descriptorType = type,
|
||||||
.offset = j * sizeof(DescriptorData),
|
.offset = j * sizeof(DescriptorData),
|
||||||
.stride = 0};
|
.stride = 0,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::DescriptorSetLayoutCreateInfo layout_info = {.bindingCount = set.binding_count,
|
const vk::DescriptorSetLayoutCreateInfo layout_info = {
|
||||||
.pBindings = set_bindings.data()};
|
.bindingCount = set.binding_count,
|
||||||
|
.pBindings = set_bindings.data(),
|
||||||
|
};
|
||||||
descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info);
|
descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info);
|
||||||
|
|
||||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||||
.descriptorUpdateEntryCount = set.binding_count,
|
.descriptorUpdateEntryCount = set.binding_count,
|
||||||
.pDescriptorUpdateEntries = update_entries.data(),
|
.pDescriptorUpdateEntries = update_entries.data(),
|
||||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||||
.descriptorSetLayout = descriptor_set_layouts[i]};
|
.descriptorSetLayout = descriptor_set_layouts[i],
|
||||||
|
};
|
||||||
update_templates[i] = device.createDescriptorUpdateTemplate(template_info);
|
update_templates[i] = device.createDescriptorUpdateTemplate(template_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = MAX_DESCRIPTOR_SETS,
|
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||||
|
.setLayoutCount = MAX_DESCRIPTOR_SETS,
|
||||||
.pSetLayouts = descriptor_set_layouts.data(),
|
.pSetLayouts = descriptor_set_layouts.data(),
|
||||||
.pushConstantRangeCount = 0,
|
.pushConstantRangeCount = 0,
|
||||||
.pPushConstantRanges = nullptr};
|
.pPushConstantRanges = nullptr,
|
||||||
|
};
|
||||||
pipeline_layout = device.createPipelineLayout(layout_info);
|
pipeline_layout = device.createPipelineLayout(layout_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) {
|
vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) {
|
||||||
vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
|
|
||||||
const vk::DescriptorSetAllocateInfo alloc_info = {
|
const vk::DescriptorSetAllocateInfo alloc_info = {
|
||||||
.descriptorPool = current_pool, .descriptorSetCount = 1, .pSetLayouts = &layout};
|
.descriptorPool = current_pool,
|
||||||
|
.descriptorSetCount = 1,
|
||||||
|
.pSetLayouts = &layout,
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return device.allocateDescriptorSets(alloc_info)[0];
|
return device.allocateDescriptorSets(alloc_info)[0];
|
||||||
|
@@ -4,16 +4,17 @@
|
|||||||
|
|
||||||
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
|
#include "video_core/renderer_vulkan/vk_descriptor_manager.h"
|
||||||
#include "video_core/renderer_vulkan/vk_format_reinterpreter.h"
|
#include "video_core/renderer_vulkan/vk_format_reinterpreter.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
|
#include "video_core/renderer_vulkan/vk_texture_runtime.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
D24S8toRGBA8::D24S8toRGBA8(const Instance& instance, Scheduler& scheduler,
|
D24S8toRGBA8::D24S8toRGBA8(const Instance& instance, Scheduler& scheduler,
|
||||||
DescriptorManager& desc_manager, TextureRuntime& runtime)
|
DescriptorManager& desc_manager, TextureRuntime& runtime)
|
||||||
: FormatReinterpreterBase{instance, scheduler, desc_manager, runtime}, device{instance.GetDevice()} {
|
: FormatReinterpreterBase{instance, scheduler, desc_manager, runtime},
|
||||||
|
device{instance.GetDevice()} {
|
||||||
constexpr std::string_view cs_source = R"(
|
constexpr std::string_view cs_source = R"(
|
||||||
#version 450 core
|
#version 450 core
|
||||||
#extension GL_EXT_samplerless_texture_functions : require
|
#extension GL_EXT_samplerless_texture_functions : require
|
||||||
@@ -38,50 +39,64 @@ imageStore(color, tex_coord, vec4(components) / (exp2(8.0) - 1.0));
|
|||||||
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
Compile(cs_source, vk::ShaderStageFlagBits::eCompute, device, ShaderOptimization::High);
|
||||||
|
|
||||||
const std::array compute_layout_bindings = {
|
const std::array compute_layout_bindings = {
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 0,
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 0,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 1,
|
},
|
||||||
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute},
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
vk::DescriptorSetLayoutBinding{.binding = 2,
|
},
|
||||||
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 2,
|
||||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute}};
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
|
const vk::DescriptorSetLayoutCreateInfo compute_layout_info = {
|
||||||
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
.bindingCount = static_cast<u32>(compute_layout_bindings.size()),
|
||||||
.pBindings = compute_layout_bindings.data()};
|
.pBindings = compute_layout_bindings.data(),
|
||||||
|
};
|
||||||
|
|
||||||
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
|
descriptor_layout = device.createDescriptorSetLayout(compute_layout_info);
|
||||||
|
|
||||||
const std::array update_template_entries = {
|
const std::array update_template_entries = {
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 0,
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 0,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.stride = sizeof(vk::DescriptorImageInfo)},
|
.stride = sizeof(vk::DescriptorImageInfo),
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 1,
|
},
|
||||||
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 1,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||||
.offset = sizeof(vk::DescriptorImageInfo),
|
.offset = sizeof(vk::DescriptorImageInfo),
|
||||||
.stride = 0},
|
},
|
||||||
vk::DescriptorUpdateTemplateEntry{.dstBinding = 2,
|
vk::DescriptorUpdateTemplateEntry{
|
||||||
|
.dstBinding = 2,
|
||||||
.dstArrayElement = 0,
|
.dstArrayElement = 0,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||||
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
.offset = 2 * sizeof(vk::DescriptorImageInfo),
|
||||||
.stride = 0}};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||||
.descriptorSetLayout = descriptor_layout};
|
.descriptorSetLayout = descriptor_layout,
|
||||||
|
};
|
||||||
|
|
||||||
update_template = device.createDescriptorUpdateTemplate(template_info);
|
update_template = device.createDescriptorUpdateTemplate(template_info);
|
||||||
|
|
||||||
@@ -91,18 +106,25 @@ imageStore(color, tex_coord, vec4(components) / (exp2(8.0) - 1.0));
|
|||||||
.size = sizeof(Common::Vec2i),
|
.size = sizeof(Common::Vec2i),
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = 1,
|
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||||
|
.setLayoutCount = 1,
|
||||||
.pSetLayouts = &descriptor_layout,
|
.pSetLayouts = &descriptor_layout,
|
||||||
.pushConstantRangeCount = 1,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = &push_range};
|
.pPushConstantRanges = &push_range,
|
||||||
|
};
|
||||||
|
|
||||||
compute_pipeline_layout = device.createPipelineLayout(layout_info);
|
compute_pipeline_layout = device.createPipelineLayout(layout_info);
|
||||||
|
|
||||||
const vk::PipelineShaderStageCreateInfo compute_stage = {
|
const vk::PipelineShaderStageCreateInfo compute_stage = {
|
||||||
.stage = vk::ShaderStageFlagBits::eCompute, .module = compute_shader, .pName = "main"};
|
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
|
.module = compute_shader,
|
||||||
|
.pName = "main",
|
||||||
|
};
|
||||||
|
|
||||||
const vk::ComputePipelineCreateInfo compute_info = {.stage = compute_stage,
|
const vk::ComputePipelineCreateInfo compute_info = {
|
||||||
.layout = compute_pipeline_layout};
|
.stage = compute_stage,
|
||||||
|
.layout = compute_pipeline_layout,
|
||||||
|
};
|
||||||
|
|
||||||
if (const auto result = device.createComputePipeline({}, compute_info);
|
if (const auto result = device.createComputePipeline({}, compute_info);
|
||||||
result.result == vk::Result::eSuccess) {
|
result.result == vk::Result::eSuccess) {
|
||||||
@@ -124,20 +146,27 @@ D24S8toRGBA8::~D24S8toRGBA8() {
|
|||||||
void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surface& dest,
|
void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surface& dest,
|
||||||
VideoCore::Rect2D dst_rect) {
|
VideoCore::Rect2D dst_rect) {
|
||||||
const std::array textures = {
|
const std::array textures = {
|
||||||
vk::DescriptorImageInfo{.imageView = source.GetDepthView(),
|
vk::DescriptorImageInfo{
|
||||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
.imageView = source.GetDepthView(),
|
||||||
vk::DescriptorImageInfo{.imageView = source.GetStencilView(),
|
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||||
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal},
|
},
|
||||||
vk::DescriptorImageInfo{.imageView = dest.GetImageView(),
|
vk::DescriptorImageInfo{
|
||||||
.imageLayout = vk::ImageLayout::eGeneral}};
|
.imageView = source.GetStencilView(),
|
||||||
|
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
|
||||||
|
},
|
||||||
|
vk::DescriptorImageInfo{
|
||||||
|
.imageView = dest.GetImageView(),
|
||||||
|
.imageLayout = vk::ImageLayout::eGeneral,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
|
vk::DescriptorSet set = desc_manager.AllocateSet(descriptor_layout);
|
||||||
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
|
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
|
||||||
|
|
||||||
runtime.GetRenderpassCache().ExitRenderpass();
|
runtime.GetRenderpassCache().ExitRenderpass();
|
||||||
scheduler.Record([this, set, src_rect,
|
scheduler.Record([this, set, src_rect, src_image = source.alloc.image,
|
||||||
src_image = source.alloc.image,
|
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf,
|
||||||
dst_image = dest.alloc.image](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
vk::CommandBuffer) {
|
||||||
const vk::ImageMemoryBarrier pre_barrier = {
|
const vk::ImageMemoryBarrier pre_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
|
vk::AccessFlagBits::eDepthStencilAttachmentWrite |
|
||||||
@@ -149,8 +178,7 @@ void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surf
|
|||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = src_image,
|
.image = src_image,
|
||||||
.subresourceRange{
|
.subresourceRange{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
.aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||||
vk::ImageAspectFlagBits::eStencil,
|
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
@@ -168,8 +196,8 @@ void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surf
|
|||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = src_image,
|
.image = src_image,
|
||||||
.subresourceRange{
|
.subresourceRange{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
.aspectMask =
|
||||||
vk::ImageAspectFlagBits::eStencil,
|
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
@@ -191,13 +219,14 @@ void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surf
|
|||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
}
|
}};
|
||||||
};
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::PipelineStageFlagBits::eComputeShader,
|
vk::PipelineStageFlagBits::eComputeShader,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
|
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barrier);
|
||||||
|
|
||||||
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout, 0, set, {});
|
render_cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, compute_pipeline_layout,
|
||||||
|
0, set, {});
|
||||||
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
|
render_cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, compute_pipeline);
|
||||||
|
|
||||||
const auto src_offset = Common::MakeVec(src_rect.left, src_rect.bottom);
|
const auto src_offset = Common::MakeVec(src_rect.left, src_rect.bottom);
|
||||||
|
@@ -76,7 +76,8 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] vk::DebugUtilsMessengerCreateInfoEXT MakeDebugUtilsMessengerInfo() {
|
[[nodiscard]] vk::DebugUtilsMessengerCreateInfoEXT MakeDebugUtilsMessengerInfo() {
|
||||||
return {.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
|
return vk::DebugUtilsMessengerCreateInfoEXT{
|
||||||
|
.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo |
|
||||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError |
|
||||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
||||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose,
|
vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose,
|
||||||
@@ -84,7 +85,8 @@ vk::Format ToVkFormat(VideoCore::PixelFormat format) {
|
|||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
|
vk::DebugUtilsMessageTypeFlagBitsEXT::eDeviceAddressBinding |
|
||||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
|
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance,
|
||||||
.pfnUserCallback = DebugHandler};
|
.pfnUserCallback = DebugHandler,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
|
std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
|
||||||
@@ -99,7 +101,6 @@ std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
|
|||||||
|
|
||||||
Instance::Instance(bool validation, bool dump_command_buffers)
|
Instance::Instance(bool validation, bool dump_command_buffers)
|
||||||
: enable_validation{validation}, dump_command_buffers{dump_command_buffers} {
|
: enable_validation{validation}, dump_command_buffers{dump_command_buffers} {
|
||||||
// Fetch instance independant function pointers
|
|
||||||
auto vkGetInstanceProcAddr =
|
auto vkGetInstanceProcAddr =
|
||||||
dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||||
@@ -110,19 +111,16 @@ Instance::Instance(bool validation, bool dump_command_buffers)
|
|||||||
// Use required platform-specific flags
|
// Use required platform-specific flags
|
||||||
auto flags = GetInstanceFlags();
|
auto flags = GetInstanceFlags();
|
||||||
|
|
||||||
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra",
|
const vk::ApplicationInfo application_info = {
|
||||||
|
.pApplicationName = "Citra",
|
||||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
.pEngineName = "Citra Vulkan",
|
.pEngineName = "Citra Vulkan",
|
||||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
.apiVersion = VK_API_VERSION_1_0};
|
.apiVersion = VK_API_VERSION_1_0,
|
||||||
|
};
|
||||||
|
|
||||||
std::array<const char*, 3> layers;
|
std::array<const char*, 2> layers;
|
||||||
#ifdef ANDROID
|
|
||||||
u32 layer_count = 1;
|
|
||||||
layers[0] = "VK_LAYER_KHRONOS_timeline_semaphore";
|
|
||||||
#else
|
|
||||||
u32 layer_count = 0;
|
u32 layer_count = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (enable_validation) {
|
if (enable_validation) {
|
||||||
layers[layer_count++] = "VK_LAYER_KHRONOS_validation";
|
layers[layer_count++] = "VK_LAYER_KHRONOS_validation";
|
||||||
@@ -132,13 +130,15 @@ Instance::Instance(bool validation, bool dump_command_buffers)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const vk::StructureChain instance_chain = {
|
const vk::StructureChain instance_chain = {
|
||||||
vk::InstanceCreateInfo{.flags = flags,
|
vk::InstanceCreateInfo{
|
||||||
|
.flags = flags,
|
||||||
.pApplicationInfo = &application_info,
|
.pApplicationInfo = &application_info,
|
||||||
.enabledLayerCount = layer_count,
|
.enabledLayerCount = layer_count,
|
||||||
.ppEnabledLayerNames = layers.data(),
|
.ppEnabledLayerNames = layers.data(),
|
||||||
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
||||||
.ppEnabledExtensionNames = extensions.data()},
|
.ppEnabledExtensionNames = extensions.data(),
|
||||||
MakeDebugUtilsMessengerInfo()};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
instance = vk::createInstance(instance_chain.get());
|
instance = vk::createInstance(instance_chain.get());
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ Instance::Instance(bool validation, bool dump_command_buffers)
|
|||||||
Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
||||||
: enable_validation{Settings::values.renderer_debug},
|
: enable_validation{Settings::values.renderer_debug},
|
||||||
dump_command_buffers{Settings::values.dump_command_buffers} {
|
dump_command_buffers{Settings::values.dump_command_buffers} {
|
||||||
auto window_info = window.GetWindowInfo();
|
const Frontend::EmuWindow::WindowSystemInfo window_info = window.GetWindowInfo();
|
||||||
|
|
||||||
// Fetch instance independant function pointers
|
// Fetch instance independant function pointers
|
||||||
auto vkGetInstanceProcAddr =
|
auto vkGetInstanceProcAddr =
|
||||||
@@ -176,11 +176,13 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::ApplicationInfo application_info = {.pApplicationName = "Citra",
|
const vk::ApplicationInfo application_info = {
|
||||||
|
.pApplicationName = "Citra",
|
||||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
.pEngineName = "Citra Vulkan",
|
.pEngineName = "Citra Vulkan",
|
||||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
.apiVersion = available_version};
|
.apiVersion = available_version,
|
||||||
|
};
|
||||||
|
|
||||||
std::array<const char*, 3> layers;
|
std::array<const char*, 3> layers;
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
@@ -198,13 +200,16 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const vk::StructureChain instance_chain = {
|
const vk::StructureChain instance_chain = {
|
||||||
vk::InstanceCreateInfo{.flags = flags,
|
vk::InstanceCreateInfo{
|
||||||
|
.flags = flags,
|
||||||
.pApplicationInfo = &application_info,
|
.pApplicationInfo = &application_info,
|
||||||
.enabledLayerCount = layer_count,
|
.enabledLayerCount = layer_count,
|
||||||
.ppEnabledLayerNames = layers.data(),
|
.ppEnabledLayerNames = layers.data(),
|
||||||
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
.enabledExtensionCount = static_cast<u32>(extensions.size()),
|
||||||
.ppEnabledExtensionNames = extensions.data()},
|
.ppEnabledExtensionNames = extensions.data(),
|
||||||
MakeDebugUtilsMessengerInfo()};
|
},
|
||||||
|
MakeDebugUtilsMessengerInfo(),
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
instance = vk::createInstance(instance_chain.get());
|
instance = vk::createInstance(instance_chain.get());
|
||||||
@@ -335,13 +340,15 @@ void Instance::CreateFormatTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const u32 index = static_cast<u32>(pixel_format);
|
const u32 index = static_cast<u32>(pixel_format);
|
||||||
format_table[index] = FormatTraits{.transfer_support = supports_transfer,
|
format_table[index] = FormatTraits{
|
||||||
|
.transfer_support = supports_transfer,
|
||||||
.blit_support = supports_blit,
|
.blit_support = supports_blit,
|
||||||
.attachment_support = supports_attachment,
|
.attachment_support = supports_attachment,
|
||||||
.storage_support = supports_storage,
|
.storage_support = supports_storage,
|
||||||
.usage = best_usage,
|
.usage = best_usage,
|
||||||
.native = format,
|
.native = format,
|
||||||
.fallback = fallback};
|
.fallback = fallback,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,12 +438,17 @@ bool Instance::CreateDevice() {
|
|||||||
static constexpr float queue_priorities[] = {1.0f};
|
static constexpr float queue_priorities[] = {1.0f};
|
||||||
|
|
||||||
const std::array queue_infos = {
|
const std::array queue_infos = {
|
||||||
vk::DeviceQueueCreateInfo{.queueFamilyIndex = graphics_queue_family_index,
|
vk::DeviceQueueCreateInfo{
|
||||||
|
.queueFamilyIndex = graphics_queue_family_index,
|
||||||
.queueCount = 1,
|
.queueCount = 1,
|
||||||
.pQueuePriorities = queue_priorities},
|
.pQueuePriorities = queue_priorities,
|
||||||
vk::DeviceQueueCreateInfo{.queueFamilyIndex = present_queue_family_index,
|
},
|
||||||
|
vk::DeviceQueueCreateInfo{
|
||||||
|
.queueFamilyIndex = present_queue_family_index,
|
||||||
.queueCount = 1,
|
.queueCount = 1,
|
||||||
.pQueuePriorities = queue_priorities}};
|
.pQueuePriorities = queue_priorities,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const u32 queue_count = graphics_queue_family_index != present_queue_family_index ? 2u : 1u;
|
const u32 queue_count = graphics_queue_family_index != present_queue_family_index ? 2u : 1u;
|
||||||
const vk::StructureChain device_chain = {
|
const vk::StructureChain device_chain = {
|
||||||
@@ -447,7 +459,9 @@ bool Instance::CreateDevice() {
|
|||||||
.ppEnabledExtensionNames = enabled_extensions.data(),
|
.ppEnabledExtensionNames = enabled_extensions.data(),
|
||||||
},
|
},
|
||||||
vk::PhysicalDeviceFeatures2{
|
vk::PhysicalDeviceFeatures2{
|
||||||
.features = {.robustBufferAccess = features.robustBufferAccess,
|
.features =
|
||||||
|
{
|
||||||
|
.robustBufferAccess = features.robustBufferAccess,
|
||||||
.geometryShader = features.geometryShader,
|
.geometryShader = features.geometryShader,
|
||||||
.dualSrcBlend = features.dualSrcBlend,
|
.dualSrcBlend = features.dualSrcBlend,
|
||||||
.logicOp = features.logicOp,
|
.logicOp = features.logicOp,
|
||||||
@@ -456,14 +470,14 @@ bool Instance::CreateDevice() {
|
|||||||
.samplerAnisotropy = features.samplerAnisotropy,
|
.samplerAnisotropy = features.samplerAnisotropy,
|
||||||
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
|
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
|
||||||
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
|
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
|
||||||
.shaderClipDistance = features.shaderClipDistance}},
|
.shaderClipDistance = features.shaderClipDistance,
|
||||||
|
},
|
||||||
|
},
|
||||||
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
|
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
|
||||||
feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(),
|
feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(),
|
||||||
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
|
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
|
||||||
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()
|
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()};
|
||||||
};
|
|
||||||
|
|
||||||
// Create logical device
|
|
||||||
try {
|
try {
|
||||||
device = physical_device.createDevice(device_chain.get());
|
device = physical_device.createDevice(device_chain.get());
|
||||||
} catch (vk::ExtensionNotPresentError& err) {
|
} catch (vk::ExtensionNotPresentError& err) {
|
||||||
@@ -484,13 +498,16 @@ bool Instance::CreateDevice() {
|
|||||||
void Instance::CreateAllocator() {
|
void Instance::CreateAllocator() {
|
||||||
const VmaVulkanFunctions functions = {
|
const VmaVulkanFunctions functions = {
|
||||||
.vkGetInstanceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr,
|
.vkGetInstanceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr,
|
||||||
.vkGetDeviceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr};
|
.vkGetDeviceProcAddr = VULKAN_HPP_DEFAULT_DISPATCHER.vkGetDeviceProcAddr,
|
||||||
|
};
|
||||||
|
|
||||||
const VmaAllocatorCreateInfo allocator_info = {.physicalDevice = physical_device,
|
const VmaAllocatorCreateInfo allocator_info = {
|
||||||
|
.physicalDevice = physical_device,
|
||||||
.device = device,
|
.device = device,
|
||||||
.pVulkanFunctions = &functions,
|
.pVulkanFunctions = &functions,
|
||||||
.instance = instance,
|
.instance = instance,
|
||||||
.vulkanApiVersion = VK_API_VERSION_1_1};
|
.vulkanApiVersion = VK_API_VERSION_1_1,
|
||||||
|
};
|
||||||
|
|
||||||
if (VkResult result = vmaCreateAllocator(&allocator_info, &allocator); result != VK_SUCCESS) {
|
if (VkResult result = vmaCreateAllocator(&allocator_info, &allocator); result != VK_SUCCESS) {
|
||||||
LOG_CRITICAL(Render_Vulkan, "Failed to initialize VMA with error {}", result);
|
LOG_CRITICAL(Render_Vulkan, "Failed to initialize VMA with error {}", result);
|
||||||
|
@@ -7,12 +7,13 @@
|
|||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
MasterSemaphore::MasterSemaphore(const Instance& instance) : device{instance.GetDevice()} {
|
MasterSemaphore::MasterSemaphore(const Instance& instance) : device{instance.GetDevice()} {
|
||||||
const vk::StructureChain semaphore_chain = {vk::SemaphoreCreateInfo{},
|
const vk::StructureChain semaphore_chain = {
|
||||||
|
vk::SemaphoreCreateInfo{},
|
||||||
vk::SemaphoreTypeCreateInfoKHR{
|
vk::SemaphoreTypeCreateInfoKHR{
|
||||||
.semaphoreType = vk::SemaphoreType::eTimeline,
|
.semaphoreType = vk::SemaphoreType::eTimeline,
|
||||||
.initialValue = 0,
|
.initialValue = 0,
|
||||||
}};
|
},
|
||||||
|
};
|
||||||
semaphore = device.createSemaphore(semaphore_chain.get());
|
semaphore = device.createSemaphore(semaphore_chain.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,10 +4,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <limits>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <vector>
|
#include <limits>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/renderer_vulkan/vk_common.h"
|
#include "video_core/renderer_vulkan/vk_common.h"
|
||||||
|
|
||||||
|
@@ -32,15 +32,32 @@ u32 AttribBytes(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vk::Format ToVkAttributeFormat(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
|
vk::Format ToVkAttributeFormat(Pica::PipelineRegs::VertexAttributeFormat format, u32 size) {
|
||||||
constexpr std::array attribute_formats = {
|
static constexpr std::array attribute_formats = {
|
||||||
std::array{vk::Format::eR8Sint, vk::Format::eR8G8Sint, vk::Format::eR8G8B8Sint,
|
std::array{
|
||||||
vk::Format::eR8G8B8A8Sint},
|
vk::Format::eR8Sint,
|
||||||
std::array{vk::Format::eR8Uint, vk::Format::eR8G8Uint, vk::Format::eR8G8B8Uint,
|
vk::Format::eR8G8Sint,
|
||||||
vk::Format::eR8G8B8A8Uint},
|
vk::Format::eR8G8B8Sint,
|
||||||
std::array{vk::Format::eR16Sint, vk::Format::eR16G16Sint, vk::Format::eR16G16B16Sint,
|
vk::Format::eR8G8B8A8Sint,
|
||||||
vk::Format::eR16G16B16A16Sint},
|
},
|
||||||
std::array{vk::Format::eR32Sfloat, vk::Format::eR32G32Sfloat, vk::Format::eR32G32B32Sfloat,
|
std::array{
|
||||||
vk::Format::eR32G32B32A32Sfloat}};
|
vk::Format::eR8Uint,
|
||||||
|
vk::Format::eR8G8Uint,
|
||||||
|
vk::Format::eR8G8B8Uint,
|
||||||
|
vk::Format::eR8G8B8A8Uint,
|
||||||
|
},
|
||||||
|
std::array{
|
||||||
|
vk::Format::eR16Sint,
|
||||||
|
vk::Format::eR16G16Sint,
|
||||||
|
vk::Format::eR16G16B16Sint,
|
||||||
|
vk::Format::eR16G16B16A16Sint,
|
||||||
|
},
|
||||||
|
std::array{
|
||||||
|
vk::Format::eR32Sfloat,
|
||||||
|
vk::Format::eR32G32Sfloat,
|
||||||
|
vk::Format::eR32G32B32Sfloat,
|
||||||
|
vk::Format::eR32G32B32A32Sfloat,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
ASSERT(size <= 4);
|
ASSERT(size <= 4);
|
||||||
return attribute_formats[static_cast<u32>(format)][size - 1];
|
return attribute_formats[static_cast<u32>(format)][size - 1];
|
||||||
@@ -126,7 +143,10 @@ void PipelineCache::LoadDiskCache() {
|
|||||||
|
|
||||||
const std::string cache_file_path = fmt::format("{}{:x}{:x}.bin", GetPipelineCacheDir(),
|
const std::string cache_file_path = fmt::format("{}{:x}{:x}.bin", GetPipelineCacheDir(),
|
||||||
instance.GetVendorID(), instance.GetDeviceID());
|
instance.GetVendorID(), instance.GetDeviceID());
|
||||||
vk::PipelineCacheCreateInfo cache_info = {.initialDataSize = 0, .pInitialData = nullptr};
|
vk::PipelineCacheCreateInfo cache_info = {
|
||||||
|
.initialDataSize = 0,
|
||||||
|
.pInitialData = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<u8> cache_data;
|
std::vector<u8> cache_data;
|
||||||
FileUtil::IOFile cache_file{cache_file_path, "r"};
|
FileUtil::IOFile cache_file{cache_file_path, "r"};
|
||||||
@@ -289,29 +309,46 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
|
|||||||
|
|
||||||
void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view) {
|
void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view) {
|
||||||
const vk::DescriptorImageInfo image_info = {
|
const vk::DescriptorImageInfo image_info = {
|
||||||
.imageView = image_view, .imageLayout = vk::ImageLayout::eGeneral};
|
.imageView = image_view,
|
||||||
|
.imageLayout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
desc_manager.SetBinding(1, binding, DescriptorData{image_info});
|
desc_manager.SetBinding(1, binding, DescriptorData{image_info});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) {
|
void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) {
|
||||||
const vk::DescriptorImageInfo image_info = {.imageView = image_view,
|
const vk::DescriptorImageInfo image_info = {
|
||||||
.imageLayout = vk::ImageLayout::eGeneral};
|
.imageView = image_view,
|
||||||
|
.imageLayout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
desc_manager.SetBinding(3, binding, DescriptorData{image_info});
|
desc_manager.SetBinding(3, binding, DescriptorData{image_info});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) {
|
void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) {
|
||||||
const DescriptorData data = {
|
const DescriptorData data = {
|
||||||
.buffer_info = vk::DescriptorBufferInfo{.buffer = buffer, .offset = offset, .range = size}};
|
.buffer_info =
|
||||||
|
vk::DescriptorBufferInfo{
|
||||||
|
.buffer = buffer,
|
||||||
|
.offset = offset,
|
||||||
|
.range = size,
|
||||||
|
},
|
||||||
|
};
|
||||||
desc_manager.SetBinding(0, binding, data);
|
desc_manager.SetBinding(0, binding, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) {
|
void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) {
|
||||||
const DescriptorData data = {.buffer_view = buffer_view};
|
const DescriptorData data = {
|
||||||
|
.buffer_view = buffer_view,
|
||||||
|
};
|
||||||
desc_manager.SetBinding(0, binding, data);
|
desc_manager.SetBinding(0, binding, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::BindSampler(u32 binding, vk::Sampler sampler) {
|
void PipelineCache::BindSampler(u32 binding, vk::Sampler sampler) {
|
||||||
const DescriptorData data = {.image_info = vk::DescriptorImageInfo{.sampler = sampler}};
|
const DescriptorData data = {
|
||||||
|
.image_info =
|
||||||
|
vk::DescriptorImageInfo{
|
||||||
|
.sampler = sampler,
|
||||||
|
},
|
||||||
|
};
|
||||||
desc_manager.SetBinding(2, binding, data);
|
desc_manager.SetBinding(2, binding, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,18 +448,21 @@ void PipelineCache::ApplyDynamic(const PipelineInfo& info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
||||||
vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
|
|
||||||
u32 shader_count = 0;
|
u32 shader_count = 0;
|
||||||
std::array<vk::PipelineShaderStageCreateInfo, MAX_SHADER_STAGES> shader_stages;
|
std::array<vk::PipelineShaderStageCreateInfo, MAX_SHADER_STAGES> shader_stages;
|
||||||
for (std::size_t i = 0; i < current_shaders.size(); i++) {
|
for (std::size_t i = 0; i < current_shaders.size(); i++) {
|
||||||
vk::ShaderModule shader = current_shaders[i];
|
const vk::ShaderModule shader = current_shaders[i];
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{
|
shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{
|
||||||
.stage = ToVkShaderStage(i), .module = shader, .pName = "main"};
|
.stage = ToVkShaderStage(i),
|
||||||
|
.module = shader,
|
||||||
|
.pName = "main",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -438,7 +478,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.binding = binding.binding,
|
.binding = binding.binding,
|
||||||
.stride = binding.stride,
|
.stride = binding.stride,
|
||||||
.inputRate = binding.fixed.Value() ? vk::VertexInputRate::eInstance
|
.inputRate = binding.fixed.Value() ? vk::VertexInputRate::eInstance
|
||||||
: vk::VertexInputRate::eVertex};
|
: vk::VertexInputRate::eVertex,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 emulated_attrib_count = 0;
|
u32 emulated_attrib_count = 0;
|
||||||
@@ -453,7 +494,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.location = attrib.location,
|
.location = attrib.location,
|
||||||
.binding = attrib.binding,
|
.binding = attrib.binding,
|
||||||
.format = is_supported ? format : ToVkAttributeFormat(attrib.type, 2),
|
.format = is_supported ? format : ToVkAttributeFormat(attrib.type, 2),
|
||||||
.offset = attrib.offset};
|
.offset = attrib.offset,
|
||||||
|
};
|
||||||
|
|
||||||
// When the requested 3-component vertex format is unsupported by the hardware
|
// When the requested 3-component vertex format is unsupported by the hardware
|
||||||
// is it emulated by breaking it into a vec2 + vec1. These are combined to a vec3
|
// is it emulated by breaking it into a vec2 + vec1. These are combined to a vec3
|
||||||
@@ -466,7 +508,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.location = location,
|
.location = location,
|
||||||
.binding = attrib.binding,
|
.binding = attrib.binding,
|
||||||
.format = ToVkAttributeFormat(attrib.type, 1),
|
.format = ToVkAttributeFormat(attrib.type, 1),
|
||||||
.offset = attrib.offset + AttribBytes(attrib.type, 2)};
|
.offset = attrib.offset + AttribBytes(attrib.type, 2),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,11 +518,13 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.pVertexBindingDescriptions = bindings.data(),
|
.pVertexBindingDescriptions = bindings.data(),
|
||||||
.vertexAttributeDescriptionCount =
|
.vertexAttributeDescriptionCount =
|
||||||
info.vertex_layout.attribute_count + emulated_attrib_count,
|
info.vertex_layout.attribute_count + emulated_attrib_count,
|
||||||
.pVertexAttributeDescriptions = attributes.data()};
|
.pVertexAttributeDescriptions = attributes.data(),
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||||
.topology = PicaToVK::PrimitiveTopology(info.rasterization.topology),
|
.topology = PicaToVK::PrimitiveTopology(info.rasterization.topology),
|
||||||
.primitiveRestartEnable = false};
|
.primitiveRestartEnable = false,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
||||||
.depthClampEnable = false,
|
.depthClampEnable = false,
|
||||||
@@ -487,10 +532,13 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.cullMode = PicaToVK::CullMode(info.rasterization.cull_mode),
|
.cullMode = PicaToVK::CullMode(info.rasterization.cull_mode),
|
||||||
.frontFace = PicaToVK::FrontFace(info.rasterization.cull_mode),
|
.frontFace = PicaToVK::FrontFace(info.rasterization.cull_mode),
|
||||||
.depthBiasEnable = false,
|
.depthBiasEnable = false,
|
||||||
.lineWidth = 1.0f};
|
.lineWidth = 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
||||||
.rasterizationSamples = vk::SampleCountFlagBits::e1, .sampleShadingEnable = false};
|
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||||
|
.sampleShadingEnable = false,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
const vk::PipelineColorBlendAttachmentState colorblend_attachment = {
|
||||||
.blendEnable = info.blending.blend_enable.Value(),
|
.blendEnable = info.blending.blend_enable.Value(),
|
||||||
@@ -500,19 +548,30 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.srcAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.src_alpha_blend_factor),
|
.srcAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.src_alpha_blend_factor),
|
||||||
.dstAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.dst_alpha_blend_factor),
|
.dstAlphaBlendFactor = PicaToVK::BlendFunc(info.blending.dst_alpha_blend_factor),
|
||||||
.alphaBlendOp = PicaToVK::BlendEquation(info.blending.alpha_blend_eq),
|
.alphaBlendOp = PicaToVK::BlendEquation(info.blending.alpha_blend_eq),
|
||||||
.colorWriteMask = static_cast<vk::ColorComponentFlags>(info.blending.color_write_mask)};
|
.colorWriteMask = static_cast<vk::ColorComponentFlags>(info.blending.color_write_mask),
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
||||||
.logicOpEnable = !info.blending.blend_enable.Value() && !instance.NeedsLogicOpEmulation(),
|
.logicOpEnable = !info.blending.blend_enable.Value() && !instance.NeedsLogicOpEmulation(),
|
||||||
.logicOp = PicaToVK::LogicOp(info.blending.logic_op.Value()),
|
.logicOp = PicaToVK::LogicOp(info.blending.logic_op.Value()),
|
||||||
.attachmentCount = 1,
|
.attachmentCount = 1,
|
||||||
.pAttachments = &colorblend_attachment,
|
.pAttachments = &colorblend_attachment,
|
||||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f}};
|
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::Viewport viewport = {
|
const vk::Viewport viewport = {
|
||||||
.x = 0.0f, .y = 0.0f, .width = 1.0f, .height = 1.0f, .minDepth = 0.0f, .maxDepth = 1.0f};
|
.x = 0.0f,
|
||||||
|
.y = 0.0f,
|
||||||
|
.width = 1.0f,
|
||||||
|
.height = 1.0f,
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::Rect2D scissor = {.offset = {0, 0}, .extent = {1, 1}};
|
const vk::Rect2D scissor = {
|
||||||
|
.offset = {0, 0},
|
||||||
|
.extent = {1, 1},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
||||||
.viewportCount = 1,
|
.viewportCount = 1,
|
||||||
@@ -542,13 +601,15 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
|
|
||||||
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
|
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
|
||||||
.dynamicStateCount = extended_dynamic_states ? static_cast<u32>(dynamic_states.size()) : 6u,
|
.dynamicStateCount = extended_dynamic_states ? static_cast<u32>(dynamic_states.size()) : 6u,
|
||||||
.pDynamicStates = dynamic_states.data()};
|
.pDynamicStates = dynamic_states.data(),
|
||||||
|
};
|
||||||
|
|
||||||
const vk::StencilOpState stencil_op_state = {
|
const vk::StencilOpState stencil_op_state = {
|
||||||
.failOp = PicaToVK::StencilOp(info.depth_stencil.stencil_fail_op),
|
.failOp = PicaToVK::StencilOp(info.depth_stencil.stencil_fail_op),
|
||||||
.passOp = PicaToVK::StencilOp(info.depth_stencil.stencil_pass_op),
|
.passOp = PicaToVK::StencilOp(info.depth_stencil.stencil_pass_op),
|
||||||
.depthFailOp = PicaToVK::StencilOp(info.depth_stencil.stencil_depth_fail_op),
|
.depthFailOp = PicaToVK::StencilOp(info.depth_stencil.stencil_depth_fail_op),
|
||||||
.compareOp = PicaToVK::CompareFunc(info.depth_stencil.stencil_compare_op)};
|
.compareOp = PicaToVK::CompareFunc(info.depth_stencil.stencil_compare_op),
|
||||||
|
};
|
||||||
|
|
||||||
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
|
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
|
||||||
.depthTestEnable = static_cast<u32>(info.depth_stencil.depth_test_enable.Value()),
|
.depthTestEnable = static_cast<u32>(info.depth_stencil.depth_test_enable.Value()),
|
||||||
@@ -557,7 +618,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.depthBoundsTestEnable = false,
|
.depthBoundsTestEnable = false,
|
||||||
.stencilTestEnable = static_cast<u32>(info.depth_stencil.stencil_test_enable.Value()),
|
.stencilTestEnable = static_cast<u32>(info.depth_stencil.stencil_test_enable.Value()),
|
||||||
.front = stencil_op_state,
|
.front = stencil_op_state,
|
||||||
.back = stencil_op_state};
|
.back = stencil_op_state,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::GraphicsPipelineCreateInfo pipeline_info = {
|
const vk::GraphicsPipelineCreateInfo pipeline_info = {
|
||||||
.stageCount = shader_count,
|
.stageCount = shader_count,
|
||||||
@@ -572,7 +634,8 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) {
|
|||||||
.pDynamicState = &dynamic_info,
|
.pDynamicState = &dynamic_info,
|
||||||
.layout = desc_manager.GetPipelineLayout(),
|
.layout = desc_manager.GetPipelineLayout(),
|
||||||
.renderPass =
|
.renderPass =
|
||||||
renderpass_cache.GetRenderpass(info.color_attachment, info.depth_attachment, false)};
|
renderpass_cache.GetRenderpass(info.color_attachment, info.depth_attachment, false),
|
||||||
|
};
|
||||||
|
|
||||||
if (const auto result = device.createGraphicsPipeline(pipeline_cache, pipeline_info);
|
if (const auto result = device.createGraphicsPipeline(pipeline_cache, pipeline_info);
|
||||||
result.result == vk::Result::eSuccess) {
|
result.result == vk::Result::eSuccess) {
|
||||||
|
@@ -26,17 +26,23 @@ constexpr u32 INDEX_BUFFER_SIZE = 16 * 1024 * 1024;
|
|||||||
constexpr u32 UNIFORM_BUFFER_SIZE = 16 * 1024 * 1024;
|
constexpr u32 UNIFORM_BUFFER_SIZE = 16 * 1024 * 1024;
|
||||||
constexpr u32 TEXTURE_BUFFER_SIZE = 512 * 1024;
|
constexpr u32 TEXTURE_BUFFER_SIZE = 512 * 1024;
|
||||||
|
|
||||||
constexpr std::array TEXTURE_BUFFER_LF_FORMATS = {vk::Format::eR32G32Sfloat};
|
constexpr std::array TEXTURE_BUFFER_LF_FORMATS = {
|
||||||
|
vk::Format::eR32G32Sfloat,
|
||||||
|
};
|
||||||
|
|
||||||
constexpr std::array TEXTURE_BUFFER_FORMATS = {vk::Format::eR32G32Sfloat,
|
constexpr std::array TEXTURE_BUFFER_FORMATS = {
|
||||||
vk::Format::eR32G32B32A32Sfloat};
|
vk::Format::eR32G32Sfloat,
|
||||||
|
vk::Format::eR32G32B32A32Sfloat,
|
||||||
|
};
|
||||||
|
|
||||||
constexpr VideoCore::SurfaceParams NULL_PARAMS = {.width = 1,
|
constexpr VideoCore::SurfaceParams NULL_PARAMS = {
|
||||||
|
.width = 1,
|
||||||
.height = 1,
|
.height = 1,
|
||||||
.stride = 1,
|
.stride = 1,
|
||||||
.texture_type = VideoCore::TextureType::Texture2D,
|
.texture_type = VideoCore::TextureType::Texture2D,
|
||||||
.pixel_format = VideoCore::PixelFormat::RGBA8,
|
.pixel_format = VideoCore::PixelFormat::RGBA8,
|
||||||
.type = VideoCore::SurfaceType::Color};
|
.type = VideoCore::SurfaceType::Color,
|
||||||
|
};
|
||||||
|
|
||||||
constexpr vk::ImageUsageFlags NULL_USAGE = vk::ImageUsageFlagBits::eSampled |
|
constexpr vk::ImageUsageFlags NULL_USAGE = vk::ImageUsageFlagBits::eSampled |
|
||||||
vk::ImageUsageFlagBits::eTransferSrc |
|
vk::ImageUsageFlagBits::eTransferSrc |
|
||||||
@@ -85,7 +91,8 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan
|
|||||||
.min_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
|
.min_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
|
||||||
.mip_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
|
.mip_filter = Pica::TexturingRegs::TextureConfig::TextureFilter::Linear,
|
||||||
.wrap_s = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder,
|
.wrap_s = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder,
|
||||||
.wrap_t = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder};
|
.wrap_t = Pica::TexturingRegs::TextureConfig::WrapMode::ClampToBorder,
|
||||||
|
};
|
||||||
|
|
||||||
default_sampler = CreateSampler(default_sampler_info);
|
default_sampler = CreateSampler(default_sampler_info);
|
||||||
|
|
||||||
@@ -265,8 +272,8 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
|
|||||||
SetupFixedAttribs();
|
SetupFixedAttribs();
|
||||||
|
|
||||||
// Bind the generated bindings
|
// Bind the generated bindings
|
||||||
scheduler.Record([this, vertex_offsets = binding_offsets](
|
scheduler.Record([this, vertex_offsets = binding_offsets](vk::CommandBuffer render_cmdbuf,
|
||||||
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
vk::CommandBuffer) {
|
||||||
render_cmdbuf.bindVertexBuffers(0, vertex_buffers, vertex_offsets);
|
render_cmdbuf.bindVertexBuffers(0, vertex_buffers, vertex_offsets);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -435,8 +442,8 @@ void RasterizerVulkan::SetupIndexArray() {
|
|||||||
|
|
||||||
index_buffer.Commit(index_buffer_size);
|
index_buffer.Commit(index_buffer_size);
|
||||||
|
|
||||||
scheduler.Record([this, index_offset = index_offset, index_type = index_type](
|
scheduler.Record([this, index_offset = index_offset,
|
||||||
vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
index_type = index_type](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
render_cmdbuf.bindIndexBuffer(index_buffer.GetHandle(), index_offset, index_type);
|
render_cmdbuf.bindIndexBuffer(index_buffer.GetHandle(), index_offset, index_type);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -548,7 +555,8 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
// nothing. Always sample from the base level until mipmaps for texture cubes are
|
// nothing. Always sample from the base level until mipmaps for texture cubes are
|
||||||
// implemented
|
// implemented
|
||||||
const bool skip_mipmap = config.type == Pica::TexturingRegs::TextureConfig::TextureCube;
|
const bool skip_mipmap = config.type == Pica::TexturingRegs::TextureConfig::TextureCube;
|
||||||
info = SamplerInfo{.mag_filter = config.mag_filter,
|
info = SamplerInfo{
|
||||||
|
.mag_filter = config.mag_filter,
|
||||||
.min_filter = config.min_filter,
|
.min_filter = config.min_filter,
|
||||||
.mip_filter = config.mip_filter,
|
.mip_filter = config.mip_filter,
|
||||||
.wrap_s = config.wrap_s,
|
.wrap_s = config.wrap_s,
|
||||||
@@ -556,7 +564,8 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
.border_color = config.border_color.raw,
|
.border_color = config.border_color.raw,
|
||||||
.lod_min = skip_mipmap ? 0.f : static_cast<float>(config.lod.min_level),
|
.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_max = skip_mipmap ? 0.f : static_cast<float>(config.lod.max_level),
|
||||||
.lod_bias = static_cast<float>(config.lod.bias)};
|
.lod_bias = static_cast<float>(config.lod.bias),
|
||||||
|
};
|
||||||
|
|
||||||
// Search the cache and bind the appropriate sampler
|
// Search the cache and bind the appropriate sampler
|
||||||
if (auto it = samplers.find(info); it != samplers.end()) {
|
if (auto it = samplers.find(info); it != samplers.end()) {
|
||||||
@@ -711,7 +720,8 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
.renderpass = renderpass_cache.GetRenderpass(pipeline_info.color_attachment,
|
.renderpass = renderpass_cache.GetRenderpass(pipeline_info.color_attachment,
|
||||||
pipeline_info.depth_attachment, false),
|
pipeline_info.depth_attachment, false),
|
||||||
.width = width,
|
.width = width,
|
||||||
.height = height};
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
auto [it, new_framebuffer] = framebuffers.try_emplace(framebuffer_info, vk::Framebuffer{});
|
auto [it, new_framebuffer] = framebuffers.try_emplace(framebuffer_info, vk::Framebuffer{});
|
||||||
if (new_framebuffer) {
|
if (new_framebuffer) {
|
||||||
@@ -721,9 +731,11 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
const RenderpassState renderpass_info = {
|
const RenderpassState renderpass_info = {
|
||||||
.renderpass = framebuffer_info.renderpass,
|
.renderpass = framebuffer_info.renderpass,
|
||||||
.framebuffer = it->second,
|
.framebuffer = it->second,
|
||||||
.render_area = vk::Rect2D{.offset = {static_cast<s32>(draw_rect.left),
|
.render_area =
|
||||||
static_cast<s32>(draw_rect.bottom)},
|
vk::Rect2D{
|
||||||
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()}},
|
.offset = {static_cast<s32>(draw_rect.left), static_cast<s32>(draw_rect.bottom)},
|
||||||
|
.extent = {draw_rect.GetWidth(), draw_rect.GetHeight()},
|
||||||
|
},
|
||||||
.clear = {},
|
.clear = {},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1086,8 +1098,11 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
|
|||||||
const auto color = PicaToVK::ColorRGBA8(info.border_color);
|
const auto color = PicaToVK::ColorRGBA8(info.border_color);
|
||||||
const vk::SamplerCustomBorderColorCreateInfoEXT border_color_info = {
|
const vk::SamplerCustomBorderColorCreateInfoEXT border_color_info = {
|
||||||
.customBorderColor =
|
.customBorderColor =
|
||||||
vk::ClearColorValue{.float32 = std::array{color[0], color[1], color[2], color[3]}},
|
vk::ClearColorValue{
|
||||||
.format = vk::Format::eUndefined};
|
.float32 = std::array{color[0], color[1], color[2], color[3]},
|
||||||
|
},
|
||||||
|
.format = vk::Format::eUndefined,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::SamplerCreateInfo sampler_info = {
|
const vk::SamplerCreateInfo sampler_info = {
|
||||||
.pNext = use_border_color ? &border_color_info : nullptr,
|
.pNext = use_border_color ? &border_color_info : nullptr,
|
||||||
@@ -1105,7 +1120,8 @@ vk::Sampler RasterizerVulkan::CreateSampler(const SamplerInfo& info) {
|
|||||||
.maxLod = info.lod_max,
|
.maxLod = info.lod_max,
|
||||||
.borderColor =
|
.borderColor =
|
||||||
use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack,
|
use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack,
|
||||||
.unnormalizedCoordinates = false};
|
.unnormalizedCoordinates = false,
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
return device.createSampler(sampler_info);
|
return device.createSampler(sampler_info);
|
||||||
@@ -1123,12 +1139,14 @@ vk::Framebuffer RasterizerVulkan::CreateFramebuffer(const FramebufferInfo& info)
|
|||||||
attachments[attachment_count++] = info.depth;
|
attachments[attachment_count++] = info.depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::FramebufferCreateInfo framebuffer_info = {.renderPass = info.renderpass,
|
const vk::FramebufferCreateInfo framebuffer_info = {
|
||||||
|
.renderPass = info.renderpass,
|
||||||
.attachmentCount = attachment_count,
|
.attachmentCount = attachment_count,
|
||||||
.pAttachments = attachments.data(),
|
.pAttachments = attachments.data(),
|
||||||
.width = info.width,
|
.width = info.width,
|
||||||
.height = info.height,
|
.height = info.height,
|
||||||
.layers = 1};
|
.layers = 1,
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
return device.createFramebuffer(framebuffer_info);
|
return device.createFramebuffer(framebuffer_info);
|
||||||
|
@@ -61,11 +61,11 @@ RenderpassCache::RenderpassCache(const Instance& instance, Scheduler& scheduler)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cached_renderpasses[color][depth][0] = CreateRenderPass(
|
cached_renderpasses[color][depth][0] =
|
||||||
color_format, depth_format, vk::AttachmentLoadOp::eLoad,
|
CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eLoad,
|
||||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
cached_renderpasses[color][depth][1] = CreateRenderPass(
|
cached_renderpasses[color][depth][1] =
|
||||||
color_format, depth_format, vk::AttachmentLoadOp::eClear,
|
CreateRenderPass(color_format, depth_format, vk::AttachmentLoadOp::eClear,
|
||||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,11 +100,13 @@ void RenderpassCache::EnterRenderpass(const RenderpassState& state) {
|
|||||||
render_cmdbuf.endRenderPass();
|
render_cmdbuf.endRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::RenderPassBeginInfo renderpass_begin_info = {.renderPass = state.renderpass,
|
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||||
|
.renderPass = state.renderpass,
|
||||||
.framebuffer = state.framebuffer,
|
.framebuffer = state.framebuffer,
|
||||||
.renderArea = state.render_area,
|
.renderArea = state.render_area,
|
||||||
.clearValueCount = 1,
|
.clearValueCount = 1,
|
||||||
.pClearValues = &state.clear};
|
.pClearValues = &state.clear,
|
||||||
|
};
|
||||||
|
|
||||||
render_cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
render_cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||||
});
|
});
|
||||||
@@ -160,17 +162,20 @@ vk::RenderPass RenderpassCache::CreateRenderPass(vk::Format color, vk::Format de
|
|||||||
vk::AttachmentReference depth_attachment_ref{};
|
vk::AttachmentReference depth_attachment_ref{};
|
||||||
|
|
||||||
if (color != vk::Format::eUndefined) {
|
if (color != vk::Format::eUndefined) {
|
||||||
attachments[attachment_count] =
|
attachments[attachment_count] = vk::AttachmentDescription{
|
||||||
vk::AttachmentDescription{.format = color,
|
.format = color,
|
||||||
.loadOp = load_op,
|
.loadOp = load_op,
|
||||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
.initialLayout = initial_layout,
|
.initialLayout = initial_layout,
|
||||||
.finalLayout = final_layout};
|
.finalLayout = final_layout,
|
||||||
|
};
|
||||||
|
|
||||||
color_attachment_ref = vk::AttachmentReference{
|
color_attachment_ref = vk::AttachmentReference{
|
||||||
.attachment = attachment_count++, .layout = vk::ImageLayout::eGeneral};
|
.attachment = attachment_count++,
|
||||||
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
|
|
||||||
use_color = true;
|
use_color = true;
|
||||||
}
|
}
|
||||||
@@ -183,34 +188,38 @@ vk::RenderPass RenderpassCache::CreateRenderPass(vk::Format color, vk::Format de
|
|||||||
.stencilLoadOp = load_op,
|
.stencilLoadOp = load_op,
|
||||||
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
||||||
.initialLayout = vk::ImageLayout::eGeneral,
|
.initialLayout = vk::ImageLayout::eGeneral,
|
||||||
.finalLayout = vk::ImageLayout::eGeneral};
|
.finalLayout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
|
|
||||||
depth_attachment_ref =
|
depth_attachment_ref = vk::AttachmentReference{
|
||||||
vk::AttachmentReference{.attachment = attachment_count++,
|
.attachment = attachment_count++,
|
||||||
.layout = vk::ImageLayout::eGeneral};
|
.layout = vk::ImageLayout::eGeneral,
|
||||||
|
};
|
||||||
|
|
||||||
use_depth = true;
|
use_depth = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We also require only one subpass
|
// We also require only one subpass
|
||||||
const vk::SubpassDescription subpass = {.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
const vk::SubpassDescription subpass = {
|
||||||
|
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||||
.inputAttachmentCount = 0,
|
.inputAttachmentCount = 0,
|
||||||
.pInputAttachments = nullptr,
|
.pInputAttachments = nullptr,
|
||||||
.colorAttachmentCount = use_color ? 1u : 0u,
|
.colorAttachmentCount = use_color ? 1u : 0u,
|
||||||
.pColorAttachments = &color_attachment_ref,
|
.pColorAttachments = &color_attachment_ref,
|
||||||
.pResolveAttachments = 0,
|
.pResolveAttachments = 0,
|
||||||
.pDepthStencilAttachment =
|
.pDepthStencilAttachment = use_depth ? &depth_attachment_ref : nullptr,
|
||||||
use_depth ? &depth_attachment_ref : nullptr};
|
};
|
||||||
|
|
||||||
const vk::RenderPassCreateInfo renderpass_info = {.attachmentCount = attachment_count,
|
const vk::RenderPassCreateInfo renderpass_info = {
|
||||||
|
.attachmentCount = attachment_count,
|
||||||
.pAttachments = attachments.data(),
|
.pAttachments = attachments.data(),
|
||||||
.subpassCount = 1,
|
.subpassCount = 1,
|
||||||
.pSubpasses = &subpass,
|
.pSubpasses = &subpass,
|
||||||
.dependencyCount = 0,
|
.dependencyCount = 0,
|
||||||
.pDependencies = nullptr};
|
.pDependencies = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
// Create the renderpass
|
const vk::Device device = instance.GetDevice();
|
||||||
vk::Device device = instance.GetDevice();
|
|
||||||
return device.createRenderPass(renderpass_info);
|
return device.createRenderPass(renderpass_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -86,7 +86,8 @@ void CommandPool::Allocate(std::size_t begin, std::size_t end) {
|
|||||||
const vk::CommandPoolCreateInfo pool_create_info = {
|
const vk::CommandPoolCreateInfo pool_create_info = {
|
||||||
.flags = vk::CommandPoolCreateFlagBits::eTransient |
|
.flags = vk::CommandPoolCreateFlagBits::eTransient |
|
||||||
vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
|
vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
|
||||||
.queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex()};
|
.queueFamilyIndex = instance.GetGraphicsQueueFamilyIndex(),
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
pool.handle = device.createCommandPool(pool_create_info);
|
pool.handle = device.createCommandPool(pool_create_info);
|
||||||
@@ -94,7 +95,8 @@ void CommandPool::Allocate(std::size_t begin, std::size_t end) {
|
|||||||
const vk::CommandBufferAllocateInfo buffer_alloc_info = {
|
const vk::CommandBufferAllocateInfo buffer_alloc_info = {
|
||||||
.commandPool = pool.handle,
|
.commandPool = pool.handle,
|
||||||
.level = vk::CommandBufferLevel::ePrimary,
|
.level = vk::CommandBufferLevel::ePrimary,
|
||||||
.commandBufferCount = COMMAND_BUFFER_POOL_SIZE};
|
.commandBufferCount = COMMAND_BUFFER_POOL_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
auto buffers = device.allocateCommandBuffers(buffer_alloc_info);
|
auto buffers = device.allocateCommandBuffers(buffer_alloc_info);
|
||||||
std::copy(buffers.begin(), buffers.end(), pool.cmdbufs.begin());
|
std::copy(buffers.begin(), buffers.end(), pool.cmdbufs.begin());
|
||||||
@@ -126,17 +128,19 @@ void DescriptorPool::Allocate(std::size_t begin, std::size_t end) {
|
|||||||
vk::DescriptorPool& pool = pools.emplace_back();
|
vk::DescriptorPool& pool = pools.emplace_back();
|
||||||
|
|
||||||
// Choose a sane pool size good for most games
|
// Choose a sane pool size good for most games
|
||||||
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {
|
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {{
|
||||||
{{vk::DescriptorType::eUniformBuffer, 4096},
|
{vk::DescriptorType::eUniformBuffer, 4096},
|
||||||
{vk::DescriptorType::eSampledImage, 4096},
|
{vk::DescriptorType::eSampledImage, 4096},
|
||||||
{vk::DescriptorType::eSampler, 4096},
|
{vk::DescriptorType::eSampler, 4096},
|
||||||
{vk::DescriptorType::eUniformTexelBuffer, 2048},
|
{vk::DescriptorType::eUniformTexelBuffer, 2048},
|
||||||
{vk::DescriptorType::eStorageImage, 1024}}};
|
{vk::DescriptorType::eStorageImage, 1024},
|
||||||
|
}};
|
||||||
|
|
||||||
const vk::DescriptorPoolCreateInfo descriptor_pool_info = {
|
const vk::DescriptorPoolCreateInfo descriptor_pool_info = {
|
||||||
.maxSets = 8192,
|
.maxSets = 8192,
|
||||||
.poolSizeCount = static_cast<u32>(pool_sizes.size()),
|
.poolSizeCount = static_cast<u32>(pool_sizes.size()),
|
||||||
.pPoolSizes = pool_sizes.data()};
|
.pPoolSizes = pool_sizes.data(),
|
||||||
|
};
|
||||||
|
|
||||||
pool = instance.GetDevice().createDescriptorPool(descriptor_pool_info);
|
pool = instance.GetDevice().createDescriptorPool(descriptor_pool_info);
|
||||||
}
|
}
|
||||||
|
@@ -139,9 +139,8 @@ void Scheduler::SubmitExecution(vk::Semaphore signal_semaphore, vk::Semaphore wa
|
|||||||
renderer.FlushBuffers();
|
renderer.FlushBuffers();
|
||||||
|
|
||||||
renderpass_cache.ExitRenderpass();
|
renderpass_cache.ExitRenderpass();
|
||||||
Record([signal_semaphore, wait_semaphore,
|
Record([signal_semaphore, wait_semaphore, handle, signal_value,
|
||||||
handle, signal_value, this](vk::CommandBuffer render_cmdbuf,
|
this](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer upload_cmdbuf) {
|
||||||
vk::CommandBuffer upload_cmdbuf) {
|
|
||||||
MICROPROFILE_SCOPE(Vulkan_Submit);
|
MICROPROFILE_SCOPE(Vulkan_Submit);
|
||||||
upload_cmdbuf.end();
|
upload_cmdbuf.end();
|
||||||
render_cmdbuf.end();
|
render_cmdbuf.end();
|
||||||
|
@@ -1768,7 +1768,8 @@ layout (set = 0, binding = 0, std140) uniform vs_config {
|
|||||||
out += fmt::format("vec4 vs_out_attr{};\n", i);
|
out += fmt::format("vec4 vs_out_attr{};\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto semantic = [&config = config.state](VSOutputAttributes::Semantic slot_semantic) -> std::string {
|
const auto semantic =
|
||||||
|
[&config = config.state](VSOutputAttributes::Semantic slot_semantic) -> std::string {
|
||||||
const u32 slot = static_cast<u32>(slot_semantic);
|
const u32 slot = static_cast<u32>(slot_semantic);
|
||||||
const u32 attrib = config.semantic_maps[slot].attribute_index;
|
const u32 attrib = config.semantic_maps[slot].attribute_index;
|
||||||
const u32 comp = config.semantic_maps[slot].component_index;
|
const u32 comp = config.semantic_maps[slot].component_index;
|
||||||
@@ -1795,8 +1796,9 @@ layout (set = 0, binding = 0, std140) uniform vs_config {
|
|||||||
out += " normquat = GetVertexQuaternion();\n";
|
out += " normquat = GetVertexQuaternion();\n";
|
||||||
|
|
||||||
out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " +
|
out += " vec4 vtx_color = vec4(" + semantic(VSOutputAttributes::COLOR_R) + ", " +
|
||||||
semantic(VSOutputAttributes::COLOR_G) + ", " + semantic(VSOutputAttributes::COLOR_B) +
|
semantic(VSOutputAttributes::COLOR_G) + ", " +
|
||||||
", " + semantic(VSOutputAttributes::COLOR_A) + ");\n";
|
semantic(VSOutputAttributes::COLOR_B) + ", " +
|
||||||
|
semantic(VSOutputAttributes::COLOR_A) + ");\n";
|
||||||
out += " primary_color = min(abs(vtx_color), vec4(1.0));\n\n";
|
out += " primary_color = min(abs(vtx_color), vec4(1.0));\n\n";
|
||||||
|
|
||||||
out += " texcoord0 = vec2(" + semantic(VSOutputAttributes::TEXCOORD0_U) + ", " +
|
out += " texcoord0 = vec2(" + semantic(VSOutputAttributes::TEXCOORD0_U) + ", " +
|
||||||
|
@@ -150,8 +150,8 @@ struct PicaFSConfig : Common::HashableStruct<PicaFSConfigState> {
|
|||||||
* PICA vertex/geometry shader.
|
* PICA vertex/geometry shader.
|
||||||
*/
|
*/
|
||||||
struct PicaShaderConfigCommon {
|
struct PicaShaderConfigCommon {
|
||||||
void Init(const Pica::RasterizerRegs& rasterizer,
|
void Init(const Pica::RasterizerRegs& rasterizer, const Pica::ShaderRegs& regs,
|
||||||
const Pica::ShaderRegs& regs, Pica::Shader::ShaderSetup& setup);
|
Pica::Shader::ShaderSetup& setup);
|
||||||
|
|
||||||
u64 program_hash;
|
u64 program_hash;
|
||||||
u64 swizzle_hash;
|
u64 swizzle_hash;
|
||||||
@@ -183,8 +183,8 @@ struct PicaShaderConfigCommon {
|
|||||||
* shader.
|
* shader.
|
||||||
*/
|
*/
|
||||||
struct PicaVSConfig : Common::HashableStruct<PicaShaderConfigCommon> {
|
struct PicaVSConfig : Common::HashableStruct<PicaShaderConfigCommon> {
|
||||||
explicit PicaVSConfig(const Pica::RasterizerRegs& rasterizer,
|
explicit PicaVSConfig(const Pica::RasterizerRegs& rasterizer, const Pica::ShaderRegs& regs,
|
||||||
const Pica::ShaderRegs& regs, Pica::Shader::ShaderSetup& setup) {
|
Pica::Shader::ShaderSetup& setup) {
|
||||||
state.Init(rasterizer, regs, setup);
|
state.Init(rasterizer, regs, setup);
|
||||||
}
|
}
|
||||||
explicit PicaVSConfig(const PicaShaderConfigCommon& conf) {
|
explicit PicaVSConfig(const PicaShaderConfigCommon& conf) {
|
||||||
|
@@ -59,9 +59,10 @@ StagingBuffer::StagingBuffer(const Instance& instance, u32 size, bool readback)
|
|||||||
const VmaAllocationCreateFlags flags =
|
const VmaAllocationCreateFlags flags =
|
||||||
readback ? VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
|
readback ? VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
|
||||||
: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||||
const VmaAllocationCreateInfo alloc_create_info = {.flags =
|
const VmaAllocationCreateInfo alloc_create_info = {
|
||||||
flags | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
.flags = flags | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST};
|
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||||
|
};
|
||||||
|
|
||||||
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
|
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
|
||||||
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
|
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
|
||||||
@@ -88,11 +89,15 @@ StreamBuffer::StreamBuffer(const Instance& instance, Scheduler& scheduler, u32 s
|
|||||||
bool readback)
|
bool readback)
|
||||||
: instance{instance}, scheduler{scheduler}, staging{instance, size, readback}, usage{usage},
|
: instance{instance}, scheduler{scheduler}, staging{instance, size, readback}, usage{usage},
|
||||||
total_size{size}, bucket_size{size / BUCKET_COUNT}, readback{readback} {
|
total_size{size}, bucket_size{size / BUCKET_COUNT}, readback{readback} {
|
||||||
const vk::BufferCreateInfo buffer_info = {
|
|
||||||
.size = total_size, .usage = usage | vk::BufferUsageFlagBits::eTransferDst};
|
|
||||||
|
|
||||||
const VmaAllocationCreateInfo alloc_create_info = {.usage =
|
const vk::BufferCreateInfo buffer_info = {
|
||||||
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE};
|
.size = total_size,
|
||||||
|
.usage = usage | vk::BufferUsageFlagBits::eTransferDst,
|
||||||
|
};
|
||||||
|
|
||||||
|
const VmaAllocationCreateInfo alloc_create_info = {
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||||
|
};
|
||||||
|
|
||||||
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
|
VkBuffer unsafe_buffer = VK_NULL_HANDLE;
|
||||||
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
|
VkBufferCreateInfo unsafe_buffer_info = static_cast<VkBufferCreateInfo>(buffer_info);
|
||||||
@@ -109,7 +114,11 @@ StreamBuffer::StreamBuffer(const Instance& instance, Scheduler& scheduler, u32 s
|
|||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
for (std::size_t i = 0; i < view_formats.size(); i++) {
|
for (std::size_t i = 0; i < view_formats.size(); i++) {
|
||||||
const vk::BufferViewCreateInfo view_info = {
|
const vk::BufferViewCreateInfo view_info = {
|
||||||
.buffer = gpu_buffer, .format = view_formats[i], .offset = 0, .range = total_size};
|
.buffer = gpu_buffer,
|
||||||
|
.format = view_formats[i],
|
||||||
|
.offset = 0,
|
||||||
|
.range = total_size,
|
||||||
|
};
|
||||||
|
|
||||||
views[i] = device.createBufferView(view_info);
|
views[i] = device.createBufferView(view_info);
|
||||||
}
|
}
|
||||||
@@ -171,7 +180,10 @@ void StreamBuffer::Flush() {
|
|||||||
scheduler.Record([this, flush_start, flush_size](vk::CommandBuffer,
|
scheduler.Record([this, flush_start, flush_size](vk::CommandBuffer,
|
||||||
vk::CommandBuffer upload_cmdbuf) {
|
vk::CommandBuffer upload_cmdbuf) {
|
||||||
const vk::BufferCopy copy_region = {
|
const vk::BufferCopy copy_region = {
|
||||||
.srcOffset = flush_start, .dstOffset = flush_start, .size = flush_size};
|
.srcOffset = flush_start,
|
||||||
|
.dstOffset = flush_start,
|
||||||
|
.size = flush_size,
|
||||||
|
};
|
||||||
|
|
||||||
upload_cmdbuf.copyBuffer(staging.buffer, gpu_buffer, copy_region);
|
upload_cmdbuf.copyBuffer(staging.buffer, gpu_buffer, copy_region);
|
||||||
|
|
||||||
@@ -182,7 +194,8 @@ void StreamBuffer::Flush() {
|
|||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.buffer = gpu_buffer,
|
.buffer = gpu_buffer,
|
||||||
.offset = flush_start,
|
.offset = flush_start,
|
||||||
.size = flush_size};
|
.size = flush_size,
|
||||||
|
};
|
||||||
|
|
||||||
upload_cmdbuf.pipelineBarrier(
|
upload_cmdbuf.pipelineBarrier(
|
||||||
vk::PipelineStageFlagBits::eTransfer, MakePipelineStage(usage),
|
vk::PipelineStageFlagBits::eTransfer, MakePipelineStage(usage),
|
||||||
|
@@ -69,7 +69,8 @@ void Swapchain::Create() {
|
|||||||
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eInherit,
|
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eInherit,
|
||||||
.presentMode = present_mode,
|
.presentMode = present_mode,
|
||||||
.clipped = true,
|
.clipped = true,
|
||||||
.oldSwapchain = swapchain};
|
.oldSwapchain = swapchain,
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
vk::SwapchainKHR new_swapchain = device.createSwapchainKHR(swapchain_info);
|
vk::SwapchainKHR new_swapchain = device.createSwapchainKHR(swapchain_info);
|
||||||
@@ -111,11 +112,14 @@ void Swapchain::AcquireNextImage() {
|
|||||||
MICROPROFILE_DEFINE(Vulkan_Present, "Vulkan", "Swapchain Present", MP_RGB(66, 185, 245));
|
MICROPROFILE_DEFINE(Vulkan_Present, "Vulkan", "Swapchain Present", MP_RGB(66, 185, 245));
|
||||||
void Swapchain::Present() {
|
void Swapchain::Present() {
|
||||||
scheduler.Record([this, index = image_index](vk::CommandBuffer, vk::CommandBuffer) {
|
scheduler.Record([this, index = image_index](vk::CommandBuffer, vk::CommandBuffer) {
|
||||||
const vk::PresentInfoKHR present_info = {.waitSemaphoreCount = 1,
|
const vk::PresentInfoKHR present_info = {
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
.pWaitSemaphores = &present_ready[index],
|
.pWaitSemaphores = &present_ready[index],
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pSwapchains = &swapchain,
|
.pSwapchains = &swapchain,
|
||||||
.pImageIndices = &index};
|
.pImageIndices = &index,
|
||||||
|
};
|
||||||
|
|
||||||
MICROPROFILE_SCOPE(Vulkan_Present);
|
MICROPROFILE_SCOPE(Vulkan_Present);
|
||||||
vk::Queue present_queue = instance.GetPresentQueue();
|
vk::Queue present_queue = instance.GetPresentQueue();
|
||||||
try {
|
try {
|
||||||
@@ -233,11 +237,15 @@ void Swapchain::SetupImages() {
|
|||||||
.image = image,
|
.image = image,
|
||||||
.viewType = vk::ImageViewType::e2D,
|
.viewType = vk::ImageViewType::e2D,
|
||||||
.format = surface_format.format,
|
.format = surface_format.format,
|
||||||
.subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1}};
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
image_views.push_back(device.createImageView(view_info));
|
image_views.push_back(device.createImageView(view_info));
|
||||||
|
|
||||||
@@ -247,7 +255,8 @@ void Swapchain::SetupImages() {
|
|||||||
.pAttachments = &image_views.back(),
|
.pAttachments = &image_views.back(),
|
||||||
.width = extent.width,
|
.width = extent.width,
|
||||||
.height = extent.height,
|
.height = extent.height,
|
||||||
.layers = 1};
|
.layers = 1,
|
||||||
|
};
|
||||||
|
|
||||||
framebuffers.push_back(device.createFramebuffer(framebuffer_info));
|
framebuffers.push_back(device.createFramebuffer(framebuffer_info));
|
||||||
}
|
}
|
||||||
|
@@ -55,14 +55,14 @@ namespace Vulkan {
|
|||||||
|
|
||||||
[[nodiscard]] vk::ClearColorValue MakeClearColorValue(VideoCore::ClearValue clear) {
|
[[nodiscard]] vk::ClearColorValue MakeClearColorValue(VideoCore::ClearValue clear) {
|
||||||
return vk::ClearColorValue{
|
return vk::ClearColorValue{
|
||||||
.float32 = std::array{clear.color[0], clear.color[1], clear.color[2], clear.color[3]}
|
.float32 = std::array{clear.color[0], clear.color[1], clear.color[2], clear.color[3]},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] vk::ClearDepthStencilValue MakeClearDepthStencilValue(VideoCore::ClearValue clear) {
|
[[nodiscard]] vk::ClearDepthStencilValue MakeClearDepthStencilValue(VideoCore::ClearValue clear) {
|
||||||
return vk::ClearDepthStencilValue{
|
return vk::ClearDepthStencilValue{
|
||||||
.depth = clear.depth,
|
.depth = clear.depth,
|
||||||
.stencil = clear.stencil
|
.stencil = clear.stencil,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,14 +142,15 @@ TextureRuntime::~TextureRuntime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StagingData TextureRuntime::FindStaging(u32 size, bool upload) {
|
StagingData TextureRuntime::FindStaging(u32 size, bool upload) {
|
||||||
// Depth uploads require 4 byte alignment, doesn't hurt to do it for everyone
|
|
||||||
auto& buffer = upload ? upload_buffer : download_buffer;
|
auto& buffer = upload ? upload_buffer : download_buffer;
|
||||||
auto [data, offset, invalidate] = buffer.Map(size);
|
auto [data, offset, invalidate] = buffer.Map(size);
|
||||||
|
|
||||||
return StagingData{.buffer = buffer.GetStagingHandle(),
|
return StagingData{
|
||||||
|
.buffer = buffer.GetStagingHandle(),
|
||||||
.size = size,
|
.size = size,
|
||||||
.mapped = std::span<std::byte>{reinterpret_cast<std::byte*>(data), size},
|
.mapped = std::span<std::byte>{reinterpret_cast<std::byte*>(data), size},
|
||||||
.buffer_offset = offset};
|
.buffer_offset = offset,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureRuntime::FlushBuffers() {
|
void TextureRuntime::FlushBuffers() {
|
||||||
@@ -192,11 +193,13 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
// The internal format does not provide enough guarantee of texture uniqueness
|
// The internal format does not provide enough guarantee of texture uniqueness
|
||||||
// especially when many pixel formats fallback to RGBA8
|
// especially when many pixel formats fallback to RGBA8
|
||||||
ASSERT(pixel_format != VideoCore::PixelFormat::Invalid);
|
ASSERT(pixel_format != VideoCore::PixelFormat::Invalid);
|
||||||
const HostTextureTag key = {.format = format,
|
const HostTextureTag key = {
|
||||||
|
.format = format,
|
||||||
.pixel_format = pixel_format,
|
.pixel_format = pixel_format,
|
||||||
.type = type,
|
.type = type,
|
||||||
.width = width,
|
.width = width,
|
||||||
.height = height};
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
// Attempt to recycle an unused allocation
|
// Attempt to recycle an unused allocation
|
||||||
if (auto it = texture_recycler.find(key); it != texture_recycler.end()) {
|
if (auto it = texture_recycler.find(key); it != texture_recycler.end()) {
|
||||||
@@ -215,14 +218,16 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
flags |= vk::ImageCreateFlagBits::eMutableFormat;
|
flags |= vk::ImageCreateFlagBits::eMutableFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::ImageCreateInfo image_info = {.flags = flags,
|
const vk::ImageCreateInfo image_info = {
|
||||||
|
.flags = flags,
|
||||||
.imageType = vk::ImageType::e2D,
|
.imageType = vk::ImageType::e2D,
|
||||||
.format = format,
|
.format = format,
|
||||||
.extent = {width, height, 1},
|
.extent = {width, height, 1},
|
||||||
.mipLevels = alloc.levels,
|
.mipLevels = alloc.levels,
|
||||||
.arrayLayers = alloc.layers,
|
.arrayLayers = alloc.layers,
|
||||||
.samples = vk::SampleCountFlagBits::e1,
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
.usage = usage};
|
.usage = usage,
|
||||||
|
};
|
||||||
|
|
||||||
const VmaAllocationCreateInfo alloc_info = {
|
const VmaAllocationCreateInfo alloc_info = {
|
||||||
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
|
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
|
||||||
@@ -247,14 +252,19 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
type == VideoCore::TextureType::CubeMap ? vk::ImageViewType::eCube : vk::ImageViewType::e2D;
|
type == VideoCore::TextureType::CubeMap ? vk::ImageViewType::eCube : vk::ImageViewType::e2D;
|
||||||
|
|
||||||
alloc.image = vk::Image{unsafe_image};
|
alloc.image = vk::Image{unsafe_image};
|
||||||
const vk::ImageViewCreateInfo view_info = {.image = alloc.image,
|
const vk::ImageViewCreateInfo view_info = {
|
||||||
|
.image = alloc.image,
|
||||||
.viewType = view_type,
|
.viewType = view_type,
|
||||||
.format = format,
|
.format = format,
|
||||||
.subresourceRange = {.aspectMask = alloc.aspect,
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = alloc.aspect,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = alloc.levels,
|
.levelCount = alloc.levels,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = alloc.layers}};
|
.layerCount = alloc.layers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
alloc.image_view = device.createImageView(view_info);
|
alloc.image_view = device.createImageView(view_info);
|
||||||
@@ -265,11 +275,15 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
.image = alloc.image,
|
.image = alloc.image,
|
||||||
.viewType = view_type,
|
.viewType = view_type,
|
||||||
.format = format,
|
.format = format,
|
||||||
.subresourceRange = {.aspectMask = alloc.aspect,
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = alloc.aspect,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = alloc.layers}};
|
.layerCount = alloc.layers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
alloc.base_view = device.createImageView(base_view_info);
|
alloc.base_view = device.createImageView(base_view_info);
|
||||||
}
|
}
|
||||||
@@ -280,11 +294,15 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
.image = alloc.image,
|
.image = alloc.image,
|
||||||
.viewType = view_type,
|
.viewType = view_type,
|
||||||
.format = format,
|
.format = format,
|
||||||
.subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eDepth,
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eDepth,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = alloc.levels,
|
.levelCount = alloc.levels,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = alloc.layers}};
|
.layerCount = alloc.layers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
alloc.depth_view = device.createImageView(view_info);
|
alloc.depth_view = device.createImageView(view_info);
|
||||||
view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eStencil;
|
view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eStencil;
|
||||||
@@ -296,16 +314,20 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
.image = alloc.image,
|
.image = alloc.image,
|
||||||
.viewType = view_type,
|
.viewType = view_type,
|
||||||
.format = vk::Format::eR32Uint,
|
.format = vk::Format::eR32Uint,
|
||||||
.subresourceRange = {.aspectMask = alloc.aspect,
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = alloc.aspect,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = alloc.levels,
|
.levelCount = alloc.levels,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = alloc.layers}};
|
.layerCount = alloc.layers,
|
||||||
|
},
|
||||||
|
};
|
||||||
alloc.storage_view = device.createImageView(storage_view_info);
|
alloc.storage_view = device.createImageView(storage_view_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler.Record([image = alloc.image,
|
scheduler.Record([image = alloc.image, aspect = alloc.aspect](vk::CommandBuffer,
|
||||||
aspect = alloc.aspect](vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) {
|
vk::CommandBuffer upload_cmdbuf) {
|
||||||
const vk::ImageMemoryBarrier init_barrier = {
|
const vk::ImageMemoryBarrier init_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eNone,
|
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eNone,
|
.dstAccessMask = vk::AccessFlagBits::eNone,
|
||||||
@@ -320,13 +342,12 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma
|
|||||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
upload_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
upload_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
||||||
vk::PipelineStageFlagBits::eTopOfPipe,
|
vk::PipelineStageFlagBits::eTopOfPipe,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, init_barrier);
|
vk::DependencyFlagBits::eByRegion, {}, {}, init_barrier);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return alloc;
|
return alloc;
|
||||||
@@ -380,14 +401,15 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea
|
|||||||
surface.type != VideoCore::SurfaceType::DepthStencil;
|
surface.type != VideoCore::SurfaceType::DepthStencil;
|
||||||
|
|
||||||
if (clear.texture_rect == surface.GetScaledRect()) {
|
if (clear.texture_rect == surface.GetScaledRect()) {
|
||||||
scheduler.Record([aspect = MakeAspect(surface.type),
|
scheduler.Record([aspect = MakeAspect(surface.type), image = surface.alloc.image, value,
|
||||||
image = surface.alloc.image,
|
is_color, clear](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
value, is_color, clear](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
const vk::ImageSubresourceRange range = {
|
||||||
const vk::ImageSubresourceRange range = {.aspectMask = aspect,
|
.aspectMask = aspect,
|
||||||
.baseMipLevel = clear.texture_level,
|
.baseMipLevel = clear.texture_level,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1};
|
.layerCount = 1,
|
||||||
|
};
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier pre_barrier = {
|
const vk::ImageMemoryBarrier pre_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||||
@@ -406,12 +428,13 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier post_barrier = {
|
const vk::ImageMemoryBarrier post_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
|
.dstAccessMask =
|
||||||
|
vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
|
||||||
vk::AccessFlagBits::eColorAttachmentRead |
|
vk::AccessFlagBits::eColorAttachmentRead |
|
||||||
vk::AccessFlagBits::eColorAttachmentWrite |
|
vk::AccessFlagBits::eColorAttachmentWrite |
|
||||||
vk::AccessFlagBits::eDepthStencilAttachmentRead |
|
vk::AccessFlagBits::eDepthStencilAttachmentRead |
|
||||||
@@ -428,7 +451,7 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
@@ -454,7 +477,8 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureRuntime::ClearTextureWithRenderpass(Surface& surface, const VideoCore::TextureClear& clear,
|
void TextureRuntime::ClearTextureWithRenderpass(Surface& surface,
|
||||||
|
const VideoCore::TextureClear& clear,
|
||||||
VideoCore::ClearValue value) {
|
VideoCore::ClearValue value) {
|
||||||
const bool is_color = surface.type != VideoCore::SurfaceType::Depth &&
|
const bool is_color = surface.type != VideoCore::SurfaceType::Depth &&
|
||||||
surface.type != VideoCore::SurfaceType::DepthStencil;
|
surface.type != VideoCore::SurfaceType::DepthStencil;
|
||||||
@@ -470,29 +494,32 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface, const VideoCor
|
|||||||
auto [it, new_framebuffer] =
|
auto [it, new_framebuffer] =
|
||||||
clear_framebuffers.try_emplace(framebuffer_view, vk::Framebuffer{});
|
clear_framebuffers.try_emplace(framebuffer_view, vk::Framebuffer{});
|
||||||
if (new_framebuffer) {
|
if (new_framebuffer) {
|
||||||
const vk::FramebufferCreateInfo framebuffer_info = {.renderPass = clear_renderpass,
|
const vk::FramebufferCreateInfo framebuffer_info = {
|
||||||
|
.renderPass = clear_renderpass,
|
||||||
.attachmentCount = 1,
|
.attachmentCount = 1,
|
||||||
.pAttachments = &framebuffer_view,
|
.pAttachments = &framebuffer_view,
|
||||||
.width = surface.GetScaledWidth(),
|
.width = surface.GetScaledWidth(),
|
||||||
.height = surface.GetScaledHeight(),
|
.height = surface.GetScaledHeight(),
|
||||||
.layers = 1};
|
.layers = 1,
|
||||||
|
};
|
||||||
|
|
||||||
vk::Device device = instance.GetDevice();
|
it->second = instance.GetDevice().createFramebuffer(framebuffer_info);
|
||||||
it->second = device.createFramebuffer(framebuffer_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderpassState clear_info = {
|
const RenderpassState clear_info = {
|
||||||
.renderpass = clear_renderpass,
|
.renderpass = clear_renderpass,
|
||||||
.framebuffer = it->second,
|
.framebuffer = it->second,
|
||||||
.render_area = vk::Rect2D{.offset = {static_cast<s32>(clear.texture_rect.left),
|
.render_area =
|
||||||
|
vk::Rect2D{
|
||||||
|
.offset = {static_cast<s32>(clear.texture_rect.left),
|
||||||
static_cast<s32>(clear.texture_rect.bottom)},
|
static_cast<s32>(clear.texture_rect.bottom)},
|
||||||
.extent = {clear.texture_rect.GetWidth(),
|
.extent = {clear.texture_rect.GetWidth(), clear.texture_rect.GetHeight()},
|
||||||
clear.texture_rect.GetHeight()}},
|
},
|
||||||
.clear = MakeClearValue(value)
|
.clear = MakeClearValue(value),
|
||||||
};
|
};
|
||||||
|
|
||||||
scheduler.Record([aspect = MakeAspect(surface.type),
|
scheduler.Record(
|
||||||
image = surface.alloc.image,
|
[aspect = MakeAspect(surface.type), image = surface.alloc.image,
|
||||||
level = clear.texture_level](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
level = clear.texture_level](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
const vk::ImageMemoryBarrier pre_barrier = {
|
const vk::ImageMemoryBarrier pre_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||||
@@ -511,7 +538,7 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface, const VideoCor
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
@@ -522,9 +549,9 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface, const VideoCor
|
|||||||
renderpass_cache.EnterRenderpass(clear_info);
|
renderpass_cache.EnterRenderpass(clear_info);
|
||||||
renderpass_cache.ExitRenderpass();
|
renderpass_cache.ExitRenderpass();
|
||||||
|
|
||||||
scheduler.Record([aspect = MakeAspect(surface.type),
|
scheduler.Record([aspect = MakeAspect(surface.type), image = surface.alloc.image,
|
||||||
image = surface.alloc.image,
|
level = clear.texture_level](vk::CommandBuffer render_cmdbuf,
|
||||||
level = clear.texture_level](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
vk::CommandBuffer) {
|
||||||
const vk::ImageMemoryBarrier post_barrier = {
|
const vk::ImageMemoryBarrier post_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
|
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
|
||||||
@@ -544,7 +571,7 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface, const VideoCor
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||||
@@ -557,21 +584,30 @@ bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
|||||||
const VideoCore::TextureCopy& copy) {
|
const VideoCore::TextureCopy& copy) {
|
||||||
renderpass_cache.ExitRenderpass();
|
renderpass_cache.ExitRenderpass();
|
||||||
|
|
||||||
scheduler.Record([src_image = source.alloc.image,
|
scheduler.Record([src_image = source.alloc.image, dst_image = dest.alloc.image,
|
||||||
dst_image = dest.alloc.image,
|
aspect = MakeAspect(source.type),
|
||||||
aspect = MakeAspect(source.type), copy](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
copy](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
const vk::ImageCopy image_copy = {
|
const vk::ImageCopy image_copy = {
|
||||||
.srcSubresource = {.aspectMask = aspect,
|
.srcSubresource =
|
||||||
|
{
|
||||||
|
.aspectMask = aspect,
|
||||||
.mipLevel = copy.src_level,
|
.mipLevel = copy.src_level,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1},
|
.layerCount = 1,
|
||||||
.srcOffset = {static_cast<s32>(copy.src_offset.x), static_cast<s32>(copy.src_offset.y), 0},
|
},
|
||||||
.dstSubresource = {.aspectMask = aspect,
|
.srcOffset = {static_cast<s32>(copy.src_offset.x), static_cast<s32>(copy.src_offset.y),
|
||||||
|
0},
|
||||||
|
.dstSubresource =
|
||||||
|
{
|
||||||
|
.aspectMask = aspect,
|
||||||
.mipLevel = copy.dst_level,
|
.mipLevel = copy.dst_level,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1},
|
.layerCount = 1,
|
||||||
.dstOffset = {static_cast<s32>(copy.dst_offset.x), static_cast<s32>(copy.dst_offset.y), 0},
|
},
|
||||||
.extent = {copy.extent.width, copy.extent.height, 1}};
|
.dstOffset = {static_cast<s32>(copy.dst_offset.x), static_cast<s32>(copy.dst_offset.y),
|
||||||
|
0},
|
||||||
|
.extent = {copy.extent.width, copy.extent.height, 1},
|
||||||
|
};
|
||||||
|
|
||||||
const std::array pre_barriers = {
|
const std::array pre_barriers = {
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
@@ -591,7 +627,7 @@ bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
.srcAccessMask = vk::AccessFlagBits::eShaderWrite |
|
||||||
@@ -610,7 +646,7 @@ bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const std::array post_barriers = {
|
const std::array post_barriers = {
|
||||||
@@ -628,11 +664,12 @@ bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
|
.dstAccessMask =
|
||||||
|
vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite |
|
||||||
vk::AccessFlagBits::eColorAttachmentRead |
|
vk::AccessFlagBits::eColorAttachmentRead |
|
||||||
vk::AccessFlagBits::eColorAttachmentWrite |
|
vk::AccessFlagBits::eColorAttachmentWrite |
|
||||||
vk::AccessFlagBits::eDepthStencilAttachmentRead |
|
vk::AccessFlagBits::eDepthStencilAttachmentRead |
|
||||||
@@ -649,7 +686,7 @@ bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -657,8 +694,8 @@ bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
|||||||
vk::PipelineStageFlagBits::eTransfer,
|
vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
vk::DependencyFlagBits::eByRegion, {}, {}, pre_barriers);
|
||||||
|
|
||||||
render_cmdbuf.copyImage(src_image, vk::ImageLayout::eTransferSrcOptimal,
|
render_cmdbuf.copyImage(src_image, vk::ImageLayout::eTransferSrcOptimal, dst_image,
|
||||||
dst_image, vk::ImageLayout::eTransferDstOptimal, image_copy);
|
vk::ImageLayout::eTransferDstOptimal, image_copy);
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
vk::PipelineStageFlagBits::eAllCommands,
|
||||||
@@ -672,30 +709,41 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||||||
const VideoCore::TextureBlit& blit) {
|
const VideoCore::TextureBlit& blit) {
|
||||||
renderpass_cache.ExitRenderpass();
|
renderpass_cache.ExitRenderpass();
|
||||||
|
|
||||||
scheduler.Record([src_image = source.alloc.image,
|
scheduler.Record([src_image = source.alloc.image, aspect = MakeAspect(source.type),
|
||||||
aspect = MakeAspect(source.type),
|
filter = MakeFilter(source.pixel_format), dst_image = dest.alloc.image,
|
||||||
filter = MakeFilter(source.pixel_format),
|
blit](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
dst_image = dest.alloc.image, blit](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
const std::array source_offsets = {
|
||||||
const std::array source_offsets = {vk::Offset3D{static_cast<s32>(blit.src_rect.left),
|
vk::Offset3D{static_cast<s32>(blit.src_rect.left),
|
||||||
static_cast<s32>(blit.src_rect.bottom), 0},
|
static_cast<s32>(blit.src_rect.bottom), 0},
|
||||||
vk::Offset3D{static_cast<s32>(blit.src_rect.right),
|
vk::Offset3D{static_cast<s32>(blit.src_rect.right), static_cast<s32>(blit.src_rect.top),
|
||||||
static_cast<s32>(blit.src_rect.top), 1}};
|
1},
|
||||||
|
};
|
||||||
|
|
||||||
const std::array dest_offsets = {vk::Offset3D{static_cast<s32>(blit.dst_rect.left),
|
const std::array dest_offsets = {
|
||||||
|
vk::Offset3D{static_cast<s32>(blit.dst_rect.left),
|
||||||
static_cast<s32>(blit.dst_rect.bottom), 0},
|
static_cast<s32>(blit.dst_rect.bottom), 0},
|
||||||
vk::Offset3D{static_cast<s32>(blit.dst_rect.right),
|
vk::Offset3D{static_cast<s32>(blit.dst_rect.right), static_cast<s32>(blit.dst_rect.top),
|
||||||
static_cast<s32>(blit.dst_rect.top), 1}};
|
1},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::ImageBlit blit_area = {.srcSubresource = {.aspectMask = aspect,
|
const vk::ImageBlit blit_area = {
|
||||||
|
.srcSubresource =
|
||||||
|
{
|
||||||
|
.aspectMask = aspect,
|
||||||
.mipLevel = blit.src_level,
|
.mipLevel = blit.src_level,
|
||||||
.baseArrayLayer = blit.src_layer,
|
.baseArrayLayer = blit.src_layer,
|
||||||
.layerCount = 1},
|
.layerCount = 1,
|
||||||
|
},
|
||||||
.srcOffsets = source_offsets,
|
.srcOffsets = source_offsets,
|
||||||
.dstSubresource = {.aspectMask = aspect,
|
.dstSubresource =
|
||||||
|
{
|
||||||
|
.aspectMask = aspect,
|
||||||
.mipLevel = blit.dst_level,
|
.mipLevel = blit.dst_level,
|
||||||
.baseArrayLayer = blit.dst_layer,
|
.baseArrayLayer = blit.dst_layer,
|
||||||
.layerCount = 1},
|
.layerCount = 1,
|
||||||
.dstOffsets = dest_offsets};
|
},
|
||||||
|
.dstOffsets = dest_offsets,
|
||||||
|
};
|
||||||
|
|
||||||
const std::array read_barriers = {
|
const std::array read_barriers = {
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
@@ -712,7 +760,7 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead |
|
.srcAccessMask = vk::AccessFlagBits::eShaderRead |
|
||||||
@@ -731,9 +779,8 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
}
|
}};
|
||||||
};
|
|
||||||
const std::array write_barriers = {
|
const std::array write_barriers = {
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eNone,
|
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||||
@@ -749,7 +796,7 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
@@ -765,17 +812,15 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
}
|
},
|
||||||
}
|
}};
|
||||||
};
|
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::PipelineStageFlagBits::eTransfer,
|
vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, read_barriers);
|
vk::DependencyFlagBits::eByRegion, {}, {}, read_barriers);
|
||||||
|
|
||||||
render_cmdbuf.blitImage(src_image, vk::ImageLayout::eTransferSrcOptimal,
|
render_cmdbuf.blitImage(src_image, vk::ImageLayout::eTransferSrcOptimal, dst_image,
|
||||||
dst_image, vk::ImageLayout::eTransferDstOptimal, blit_area,
|
vk::ImageLayout::eTransferDstOptimal, blit_area, filter);
|
||||||
filter);
|
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
vk::PipelineStageFlagBits::eAllCommands,
|
||||||
@@ -861,11 +906,13 @@ Surface::Surface(const VideoCore::SurfaceParams& params, vk::Format format,
|
|||||||
|
|
||||||
Surface::~Surface() {
|
Surface::~Surface() {
|
||||||
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
if (pixel_format != VideoCore::PixelFormat::Invalid) {
|
||||||
const HostTextureTag tag = {.format = alloc.format,
|
const HostTextureTag tag = {
|
||||||
|
.format = alloc.format,
|
||||||
.pixel_format = pixel_format,
|
.pixel_format = pixel_format,
|
||||||
.type = texture_type,
|
.type = texture_type,
|
||||||
.width = GetScaledWidth(),
|
.width = GetScaledWidth(),
|
||||||
.height = GetScaledHeight()};
|
.height = GetScaledHeight(),
|
||||||
|
};
|
||||||
|
|
||||||
runtime.Recycle(tag, std::move(alloc));
|
runtime.Recycle(tag, std::move(alloc));
|
||||||
}
|
}
|
||||||
@@ -886,8 +933,8 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
|||||||
if (is_scaled) {
|
if (is_scaled) {
|
||||||
ScaledUpload(upload, staging);
|
ScaledUpload(upload, staging);
|
||||||
} else {
|
} else {
|
||||||
scheduler.Record([aspect = alloc.aspect, image = alloc.image,
|
scheduler.Record([aspect = alloc.aspect, image = alloc.image, format = alloc.format,
|
||||||
format = alloc.format, staging, upload](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
staging, upload](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
u32 num_copies = 1;
|
u32 num_copies = 1;
|
||||||
std::array<vk::BufferImageCopy, 2> buffer_image_copies;
|
std::array<vk::BufferImageCopy, 2> buffer_image_copies;
|
||||||
|
|
||||||
@@ -896,15 +943,20 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
|||||||
.bufferOffset = staging.buffer_offset + upload.buffer_offset,
|
.bufferOffset = staging.buffer_offset + upload.buffer_offset,
|
||||||
.bufferRowLength = rect.GetWidth(),
|
.bufferRowLength = rect.GetWidth(),
|
||||||
.bufferImageHeight = rect.GetHeight(),
|
.bufferImageHeight = rect.GetHeight(),
|
||||||
.imageSubresource = {.aspectMask = aspect,
|
.imageSubresource =
|
||||||
|
{
|
||||||
|
.aspectMask = aspect,
|
||||||
.mipLevel = upload.texture_level,
|
.mipLevel = upload.texture_level,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1},
|
.layerCount = 1,
|
||||||
|
},
|
||||||
.imageOffset = {static_cast<s32>(rect.left), static_cast<s32>(rect.bottom), 0},
|
.imageOffset = {static_cast<s32>(rect.left), static_cast<s32>(rect.bottom), 0},
|
||||||
.imageExtent = {rect.GetWidth(), rect.GetHeight(), 1}};
|
.imageExtent = {rect.GetWidth(), rect.GetHeight(), 1},
|
||||||
|
};
|
||||||
|
|
||||||
if (aspect & vk::ImageAspectFlagBits::eStencil) {
|
if (aspect & vk::ImageAspectFlagBits::eStencil) {
|
||||||
buffer_image_copies[0].imageSubresource.aspectMask = vk::ImageAspectFlagBits::eDepth;
|
buffer_image_copies[0].imageSubresource.aspectMask =
|
||||||
|
vk::ImageAspectFlagBits::eDepth;
|
||||||
vk::BufferImageCopy& stencil_copy = buffer_image_copies[1];
|
vk::BufferImageCopy& stencil_copy = buffer_image_copies[1];
|
||||||
stencil_copy = buffer_image_copies[0];
|
stencil_copy = buffer_image_copies[0];
|
||||||
stencil_copy.bufferOffset += UnpackDepthStencil(staging, format);
|
stencil_copy.bufferOffset += UnpackDepthStencil(staging, format);
|
||||||
@@ -927,7 +979,8 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
|||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = {
|
.subresourceRange =
|
||||||
|
{
|
||||||
.aspectMask = aspect,
|
.aspectMask = aspect,
|
||||||
.baseMipLevel = upload.texture_level,
|
.baseMipLevel = upload.texture_level,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
@@ -943,7 +996,8 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
|||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = {
|
.subresourceRange =
|
||||||
|
{
|
||||||
.aspectMask = aspect,
|
.aspectMask = aspect,
|
||||||
.baseMipLevel = upload.texture_level,
|
.baseMipLevel = upload.texture_level,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
@@ -956,8 +1010,9 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
|||||||
vk::PipelineStageFlagBits::eTransfer,
|
vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, read_barrier);
|
vk::DependencyFlagBits::eByRegion, {}, {}, read_barrier);
|
||||||
|
|
||||||
render_cmdbuf.copyBufferToImage(staging.buffer, image, vk::ImageLayout::eTransferDstOptimal,
|
render_cmdbuf.copyBufferToImage(staging.buffer, image,
|
||||||
num_copies, buffer_image_copies.data());
|
vk::ImageLayout::eTransferDstOptimal, num_copies,
|
||||||
|
buffer_image_copies.data());
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
vk::PipelineStageFlagBits::eAllCommands,
|
||||||
@@ -987,19 +1042,23 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
|
|||||||
if (is_scaled) {
|
if (is_scaled) {
|
||||||
ScaledDownload(download, staging);
|
ScaledDownload(download, staging);
|
||||||
} else {
|
} else {
|
||||||
scheduler.Record([aspect = alloc.aspect, image = alloc.image,
|
scheduler.Record([aspect = alloc.aspect, image = alloc.image, staging,
|
||||||
staging, download](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer){
|
download](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {
|
||||||
const VideoCore::Rect2D rect = download.texture_rect;
|
const VideoCore::Rect2D rect = download.texture_rect;
|
||||||
const vk::BufferImageCopy buffer_image_copy = {
|
const vk::BufferImageCopy buffer_image_copy = {
|
||||||
.bufferOffset = staging.buffer_offset + download.buffer_offset,
|
.bufferOffset = staging.buffer_offset + download.buffer_offset,
|
||||||
.bufferRowLength = rect.GetWidth(),
|
.bufferRowLength = rect.GetWidth(),
|
||||||
.bufferImageHeight = rect.GetHeight(),
|
.bufferImageHeight = rect.GetHeight(),
|
||||||
.imageSubresource = {.aspectMask = aspect,
|
.imageSubresource =
|
||||||
|
{
|
||||||
|
.aspectMask = aspect,
|
||||||
.mipLevel = download.texture_level,
|
.mipLevel = download.texture_level,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1},
|
.layerCount = 1,
|
||||||
|
},
|
||||||
.imageOffset = {static_cast<s32>(rect.left), static_cast<s32>(rect.bottom), 0},
|
.imageOffset = {static_cast<s32>(rect.left), static_cast<s32>(rect.bottom), 0},
|
||||||
.imageExtent = {rect.GetWidth(), rect.GetHeight(), 1}};
|
.imageExtent = {rect.GetWidth(), rect.GetHeight(), 1},
|
||||||
|
};
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier read_barrier = {
|
const vk::ImageMemoryBarrier read_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
|
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
|
||||||
@@ -1009,7 +1068,8 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
|
|||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = {
|
.subresourceRange =
|
||||||
|
{
|
||||||
.aspectMask = aspect,
|
.aspectMask = aspect,
|
||||||
.baseMipLevel = download.texture_level,
|
.baseMipLevel = download.texture_level,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
@@ -1025,7 +1085,8 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
|
|||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = {
|
.subresourceRange =
|
||||||
|
{
|
||||||
.aspectMask = aspect,
|
.aspectMask = aspect,
|
||||||
.baseMipLevel = download.texture_level,
|
.baseMipLevel = download.texture_level,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
@@ -1045,10 +1106,9 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
|
|||||||
render_cmdbuf.copyImageToBuffer(image, vk::ImageLayout::eTransferSrcOptimal,
|
render_cmdbuf.copyImageToBuffer(image, vk::ImageLayout::eTransferSrcOptimal,
|
||||||
staging.buffer, buffer_image_copy);
|
staging.buffer, buffer_image_copy);
|
||||||
|
|
||||||
render_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
render_cmdbuf.pipelineBarrier(
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::DependencyFlagBits::eByRegion,
|
vk::DependencyFlagBits::eByRegion, memory_write_barrier, {}, image_write_barrier);
|
||||||
memory_write_barrier, {}, image_write_barrier);
|
|
||||||
});
|
});
|
||||||
runtime.download_buffer.Commit(staging.size);
|
runtime.download_buffer.Commit(staging.size);
|
||||||
}
|
}
|
||||||
@@ -1077,18 +1137,22 @@ void Surface::ScaledUpload(const VideoCore::BufferTextureCopy& upload, const Sta
|
|||||||
unscaled_params.res_scale = 1;
|
unscaled_params.res_scale = 1;
|
||||||
Surface unscaled_surface{unscaled_params, runtime};
|
Surface unscaled_surface{unscaled_params, runtime};
|
||||||
|
|
||||||
const VideoCore::BufferTextureCopy unscaled_upload = {.buffer_offset = upload.buffer_offset,
|
const VideoCore::BufferTextureCopy unscaled_upload = {
|
||||||
|
.buffer_offset = upload.buffer_offset,
|
||||||
.buffer_size = upload.buffer_size,
|
.buffer_size = upload.buffer_size,
|
||||||
.texture_rect = unscaled_rect};
|
.texture_rect = unscaled_rect,
|
||||||
|
};
|
||||||
|
|
||||||
unscaled_surface.Upload(unscaled_upload, staging);
|
unscaled_surface.Upload(unscaled_upload, staging);
|
||||||
|
|
||||||
const VideoCore::TextureBlit blit = {.src_level = 0,
|
const VideoCore::TextureBlit blit = {
|
||||||
|
.src_level = 0,
|
||||||
.dst_level = upload.texture_level,
|
.dst_level = upload.texture_level,
|
||||||
.src_layer = 0,
|
.src_layer = 0,
|
||||||
.dst_layer = 0,
|
.dst_layer = 0,
|
||||||
.src_rect = unscaled_rect,
|
.src_rect = unscaled_rect,
|
||||||
.dst_rect = scaled_rect};
|
.dst_rect = scaled_rect,
|
||||||
|
};
|
||||||
|
|
||||||
runtime.BlitTextures(unscaled_surface, *this, blit);
|
runtime.BlitTextures(unscaled_surface, *this, blit);
|
||||||
}
|
}
|
||||||
@@ -1108,20 +1172,24 @@ void Surface::ScaledDownload(const VideoCore::BufferTextureCopy& download,
|
|||||||
unscaled_params.res_scale = 1;
|
unscaled_params.res_scale = 1;
|
||||||
Surface unscaled_surface{unscaled_params, runtime};
|
Surface unscaled_surface{unscaled_params, runtime};
|
||||||
|
|
||||||
const VideoCore::TextureBlit blit = {.src_level = download.texture_level,
|
const VideoCore::TextureBlit blit = {
|
||||||
|
.src_level = download.texture_level,
|
||||||
.dst_level = 0,
|
.dst_level = 0,
|
||||||
.src_layer = 0,
|
.src_layer = 0,
|
||||||
.dst_layer = 0,
|
.dst_layer = 0,
|
||||||
.src_rect = scaled_rect,
|
.src_rect = scaled_rect,
|
||||||
.dst_rect = unscaled_rect};
|
.dst_rect = unscaled_rect,
|
||||||
|
};
|
||||||
|
|
||||||
// Blit the scaled rectangle to the unscaled texture
|
// Blit the scaled rectangle to the unscaled texture
|
||||||
runtime.BlitTextures(*this, unscaled_surface, blit);
|
runtime.BlitTextures(*this, unscaled_surface, blit);
|
||||||
|
|
||||||
const VideoCore::BufferTextureCopy unscaled_download = {.buffer_offset = download.buffer_offset,
|
const VideoCore::BufferTextureCopy unscaled_download = {
|
||||||
|
.buffer_offset = download.buffer_offset,
|
||||||
.buffer_size = download.buffer_size,
|
.buffer_size = download.buffer_size,
|
||||||
.texture_rect = unscaled_rect,
|
.texture_rect = unscaled_rect,
|
||||||
.texture_level = 0};
|
.texture_level = 0,
|
||||||
|
};
|
||||||
|
|
||||||
unscaled_surface.Download(unscaled_download, staging);
|
unscaled_surface.Download(unscaled_download, staging);
|
||||||
}
|
}
|
||||||
@@ -1149,32 +1217,38 @@ void Surface::DepthStencilDownload(const VideoCore::BufferTextureCopy& download,
|
|||||||
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eStorage,
|
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eStorage,
|
||||||
runtime};
|
runtime};
|
||||||
|
|
||||||
const VideoCore::TextureBlit blit = {.src_level = download.texture_level,
|
const VideoCore::TextureBlit blit = {
|
||||||
|
.src_level = download.texture_level,
|
||||||
.dst_level = 0,
|
.dst_level = 0,
|
||||||
.src_layer = 0,
|
.src_layer = 0,
|
||||||
.dst_layer = 0,
|
.dst_layer = 0,
|
||||||
.src_rect = scaled_rect,
|
.src_rect = scaled_rect,
|
||||||
.dst_rect = r32_scaled_rect};
|
.dst_rect = r32_scaled_rect,
|
||||||
|
};
|
||||||
|
|
||||||
runtime.blit_helper.BlitD24S8ToR32(*this, r32_surface, blit);
|
runtime.blit_helper.BlitD24S8ToR32(*this, r32_surface, blit);
|
||||||
|
|
||||||
// Blit the upper mip level to the lower one to scale without additional allocations
|
// Blit the upper mip level to the lower one to scale without additional allocations
|
||||||
const bool is_scaled = res_scale != 1;
|
const bool is_scaled = res_scale != 1;
|
||||||
if (is_scaled) {
|
if (is_scaled) {
|
||||||
const VideoCore::TextureBlit r32_blit = {.src_level = 0,
|
const VideoCore::TextureBlit r32_blit = {
|
||||||
|
.src_level = 0,
|
||||||
.dst_level = 1,
|
.dst_level = 1,
|
||||||
.src_layer = 0,
|
.src_layer = 0,
|
||||||
.dst_layer = 0,
|
.dst_layer = 0,
|
||||||
.src_rect = r32_scaled_rect,
|
.src_rect = r32_scaled_rect,
|
||||||
.dst_rect = unscaled_rect};
|
.dst_rect = unscaled_rect,
|
||||||
|
};
|
||||||
|
|
||||||
runtime.BlitTextures(r32_surface, r32_surface, r32_blit);
|
runtime.BlitTextures(r32_surface, r32_surface, r32_blit);
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoCore::BufferTextureCopy r32_download = {.buffer_offset = download.buffer_offset,
|
const VideoCore::BufferTextureCopy r32_download = {
|
||||||
|
.buffer_offset = download.buffer_offset,
|
||||||
.buffer_size = download.buffer_size,
|
.buffer_size = download.buffer_size,
|
||||||
.texture_rect = unscaled_rect,
|
.texture_rect = unscaled_rect,
|
||||||
.texture_level = is_scaled ? 1u : 0u};
|
.texture_level = is_scaled ? 1u : 0u,
|
||||||
|
};
|
||||||
|
|
||||||
r32_surface.Download(r32_download, staging);
|
r32_surface.Download(r32_download, staging);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user