diff options
| author | 2020-04-24 01:44:14 -0300 | |
|---|---|---|
| committer | 2020-04-26 01:38:51 -0300 | |
| commit | ddd82ef42b7bb7bea4c80edeb96bca8512580df3 (patch) | |
| tree | b2b09f597fe519128d065f034d51103f478e6776 /src/video_core/renderer_vulkan | |
| parent | Merge pull request #3768 from H27CK/cmd-title-fmt (diff) | |
| download | yuzu-ddd82ef42b7bb7bea4c80edeb96bca8512580df3.tar.gz yuzu-ddd82ef42b7bb7bea4c80edeb96bca8512580df3.tar.xz yuzu-ddd82ef42b7bb7bea4c80edeb96bca8512580df3.zip | |
shader/memory_util: Deduplicate code
Deduplicate code shared between vk_pipeline_cache and gl_shader_cache as
well as shader decoder code.
While we are at it, fix a bug in gl_shader_cache where compute shaders
had an start offset of a stage shader.
Diffstat (limited to 'src/video_core/renderer_vulkan')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 69 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.h | 8 |
2 files changed, 14 insertions, 63 deletions
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 91b1b16a5..8cedeaeba 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -27,12 +27,18 @@ | |||
| 27 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 27 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 28 | #include "video_core/renderer_vulkan/wrapper.h" | 28 | #include "video_core/renderer_vulkan/wrapper.h" |
| 29 | #include "video_core/shader/compiler_settings.h" | 29 | #include "video_core/shader/compiler_settings.h" |
| 30 | #include "video_core/shader/memory_util.h" | ||
| 30 | 31 | ||
| 31 | namespace Vulkan { | 32 | namespace Vulkan { |
| 32 | 33 | ||
| 33 | MICROPROFILE_DECLARE(Vulkan_PipelineCache); | 34 | MICROPROFILE_DECLARE(Vulkan_PipelineCache); |
| 34 | 35 | ||
| 35 | using Tegra::Engines::ShaderType; | 36 | using Tegra::Engines::ShaderType; |
| 37 | using VideoCommon::Shader::GetShaderAddress; | ||
| 38 | using VideoCommon::Shader::GetShaderCode; | ||
| 39 | using VideoCommon::Shader::KERNEL_MAIN_OFFSET; | ||
| 40 | using VideoCommon::Shader::ProgramCode; | ||
| 41 | using VideoCommon::Shader::STAGE_MAIN_OFFSET; | ||
| 36 | 42 | ||
| 37 | namespace { | 43 | namespace { |
| 38 | 44 | ||
| @@ -45,60 +51,6 @@ constexpr VkDescriptorType STORAGE_IMAGE = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; | |||
| 45 | constexpr VideoCommon::Shader::CompilerSettings compiler_settings{ | 51 | constexpr VideoCommon::Shader::CompilerSettings compiler_settings{ |
| 46 | VideoCommon::Shader::CompileDepth::FullDecompile}; | 52 | VideoCommon::Shader::CompileDepth::FullDecompile}; |
| 47 | 53 | ||
| 48 | /// Gets the address for the specified shader stage program | ||
| 49 | GPUVAddr GetShaderAddress(Core::System& system, Maxwell::ShaderProgram program) { | ||
| 50 | const auto& gpu{system.GPU().Maxwell3D()}; | ||
| 51 | const auto& shader_config{gpu.regs.shader_config[static_cast<std::size_t>(program)]}; | ||
| 52 | return gpu.regs.code_address.CodeAddress() + shader_config.offset; | ||
| 53 | } | ||
| 54 | |||
| 55 | /// Gets if the current instruction offset is a scheduler instruction | ||
| 56 | constexpr bool IsSchedInstruction(std::size_t offset, std::size_t main_offset) { | ||
| 57 | // Sched instructions appear once every 4 instructions. | ||
| 58 | constexpr std::size_t SchedPeriod = 4; | ||
| 59 | const std::size_t absolute_offset = offset - main_offset; | ||
| 60 | return (absolute_offset % SchedPeriod) == 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Calculates the size of a program stream | ||
| 64 | std::size_t CalculateProgramSize(const ProgramCode& program, bool is_compute) { | ||
| 65 | const std::size_t start_offset = is_compute ? 0 : 10; | ||
| 66 | // This is the encoded version of BRA that jumps to itself. All Nvidia | ||
| 67 | // shaders end with one. | ||
| 68 | constexpr u64 self_jumping_branch = 0xE2400FFFFF07000FULL; | ||
| 69 | constexpr u64 mask = 0xFFFFFFFFFF7FFFFFULL; | ||
| 70 | std::size_t offset = start_offset; | ||
| 71 | while (offset < program.size()) { | ||
| 72 | const u64 instruction = program[offset]; | ||
| 73 | if (!IsSchedInstruction(offset, start_offset)) { | ||
| 74 | if ((instruction & mask) == self_jumping_branch) { | ||
| 75 | // End on Maxwell's "nop" instruction | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | if (instruction == 0) { | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | ++offset; | ||
| 83 | } | ||
| 84 | // The last instruction is included in the program size | ||
| 85 | return std::min(offset + 1, program.size()); | ||
| 86 | } | ||
| 87 | |||
| 88 | /// Gets the shader program code from memory for the specified address | ||
| 89 | ProgramCode GetShaderCode(Tegra::MemoryManager& memory_manager, const GPUVAddr gpu_addr, | ||
| 90 | const u8* host_ptr, bool is_compute) { | ||
| 91 | ProgramCode program_code(VideoCommon::Shader::MAX_PROGRAM_LENGTH); | ||
| 92 | ASSERT_OR_EXECUTE(host_ptr != nullptr, { | ||
| 93 | std::fill(program_code.begin(), program_code.end(), 0); | ||
| 94 | return program_code; | ||
| 95 | }); | ||
| 96 | memory_manager.ReadBlockUnsafe(gpu_addr, program_code.data(), | ||
| 97 | program_code.size() * sizeof(u64)); | ||
| 98 | program_code.resize(CalculateProgramSize(program_code, is_compute)); | ||
| 99 | return program_code; | ||
| 100 | } | ||
| 101 | |||
| 102 | constexpr std::size_t GetStageFromProgram(std::size_t program) { | 54 | constexpr std::size_t GetStageFromProgram(std::size_t program) { |
| 103 | return program == 0 ? 0 : program - 1; | 55 | return program == 0 ? 0 : program - 1; |
| 104 | } | 56 | } |
| @@ -212,9 +164,9 @@ std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { | |||
| 212 | const auto host_ptr{memory_manager.GetPointer(program_addr)}; | 164 | const auto host_ptr{memory_manager.GetPointer(program_addr)}; |
| 213 | 165 | ||
| 214 | // No shader found - create a new one | 166 | // No shader found - create a new one |
| 215 | constexpr u32 stage_offset = 10; | 167 | constexpr u32 stage_offset = STAGE_MAIN_OFFSET; |
| 216 | const auto stage = static_cast<Tegra::Engines::ShaderType>(index == 0 ? 0 : index - 1); | 168 | const auto stage = static_cast<Tegra::Engines::ShaderType>(index == 0 ? 0 : index - 1); |
| 217 | auto code = GetShaderCode(memory_manager, program_addr, host_ptr, false); | 169 | ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, false); |
| 218 | 170 | ||
| 219 | shader = std::make_shared<CachedShader>(system, stage, program_addr, *cpu_addr, | 171 | shader = std::make_shared<CachedShader>(system, stage, program_addr, *cpu_addr, |
| 220 | std::move(code), stage_offset); | 172 | std::move(code), stage_offset); |
| @@ -270,11 +222,10 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach | |||
| 270 | // No shader found - create a new one | 222 | // No shader found - create a new one |
| 271 | const auto host_ptr = memory_manager.GetPointer(program_addr); | 223 | const auto host_ptr = memory_manager.GetPointer(program_addr); |
| 272 | 224 | ||
| 273 | auto code = GetShaderCode(memory_manager, program_addr, host_ptr, true); | 225 | ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, true); |
| 274 | constexpr u32 kernel_main_offset = 0; | ||
| 275 | shader = std::make_shared<CachedShader>(system, Tegra::Engines::ShaderType::Compute, | 226 | shader = std::make_shared<CachedShader>(system, Tegra::Engines::ShaderType::Compute, |
| 276 | program_addr, *cpu_addr, std::move(code), | 227 | program_addr, *cpu_addr, std::move(code), |
| 277 | kernel_main_offset); | 228 | KERNEL_MAIN_OFFSET); |
| 278 | if (cpu_addr) { | 229 | if (cpu_addr) { |
| 279 | Register(shader); | 230 | Register(shader); |
| 280 | } else { | 231 | } else { |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 602a0a340..2cce53162 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include "video_core/renderer_vulkan/vk_resource_manager.h" | 25 | #include "video_core/renderer_vulkan/vk_resource_manager.h" |
| 26 | #include "video_core/renderer_vulkan/vk_shader_decompiler.h" | 26 | #include "video_core/renderer_vulkan/vk_shader_decompiler.h" |
| 27 | #include "video_core/renderer_vulkan/wrapper.h" | 27 | #include "video_core/renderer_vulkan/wrapper.h" |
| 28 | #include "video_core/shader/memory_util.h" | ||
| 28 | #include "video_core/shader/registry.h" | 29 | #include "video_core/shader/registry.h" |
| 29 | #include "video_core/shader/shader_ir.h" | 30 | #include "video_core/shader/shader_ir.h" |
| 30 | #include "video_core/surface.h" | 31 | #include "video_core/surface.h" |
| @@ -47,8 +48,6 @@ class CachedShader; | |||
| 47 | using Shader = std::shared_ptr<CachedShader>; | 48 | using Shader = std::shared_ptr<CachedShader>; |
| 48 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 49 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 49 | 50 | ||
| 50 | using ProgramCode = std::vector<u64>; | ||
| 51 | |||
| 52 | struct GraphicsPipelineCacheKey { | 51 | struct GraphicsPipelineCacheKey { |
| 53 | FixedPipelineState fixed_state; | 52 | FixedPipelineState fixed_state; |
| 54 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders; | 53 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders; |
| @@ -113,7 +112,8 @@ namespace Vulkan { | |||
| 113 | class CachedShader final : public RasterizerCacheObject { | 112 | class CachedShader final : public RasterizerCacheObject { |
| 114 | public: | 113 | public: |
| 115 | explicit CachedShader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr, | 114 | explicit CachedShader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr, |
| 116 | VAddr cpu_addr, ProgramCode program_code, u32 main_offset); | 115 | VAddr cpu_addr, VideoCommon::Shader::ProgramCode program_code, |
| 116 | u32 main_offset); | ||
| 117 | ~CachedShader(); | 117 | ~CachedShader(); |
| 118 | 118 | ||
| 119 | GPUVAddr GetGpuAddr() const { | 119 | GPUVAddr GetGpuAddr() const { |
| @@ -145,7 +145,7 @@ private: | |||
| 145 | Tegra::Engines::ShaderType stage); | 145 | Tegra::Engines::ShaderType stage); |
| 146 | 146 | ||
| 147 | GPUVAddr gpu_addr{}; | 147 | GPUVAddr gpu_addr{}; |
| 148 | ProgramCode program_code; | 148 | VideoCommon::Shader::ProgramCode program_code; |
| 149 | VideoCommon::Shader::Registry registry; | 149 | VideoCommon::Shader::Registry registry; |
| 150 | VideoCommon::Shader::ShaderIR shader_ir; | 150 | VideoCommon::Shader::ShaderIR shader_ir; |
| 151 | ShaderEntries entries; | 151 | ShaderEntries entries; |