summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2021-02-17 00:52:12 +0100
committerameerj <52414509+ameerj@users.noreply.github.com>2021-07-23 03:51:22 +0200
commitc67d64365a712830fe140dd36e24e2efd9b8a812 (patch)
tree9287589f2b72d1cbd0cb113c2024b2bc531408c3 /src/video_core/renderer_vulkan
parentshader: Add XMAD multiplication folding optimization (diff)
downloadyuzu-c67d64365a712830fe140dd36e24e2efd9b8a812.tar
yuzu-c67d64365a712830fe140dd36e24e2efd9b8a812.tar.gz
yuzu-c67d64365a712830fe140dd36e24e2efd9b8a812.tar.bz2
yuzu-c67d64365a712830fe140dd36e24e2efd9b8a812.tar.lz
yuzu-c67d64365a712830fe140dd36e24e2efd9b8a812.tar.xz
yuzu-c67d64365a712830fe140dd36e24e2efd9b8a812.tar.zst
yuzu-c67d64365a712830fe140dd36e24e2efd9b8a812.zip
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp136
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.h47
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp484
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h103
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp375
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h91
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp361
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h47
9 files changed, 41 insertions, 1604 deletions
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index b7f5b8bc2..6c0d5c7f4 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -323,7 +323,6 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi
cmdbuf.SetScissor(0, scissor);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
}
-
} // Anonymous namespace
BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 3a48219b7..7a3660496 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -8,146 +8,14 @@
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
-#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
-VKComputePipeline::VKComputePipeline(const Device& device_, VKScheduler& scheduler_,
- VKDescriptorPool& descriptor_pool_,
- VKUpdateDescriptorQueue& update_descriptor_queue_,
- const SPIRVShader& shader_)
- : device{device_}, scheduler{scheduler_}, entries{shader_.entries},
- descriptor_set_layout{CreateDescriptorSetLayout()},
- descriptor_allocator{descriptor_pool_, *descriptor_set_layout},
- update_descriptor_queue{update_descriptor_queue_}, layout{CreatePipelineLayout()},
- descriptor_template{CreateDescriptorUpdateTemplate()},
- shader_module{CreateShaderModule(shader_.code)}, pipeline{CreatePipeline()} {}
+ComputePipeline::ComputePipeline() = default;
-VKComputePipeline::~VKComputePipeline() = default;
-
-VkDescriptorSet VKComputePipeline::CommitDescriptorSet() {
- if (!descriptor_template) {
- return {};
- }
- const VkDescriptorSet set = descriptor_allocator.Commit();
- update_descriptor_queue.Send(*descriptor_template, set);
- return set;
-}
-
-vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
- std::vector<VkDescriptorSetLayoutBinding> bindings;
- u32 binding = 0;
- const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) {
- // TODO(Rodrigo): Maybe make individual bindings here?
- for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) {
- bindings.push_back({
- .binding = binding++,
- .descriptorType = descriptor_type,
- .descriptorCount = 1,
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
- .pImmutableSamplers = nullptr,
- });
- }
- };
- add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size());
- add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, entries.global_buffers.size());
- add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, entries.uniform_texels.size());
- add_bindings(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, entries.samplers.size());
- add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size());
- add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size());
-
- return device.GetLogical().CreateDescriptorSetLayout({
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .bindingCount = static_cast<u32>(bindings.size()),
- .pBindings = bindings.data(),
- });
-}
-
-vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const {
- return device.GetLogical().CreatePipelineLayout({
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .setLayoutCount = 1,
- .pSetLayouts = descriptor_set_layout.address(),
- .pushConstantRangeCount = 0,
- .pPushConstantRanges = nullptr,
- });
-}
-
-vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const {
- std::vector<VkDescriptorUpdateTemplateEntryKHR> template_entries;
- u32 binding = 0;
- u32 offset = 0;
- FillDescriptorUpdateTemplateEntries(entries, binding, offset, template_entries);
- if (template_entries.empty()) {
- // If the shader doesn't use descriptor sets, skip template creation.
- return {};
- }
-
- return device.GetLogical().CreateDescriptorUpdateTemplateKHR({
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
- .pNext = nullptr,
- .flags = 0,
- .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
- .pDescriptorUpdateEntries = template_entries.data(),
- .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
- .descriptorSetLayout = *descriptor_set_layout,
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .pipelineLayout = *layout,
- .set = DESCRIPTOR_SET,
- });
-}
-
-vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const {
- device.SaveShader(code);
-
- return device.GetLogical().CreateShaderModule({
- .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .codeSize = code.size() * sizeof(u32),
- .pCode = code.data(),
- });
-}
-
-vk::Pipeline VKComputePipeline::CreatePipeline() const {
-
- VkComputePipelineCreateInfo ci{
- .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .stage =
- {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .stage = VK_SHADER_STAGE_COMPUTE_BIT,
- .module = *shader_module,
- .pName = "main",
- .pSpecializationInfo = nullptr,
- },
- .layout = *layout,
- .basePipelineHandle = nullptr,
- .basePipelineIndex = 0,
- };
-
- const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
- .pNext = nullptr,
- .requiredSubgroupSize = GuestWarpSize,
- };
-
- if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) {
- ci.stage.pNext = &subgroup_size_ci;
- }
-
- return device.GetLogical().CreateComputePipeline(ci);
-}
+ComputePipeline::~ComputePipeline() = default;
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index 7e16575ac..433d8bb3d 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -6,7 +6,6 @@
#include "common/common_types.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
-#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
@@ -15,50 +14,10 @@ class Device;
class VKScheduler;
class VKUpdateDescriptorQueue;
-class VKComputePipeline final {
+class ComputePipeline {
public:
- explicit VKComputePipeline(const Device& device_, VKScheduler& scheduler_,
- VKDescriptorPool& descriptor_pool_,
- VKUpdateDescriptorQueue& update_descriptor_queue_,
- const SPIRVShader& shader_);
- ~VKComputePipeline();
-
- VkDescriptorSet CommitDescriptorSet();
-
- VkPipeline GetHandle() const {
- return *pipeline;
- }
-
- VkPipelineLayout GetLayout() const {
- return *layout;
- }
-
- const ShaderEntries& GetEntries() const {
- return entries;
- }
-
-private:
- vk::DescriptorSetLayout CreateDescriptorSetLayout() const;
-
- vk::PipelineLayout CreatePipelineLayout() const;
-
- vk::DescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplate() const;
-
- vk::ShaderModule CreateShaderModule(const std::vector<u32>& code) const;
-
- vk::Pipeline CreatePipeline() const;
-
- const Device& device;
- VKScheduler& scheduler;
- ShaderEntries entries;
-
- vk::DescriptorSetLayout descriptor_set_layout;
- DescriptorAllocator descriptor_allocator;
- VKUpdateDescriptorQueue& update_descriptor_queue;
- vk::PipelineLayout layout;
- vk::DescriptorUpdateTemplateKHR descriptor_template;
- vk::ShaderModule shader_module;
- vk::Pipeline pipeline;
+ explicit ComputePipeline();
+ ~ComputePipeline();
};
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
deleted file mode 100644
index fc6dd83eb..000000000
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <array>
-#include <cstring>
-#include <vector>
-
-#include "common/common_types.h"
-#include "common/microprofile.h"
-#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
-#include "video_core/renderer_vulkan/maxwell_to_vk.h"
-#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
-#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
-#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
-#include "video_core/renderer_vulkan/vk_scheduler.h"
-#include "video_core/renderer_vulkan/vk_update_descriptor.h"
-#include "video_core/vulkan_common/vulkan_device.h"
-#include "video_core/vulkan_common/vulkan_wrapper.h"
-
-namespace Vulkan {
-
-MICROPROFILE_DECLARE(Vulkan_PipelineCache);
-
-namespace {
-
-template <class StencilFace>
-VkStencilOpState GetStencilFaceState(const StencilFace& face) {
- return {
- .failOp = MaxwellToVK::StencilOp(face.ActionStencilFail()),
- .passOp = MaxwellToVK::StencilOp(face.ActionDepthPass()),
- .depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail()),
- .compareOp = MaxwellToVK::ComparisonOp(face.TestFunc()),
- .compareMask = 0,
- .writeMask = 0,
- .reference = 0,
- };
-}
-
-bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
- static constexpr std::array unsupported_topologies = {
- VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
- VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
- VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
- VK_PRIMITIVE_TOPOLOGY_PATCH_LIST};
- return std::find(std::begin(unsupported_topologies), std::end(unsupported_topologies),
- topology) == std::end(unsupported_topologies);
-}
-
-VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) {
- union Swizzle {
- u32 raw;
- BitField<0, 3, Maxwell::ViewportSwizzle> x;
- BitField<4, 3, Maxwell::ViewportSwizzle> y;
- BitField<8, 3, Maxwell::ViewportSwizzle> z;
- BitField<12, 3, Maxwell::ViewportSwizzle> w;
- };
- const Swizzle unpacked{swizzle};
-
- return {
- .x = MaxwellToVK::ViewportSwizzle(unpacked.x),
- .y = MaxwellToVK::ViewportSwizzle(unpacked.y),
- .z = MaxwellToVK::ViewportSwizzle(unpacked.z),
- .w = MaxwellToVK::ViewportSwizzle(unpacked.w),
- };
-}
-
-VkSampleCountFlagBits ConvertMsaaMode(Tegra::Texture::MsaaMode msaa_mode) {
- switch (msaa_mode) {
- case Tegra::Texture::MsaaMode::Msaa1x1:
- return VK_SAMPLE_COUNT_1_BIT;
- case Tegra::Texture::MsaaMode::Msaa2x1:
- case Tegra::Texture::MsaaMode::Msaa2x1_D3D:
- return VK_SAMPLE_COUNT_2_BIT;
- case Tegra::Texture::MsaaMode::Msaa2x2:
- case Tegra::Texture::MsaaMode::Msaa2x2_VC4:
- case Tegra::Texture::MsaaMode::Msaa2x2_VC12:
- return VK_SAMPLE_COUNT_4_BIT;
- case Tegra::Texture::MsaaMode::Msaa4x2:
- case Tegra::Texture::MsaaMode::Msaa4x2_D3D:
- case Tegra::Texture::MsaaMode::Msaa4x2_VC8:
- case Tegra::Texture::MsaaMode::Msaa4x2_VC24:
- return VK_SAMPLE_COUNT_8_BIT;
- case Tegra::Texture::MsaaMode::Msaa4x4:
- return VK_SAMPLE_COUNT_16_BIT;
- default:
- UNREACHABLE_MSG("Invalid msaa_mode={}", static_cast<int>(msaa_mode));
- return VK_SAMPLE_COUNT_1_BIT;
- }
-}
-
-} // Anonymous namespace
-
-VKGraphicsPipeline::VKGraphicsPipeline(const Device& device_, VKScheduler& scheduler_,
- VKDescriptorPool& descriptor_pool_,
- VKUpdateDescriptorQueue& update_descriptor_queue_,
- const GraphicsPipelineCacheKey& key,
- vk::Span<VkDescriptorSetLayoutBinding> bindings,
- const SPIRVProgram& program, u32 num_color_buffers)
- : device{device_}, scheduler{scheduler_}, cache_key{key}, hash{cache_key.Hash()},
- descriptor_set_layout{CreateDescriptorSetLayout(bindings)},
- descriptor_allocator{descriptor_pool_, *descriptor_set_layout},
- update_descriptor_queue{update_descriptor_queue_}, layout{CreatePipelineLayout()},
- descriptor_template{CreateDescriptorUpdateTemplate(program)},
- modules(CreateShaderModules(program)),
- pipeline(CreatePipeline(program, cache_key.renderpass, num_color_buffers)) {}
-
-VKGraphicsPipeline::~VKGraphicsPipeline() = default;
-
-VkDescriptorSet VKGraphicsPipeline::CommitDescriptorSet() {
- if (!descriptor_template) {
- return {};
- }
- const VkDescriptorSet set = descriptor_allocator.Commit();
- update_descriptor_queue.Send(*descriptor_template, set);
- return set;
-}
-
-vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout(
- vk::Span<VkDescriptorSetLayoutBinding> bindings) const {
- const VkDescriptorSetLayoutCreateInfo ci{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .bindingCount = bindings.size(),
- .pBindings = bindings.data(),
- };
- return device.GetLogical().CreateDescriptorSetLayout(ci);
-}
-
-vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const {
- const VkPipelineLayoutCreateInfo ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .setLayoutCount = 1,
- .pSetLayouts = descriptor_set_layout.address(),
- .pushConstantRangeCount = 0,
- .pPushConstantRanges = nullptr,
- };
- return device.GetLogical().CreatePipelineLayout(ci);
-}
-
-vk::DescriptorUpdateTemplateKHR VKGraphicsPipeline::CreateDescriptorUpdateTemplate(
- const SPIRVProgram& program) const {
- std::vector<VkDescriptorUpdateTemplateEntry> template_entries;
- u32 binding = 0;
- u32 offset = 0;
- for (const auto& stage : program) {
- if (stage) {
- FillDescriptorUpdateTemplateEntries(stage->entries, binding, offset, template_entries);
- }
- }
- if (template_entries.empty()) {
- // If the shader doesn't use descriptor sets, skip template creation.
- return {};
- }
-
- const VkDescriptorUpdateTemplateCreateInfoKHR ci{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
- .pNext = nullptr,
- .flags = 0,
- .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
- .pDescriptorUpdateEntries = template_entries.data(),
- .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
- .descriptorSetLayout = *descriptor_set_layout,
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .pipelineLayout = *layout,
- .set = DESCRIPTOR_SET,
- };
- return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci);
-}
-
-std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules(
- const SPIRVProgram& program) const {
- VkShaderModuleCreateInfo ci{
- .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .codeSize = 0,
- .pCode = nullptr,
- };
-
- std::vector<vk::ShaderModule> shader_modules;
- shader_modules.reserve(Maxwell::MaxShaderStage);
- for (std::size_t i = 0; i < Maxwell::MaxShaderStage; ++i) {
- const auto& stage = program[i];
- if (!stage) {
- continue;
- }
-
- device.SaveShader(stage->code);
-
- ci.codeSize = stage->code.size() * sizeof(u32);
- ci.pCode = stage->code.data();
- shader_modules.push_back(device.GetLogical().CreateShaderModule(ci));
- }
- return shader_modules;
-}
-
-vk::Pipeline VKGraphicsPipeline::CreatePipeline(const SPIRVProgram& program,
- VkRenderPass renderpass,
- u32 num_color_buffers) const {
- const auto& state = cache_key.fixed_state;
- const auto& viewport_swizzles = state.viewport_swizzles;
-
- FixedPipelineState::DynamicState dynamic;
- if (device.IsExtExtendedDynamicStateSupported()) {
- // Insert dummy values, as long as they are valid they don't matter as extended dynamic
- // state is ignored
- dynamic.raw1 = 0;
- dynamic.raw2 = 0;
- dynamic.vertex_strides.fill(0);
- } else {
- dynamic = state.dynamic_state;
- }
-
- std::vector<VkVertexInputBindingDescription> vertex_bindings;
- std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors;
- for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
- const bool instanced = state.binding_divisors[index] != 0;
- const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
- vertex_bindings.push_back({
- .binding = static_cast<u32>(index),
- .stride = dynamic.vertex_strides[index],
- .inputRate = rate,
- });
- if (instanced) {
- vertex_binding_divisors.push_back({
- .binding = static_cast<u32>(index),
- .divisor = state.binding_divisors[index],
- });
- }
- }
-
- std::vector<VkVertexInputAttributeDescription> vertex_attributes;
- const auto& input_attributes = program[0]->entries.attributes;
- for (std::size_t index = 0; index < state.attributes.size(); ++index) {
- const auto& attribute = state.attributes[index];
- if (!attribute.enabled) {
- continue;
- }
- if (!input_attributes.contains(static_cast<u32>(index))) {
- // Skip attributes not used by the vertex shaders.
- continue;
- }
- vertex_attributes.push_back({
- .location = static_cast<u32>(index),
- .binding = attribute.buffer,
- .format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size()),
- .offset = attribute.offset,
- });
- }
-
- VkPipelineVertexInputStateCreateInfo vertex_input_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .vertexBindingDescriptionCount = static_cast<u32>(vertex_bindings.size()),
- .pVertexBindingDescriptions = vertex_bindings.data(),
- .vertexAttributeDescriptionCount = static_cast<u32>(vertex_attributes.size()),
- .pVertexAttributeDescriptions = vertex_attributes.data(),
- };
-
- const VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT,
- .pNext = nullptr,
- .vertexBindingDivisorCount = static_cast<u32>(vertex_binding_divisors.size()),
- .pVertexBindingDivisors = vertex_binding_divisors.data(),
- };
- if (!vertex_binding_divisors.empty()) {
- vertex_input_ci.pNext = &input_divisor_ci;
- }
-
- const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, state.topology);
- const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .topology = MaxwellToVK::PrimitiveTopology(device, state.topology),
- .primitiveRestartEnable = state.primitive_restart_enable != 0 &&
- SupportsPrimitiveRestart(input_assembly_topology),
- };
-
- const VkPipelineTessellationStateCreateInfo tessellation_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .patchControlPoints = state.patch_control_points_minus_one.Value() + 1,
- };
-
- VkPipelineViewportStateCreateInfo viewport_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .viewportCount = Maxwell::NumViewports,
- .pViewports = nullptr,
- .scissorCount = Maxwell::NumViewports,
- .pScissors = nullptr,
- };
-
- std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles;
- std::ranges::transform(viewport_swizzles, swizzles.begin(), UnpackViewportSwizzle);
- VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV,
- .pNext = nullptr,
- .flags = 0,
- .viewportCount = Maxwell::NumViewports,
- .pViewportSwizzles = swizzles.data(),
- };
- if (device.IsNvViewportSwizzleSupported()) {
- viewport_ci.pNext = &swizzle_ci;
- }
-
- const VkPipelineRasterizationStateCreateInfo rasterization_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .depthClampEnable =
- static_cast<VkBool32>(state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE),
- .rasterizerDiscardEnable =
- static_cast<VkBool32>(state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE),
- .polygonMode = VK_POLYGON_MODE_FILL,
- .cullMode = static_cast<VkCullModeFlags>(
- dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE),
- .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
- .depthBiasEnable = state.depth_bias_enable,
- .depthBiasConstantFactor = 0.0f,
- .depthBiasClamp = 0.0f,
- .depthBiasSlopeFactor = 0.0f,
- .lineWidth = 1.0f,
- };
-
- const VkPipelineMultisampleStateCreateInfo multisample_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .rasterizationSamples = ConvertMsaaMode(state.msaa_mode),
- .sampleShadingEnable = VK_FALSE,
- .minSampleShading = 0.0f,
- .pSampleMask = nullptr,
- .alphaToCoverageEnable = VK_FALSE,
- .alphaToOneEnable = VK_FALSE,
- };
-
- const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .depthTestEnable = dynamic.depth_test_enable,
- .depthWriteEnable = dynamic.depth_write_enable,
- .depthCompareOp = dynamic.depth_test_enable
- ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc())
- : VK_COMPARE_OP_ALWAYS,
- .depthBoundsTestEnable = dynamic.depth_bounds_enable,
- .stencilTestEnable = dynamic.stencil_enable,
- .front = GetStencilFaceState(dynamic.front),
- .back = GetStencilFaceState(dynamic.back),
- .minDepthBounds = 0.0f,
- .maxDepthBounds = 0.0f,
- };
-
- std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments;
- for (std::size_t index = 0; index < num_color_buffers; ++index) {
- static constexpr std::array COMPONENT_TABLE{
- VK_COLOR_COMPONENT_R_BIT,
- VK_COLOR_COMPONENT_G_BIT,
- VK_COLOR_COMPONENT_B_BIT,
- VK_COLOR_COMPONENT_A_BIT,
- };
- const auto& blend = state.attachments[index];
-
- VkColorComponentFlags color_components = 0;
- for (std::size_t i = 0; i < COMPONENT_TABLE.size(); ++i) {
- if (blend.Mask()[i]) {
- color_components |= COMPONENT_TABLE[i];
- }
- }
-
- cb_attachments[index] = {
- .blendEnable = blend.enable != 0,
- .srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor()),
- .dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor()),
- .colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB()),
- .srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor()),
- .dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor()),
- .alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha()),
- .colorWriteMask = color_components,
- };
- }
-
- const VkPipelineColorBlendStateCreateInfo color_blend_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .logicOpEnable = VK_FALSE,
- .logicOp = VK_LOGIC_OP_COPY,
- .attachmentCount = num_color_buffers,
- .pAttachments = cb_attachments.data(),
- .blendConstants = {},
- };
-
- std::vector dynamic_states{
- VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
- VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
- VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
- VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
- };
- if (device.IsExtExtendedDynamicStateSupported()) {
- static constexpr std::array extended{
- VK_DYNAMIC_STATE_CULL_MODE_EXT,
- VK_DYNAMIC_STATE_FRONT_FACE_EXT,
- VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
- VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
- VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
- VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
- VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
- VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
- VK_DYNAMIC_STATE_STENCIL_OP_EXT,
- };
- dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
- }
-
- const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
- .pDynamicStates = dynamic_states.data(),
- };
-
- const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
- .pNext = nullptr,
- .requiredSubgroupSize = GuestWarpSize,
- };
-
- std::vector<VkPipelineShaderStageCreateInfo> shader_stages;
- std::size_t module_index = 0;
- for (std::size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
- if (!program[stage]) {
- continue;
- }
-
- VkPipelineShaderStageCreateInfo& stage_ci = shader_stages.emplace_back();
- stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- stage_ci.pNext = nullptr;
- stage_ci.flags = 0;
- stage_ci.stage = MaxwellToVK::ShaderStage(static_cast<Tegra::Engines::ShaderType>(stage));
- stage_ci.module = *modules[module_index++];
- stage_ci.pName = "main";
- stage_ci.pSpecializationInfo = nullptr;
-
- if (program[stage]->entries.uses_warps && device.IsGuestWarpSizeSupported(stage_ci.stage)) {
- stage_ci.pNext = &subgroup_size_ci;
- }
- }
- return device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
- .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0,
- .stageCount = static_cast<u32>(shader_stages.size()),
- .pStages = shader_stages.data(),
- .pVertexInputState = &vertex_input_ci,
- .pInputAssemblyState = &input_assembly_ci,
- .pTessellationState = &tessellation_ci,
- .pViewportState = &viewport_ci,
- .pRasterizationState = &rasterization_ci,
- .pMultisampleState = &multisample_ci,
- .pDepthStencilState = &depth_stencil_ci,
- .pColorBlendState = &color_blend_ci,
- .pDynamicState = &dynamic_state_ci,
- .layout = *layout,
- .renderPass = renderpass,
- .subpass = 0,
- .basePipelineHandle = nullptr,
- .basePipelineIndex = 0,
- });
-}
-
-} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
deleted file mode 100644
index 8b6a98fe0..000000000
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <optional>
-#include <vector>
-
-#include "common/common_types.h"
-#include "video_core/engines/maxwell_3d.h"
-#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
-#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
-#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
-#include "video_core/vulkan_common/vulkan_wrapper.h"
-
-namespace Vulkan {
-
-using Maxwell = Tegra::Engines::Maxwell3D::Regs;
-
-struct GraphicsPipelineCacheKey {
- VkRenderPass renderpass;
- std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders;
- FixedPipelineState fixed_state;
-
- std::size_t Hash() const noexcept;
-
- bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept;
-
- bool operator!=(const GraphicsPipelineCacheKey& rhs) const noexcept {
- return !operator==(rhs);
- }
-
- std::size_t Size() const noexcept {
- return sizeof(renderpass) + sizeof(shaders) + fixed_state.Size();
- }
-};
-static_assert(std::has_unique_object_representations_v<GraphicsPipelineCacheKey>);
-static_assert(std::is_trivially_copyable_v<GraphicsPipelineCacheKey>);
-static_assert(std::is_trivially_constructible_v<GraphicsPipelineCacheKey>);
-
-class Device;
-class VKDescriptorPool;
-class VKScheduler;
-class VKUpdateDescriptorQueue;
-
-using SPIRVProgram = std::array<std::optional<SPIRVShader>, Maxwell::MaxShaderStage>;
-
-class VKGraphicsPipeline final {
-public:
- explicit VKGraphicsPipeline(const Device& device_, VKScheduler& scheduler_,
- VKDescriptorPool& descriptor_pool,
- VKUpdateDescriptorQueue& update_descriptor_queue_,
- const GraphicsPipelineCacheKey& key,
- vk::Span<VkDescriptorSetLayoutBinding> bindings,
- const SPIRVProgram& program, u32 num_color_buffers);
- ~VKGraphicsPipeline();
-
- VkDescriptorSet CommitDescriptorSet();
-
- VkPipeline GetHandle() const {
- return *pipeline;
- }
-
- VkPipelineLayout GetLayout() const {
- return *layout;
- }
-
- GraphicsPipelineCacheKey GetCacheKey() const {
- return cache_key;
- }
-
-private:
- vk::DescriptorSetLayout CreateDescriptorSetLayout(
- vk::Span<VkDescriptorSetLayoutBinding> bindings) const;
-
- vk::PipelineLayout CreatePipelineLayout() const;
-
- vk::DescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplate(
- const SPIRVProgram& program) const;
-
- std::vector<vk::ShaderModule> CreateShaderModules(const SPIRVProgram& program) const;
-
- vk::Pipeline CreatePipeline(const SPIRVProgram& program, VkRenderPass renderpass,
- u32 num_color_buffers) const;
-
- const Device& device;
- VKScheduler& scheduler;
- const GraphicsPipelineCacheKey cache_key;
- const u64 hash;
-
- vk::DescriptorSetLayout descriptor_set_layout;
- DescriptorAllocator descriptor_allocator;
- VKUpdateDescriptorQueue& update_descriptor_queue;
- vk::PipelineLayout layout;
- vk::DescriptorUpdateTemplateKHR descriptor_template;
- std::vector<vk::ShaderModule> modules;
-
- vk::Pipeline pipeline;
-};
-
-} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 8991505ca..7d0ba1180 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -19,49 +19,27 @@
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
-#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
-#include "video_core/shader/compiler_settings.h"
-#include "video_core/shader/memory_util.h"
#include "video_core/shader_cache.h"
#include "video_core/shader_notify.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan {
-
MICROPROFILE_DECLARE(Vulkan_PipelineCache);
using Tegra::Engines::ShaderType;
-using VideoCommon::Shader::GetShaderAddress;
-using VideoCommon::Shader::GetShaderCode;
-using VideoCommon::Shader::KERNEL_MAIN_OFFSET;
-using VideoCommon::Shader::ProgramCode;
-using VideoCommon::Shader::STAGE_MAIN_OFFSET;
namespace {
-
-constexpr VkDescriptorType UNIFORM_BUFFER = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-constexpr VkDescriptorType STORAGE_BUFFER = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
-constexpr VkDescriptorType UNIFORM_TEXEL_BUFFER = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
-constexpr VkDescriptorType COMBINED_IMAGE_SAMPLER = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-constexpr VkDescriptorType STORAGE_TEXEL_BUFFER = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
-constexpr VkDescriptorType STORAGE_IMAGE = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
-
-constexpr VideoCommon::Shader::CompilerSettings compiler_settings{
- .depth = VideoCommon::Shader::CompileDepth::FullDecompile,
- .disable_else_derivation = true,
-};
-
-constexpr std::size_t GetStageFromProgram(std::size_t program) {
+size_t StageFromProgram(size_t program) {
return program == 0 ? 0 : program - 1;
}
-constexpr ShaderType GetStageFromProgram(Maxwell::ShaderProgram program) {
- return static_cast<ShaderType>(GetStageFromProgram(static_cast<std::size_t>(program)));
+ShaderType StageFromProgram(Maxwell::ShaderProgram program) {
+ return static_cast<ShaderType>(StageFromProgram(static_cast<size_t>(program)));
}
ShaderType GetShaderType(Maxwell::ShaderProgram program) {
@@ -81,165 +59,35 @@ ShaderType GetShaderType(Maxwell::ShaderProgram program) {
return ShaderType::Vertex;
}
}
-
-template <VkDescriptorType descriptor_type, class Container>
-void AddBindings(std::vector<VkDescriptorSetLayoutBinding>& bindings, u32& binding,
- VkShaderStageFlags stage_flags, const Container& container) {
- const u32 num_entries = static_cast<u32>(std::size(container));
- for (std::size_t i = 0; i < num_entries; ++i) {
- u32 count = 1;
- if constexpr (descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
- // Combined image samplers can be arrayed.
- count = container[i].size;
- }
- bindings.push_back({
- .binding = binding++,
- .descriptorType = descriptor_type,
- .descriptorCount = count,
- .stageFlags = stage_flags,
- .pImmutableSamplers = nullptr,
- });
- }
-}
-
-u32 FillDescriptorLayout(const ShaderEntries& entries,
- std::vector<VkDescriptorSetLayoutBinding>& bindings,
- Maxwell::ShaderProgram program_type, u32 base_binding) {
- const ShaderType stage = GetStageFromProgram(program_type);
- const VkShaderStageFlags flags = MaxwellToVK::ShaderStage(stage);
-
- u32 binding = base_binding;
- AddBindings<UNIFORM_BUFFER>(bindings, binding, flags, entries.const_buffers);
- AddBindings<STORAGE_BUFFER>(bindings, binding, flags, entries.global_buffers);
- AddBindings<UNIFORM_TEXEL_BUFFER>(bindings, binding, flags, entries.uniform_texels);
- AddBindings<COMBINED_IMAGE_SAMPLER>(bindings, binding, flags, entries.samplers);
- AddBindings<STORAGE_TEXEL_BUFFER>(bindings, binding, flags, entries.storage_texels);
- AddBindings<STORAGE_IMAGE>(bindings, binding, flags, entries.images);
- return binding;
-}
-
} // Anonymous namespace
-std::size_t GraphicsPipelineCacheKey::Hash() const noexcept {
- const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), Size());
- return static_cast<std::size_t>(hash);
-}
-
-bool GraphicsPipelineCacheKey::operator==(const GraphicsPipelineCacheKey& rhs) const noexcept {
- return std::memcmp(&rhs, this, Size()) == 0;
-}
-
-std::size_t ComputePipelineCacheKey::Hash() const noexcept {
+size_t ComputePipelineCacheKey::Hash() const noexcept {
const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this);
- return static_cast<std::size_t>(hash);
+ return static_cast<size_t>(hash);
}
bool ComputePipelineCacheKey::operator==(const ComputePipelineCacheKey& rhs) const noexcept {
return std::memcmp(&rhs, this, sizeof *this) == 0;
}
-Shader::Shader(Tegra::Engines::ConstBufferEngineInterface& engine_, ShaderType stage_,
- GPUVAddr gpu_addr_, VAddr cpu_addr_, ProgramCode program_code_, u32 main_offset_)
- : gpu_addr(gpu_addr_), program_code(std::move(program_code_)), registry(stage_, engine_),
- shader_ir(program_code, main_offset_, compiler_settings, registry),
- entries(GenerateShaderEntries(shader_ir)) {}
+Shader::Shader() = default;
Shader::~Shader() = default;
-VKPipelineCache::VKPipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_,
- Tegra::Engines::Maxwell3D& maxwell3d_,
- Tegra::Engines::KeplerCompute& kepler_compute_,
- Tegra::MemoryManager& gpu_memory_, const Device& device_,
- VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_,
- VKUpdateDescriptorQueue& update_descriptor_queue_)
+PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_,
+ Tegra::Engines::Maxwell3D& maxwell3d_,
+ Tegra::Engines::KeplerCompute& kepler_compute_,
+ Tegra::MemoryManager& gpu_memory_, const Device& device_,
+ VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_,
+ VKUpdateDescriptorQueue& update_descriptor_queue_)
: VideoCommon::ShaderCache<Shader>{rasterizer_}, gpu{gpu_}, maxwell3d{maxwell3d_},
kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_},
scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, update_descriptor_queue{
update_descriptor_queue_} {}
-VKPipelineCache::~VKPipelineCache() = default;
-
-std::array<Shader*, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() {
- std::array<Shader*, Maxwell::MaxShaderProgram> shaders{};
-
- for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
- const auto program{static_cast<Maxwell::ShaderProgram>(index)};
-
- // Skip stages that are not enabled
- if (!maxwell3d.regs.IsShaderConfigEnabled(index)) {
- continue;
- }
-
- const GPUVAddr gpu_addr{GetShaderAddress(maxwell3d, program)};
- const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr);
- ASSERT(cpu_addr);
-
- Shader* result = cpu_addr ? TryGet(*cpu_addr) : null_shader.get();
- if (!result) {
- const u8* const host_ptr{gpu_memory.GetPointer(gpu_addr)};
-
- // No shader found - create a new one
- static constexpr u32 stage_offset = STAGE_MAIN_OFFSET;
- const auto stage = static_cast<ShaderType>(index == 0 ? 0 : index - 1);
- ProgramCode code = GetShaderCode(gpu_memory, gpu_addr, host_ptr, false);
- const std::size_t size_in_bytes = code.size() * sizeof(u64);
-
- auto shader = std::make_unique<Shader>(maxwell3d, stage, gpu_addr, *cpu_addr,
- std::move(code), stage_offset);
- result = shader.get();
-
- if (cpu_addr) {
- Register(std::move(shader), *cpu_addr, size_in_bytes);
- } else {
- null_shader = std::move(shader);
- }
- }
- shaders[index] = result;
- }
- return last_shaders = shaders;
-}
-
-VKGraphicsPipeline* VKPipelineCache::GetGraphicsPipeline(
- const GraphicsPipelineCacheKey& key, u32 num_color_buffers,
- VideoCommon::Shader::AsyncShaders& async_shaders) {
- MICROPROFILE_SCOPE(Vulkan_PipelineCache);
-
- if (last_graphics_pipeline && last_graphics_key == key) {
- return last_graphics_pipeline;
- }
- last_graphics_key = key;
-
- if (device.UseAsynchronousShaders() && async_shaders.IsShaderAsync(gpu)) {
- std::unique_lock lock{pipeline_cache};
- const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key);
- if (is_cache_miss) {
- gpu.ShaderNotify().MarkSharderBuilding();
- LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash());
- const auto [program, bindings] = DecompileShaders(key.fixed_state);
- async_shaders.QueueVulkanShader(this, device, scheduler, descriptor_pool,
- update_descriptor_queue, bindings, program, key,
- num_color_buffers);
- }
- last_graphics_pipeline = pair->second.get();
- return last_graphics_pipeline;
- }
-
- const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key);
- auto& entry = pair->second;
- if (is_cache_miss) {
- gpu.ShaderNotify().MarkSharderBuilding();
- LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash());
- const auto [program, bindings] = DecompileShaders(key.fixed_state);
- entry = std::make_unique<VKGraphicsPipeline>(device, scheduler, descriptor_pool,
- update_descriptor_queue, key, bindings,
- program, num_color_buffers);
- gpu.ShaderNotify().MarkShaderComplete();
- }
- last_graphics_pipeline = entry.get();
- return last_graphics_pipeline;
-}
+PipelineCache::~PipelineCache() = default;
-VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) {
+ComputePipeline& PipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) {
MICROPROFILE_SCOPE(Vulkan_PipelineCache);
const auto [pair, is_cache_miss] = compute_cache.try_emplace(key);
@@ -248,200 +96,9 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
return *entry;
}
LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash());
-
- const GPUVAddr gpu_addr = key.shader;
-
- const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr);
- ASSERT(cpu_addr);
-
- Shader* shader = cpu_addr ? TryGet(*cpu_addr) : null_kernel.get();
- if (!shader) {
- // No shader found - create a new one
- const auto host_ptr = gpu_memory.GetPointer(gpu_addr);
-
- ProgramCode code = GetShaderCode(gpu_memory, gpu_addr, host_ptr, true);
- const std::size_t size_in_bytes = code.size() * sizeof(u64);
-
- auto shader_info = std::make_unique<Shader>(kepler_compute, ShaderType::Compute, gpu_addr,
- *cpu_addr, std::move(code), KERNEL_MAIN_OFFSET);
- shader = shader_info.get();
-
- if (cpu_addr) {
- Register(std::move(shader_info), *cpu_addr, size_in_bytes);
- } else {
- null_kernel = std::move(shader_info);
- }
- }
-
- const Specialization specialization{
- .base_binding = 0,
- .workgroup_size = key.workgroup_size,
- .shared_memory_size = key.shared_memory_size,
- .point_size = std::nullopt,
- .enabled_attributes = {},
- .attribute_types = {},
- .ndc_minus_one_to_one = false,
- };
- const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute,
- shader->GetRegistry(), specialization),
- shader->GetEntries()};
- entry = std::make_unique<VKComputePipeline>(device, scheduler, descriptor_pool,
- update_descriptor_queue, spirv_shader);
- return *entry;
-}
-
-void VKPipelineCache::EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline) {
- gpu.ShaderNotify().MarkShaderComplete();
- std::unique_lock lock{pipeline_cache};
- graphics_cache.at(pipeline->GetCacheKey()) = std::move(pipeline);
-}
-
-void VKPipelineCache::OnShaderRemoval(Shader* shader) {
- bool finished = false;
- const auto Finish = [&] {
- // TODO(Rodrigo): Instead of finishing here, wait for the fences that use this pipeline and
- // flush.
- if (finished) {
- return;
- }
- finished = true;
- scheduler.Finish();
- };
-
- const GPUVAddr invalidated_addr = shader->GetGpuAddr();
- for (auto it = graphics_cache.begin(); it != graphics_cache.end();) {
- auto& entry = it->first;
- if (std::find(entry.shaders.begin(), entry.shaders.end(), invalidated_addr) ==
- entry.shaders.end()) {
- ++it;
- continue;
- }
- Finish();
- it = graphics_cache.erase(it);
- }
- for (auto it = compute_cache.begin(); it != compute_cache.end();) {
- auto& entry = it->first;
- if (entry.shader != invalidated_addr) {
- ++it;
- continue;
- }
- Finish();
- it = compute_cache.erase(it);
- }
-}
-
-std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>>
-VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
- Specialization specialization;
- if (fixed_state.topology == Maxwell::PrimitiveTopology::Points) {
- float point_size;
- std::memcpy(&point_size, &fixed_state.point_size, sizeof(float));
- specialization.point_size = point_size;
- ASSERT(point_size != 0.0f);
- }
- for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) {
- const auto& attribute = fixed_state.attributes[i];
- specialization.enabled_attributes[i] = attribute.enabled.Value() != 0;
- specialization.attribute_types[i] = attribute.Type();
- }
- specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one;
- specialization.early_fragment_tests = fixed_state.early_z;
-
- // Alpha test
- specialization.alpha_test_func =
- FixedPipelineState::UnpackComparisonOp(fixed_state.alpha_test_func.Value());
- specialization.alpha_test_ref = Common::BitCast<float>(fixed_state.alpha_test_ref);
-
- SPIRVProgram program;
- std::vector<VkDescriptorSetLayoutBinding> bindings;
-
- for (std::size_t index = 1; index < Maxwell::MaxShaderProgram; ++index) {
- const auto program_enum = static_cast<Maxwell::ShaderProgram>(index);
- // Skip stages that are not enabled
- if (!maxwell3d.regs.IsShaderConfigEnabled(index)) {
- continue;
- }
- const GPUVAddr gpu_addr = GetShaderAddress(maxwell3d, program_enum);
- const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr);
- Shader* const shader = cpu_addr ? TryGet(*cpu_addr) : null_shader.get();
-
- const std::size_t stage = index == 0 ? 0 : index - 1; // Stage indices are 0 - 5
- const ShaderType program_type = GetShaderType(program_enum);
- const auto& entries = shader->GetEntries();
- program[stage] = {
- Decompile(device, shader->GetIR(), program_type, shader->GetRegistry(), specialization),
- entries,
- };
-
- const u32 old_binding = specialization.base_binding;
- specialization.base_binding =
- FillDescriptorLayout(entries, bindings, program_enum, specialization.base_binding);
- ASSERT(old_binding + entries.NumBindings() == specialization.base_binding);
- }
- return {std::move(program), std::move(bindings)};
+ throw "Bad";
}
-template <VkDescriptorType descriptor_type, class Container>
-void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u32& binding,
- u32& offset, const Container& container) {
- static constexpr u32 entry_size = static_cast<u32>(sizeof(DescriptorUpdateEntry));
- const u32 count = static_cast<u32>(std::size(container));
-
- if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) {
- for (u32 i = 0; i < count; ++i) {
- const u32 num_samplers = container[i].size;
- template_entries.push_back({
- .dstBinding = binding,
- .dstArrayElement = 0,
- .descriptorCount = num_samplers,
- .descriptorType = descriptor_type,
- .offset = offset,
- .stride = entry_size,
- });
-
- ++binding;
- offset += num_samplers * entry_size;
- }
- return;
- }
-
- if constexpr (descriptor_type == UNIFORM_TEXEL_BUFFER ||
- descriptor_type == STORAGE_TEXEL_BUFFER) {
- // Nvidia has a bug where updating multiple texels at once causes the driver to crash.
- // Note: Fixed in driver Windows 443.24, Linux 440.66.15
- for (u32 i = 0; i < count; ++i) {
- template_entries.push_back({
- .dstBinding = binding + i,
- .dstArrayElement = 0,
- .descriptorCount = 1,
- .descriptorType = descriptor_type,
- .offset = static_cast<std::size_t>(offset + i * entry_size),
- .stride = entry_size,
- });
- }
- } else if (count > 0) {
- template_entries.push_back({
- .dstBinding = binding,
- .dstArrayElement = 0,
- .descriptorCount = count,
- .descriptorType = descriptor_type,
- .offset = offset,
- .stride = entry_size,
- });
- }
- offset += count * entry_size;
- binding += count;
-}
-
-void FillDescriptorUpdateTemplateEntries(
- const ShaderEntries& entries, u32& binding, u32& offset,
- std::vector<VkDescriptorUpdateTemplateEntryKHR>& template_entries) {
- AddEntry<UNIFORM_BUFFER>(template_entries, offset, binding, entries.const_buffers);
- AddEntry<STORAGE_BUFFER>(template_entries, offset, binding, entries.global_buffers);
- AddEntry<UNIFORM_TEXEL_BUFFER>(template_entries, offset, binding, entries.uniform_texels);
- AddEntry<COMBINED_IMAGE_SAMPLER>(template_entries, offset, binding, entries.samplers);
- AddEntry<STORAGE_TEXEL_BUFFER>(template_entries, offset, binding, entries.storage_texels);
- AddEntry<STORAGE_IMAGE>(template_entries, offset, binding, entries.images);
-}
+void PipelineCache::OnShaderRemoval(Shader*) {}
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index 89d635a3d..e3e63340d 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -15,15 +15,8 @@
#include <boost/functional/hash.hpp>
#include "common/common_types.h"
-#include "video_core/engines/const_buffer_engine_interface.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
-#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
-#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
-#include "video_core/shader/async_shaders.h"
-#include "video_core/shader/memory_util.h"
-#include "video_core/shader/registry.h"
-#include "video_core/shader/shader_ir.h"
#include "video_core/shader_cache.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -35,7 +28,7 @@ namespace Vulkan {
class Device;
class RasterizerVulkan;
-class VKComputePipeline;
+class ComputePipeline;
class VKDescriptorPool;
class VKScheduler;
class VKUpdateDescriptorQueue;
@@ -47,7 +40,7 @@ struct ComputePipelineCacheKey {
u32 shared_memory_size;
std::array<u32, 3> workgroup_size;
- std::size_t Hash() const noexcept;
+ size_t Hash() const noexcept;
bool operator==(const ComputePipelineCacheKey& rhs) const noexcept;
@@ -64,15 +57,8 @@ static_assert(std::is_trivially_constructible_v<ComputePipelineCacheKey>);
namespace std {
template <>
-struct hash<Vulkan::GraphicsPipelineCacheKey> {
- std::size_t operator()(const Vulkan::GraphicsPipelineCacheKey& k) const noexcept {
- return k.Hash();
- }
-};
-
-template <>
struct hash<Vulkan::ComputePipelineCacheKey> {
- std::size_t operator()(const Vulkan::ComputePipelineCacheKey& k) const noexcept {
+ size_t operator()(const Vulkan::ComputePipelineCacheKey& k) const noexcept {
return k.Hash();
}
};
@@ -83,66 +69,26 @@ namespace Vulkan {
class Shader {
public:
- explicit Shader(Tegra::Engines::ConstBufferEngineInterface& engine_,
- Tegra::Engines::ShaderType stage_, GPUVAddr gpu_addr, VAddr cpu_addr_,
- VideoCommon::Shader::ProgramCode program_code, u32 main_offset_);
+ explicit Shader();
~Shader();
-
- GPUVAddr GetGpuAddr() const {
- return gpu_addr;
- }
-
- VideoCommon::Shader::ShaderIR& GetIR() {
- return shader_ir;
- }
-
- const VideoCommon::Shader::ShaderIR& GetIR() const {
- return shader_ir;
- }
-
- const VideoCommon::Shader::Registry& GetRegistry() const {
- return registry;
- }
-
- const ShaderEntries& GetEntries() const {
- return entries;
- }
-
-private:
- GPUVAddr gpu_addr{};
- VideoCommon::Shader::ProgramCode program_code;
- VideoCommon::Shader::Registry registry;
- VideoCommon::Shader::ShaderIR shader_ir;
- ShaderEntries entries;
};
-class VKPipelineCache final : public VideoCommon::ShaderCache<Shader> {
+class PipelineCache final : public VideoCommon::ShaderCache<Shader> {
public:
- explicit VKPipelineCache(RasterizerVulkan& rasterizer, Tegra::GPU& gpu,
- Tegra::Engines::Maxwell3D& maxwell3d,
- Tegra::Engines::KeplerCompute& kepler_compute,
- Tegra::MemoryManager& gpu_memory, const Device& device,
- VKScheduler& scheduler, VKDescriptorPool& descriptor_pool,
- VKUpdateDescriptorQueue& update_descriptor_queue);
- ~VKPipelineCache() override;
-
- std::array<Shader*, Maxwell::MaxShaderProgram> GetShaders();
+ explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::GPU& gpu,
+ Tegra::Engines::Maxwell3D& maxwell3d,
+ Tegra::Engines::KeplerCompute& kepler_compute,
+ Tegra::MemoryManager& gpu_memory, const Device& device,
+ VKScheduler& scheduler, VKDescriptorPool& descriptor_pool,
+ VKUpdateDescriptorQueue& update_descriptor_queue);
+ ~PipelineCache() override;
- VKGraphicsPipeline* GetGraphicsPipeline(const GraphicsPipelineCacheKey& key,
- u32 num_color_buffers,
- VideoCommon::Shader::AsyncShaders& async_shaders);
-
- VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key);
-
- void EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline);
+ ComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key);
protected:
void OnShaderRemoval(Shader* shader) final;
private:
- std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> DecompileShaders(
- const FixedPipelineState& fixed_state);
-
Tegra::GPU& gpu;
Tegra::Engines::Maxwell3D& maxwell3d;
Tegra::Engines::KeplerCompute& kepler_compute;
@@ -158,17 +104,8 @@ private:
std::array<Shader*, Maxwell::MaxShaderProgram> last_shaders{};
- GraphicsPipelineCacheKey last_graphics_key;
- VKGraphicsPipeline* last_graphics_pipeline = nullptr;
-
std::mutex pipeline_cache;
- std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<VKGraphicsPipeline>>
- graphics_cache;
- std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<VKComputePipeline>> compute_cache;
+ std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache;
};
-void FillDescriptorUpdateTemplateEntries(
- const ShaderEntries& entries, u32& binding, u32& offset,
- std::vector<VkDescriptorUpdateTemplateEntryKHR>& template_entries);
-
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index f57c15b37..f152297d9 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -24,7 +24,6 @@
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
-#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
@@ -97,15 +96,6 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index) {
return scissor;
}
-std::array<GPUVAddr, Maxwell::MaxShaderProgram> GetShaderAddresses(
- const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders) {
- std::array<GPUVAddr, Maxwell::MaxShaderProgram> addresses;
- for (size_t i = 0; i < std::size(addresses); ++i) {
- addresses[i] = shaders[i] ? shaders[i]->GetGpuAddr() : 0;
- }
- return addresses;
-}
-
struct TextureHandle {
constexpr TextureHandle(u32 data, bool via_header_index) {
const Tegra::Texture::TextureHandle handle{data};
@@ -117,98 +107,6 @@ struct TextureHandle {
u32 sampler;
};
-template <typename Engine, typename Entry>
-TextureHandle GetTextureInfo(const Engine& engine, bool via_header_index, const Entry& entry,
- size_t stage, size_t index = 0) {
- const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage);
- if constexpr (std::is_same_v<Entry, SamplerEntry>) {
- if (entry.is_separated) {
- const u32 buffer_1 = entry.buffer;
- const u32 buffer_2 = entry.secondary_buffer;
- const u32 offset_1 = entry.offset;
- const u32 offset_2 = entry.secondary_offset;
- const u32 handle_1 = engine.AccessConstBuffer32(shader_type, buffer_1, offset_1);
- const u32 handle_2 = engine.AccessConstBuffer32(shader_type, buffer_2, offset_2);
- return TextureHandle(handle_1 | handle_2, via_header_index);
- }
- }
- if (entry.is_bindless) {
- const u32 raw = engine.AccessConstBuffer32(shader_type, entry.buffer, entry.offset);
- return TextureHandle(raw, via_header_index);
- }
- const u32 buffer = engine.GetBoundBuffer();
- const u64 offset = (entry.offset + index) * sizeof(u32);
- return TextureHandle(engine.AccessConstBuffer32(shader_type, buffer, offset), via_header_index);
-}
-
-ImageViewType ImageViewTypeFromEntry(const SamplerEntry& entry) {
- if (entry.is_buffer) {
- return ImageViewType::e2D;
- }
- switch (entry.type) {
- case Tegra::Shader::TextureType::Texture1D:
- return entry.is_array ? ImageViewType::e1DArray : ImageViewType::e1D;
- case Tegra::Shader::TextureType::Texture2D:
- return entry.is_array ? ImageViewType::e2DArray : ImageViewType::e2D;
- case Tegra::Shader::TextureType::Texture3D:
- return ImageViewType::e3D;
- case Tegra::Shader::TextureType::TextureCube:
- return entry.is_array ? ImageViewType::CubeArray : ImageViewType::Cube;
- }
- UNREACHABLE();
- return ImageViewType::e2D;
-}
-
-ImageViewType ImageViewTypeFromEntry(const ImageEntry& entry) {
- switch (entry.type) {
- case Tegra::Shader::ImageType::Texture1D:
- return ImageViewType::e1D;
- case Tegra::Shader::ImageType::Texture1DArray:
- return ImageViewType::e1DArray;
- case Tegra::Shader::ImageType::Texture2D:
- return ImageViewType::e2D;
- case Tegra::Shader::ImageType::Texture2DArray:
- return ImageViewType::e2DArray;
- case Tegra::Shader::ImageType::Texture3D:
- return ImageViewType::e3D;
- case Tegra::Shader::ImageType::TextureBuffer:
- return ImageViewType::Buffer;
- }
- UNREACHABLE();
- return ImageViewType::e2D;
-}
-
-void PushImageDescriptors(const ShaderEntries& entries, TextureCache& texture_cache,
- VKUpdateDescriptorQueue& update_descriptor_queue,
- ImageViewId*& image_view_id_ptr, VkSampler*& sampler_ptr) {
- for ([[maybe_unused]] const auto& entry : entries.uniform_texels) {
- const ImageViewId image_view_id = *image_view_id_ptr++;
- const ImageView& image_view = texture_cache.GetImageView(image_view_id);
- update_descriptor_queue.AddTexelBuffer(image_view.BufferView());
- }
- for (const auto& entry : entries.samplers) {
- for (size_t i = 0; i < entry.size; ++i) {
- const VkSampler sampler = *sampler_ptr++;
- const ImageViewId image_view_id = *image_view_id_ptr++;
- const ImageView& image_view = texture_cache.GetImageView(image_view_id);
- const VkImageView handle = image_view.Handle(ImageViewTypeFromEntry(entry));
- update_descriptor_queue.AddSampledImage(handle, sampler);
- }
- }
- for ([[maybe_unused]] const auto& entry : entries.storage_texels) {
- const ImageViewId image_view_id = *image_view_id_ptr++;
- const ImageView& image_view = texture_cache.GetImageView(image_view_id);
- update_descriptor_queue.AddTexelBuffer(image_view.BufferView());
- }
- for (const auto& entry : entries.images) {
- // TODO: Mark as modified
- const ImageViewId image_view_id = *image_view_id_ptr++;
- const ImageView& image_view = texture_cache.GetImageView(image_view_id);
- const VkImageView handle = image_view.Handle(ImageViewTypeFromEntry(entry));
- update_descriptor_queue.AddImage(handle);
- }
-}
-
DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_instanced,
bool is_indexed) {
DrawParams params{
@@ -253,71 +151,14 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
descriptor_pool, update_descriptor_queue),
query_cache{*this, maxwell3d, gpu_memory, device, scheduler}, accelerate_dma{buffer_cache},
fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler),
- wfi_event(device.GetLogical().CreateEvent()), async_shaders(emu_window_) {
+ wfi_event(device.GetLogical().CreateEvent()) {
scheduler.SetQueryCache(query_cache);
- if (device.UseAsynchronousShaders()) {
- async_shaders.AllocateWorkers();
- }
}
RasterizerVulkan::~RasterizerVulkan() = default;
void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
- MICROPROFILE_SCOPE(Vulkan_Drawing);
-
- SCOPE_EXIT({ gpu.TickWork(); });
- FlushWork();
-
- query_cache.UpdateCounters();
-
- graphics_key.fixed_state.Refresh(maxwell3d, device.IsExtExtendedDynamicStateSupported());
-
- std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
-
- texture_cache.SynchronizeGraphicsDescriptors();
- texture_cache.UpdateRenderTargets(false);
-
- const auto shaders = pipeline_cache.GetShaders();
- graphics_key.shaders = GetShaderAddresses(shaders);
-
- SetupShaderDescriptors(shaders, is_indexed);
-
- const Framebuffer* const framebuffer = texture_cache.GetFramebuffer();
- graphics_key.renderpass = framebuffer->RenderPass();
-
- VKGraphicsPipeline* const pipeline = pipeline_cache.GetGraphicsPipeline(
- graphics_key, framebuffer->NumColorBuffers(), async_shaders);
- if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) {
- // Async graphics pipeline was not ready.
- return;
- }
-
- BeginTransformFeedback();
-
- scheduler.RequestRenderpass(framebuffer);
- scheduler.BindGraphicsPipeline(pipeline->GetHandle());
- UpdateDynamicStates();
-
- const auto& regs = maxwell3d.regs;
- const u32 num_instances = maxwell3d.mme_draw.instance_count;
- const DrawParams draw_params = MakeDrawParams(regs, num_instances, is_instanced, is_indexed);
- const VkPipelineLayout pipeline_layout = pipeline->GetLayout();
- const VkDescriptorSet descriptor_set = pipeline->CommitDescriptorSet();
- scheduler.Record([pipeline_layout, descriptor_set, draw_params](vk::CommandBuffer cmdbuf) {
- if (descriptor_set) {
- cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout,
- DESCRIPTOR_SET, descriptor_set, nullptr);
- }
- if (draw_params.is_indexed) {
- cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances, 0,
- draw_params.base_vertex, draw_params.base_instance);
- } else {
- cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances,
- draw_params.base_vertex, draw_params.base_instance);
- }
- });
-
- EndTransformFeedback();
+ UNREACHABLE_MSG("Rendering not implemented {} {}", is_indexed, is_instanced);
}
void RasterizerVulkan::Clear() {
@@ -395,73 +236,8 @@ void RasterizerVulkan::Clear() {
});
}
-void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) {
- MICROPROFILE_SCOPE(Vulkan_Compute);
-
- query_cache.UpdateCounters();
-
- const auto& launch_desc = kepler_compute.launch_description;
- auto& pipeline = pipeline_cache.GetComputePipeline({
- .shader = code_addr,
- .shared_memory_size = launch_desc.shared_alloc,
- .workgroup_size{
- launch_desc.block_dim_x,
- launch_desc.block_dim_y,
- launch_desc.block_dim_z,
- },
- });
-
- // Compute dispatches can't be executed inside a renderpass
- scheduler.RequestOutsideRenderPassOperationContext();
-
- image_view_indices.clear();
- sampler_handles.clear();
-
- std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
-
- const auto& entries = pipeline.GetEntries();
- buffer_cache.SetEnabledComputeUniformBuffers(entries.enabled_uniform_buffers);
- buffer_cache.UnbindComputeStorageBuffers();
- u32 ssbo_index = 0;
- for (const auto& buffer : entries.global_buffers) {
- buffer_cache.BindComputeStorageBuffer(ssbo_index, buffer.cbuf_index, buffer.cbuf_offset,
- buffer.is_written);
- ++ssbo_index;
- }
- buffer_cache.UpdateComputeBuffers();
-
- texture_cache.SynchronizeComputeDescriptors();
-
- SetupComputeUniformTexels(entries);
- SetupComputeTextures(entries);
- SetupComputeStorageTexels(entries);
- SetupComputeImages(entries);
-
- const std::span indices_span(image_view_indices.data(), image_view_indices.size());
- texture_cache.FillComputeImageViews(indices_span, image_view_ids);
-
- update_descriptor_queue.Acquire();
-
- buffer_cache.BindHostComputeBuffers();
-
- ImageViewId* image_view_id_ptr = image_view_ids.data();
- VkSampler* sampler_ptr = sampler_handles.data();
- PushImageDescriptors(entries, texture_cache, update_descriptor_queue, image_view_id_ptr,
- sampler_ptr);
-
- const VkPipeline pipeline_handle = pipeline.GetHandle();
- const VkPipelineLayout pipeline_layout = pipeline.GetLayout();
- const VkDescriptorSet descriptor_set = pipeline.CommitDescriptorSet();
- scheduler.Record([grid_x = launch_desc.grid_dim_x, grid_y = launch_desc.grid_dim_y,
- grid_z = launch_desc.grid_dim_z, pipeline_handle, pipeline_layout,
- descriptor_set](vk::CommandBuffer cmdbuf) {
- cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_handle);
- if (descriptor_set) {
- cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout,
- DESCRIPTOR_SET, descriptor_set, nullptr);
- }
- cmdbuf.Dispatch(grid_x, grid_y, grid_z);
- });
+void RasterizerVulkan::DispatchCompute() {
+ UNREACHABLE_MSG("Not implemented");
}
void RasterizerVulkan::ResetCounter(VideoCore::QueryType type) {
@@ -716,52 +492,6 @@ bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64
return buffer_cache.DMACopy(src_address, dest_address, amount);
}
-void RasterizerVulkan::SetupShaderDescriptors(
- const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders, bool is_indexed) {
- image_view_indices.clear();
- sampler_handles.clear();
- for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
- Shader* const shader = shaders[stage + 1];
- if (!shader) {
- continue;
- }
- const ShaderEntries& entries = shader->GetEntries();
- SetupGraphicsUniformTexels(entries, stage);
- SetupGraphicsTextures(entries, stage);
- SetupGraphicsStorageTexels(entries, stage);
- SetupGraphicsImages(entries, stage);
-
- buffer_cache.SetEnabledUniformBuffers(stage, entries.enabled_uniform_buffers);
- buffer_cache.UnbindGraphicsStorageBuffers(stage);
- u32 ssbo_index = 0;
- for (const auto& buffer : entries.global_buffers) {
- buffer_cache.BindGraphicsStorageBuffer(stage, ssbo_index, buffer.cbuf_index,
- buffer.cbuf_offset, buffer.is_written);
- ++ssbo_index;
- }
- }
- const std::span indices_span(image_view_indices.data(), image_view_indices.size());
- buffer_cache.UpdateGraphicsBuffers(is_indexed);
- texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
-
- buffer_cache.BindHostGeometryBuffers(is_indexed);
-
- update_descriptor_queue.Acquire();
-
- ImageViewId* image_view_id_ptr = image_view_ids.data();
- VkSampler* sampler_ptr = sampler_handles.data();
- for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
- // Skip VertexA stage
- Shader* const shader = shaders[stage + 1];
- if (!shader) {
- continue;
- }
- buffer_cache.BindHostStageBuffers(stage);
- PushImageDescriptors(shader->GetEntries(), texture_cache, update_descriptor_queue,
- image_view_id_ptr, sampler_ptr);
- }
-}
-
void RasterizerVulkan::UpdateDynamicStates() {
auto& regs = maxwell3d.regs;
UpdateViewportsState(regs);
@@ -810,89 +540,6 @@ void RasterizerVulkan::EndTransformFeedback() {
[](vk::CommandBuffer cmdbuf) { cmdbuf.EndTransformFeedbackEXT(0, 0, nullptr, nullptr); });
}
-void RasterizerVulkan::SetupGraphicsUniformTexels(const ShaderEntries& entries, size_t stage) {
- const auto& regs = maxwell3d.regs;
- const bool via_header_index = regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex;
- for (const auto& entry : entries.uniform_texels) {
- const TextureHandle handle = GetTextureInfo(maxwell3d, via_header_index, entry, stage);
- image_view_indices.push_back(handle.image);
- }
-}
-
-void RasterizerVulkan::SetupGraphicsTextures(const ShaderEntries& entries, size_t stage) {
- const auto& regs = maxwell3d.regs;
- const bool via_header_index = regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex;
- for (const auto& entry : entries.samplers) {
- for (size_t index = 0; index < entry.size; ++index) {
- const TextureHandle handle =
- GetTextureInfo(maxwell3d, via_header_index, entry, stage, index);
- image_view_indices.push_back(handle.image);
-
- Sampler* const sampler = texture_cache.GetGraphicsSampler(handle.sampler);
- sampler_handles.push_back(sampler->Handle());
- }
- }
-}
-
-void RasterizerVulkan::SetupGraphicsStorageTexels(const ShaderEntries& entries, size_t stage) {
- const auto& regs = maxwell3d.regs;
- const bool via_header_index = regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex;
- for (const auto& entry : entries.storage_texels) {
- const TextureHandle handle = GetTextureInfo(maxwell3d, via_header_index, entry, stage);
- image_view_indices.push_back(handle.image);
- }
-}
-
-void RasterizerVulkan::SetupGraphicsImages(const ShaderEntries& entries, size_t stage) {
- const auto& regs = maxwell3d.regs;
- const bool via_header_index = regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex;
- for (const auto& entry : entries.images) {
- const TextureHandle handle = GetTextureInfo(maxwell3d, via_header_index, entry, stage);
- image_view_indices.push_back(handle.image);
- }
-}
-
-void RasterizerVulkan::SetupComputeUniformTexels(const ShaderEntries& entries) {
- const bool via_header_index = kepler_compute.launch_description.linked_tsc;
- for (const auto& entry : entries.uniform_texels) {
- const TextureHandle handle =
- GetTextureInfo(kepler_compute, via_header_index, entry, COMPUTE_SHADER_INDEX);
- image_view_indices.push_back(handle.image);
- }
-}
-
-void RasterizerVulkan::SetupComputeTextures(const ShaderEntries& entries) {
- const bool via_header_index = kepler_compute.launch_description.linked_tsc;
- for (const auto& entry : entries.samplers) {
- for (size_t index = 0; index < entry.size; ++index) {
- const TextureHandle handle = GetTextureInfo(kepler_compute, via_header_index, entry,
- COMPUTE_SHADER_INDEX, index);
- image_view_indices.push_back(handle.image);
-
- Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler);
- sampler_handles.push_back(sampler->Handle());
- }
- }
-}
-
-void RasterizerVulkan::SetupComputeStorageTexels(const ShaderEntries& entries) {
- const bool via_header_index = kepler_compute.launch_description.linked_tsc;
- for (const auto& entry : entries.storage_texels) {
- const TextureHandle handle =
- GetTextureInfo(kepler_compute, via_header_index, entry, COMPUTE_SHADER_INDEX);
- image_view_indices.push_back(handle.image);
- }
-}
-
-void RasterizerVulkan::SetupComputeImages(const ShaderEntries& entries) {
- const bool via_header_index = kepler_compute.launch_description.linked_tsc;
- for (const auto& entry : entries.images) {
- const TextureHandle handle =
- GetTextureInfo(kepler_compute, via_header_index, entry, COMPUTE_SHADER_INDEX);
- image_view_indices.push_back(handle.image);
- }
-}
-
void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchViewports()) {
return;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 2065209be..31017dc2b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -28,7 +28,6 @@
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
#include "video_core/renderer_vulkan/vk_texture_cache.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
-#include "video_core/shader/async_shaders.h"
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -73,7 +72,7 @@ public:
void Draw(bool is_indexed, bool is_instanced) override;
void Clear() override;
- void DispatchCompute(GPUVAddr code_addr) override;
+ void DispatchCompute() override;
void ResetCounter(VideoCore::QueryType type) override;
void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override;
void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
@@ -103,19 +102,6 @@ public:
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride) override;
- VideoCommon::Shader::AsyncShaders& GetAsyncShaders() {
- return async_shaders;
- }
-
- const VideoCommon::Shader::AsyncShaders& GetAsyncShaders() const {
- return async_shaders;
- }
-
- /// Maximum supported size that a constbuffer can have in bytes.
- static constexpr size_t MaxConstbufferSize = 0x10000;
- static_assert(MaxConstbufferSize % (4 * sizeof(float)) == 0,
- "The maximum size of a constbuffer must be a multiple of the size of GLvec4");
-
private:
static constexpr size_t MAX_TEXTURES = 192;
static constexpr size_t MAX_IMAGES = 48;
@@ -125,40 +111,12 @@ private:
void FlushWork();
- /// Setup descriptors in the graphics pipeline.
- void SetupShaderDescriptors(const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders,
- bool is_indexed);
-
void UpdateDynamicStates();
void BeginTransformFeedback();
void EndTransformFeedback();
- /// Setup uniform texels in the graphics pipeline.
- void SetupGraphicsUniformTexels(const ShaderEntries& entries, std::size_t stage);
-
- /// Setup textures in the graphics pipeline.
- void SetupGraphicsTextures(const ShaderEntries& entries, std::size_t stage);
-
- /// Setup storage texels in the graphics pipeline.
- void SetupGraphicsStorageTexels(const ShaderEntries& entries, std::size_t stage);
-
- /// Setup images in the graphics pipeline.
- void SetupGraphicsImages(const ShaderEntries& entries, std::size_t stage);
-
- /// Setup texel buffers in the compute pipeline.
- void SetupComputeUniformTexels(const ShaderEntries& entries);
-
- /// Setup textures in the compute pipeline.
- void SetupComputeTextures(const ShaderEntries& entries);
-
- /// Setup storage texels in the compute pipeline.
- void SetupComputeStorageTexels(const ShaderEntries& entries);
-
- /// Setup images in the compute pipeline.
- void SetupComputeImages(const ShaderEntries& entries);
-
void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs);
@@ -198,13 +156,12 @@ private:
TextureCache texture_cache;
BufferCacheRuntime buffer_cache_runtime;
BufferCache buffer_cache;
- VKPipelineCache pipeline_cache;
+ PipelineCache pipeline_cache;
VKQueryCache query_cache;
AccelerateDMA accelerate_dma;
VKFenceManager fence_manager;
vk::Event wfi_event;
- VideoCommon::Shader::AsyncShaders async_shaders;
boost::container::static_vector<u32, MAX_IMAGE_VIEWS> image_view_indices;
std::array<VideoCommon::ImageViewId, MAX_IMAGE_VIEWS> image_view_ids;