diff options
5 files changed, 59 insertions, 47 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index be1c31978..a7f256ff9 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -140,6 +140,12 @@ void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size | |||
| 140 | enable.Assign(1); | 140 | enable.Assign(1); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | void FixedPipelineState::Fill(const Maxwell& regs) { | ||
| 144 | rasterizer.Fill(regs); | ||
| 145 | depth_stencil.Fill(regs); | ||
| 146 | color_blending.Fill(regs); | ||
| 147 | } | ||
| 148 | |||
| 143 | std::size_t FixedPipelineState::Hash() const noexcept { | 149 | std::size_t FixedPipelineState::Hash() const noexcept { |
| 144 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this); | 150 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this); |
| 145 | return static_cast<std::size_t>(hash); | 151 | return static_cast<std::size_t>(hash); |
| @@ -149,15 +155,6 @@ bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcep | |||
| 149 | return std::memcmp(this, &rhs, sizeof *this) == 0; | 155 | return std::memcmp(this, &rhs, sizeof *this) == 0; |
| 150 | } | 156 | } |
| 151 | 157 | ||
| 152 | FixedPipelineState GetFixedPipelineState(const Maxwell& regs) { | ||
| 153 | FixedPipelineState fixed_state; | ||
| 154 | fixed_state.rasterizer.Fill(regs); | ||
| 155 | fixed_state.depth_stencil.Fill(regs); | ||
| 156 | fixed_state.color_blending.Fill(regs); | ||
| 157 | fixed_state.padding = {}; | ||
| 158 | return fixed_state; | ||
| 159 | } | ||
| 160 | |||
| 161 | u32 FixedPipelineState::PackComparisonOp(Maxwell::ComparisonOp op) noexcept { | 158 | u32 FixedPipelineState::PackComparisonOp(Maxwell::ComparisonOp op) noexcept { |
| 162 | // OpenGL enums go from 0x200 to 0x207 and the others from 1 to 8 | 159 | // OpenGL enums go from 0x200 to 0x207 and the others from 1 to 8 |
| 163 | // If we substract 0x200 to OpenGL enums and 1 to the others we get a 0-7 range. | 160 | // If we substract 0x200 to OpenGL enums and 1 to the others we get a 0-7 range. |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 9fe6bdbf9..d4fd4d3f1 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -17,7 +17,7 @@ namespace Vulkan { | |||
| 17 | 17 | ||
| 18 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 18 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 19 | 19 | ||
| 20 | struct alignas(32) FixedPipelineState { | 20 | struct FixedPipelineState { |
| 21 | static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept; | 21 | static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept; |
| 22 | static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept; | 22 | static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept; |
| 23 | 23 | ||
| @@ -237,7 +237,8 @@ struct alignas(32) FixedPipelineState { | |||
| 237 | Rasterizer rasterizer; | 237 | Rasterizer rasterizer; |
| 238 | DepthStencil depth_stencil; | 238 | DepthStencil depth_stencil; |
| 239 | ColorBlending color_blending; | 239 | ColorBlending color_blending; |
| 240 | std::array<u8, 20> padding; | 240 | |
| 241 | void Fill(const Maxwell& regs); | ||
| 241 | 242 | ||
| 242 | std::size_t Hash() const noexcept; | 243 | std::size_t Hash() const noexcept; |
| 243 | 244 | ||
| @@ -250,9 +251,6 @@ struct alignas(32) FixedPipelineState { | |||
| 250 | static_assert(std::has_unique_object_representations_v<FixedPipelineState>); | 251 | static_assert(std::has_unique_object_representations_v<FixedPipelineState>); |
| 251 | static_assert(std::is_trivially_copyable_v<FixedPipelineState>); | 252 | static_assert(std::is_trivially_copyable_v<FixedPipelineState>); |
| 252 | static_assert(std::is_trivially_constructible_v<FixedPipelineState>); | 253 | static_assert(std::is_trivially_constructible_v<FixedPipelineState>); |
| 253 | static_assert(sizeof(FixedPipelineState) % 32 == 0, "Size is not aligned"); | ||
| 254 | |||
| 255 | FixedPipelineState GetFixedPipelineState(const Maxwell& regs); | ||
| 256 | 254 | ||
| 257 | } // namespace Vulkan | 255 | } // namespace Vulkan |
| 258 | 256 | ||
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 91b1b16a5..e6d4adc92 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -161,6 +161,24 @@ u32 FillDescriptorLayout(const ShaderEntries& entries, | |||
| 161 | 161 | ||
| 162 | } // Anonymous namespace | 162 | } // Anonymous namespace |
| 163 | 163 | ||
| 164 | std::size_t GraphicsPipelineCacheKey::Hash() const noexcept { | ||
| 165 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this); | ||
| 166 | return static_cast<std::size_t>(hash); | ||
| 167 | } | ||
| 168 | |||
| 169 | bool GraphicsPipelineCacheKey::operator==(const GraphicsPipelineCacheKey& rhs) const noexcept { | ||
| 170 | return std::memcmp(&rhs, this, sizeof *this) == 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | std::size_t ComputePipelineCacheKey::Hash() const noexcept { | ||
| 174 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this); | ||
| 175 | return static_cast<std::size_t>(hash); | ||
| 176 | } | ||
| 177 | |||
| 178 | bool ComputePipelineCacheKey::operator==(const ComputePipelineCacheKey& rhs) const noexcept { | ||
| 179 | return std::memcmp(&rhs, this, sizeof *this) == 0; | ||
| 180 | } | ||
| 181 | |||
| 164 | CachedShader::CachedShader(Core::System& system, Tegra::Engines::ShaderType stage, | 182 | CachedShader::CachedShader(Core::System& system, Tegra::Engines::ShaderType stage, |
| 165 | GPUVAddr gpu_addr, VAddr cpu_addr, ProgramCode program_code, | 183 | GPUVAddr gpu_addr, VAddr cpu_addr, ProgramCode program_code, |
| 166 | u32 main_offset) | 184 | u32 main_offset) |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 602a0a340..84d26b822 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstddef> | 8 | #include <cstddef> |
| 9 | #include <memory> | 9 | #include <memory> |
| 10 | #include <tuple> | ||
| 11 | #include <type_traits> | 10 | #include <type_traits> |
| 12 | #include <unordered_map> | 11 | #include <unordered_map> |
| 13 | #include <utility> | 12 | #include <utility> |
| @@ -51,42 +50,38 @@ using ProgramCode = std::vector<u64>; | |||
| 51 | 50 | ||
| 52 | struct GraphicsPipelineCacheKey { | 51 | struct GraphicsPipelineCacheKey { |
| 53 | FixedPipelineState fixed_state; | 52 | FixedPipelineState fixed_state; |
| 54 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders; | ||
| 55 | RenderPassParams renderpass_params; | 53 | RenderPassParams renderpass_params; |
| 54 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders; | ||
| 55 | u64 padding; // This is necessary for unique object representations | ||
| 56 | 56 | ||
| 57 | std::size_t Hash() const noexcept { | 57 | std::size_t Hash() const noexcept; |
| 58 | std::size_t hash = fixed_state.Hash(); | 58 | |
| 59 | for (const auto& shader : shaders) { | 59 | bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept; |
| 60 | boost::hash_combine(hash, shader); | ||
| 61 | } | ||
| 62 | boost::hash_combine(hash, renderpass_params.Hash()); | ||
| 63 | return hash; | ||
| 64 | } | ||
| 65 | 60 | ||
| 66 | bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept { | 61 | bool operator!=(const GraphicsPipelineCacheKey& rhs) const noexcept { |
| 67 | return std::tie(fixed_state, shaders, renderpass_params) == | 62 | return !operator==(rhs); |
| 68 | std::tie(rhs.fixed_state, rhs.shaders, rhs.renderpass_params); | ||
| 69 | } | 63 | } |
| 70 | }; | 64 | }; |
| 65 | static_assert(std::has_unique_object_representations_v<GraphicsPipelineCacheKey>); | ||
| 66 | static_assert(std::is_trivially_copyable_v<GraphicsPipelineCacheKey>); | ||
| 67 | static_assert(std::is_trivially_constructible_v<GraphicsPipelineCacheKey>); | ||
| 71 | 68 | ||
| 72 | struct ComputePipelineCacheKey { | 69 | struct ComputePipelineCacheKey { |
| 73 | GPUVAddr shader{}; | 70 | GPUVAddr shader; |
| 74 | u32 shared_memory_size{}; | 71 | u32 shared_memory_size; |
| 75 | std::array<u32, 3> workgroup_size{}; | 72 | std::array<u32, 3> workgroup_size; |
| 76 | 73 | ||
| 77 | std::size_t Hash() const noexcept { | 74 | std::size_t Hash() const noexcept; |
| 78 | return static_cast<std::size_t>(shader) ^ | 75 | |
| 79 | ((static_cast<std::size_t>(shared_memory_size) >> 7) << 40) ^ | 76 | bool operator==(const ComputePipelineCacheKey& rhs) const noexcept; |
| 80 | static_cast<std::size_t>(workgroup_size[0]) ^ | ||
| 81 | (static_cast<std::size_t>(workgroup_size[1]) << 16) ^ | ||
| 82 | (static_cast<std::size_t>(workgroup_size[2]) << 24); | ||
| 83 | } | ||
| 84 | 77 | ||
| 85 | bool operator==(const ComputePipelineCacheKey& rhs) const noexcept { | 78 | bool operator!=(const ComputePipelineCacheKey& rhs) const noexcept { |
| 86 | return std::tie(shader, shared_memory_size, workgroup_size) == | 79 | return !operator==(rhs); |
| 87 | std::tie(rhs.shader, rhs.shared_memory_size, rhs.workgroup_size); | ||
| 88 | } | 80 | } |
| 89 | }; | 81 | }; |
| 82 | static_assert(std::has_unique_object_representations_v<ComputePipelineCacheKey>); | ||
| 83 | static_assert(std::is_trivially_copyable_v<ComputePipelineCacheKey>); | ||
| 84 | static_assert(std::is_trivially_constructible_v<ComputePipelineCacheKey>); | ||
| 90 | 85 | ||
| 91 | } // namespace Vulkan | 86 | } // namespace Vulkan |
| 92 | 87 | ||
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index ef21b186b..8a5482e55 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -316,7 +316,8 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 316 | query_cache.UpdateCounters(); | 316 | query_cache.UpdateCounters(); |
| 317 | 317 | ||
| 318 | const auto& gpu = system.GPU().Maxwell3D(); | 318 | const auto& gpu = system.GPU().Maxwell3D(); |
| 319 | GraphicsPipelineCacheKey key{GetFixedPipelineState(gpu.regs)}; | 319 | GraphicsPipelineCacheKey key; |
| 320 | key.fixed_state.Fill(gpu.regs); | ||
| 320 | 321 | ||
| 321 | buffer_cache.Map(CalculateGraphicsStreamBufferSize(is_indexed)); | 322 | buffer_cache.Map(CalculateGraphicsStreamBufferSize(is_indexed)); |
| 322 | 323 | ||
| @@ -334,10 +335,11 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 334 | 335 | ||
| 335 | buffer_cache.Unmap(); | 336 | buffer_cache.Unmap(); |
| 336 | 337 | ||
| 337 | const auto texceptions = UpdateAttachments(); | 338 | const Texceptions texceptions = UpdateAttachments(); |
| 338 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); | 339 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); |
| 339 | 340 | ||
| 340 | key.renderpass_params = GetRenderPassParams(texceptions); | 341 | key.renderpass_params = GetRenderPassParams(texceptions); |
| 342 | key.padding = 0; | ||
| 341 | 343 | ||
| 342 | auto& pipeline = pipeline_cache.GetGraphicsPipeline(key); | 344 | auto& pipeline = pipeline_cache.GetGraphicsPipeline(key); |
| 343 | scheduler.BindGraphicsPipeline(pipeline.GetHandle()); | 345 | scheduler.BindGraphicsPipeline(pipeline.GetHandle()); |
| @@ -453,10 +455,12 @@ void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) { | |||
| 453 | query_cache.UpdateCounters(); | 455 | query_cache.UpdateCounters(); |
| 454 | 456 | ||
| 455 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; | 457 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; |
| 456 | const ComputePipelineCacheKey key{ | 458 | ComputePipelineCacheKey key; |
| 457 | code_addr, | 459 | key.shader = code_addr; |
| 458 | launch_desc.shared_alloc, | 460 | key.shared_memory_size = launch_desc.shared_alloc; |
| 459 | {launch_desc.block_dim_x, launch_desc.block_dim_y, launch_desc.block_dim_z}}; | 461 | key.workgroup_size = {launch_desc.block_dim_x, launch_desc.block_dim_y, |
| 462 | launch_desc.block_dim_z}; | ||
| 463 | |||
| 460 | auto& pipeline = pipeline_cache.GetComputePipeline(key); | 464 | auto& pipeline = pipeline_cache.GetComputePipeline(key); |
| 461 | 465 | ||
| 462 | // Compute dispatches can't be executed inside a renderpass | 466 | // Compute dispatches can't be executed inside a renderpass |