diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.cpp | 45 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.h | 30 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 25 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 54 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.h | 29 |
11 files changed, 163 insertions, 75 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 1e31a2900..6821f275d 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -36,6 +36,8 @@ add_library(video_core STATIC | |||
| 36 | renderer_base.h | 36 | renderer_base.h |
| 37 | renderer_opengl/gl_buffer_cache.cpp | 37 | renderer_opengl/gl_buffer_cache.cpp |
| 38 | renderer_opengl/gl_buffer_cache.h | 38 | renderer_opengl/gl_buffer_cache.h |
| 39 | renderer_opengl/gl_device.cpp | ||
| 40 | renderer_opengl/gl_device.h | ||
| 39 | renderer_opengl/gl_global_cache.cpp | 41 | renderer_opengl/gl_global_cache.cpp |
| 40 | renderer_opengl/gl_global_cache.h | 42 | renderer_opengl/gl_global_cache.h |
| 41 | renderer_opengl/gl_primitive_assembler.cpp | 43 | renderer_opengl/gl_primitive_assembler.cpp |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp new file mode 100644 index 000000000..b6d9e0ddb --- /dev/null +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <cstddef> | ||
| 6 | #include <glad/glad.h> | ||
| 7 | |||
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "video_core/renderer_opengl/gl_device.h" | ||
| 10 | |||
| 11 | namespace OpenGL { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | template <typename T> | ||
| 15 | T GetInteger(GLenum pname) { | ||
| 16 | GLint temporary; | ||
| 17 | glGetIntegerv(pname, &temporary); | ||
| 18 | return static_cast<T>(temporary); | ||
| 19 | } | ||
| 20 | } // Anonymous namespace | ||
| 21 | |||
| 22 | Device::Device() { | ||
| 23 | uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); | ||
| 24 | has_variable_aoffi = TestVariableAoffi(); | ||
| 25 | } | ||
| 26 | |||
| 27 | bool Device::TestVariableAoffi() { | ||
| 28 | const GLchar* AOFFI_TEST = R"(#version 430 core | ||
| 29 | uniform sampler2D tex; | ||
| 30 | uniform ivec2 variable_offset; | ||
| 31 | void main() { | ||
| 32 | gl_Position = textureOffset(tex, vec2(0), variable_offset); | ||
| 33 | } | ||
| 34 | )"; | ||
| 35 | const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &AOFFI_TEST)}; | ||
| 36 | GLint link_status{}; | ||
| 37 | glGetProgramiv(shader, GL_LINK_STATUS, &link_status); | ||
| 38 | glDeleteProgram(shader); | ||
| 39 | |||
| 40 | const bool supported{link_status == GL_TRUE}; | ||
| 41 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", supported); | ||
| 42 | return supported; | ||
| 43 | } | ||
| 44 | |||
| 45 | } // namespace OpenGL | ||
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h new file mode 100644 index 000000000..78ff5ee58 --- /dev/null +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <cstddef> | ||
| 8 | |||
| 9 | namespace OpenGL { | ||
| 10 | |||
| 11 | class Device { | ||
| 12 | public: | ||
| 13 | Device(); | ||
| 14 | |||
| 15 | std::size_t GetUniformBufferAlignment() const { | ||
| 16 | return uniform_buffer_alignment; | ||
| 17 | } | ||
| 18 | |||
| 19 | bool HasVariableAoffi() const { | ||
| 20 | return has_variable_aoffi; | ||
| 21 | } | ||
| 22 | |||
| 23 | private: | ||
| 24 | static bool TestVariableAoffi(); | ||
| 25 | |||
| 26 | std::size_t uniform_buffer_alignment{}; | ||
| 27 | bool has_variable_aoffi{}; | ||
| 28 | }; | ||
| 29 | |||
| 30 | } // namespace OpenGL | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 6034dc489..9a088a503 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -99,7 +99,7 @@ struct FramebufferCacheKey { | |||
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info) | 101 | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info) |
| 102 | : res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system}, | 102 | : res_cache{*this}, shader_cache{*this, system, device}, global_cache{*this}, system{system}, |
| 103 | screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) { | 103 | screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) { |
| 104 | OpenGLState::ApplyDefaultState(); | 104 | OpenGLState::ApplyDefaultState(); |
| 105 | 105 | ||
| @@ -107,8 +107,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info) | |||
| 107 | state.draw.shader_program = 0; | 107 | state.draw.shader_program = 0; |
| 108 | state.Apply(); | 108 | state.Apply(); |
| 109 | 109 | ||
| 110 | glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment); | ||
| 111 | |||
| 112 | LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here"); | 110 | LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here"); |
| 113 | CheckExtensions(); | 111 | CheckExtensions(); |
| 114 | } | 112 | } |
| @@ -315,8 +313,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 315 | 313 | ||
| 316 | GLShader::MaxwellUniformData ubo{}; | 314 | GLShader::MaxwellUniformData ubo{}; |
| 317 | ubo.SetFromRegs(gpu, stage); | 315 | ubo.SetFromRegs(gpu, stage); |
| 318 | const GLintptr offset = buffer_cache.UploadHostMemory( | 316 | const GLintptr offset = |
| 319 | &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); | 317 | buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); |
| 320 | 318 | ||
| 321 | // Bind the emulation info buffer | 319 | // Bind the emulation info buffer |
| 322 | bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), offset, | 320 | bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), offset, |
| @@ -700,23 +698,24 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 700 | // Add space for index buffer (keeping in mind non-core primitives) | 698 | // Add space for index buffer (keeping in mind non-core primitives) |
| 701 | switch (regs.draw.topology) { | 699 | switch (regs.draw.topology) { |
| 702 | case Maxwell::PrimitiveTopology::Quads: | 700 | case Maxwell::PrimitiveTopology::Quads: |
| 703 | buffer_size = Common::AlignUp<std::size_t>(buffer_size, 4) + | 701 | buffer_size = Common::AlignUp(buffer_size, 4) + |
| 704 | primitive_assembler.CalculateQuadSize(regs.vertex_buffer.count); | 702 | primitive_assembler.CalculateQuadSize(regs.vertex_buffer.count); |
| 705 | break; | 703 | break; |
| 706 | default: | 704 | default: |
| 707 | if (is_indexed) { | 705 | if (is_indexed) { |
| 708 | buffer_size = Common::AlignUp<std::size_t>(buffer_size, 4) + CalculateIndexBufferSize(); | 706 | buffer_size = Common::AlignUp(buffer_size, 4) + CalculateIndexBufferSize(); |
| 709 | } | 707 | } |
| 710 | break; | 708 | break; |
| 711 | } | 709 | } |
| 712 | 710 | ||
| 713 | // Uniform space for the 5 shader stages | 711 | // Uniform space for the 5 shader stages |
| 714 | buffer_size = | 712 | buffer_size = Common::AlignUp<std::size_t>(buffer_size, 4) + |
| 715 | Common::AlignUp<std::size_t>(buffer_size, 4) + | 713 | (sizeof(GLShader::MaxwellUniformData) + device.GetUniformBufferAlignment()) * |
| 716 | (sizeof(GLShader::MaxwellUniformData) + uniform_buffer_alignment) * Maxwell::MaxShaderStage; | 714 | Maxwell::MaxShaderStage; |
| 717 | 715 | ||
| 718 | // Add space for at least 18 constant buffers | 716 | // Add space for at least 18 constant buffers |
| 719 | buffer_size += Maxwell::MaxConstBuffers * (MaxConstbufferSize + uniform_buffer_alignment); | 717 | buffer_size += |
| 718 | Maxwell::MaxConstBuffers * (MaxConstbufferSize + device.GetUniformBufferAlignment()); | ||
| 720 | 719 | ||
| 721 | const bool invalidate = buffer_cache.Map(buffer_size); | 720 | const bool invalidate = buffer_cache.Map(buffer_size); |
| 722 | if (invalidate) { | 721 | if (invalidate) { |
| @@ -848,8 +847,8 @@ void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::Shader | |||
| 848 | size = Common::AlignUp(size, sizeof(GLvec4)); | 847 | size = Common::AlignUp(size, sizeof(GLvec4)); |
| 849 | ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big"); | 848 | ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big"); |
| 850 | 849 | ||
| 851 | const GLintptr const_buffer_offset = buffer_cache.UploadMemory( | 850 | const GLintptr const_buffer_offset = |
| 852 | buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment)); | 851 | buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); |
| 853 | 852 | ||
| 854 | bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size); | 853 | bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size); |
| 855 | } | 854 | } |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index a0e056142..71b9c5ead 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include "video_core/rasterizer_cache.h" | 21 | #include "video_core/rasterizer_cache.h" |
| 22 | #include "video_core/rasterizer_interface.h" | 22 | #include "video_core/rasterizer_interface.h" |
| 23 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 23 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 24 | #include "video_core/renderer_opengl/gl_device.h" | ||
| 24 | #include "video_core/renderer_opengl/gl_global_cache.h" | 25 | #include "video_core/renderer_opengl/gl_global_cache.h" |
| 25 | #include "video_core/renderer_opengl/gl_primitive_assembler.h" | 26 | #include "video_core/renderer_opengl/gl_primitive_assembler.h" |
| 26 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | 27 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" |
| @@ -172,6 +173,7 @@ private: | |||
| 172 | /// but are needed for correct emulation | 173 | /// but are needed for correct emulation |
| 173 | void CheckExtensions(); | 174 | void CheckExtensions(); |
| 174 | 175 | ||
| 176 | const Device device; | ||
| 175 | OpenGLState state; | 177 | OpenGLState state; |
| 176 | 178 | ||
| 177 | RasterizerCacheOpenGL res_cache; | 179 | RasterizerCacheOpenGL res_cache; |
| @@ -180,7 +182,6 @@ private: | |||
| 180 | SamplerCacheOpenGL sampler_cache; | 182 | SamplerCacheOpenGL sampler_cache; |
| 181 | 183 | ||
| 182 | Core::System& system; | 184 | Core::System& system; |
| 183 | |||
| 184 | ScreenInfo& screen_info; | 185 | ScreenInfo& screen_info; |
| 185 | 186 | ||
| 186 | std::unique_ptr<GLShader::ProgramManager> shader_program_manager; | 187 | std::unique_ptr<GLShader::ProgramManager> shader_program_manager; |
| @@ -196,7 +197,6 @@ private: | |||
| 196 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; | 197 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; |
| 197 | OGLBufferCache buffer_cache; | 198 | OGLBufferCache buffer_cache; |
| 198 | PrimitiveAssembler primitive_assembler{buffer_cache}; | 199 | PrimitiveAssembler primitive_assembler{buffer_cache}; |
| 199 | GLint uniform_buffer_alignment; | ||
| 200 | 200 | ||
| 201 | BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER}; | 201 | BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER}; |
| 202 | BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER}; | 202 | BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER}; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 43f2906a8..2a81b1169 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -136,8 +136,8 @@ u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode& | |||
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | /// Creates an unspecialized program from code streams | 138 | /// Creates an unspecialized program from code streams |
| 139 | GLShader::ProgramResult CreateProgram(Maxwell::ShaderProgram program_type, ProgramCode program_code, | 139 | GLShader::ProgramResult CreateProgram(const Device& device, Maxwell::ShaderProgram program_type, |
| 140 | ProgramCode program_code_b) { | 140 | ProgramCode program_code, ProgramCode program_code_b) { |
| 141 | GLShader::ShaderSetup setup(program_code); | 141 | GLShader::ShaderSetup setup(program_code); |
| 142 | if (program_type == Maxwell::ShaderProgram::VertexA) { | 142 | if (program_type == Maxwell::ShaderProgram::VertexA) { |
| 143 | // VertexB is always enabled, so when VertexA is enabled, we have two vertex shaders. | 143 | // VertexB is always enabled, so when VertexA is enabled, we have two vertex shaders. |
| @@ -151,11 +151,11 @@ GLShader::ProgramResult CreateProgram(Maxwell::ShaderProgram program_type, Progr | |||
| 151 | switch (program_type) { | 151 | switch (program_type) { |
| 152 | case Maxwell::ShaderProgram::VertexA: | 152 | case Maxwell::ShaderProgram::VertexA: |
| 153 | case Maxwell::ShaderProgram::VertexB: | 153 | case Maxwell::ShaderProgram::VertexB: |
| 154 | return GLShader::GenerateVertexShader(setup); | 154 | return GLShader::GenerateVertexShader(device, setup); |
| 155 | case Maxwell::ShaderProgram::Geometry: | 155 | case Maxwell::ShaderProgram::Geometry: |
| 156 | return GLShader::GenerateGeometryShader(setup); | 156 | return GLShader::GenerateGeometryShader(device, setup); |
| 157 | case Maxwell::ShaderProgram::Fragment: | 157 | case Maxwell::ShaderProgram::Fragment: |
| 158 | return GLShader::GenerateFragmentShader(setup); | 158 | return GLShader::GenerateFragmentShader(device, setup); |
| 159 | default: | 159 | default: |
| 160 | LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type)); | 160 | LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type)); |
| 161 | UNREACHABLE(); | 161 | UNREACHABLE(); |
| @@ -214,22 +214,20 @@ std::set<GLenum> GetSupportedFormats() { | |||
| 214 | return supported_formats; | 214 | return supported_formats; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | } // namespace | 217 | } // Anonymous namespace |
| 218 | 218 | ||
| 219 | CachedShader::CachedShader(VAddr cpu_addr, u64 unique_identifier, | 219 | CachedShader::CachedShader(const Device& device, VAddr cpu_addr, u64 unique_identifier, |
| 220 | Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache, | 220 | Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache, |
| 221 | const PrecompiledPrograms& precompiled_programs, | 221 | const PrecompiledPrograms& precompiled_programs, |
| 222 | ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr) | 222 | ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr) |
| 223 | : RasterizerCacheObject{host_ptr}, host_ptr{host_ptr}, cpu_addr{cpu_addr}, | 223 | : RasterizerCacheObject{host_ptr}, host_ptr{host_ptr}, cpu_addr{cpu_addr}, |
| 224 | unique_identifier{unique_identifier}, program_type{program_type}, disk_cache{disk_cache}, | 224 | unique_identifier{unique_identifier}, program_type{program_type}, disk_cache{disk_cache}, |
| 225 | precompiled_programs{precompiled_programs} { | 225 | precompiled_programs{precompiled_programs} { |
| 226 | 226 | const std::size_t code_size{CalculateProgramSize(program_code)}; | |
| 227 | const std::size_t code_size = CalculateProgramSize(program_code); | 227 | const std::size_t code_size_b{program_code_b.empty() ? 0 |
| 228 | const std::size_t code_size_b = | 228 | : CalculateProgramSize(program_code_b)}; |
| 229 | program_code_b.empty() ? 0 : CalculateProgramSize(program_code_b); | 229 | GLShader::ProgramResult program_result{ |
| 230 | 230 | CreateProgram(device, program_type, program_code, program_code_b)}; | |
| 231 | GLShader::ProgramResult program_result = | ||
| 232 | CreateProgram(program_type, program_code, program_code_b); | ||
| 233 | if (program_result.first.empty()) { | 231 | if (program_result.first.empty()) { |
| 234 | // TODO(Rodrigo): Unimplemented shader stages hit here, avoid using these for now | 232 | // TODO(Rodrigo): Unimplemented shader stages hit here, avoid using these for now |
| 235 | return; | 233 | return; |
| @@ -253,7 +251,6 @@ CachedShader::CachedShader(VAddr cpu_addr, u64 unique_identifier, | |||
| 253 | : RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, unique_identifier{unique_identifier}, | 251 | : RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, unique_identifier{unique_identifier}, |
| 254 | program_type{program_type}, disk_cache{disk_cache}, precompiled_programs{ | 252 | program_type{program_type}, disk_cache{disk_cache}, precompiled_programs{ |
| 255 | precompiled_programs} { | 253 | precompiled_programs} { |
| 256 | |||
| 257 | code = std::move(result.first); | 254 | code = std::move(result.first); |
| 258 | entries = result.second; | 255 | entries = result.second; |
| 259 | shader_length = entries.shader_length; | 256 | shader_length = entries.shader_length; |
| @@ -346,8 +343,9 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode, | |||
| 346 | return {unique_identifier, base_bindings, primitive_mode}; | 343 | return {unique_identifier, base_bindings, primitive_mode}; |
| 347 | } | 344 | } |
| 348 | 345 | ||
| 349 | ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system) | 346 | ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system, |
| 350 | : RasterizerCache{rasterizer}, disk_cache{system} {} | 347 | const Device& device) |
| 348 | : RasterizerCache{rasterizer}, disk_cache{system}, device{device} {} | ||
| 351 | 349 | ||
| 352 | void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, | 350 | void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, |
| 353 | const VideoCore::DiskResourceLoadCallback& callback) { | 351 | const VideoCore::DiskResourceLoadCallback& callback) { |
| @@ -441,17 +439,18 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia | |||
| 441 | const std::unordered_map<u64, ShaderDiskCacheDecompiled>& decompiled) { | 439 | const std::unordered_map<u64, ShaderDiskCacheDecompiled>& decompiled) { |
| 442 | std::unordered_map<u64, UnspecializedShader> unspecialized; | 440 | std::unordered_map<u64, UnspecializedShader> unspecialized; |
| 443 | 441 | ||
| 444 | if (callback) | 442 | if (callback) { |
| 445 | callback(VideoCore::LoadCallbackStage::Decompile, 0, raws.size()); | 443 | callback(VideoCore::LoadCallbackStage::Decompile, 0, raws.size()); |
| 444 | } | ||
| 446 | 445 | ||
| 447 | for (std::size_t i = 0; i < raws.size(); ++i) { | 446 | for (std::size_t i = 0; i < raws.size(); ++i) { |
| 448 | if (stop_loading) | 447 | if (stop_loading) { |
| 449 | return {}; | 448 | return {}; |
| 450 | 449 | } | |
| 451 | const auto& raw{raws[i]}; | 450 | const auto& raw{raws[i]}; |
| 452 | const u64 unique_identifier = raw.GetUniqueIdentifier(); | 451 | const u64 unique_identifier{raw.GetUniqueIdentifier()}; |
| 453 | const u64 calculated_hash = | 452 | const u64 calculated_hash{ |
| 454 | GetUniqueIdentifier(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB()); | 453 | GetUniqueIdentifier(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB())}; |
| 455 | if (unique_identifier != calculated_hash) { | 454 | if (unique_identifier != calculated_hash) { |
| 456 | LOG_ERROR( | 455 | LOG_ERROR( |
| 457 | Render_OpenGL, | 456 | Render_OpenGL, |
| @@ -468,8 +467,8 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia | |||
| 468 | result = {stored_decompiled.code, stored_decompiled.entries}; | 467 | result = {stored_decompiled.code, stored_decompiled.entries}; |
| 469 | } else { | 468 | } else { |
| 470 | // Otherwise decompile the shader at boot and save the result to the decompiled file | 469 | // Otherwise decompile the shader at boot and save the result to the decompiled file |
| 471 | result = | 470 | result = CreateProgram(device, raw.GetProgramType(), raw.GetProgramCode(), |
| 472 | CreateProgram(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB()); | 471 | raw.GetProgramCodeB()); |
| 473 | disk_cache.SaveDecompiled(unique_identifier, result.first, result.second); | 472 | disk_cache.SaveDecompiled(unique_identifier, result.first, result.second); |
| 474 | } | 473 | } |
| 475 | 474 | ||
| @@ -479,8 +478,9 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia | |||
| 479 | {raw.GetUniqueIdentifier(), | 478 | {raw.GetUniqueIdentifier(), |
| 480 | {std::move(result.first), std::move(result.second), raw.GetProgramType()}}); | 479 | {std::move(result.first), std::move(result.second), raw.GetProgramType()}}); |
| 481 | 480 | ||
| 482 | if (callback) | 481 | if (callback) { |
| 483 | callback(VideoCore::LoadCallbackStage::Decompile, i, raws.size()); | 482 | callback(VideoCore::LoadCallbackStage::Decompile, i, raws.size()); |
| 483 | } | ||
| 484 | } | 484 | } |
| 485 | return unspecialized; | 485 | return unspecialized; |
| 486 | } | 486 | } |
| @@ -515,7 +515,7 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | |||
| 515 | precompiled_programs, found->second, host_ptr); | 515 | precompiled_programs, found->second, host_ptr); |
| 516 | } else { | 516 | } else { |
| 517 | shader = std::make_shared<CachedShader>( | 517 | shader = std::make_shared<CachedShader>( |
| 518 | cpu_addr, unique_identifier, program, disk_cache, precompiled_programs, | 518 | device, cpu_addr, unique_identifier, program, disk_cache, precompiled_programs, |
| 519 | std::move(program_code), std::move(program_code_b), host_ptr); | 519 | std::move(program_code), std::move(program_code_b), host_ptr); |
| 520 | } | 520 | } |
| 521 | Register(shader); | 521 | Register(shader); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 0cf8e0b3d..a332087f8 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -27,6 +27,7 @@ class System; | |||
| 27 | namespace OpenGL { | 27 | namespace OpenGL { |
| 28 | 28 | ||
| 29 | class CachedShader; | 29 | class CachedShader; |
| 30 | class Device; | ||
| 30 | class RasterizerOpenGL; | 31 | class RasterizerOpenGL; |
| 31 | struct UnspecializedShader; | 32 | struct UnspecializedShader; |
| 32 | 33 | ||
| @@ -38,7 +39,7 @@ using PrecompiledShaders = std::unordered_map<u64, GLShader::ProgramResult>; | |||
| 38 | 39 | ||
| 39 | class CachedShader final : public RasterizerCacheObject { | 40 | class CachedShader final : public RasterizerCacheObject { |
| 40 | public: | 41 | public: |
| 41 | explicit CachedShader(VAddr cpu_addr, u64 unique_identifier, | 42 | explicit CachedShader(const Device& device, VAddr cpu_addr, u64 unique_identifier, |
| 42 | Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache, | 43 | Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache, |
| 43 | const PrecompiledPrograms& precompiled_programs, | 44 | const PrecompiledPrograms& precompiled_programs, |
| 44 | ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr); | 45 | ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr); |
| @@ -112,7 +113,8 @@ private: | |||
| 112 | 113 | ||
| 113 | class ShaderCacheOpenGL final : public RasterizerCache<Shader> { | 114 | class ShaderCacheOpenGL final : public RasterizerCache<Shader> { |
| 114 | public: | 115 | public: |
| 115 | explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system); | 116 | explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system, |
| 117 | const Device& device); | ||
| 116 | 118 | ||
| 117 | /// Loads disk cache for the current game | 119 | /// Loads disk cache for the current game |
| 118 | void LoadDiskCache(const std::atomic_bool& stop_loading, | 120 | void LoadDiskCache(const std::atomic_bool& stop_loading, |
| @@ -130,6 +132,8 @@ private: | |||
| 130 | CachedProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump, | 132 | CachedProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump, |
| 131 | const std::set<GLenum>& supported_formats); | 133 | const std::set<GLenum>& supported_formats); |
| 132 | 134 | ||
| 135 | const Device& device; | ||
| 136 | |||
| 133 | std::array<Shader, Maxwell::MaxShaderProgram> last_shaders; | 137 | std::array<Shader, Maxwell::MaxShaderProgram> last_shaders; |
| 134 | 138 | ||
| 135 | ShaderDiskCacheOpenGL disk_cache; | 139 | ShaderDiskCacheOpenGL disk_cache; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index cd462621d..ef1a1995f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "common/assert.h" | 15 | #include "common/assert.h" |
| 16 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 17 | #include "video_core/engines/maxwell_3d.h" | 17 | #include "video_core/engines/maxwell_3d.h" |
| 18 | #include "video_core/renderer_opengl/gl_device.h" | ||
| 18 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 19 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 19 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 20 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 20 | #include "video_core/shader/shader_ir.h" | 21 | #include "video_core/shader/shader_ir.h" |
| @@ -135,8 +136,9 @@ bool IsPrecise(Node node) { | |||
| 135 | 136 | ||
| 136 | class GLSLDecompiler final { | 137 | class GLSLDecompiler final { |
| 137 | public: | 138 | public: |
| 138 | explicit GLSLDecompiler(const ShaderIR& ir, ShaderStage stage, std::string suffix) | 139 | explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ShaderStage stage, |
| 139 | : ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {} | 140 | std::string suffix) |
| 141 | : device{device}, ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {} | ||
| 140 | 142 | ||
| 141 | void Decompile() { | 143 | void Decompile() { |
| 142 | DeclareVertex(); | 144 | DeclareVertex(); |
| @@ -802,8 +804,12 @@ private: | |||
| 802 | // Inline the string as an immediate integer in GLSL (AOFFI arguments are required | 804 | // Inline the string as an immediate integer in GLSL (AOFFI arguments are required |
| 803 | // to be constant by the standard). | 805 | // to be constant by the standard). |
| 804 | expr += std::to_string(static_cast<s32>(immediate->GetValue())); | 806 | expr += std::to_string(static_cast<s32>(immediate->GetValue())); |
| 805 | } else { | 807 | } else if (device.HasVariableAoffi()) { |
| 808 | // Avoid using variable AOFFI on unsupported devices. | ||
| 806 | expr += "ftoi(" + Visit(operand) + ')'; | 809 | expr += "ftoi(" + Visit(operand) + ')'; |
| 810 | } else { | ||
| 811 | // Insert 0 on devices not supporting variable AOFFI. | ||
| 812 | expr += '0'; | ||
| 807 | } | 813 | } |
| 808 | if (index + 1 < aoffi.size()) { | 814 | if (index + 1 < aoffi.size()) { |
| 809 | expr += ", "; | 815 | expr += ", "; |
| @@ -1645,6 +1651,7 @@ private: | |||
| 1645 | return name + '_' + std::to_string(index) + '_' + suffix; | 1651 | return name + '_' + std::to_string(index) + '_' + suffix; |
| 1646 | } | 1652 | } |
| 1647 | 1653 | ||
| 1654 | const Device& device; | ||
| 1648 | const ShaderIR& ir; | 1655 | const ShaderIR& ir; |
| 1649 | const ShaderStage stage; | 1656 | const ShaderStage stage; |
| 1650 | const std::string suffix; | 1657 | const std::string suffix; |
| @@ -1676,8 +1683,9 @@ std::string GetCommonDeclarations() { | |||
| 1676 | "}\n"; | 1683 | "}\n"; |
| 1677 | } | 1684 | } |
| 1678 | 1685 | ||
| 1679 | ProgramResult Decompile(const ShaderIR& ir, Maxwell::ShaderStage stage, const std::string& suffix) { | 1686 | ProgramResult Decompile(const Device& device, const ShaderIR& ir, Maxwell::ShaderStage stage, |
| 1680 | GLSLDecompiler decompiler(ir, stage, suffix); | 1687 | const std::string& suffix) { |
| 1688 | GLSLDecompiler decompiler(device, ir, stage, suffix); | ||
| 1681 | decompiler.Decompile(); | 1689 | decompiler.Decompile(); |
| 1682 | return {decompiler.GetResult(), decompiler.GetShaderEntries()}; | 1690 | return {decompiler.GetResult(), decompiler.GetShaderEntries()}; |
| 1683 | } | 1691 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h index 74032d237..c1569e737 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.h +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "video_core/engines/maxwell_3d.h" | 12 | #include "video_core/engines/maxwell_3d.h" |
| 13 | #include "video_core/shader/shader_ir.h" | 13 | #include "video_core/shader/shader_ir.h" |
| 14 | 14 | ||
| 15 | namespace OpenGL { | ||
| 16 | class Device; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace VideoCommon::Shader { | 19 | namespace VideoCommon::Shader { |
| 16 | class ShaderIR; | 20 | class ShaderIR; |
| 17 | } | 21 | } |
| @@ -77,7 +81,7 @@ struct ShaderEntries { | |||
| 77 | 81 | ||
| 78 | std::string GetCommonDeclarations(); | 82 | std::string GetCommonDeclarations(); |
| 79 | 83 | ||
| 80 | ProgramResult Decompile(const VideoCommon::Shader::ShaderIR& ir, Maxwell::ShaderStage stage, | 84 | ProgramResult Decompile(const Device& device, const VideoCommon::Shader::ShaderIR& ir, |
| 81 | const std::string& suffix); | 85 | Maxwell::ShaderStage stage, const std::string& suffix); |
| 82 | 86 | ||
| 83 | } // namespace OpenGL::GLShader | 87 | } // namespace OpenGL::GLShader |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 8763d9c71..c055005ed 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -16,7 +16,7 @@ using VideoCommon::Shader::ShaderIR; | |||
| 16 | 16 | ||
| 17 | static constexpr u32 PROGRAM_OFFSET{10}; | 17 | static constexpr u32 PROGRAM_OFFSET{10}; |
| 18 | 18 | ||
| 19 | ProgramResult GenerateVertexShader(const ShaderSetup& setup) { | 19 | ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setup) { |
| 20 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 20 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 21 | 21 | ||
| 22 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; | 22 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; |
| @@ -34,14 +34,15 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { | |||
| 34 | 34 | ||
| 35 | )"; | 35 | )"; |
| 36 | ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); | 36 | ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); |
| 37 | ProgramResult program = Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex"); | 37 | ProgramResult program = |
| 38 | Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex"); | ||
| 38 | 39 | ||
| 39 | out += program.first; | 40 | out += program.first; |
| 40 | 41 | ||
| 41 | if (setup.IsDualProgram()) { | 42 | if (setup.IsDualProgram()) { |
| 42 | ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET); | 43 | ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET); |
| 43 | ProgramResult program_b = | 44 | ProgramResult program_b = |
| 44 | Decompile(program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b"); | 45 | Decompile(device, program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b"); |
| 45 | 46 | ||
| 46 | out += program_b.first; | 47 | out += program_b.first; |
| 47 | } | 48 | } |
| @@ -75,7 +76,7 @@ void main() { | |||
| 75 | return {out, program.second}; | 76 | return {out, program.second}; |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { | 79 | ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) { |
| 79 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 80 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 80 | 81 | ||
| 81 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; | 82 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; |
| @@ -95,7 +96,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config { | |||
| 95 | )"; | 96 | )"; |
| 96 | ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); | 97 | ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); |
| 97 | ProgramResult program = | 98 | ProgramResult program = |
| 98 | Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry"); | 99 | Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry"); |
| 99 | out += program.first; | 100 | out += program.first; |
| 100 | 101 | ||
| 101 | out += R"( | 102 | out += R"( |
| @@ -106,7 +107,7 @@ void main() { | |||
| 106 | return {out, program.second}; | 107 | return {out, program.second}; |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | ProgramResult GenerateFragmentShader(const ShaderSetup& setup) { | 110 | ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) { |
| 110 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 111 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 111 | 112 | ||
| 112 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; | 113 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; |
| @@ -158,7 +159,7 @@ bool AlphaFunc(in float value) { | |||
| 158 | )"; | 159 | )"; |
| 159 | ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); | 160 | ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); |
| 160 | ProgramResult program = | 161 | ProgramResult program = |
| 161 | Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment"); | 162 | Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment"); |
| 162 | 163 | ||
| 163 | out += program.first; | 164 | out += program.first; |
| 164 | 165 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index fad346b48..0536c8a03 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h | |||
| @@ -10,6 +10,10 @@ | |||
| 10 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 10 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 11 | #include "video_core/shader/shader_ir.h" | 11 | #include "video_core/shader/shader_ir.h" |
| 12 | 12 | ||
| 13 | namespace OpenGL { | ||
| 14 | class Device; | ||
| 15 | } | ||
| 16 | |||
| 13 | namespace OpenGL::GLShader { | 17 | namespace OpenGL::GLShader { |
| 14 | 18 | ||
| 15 | using VideoCommon::Shader::ProgramCode; | 19 | using VideoCommon::Shader::ProgramCode; |
| @@ -39,22 +43,13 @@ private: | |||
| 39 | bool has_program_b{}; | 43 | bool has_program_b{}; |
| 40 | }; | 44 | }; |
| 41 | 45 | ||
| 42 | /** | 46 | /// Generates the GLSL vertex shader program source code for the given VS program |
| 43 | * Generates the GLSL vertex shader program source code for the given VS program | 47 | ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setup); |
| 44 | * @returns String of the shader source code | 48 | |
| 45 | */ | 49 | /// Generates the GLSL geometry shader program source code for the given GS program |
| 46 | ProgramResult GenerateVertexShader(const ShaderSetup& setup); | 50 | ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup); |
| 47 | 51 | ||
| 48 | /** | 52 | /// Generates the GLSL fragment shader program source code for the given FS program |
| 49 | * Generates the GLSL geometry shader program source code for the given GS program | 53 | ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup); |
| 50 | * @returns String of the shader source code | ||
| 51 | */ | ||
| 52 | ProgramResult GenerateGeometryShader(const ShaderSetup& setup); | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Generates the GLSL fragment shader program source code for the given FS program | ||
| 56 | * @returns String of the shader source code | ||
| 57 | */ | ||
| 58 | ProgramResult GenerateFragmentShader(const ShaderSetup& setup); | ||
| 59 | 54 | ||
| 60 | } // namespace OpenGL::GLShader | 55 | } // namespace OpenGL::GLShader |