diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 130 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 41 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 146 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.h | 90 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.h | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 13 |
7 files changed, 194 insertions, 249 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index ca421ef28..ee313cb2f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -297,11 +297,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 297 | MICROPROFILE_SCOPE(OpenGL_Shader); | 297 | MICROPROFILE_SCOPE(OpenGL_Shader); |
| 298 | auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); | 298 | auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); |
| 299 | 299 | ||
| 300 | // Next available bindpoints to use when uploading the const buffers and textures to the GLSL | 300 | BaseBindings base_bindings; |
| 301 | // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points. | ||
| 302 | u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; | ||
| 303 | u32 current_gmem_bindpoint = 0; | ||
| 304 | u32 current_texture_bindpoint = 0; | ||
| 305 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | 301 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; |
| 306 | 302 | ||
| 307 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 303 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| @@ -325,47 +321,35 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 325 | const GLintptr offset = buffer_cache.UploadHostMemory( | 321 | const GLintptr offset = buffer_cache.UploadHostMemory( |
| 326 | &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); | 322 | &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); |
| 327 | 323 | ||
| 328 | // Bind the buffer | 324 | // Bind the emulation info buffer |
| 329 | glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(stage), buffer_cache.GetHandle(), | 325 | glBindBufferRange(GL_UNIFORM_BUFFER, base_bindings.cbuf, buffer_cache.GetHandle(), offset, |
| 330 | offset, static_cast<GLsizeiptr>(sizeof(ubo))); | 326 | static_cast<GLsizeiptr>(sizeof(ubo))); |
| 331 | 327 | ||
| 332 | Shader shader{shader_cache.GetStageProgram(program)}; | 328 | Shader shader{shader_cache.GetStageProgram(program)}; |
| 329 | const auto [program_handle, next_bindings] = | ||
| 330 | shader->GetProgramHandle(primitive_mode, base_bindings); | ||
| 333 | 331 | ||
| 334 | switch (program) { | 332 | switch (program) { |
| 335 | case Maxwell::ShaderProgram::VertexA: | 333 | case Maxwell::ShaderProgram::VertexA: |
| 336 | case Maxwell::ShaderProgram::VertexB: { | 334 | case Maxwell::ShaderProgram::VertexB: |
| 337 | shader_program_manager->UseProgrammableVertexShader( | 335 | shader_program_manager->UseProgrammableVertexShader(program_handle); |
| 338 | shader->GetProgramHandle(primitive_mode)); | ||
| 339 | break; | 336 | break; |
| 340 | } | 337 | case Maxwell::ShaderProgram::Geometry: |
| 341 | case Maxwell::ShaderProgram::Geometry: { | 338 | shader_program_manager->UseProgrammableGeometryShader(program_handle); |
| 342 | shader_program_manager->UseProgrammableGeometryShader( | ||
| 343 | shader->GetProgramHandle(primitive_mode)); | ||
| 344 | break; | 339 | break; |
| 345 | } | 340 | case Maxwell::ShaderProgram::Fragment: |
| 346 | case Maxwell::ShaderProgram::Fragment: { | 341 | shader_program_manager->UseProgrammableFragmentShader(program_handle); |
| 347 | shader_program_manager->UseProgrammableFragmentShader( | ||
| 348 | shader->GetProgramHandle(primitive_mode)); | ||
| 349 | break; | 342 | break; |
| 350 | } | ||
| 351 | default: | 343 | default: |
| 352 | LOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset=0x{:08X}", index, | 344 | LOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset=0x{:08X}", index, |
| 353 | shader_config.enable.Value(), shader_config.offset); | 345 | shader_config.enable.Value(), shader_config.offset); |
| 354 | UNREACHABLE(); | 346 | UNREACHABLE(); |
| 355 | } | 347 | } |
| 356 | 348 | ||
| 357 | // Configure the const buffers for this shader stage. | 349 | const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage); |
| 358 | current_constbuffer_bindpoint = | 350 | SetupConstBuffers(stage_enum, shader, program_handle, base_bindings); |
| 359 | SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), shader, primitive_mode, | 351 | SetupGlobalRegions(stage_enum, shader, program_handle, base_bindings); |
| 360 | current_constbuffer_bindpoint); | 352 | SetupTextures(stage_enum, shader, program_handle, base_bindings); |
| 361 | |||
| 362 | // Configure global memory regions for this shader stage. | ||
| 363 | current_gmem_bindpoint = SetupGlobalRegions(static_cast<Maxwell::ShaderStage>(stage), | ||
| 364 | shader, primitive_mode, current_gmem_bindpoint); | ||
| 365 | |||
| 366 | // Configure the textures for this shader stage. | ||
| 367 | current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader, | ||
| 368 | primitive_mode, current_texture_bindpoint); | ||
| 369 | 353 | ||
| 370 | // Workaround for Intel drivers. | 354 | // Workaround for Intel drivers. |
| 371 | // When a clip distance is enabled but not set in the shader it crops parts of the screen | 355 | // When a clip distance is enabled but not set in the shader it crops parts of the screen |
| @@ -380,6 +364,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 380 | // VertexB was combined with VertexA, so we skip the VertexB iteration | 364 | // VertexB was combined with VertexA, so we skip the VertexB iteration |
| 381 | index++; | 365 | index++; |
| 382 | } | 366 | } |
| 367 | |||
| 368 | base_bindings = next_bindings; | ||
| 383 | } | 369 | } |
| 384 | 370 | ||
| 385 | SyncClipEnabled(clip_distances); | 371 | SyncClipEnabled(clip_distances); |
| @@ -929,8 +915,9 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr | |||
| 929 | } | 915 | } |
| 930 | } | 916 | } |
| 931 | 917 | ||
| 932 | u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader, | 918 | void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, |
| 933 | GLenum primitive_mode, u32 current_bindpoint) { | 919 | const Shader& shader, GLuint program_handle, |
| 920 | BaseBindings base_bindings) { | ||
| 934 | MICROPROFILE_SCOPE(OpenGL_UBO); | 921 | MICROPROFILE_SCOPE(OpenGL_UBO); |
| 935 | const auto& gpu = Core::System::GetInstance().GPU(); | 922 | const auto& gpu = Core::System::GetInstance().GPU(); |
| 936 | const auto& maxwell3d = gpu.Maxwell3D(); | 923 | const auto& maxwell3d = gpu.Maxwell3D(); |
| @@ -978,92 +965,73 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad | |||
| 978 | size = Common::AlignUp(size, sizeof(GLvec4)); | 965 | size = Common::AlignUp(size, sizeof(GLvec4)); |
| 979 | ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big"); | 966 | ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big"); |
| 980 | 967 | ||
| 981 | GLintptr const_buffer_offset = buffer_cache.UploadMemory( | 968 | const GLintptr const_buffer_offset = buffer_cache.UploadMemory( |
| 982 | buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment)); | 969 | buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment)); |
| 983 | 970 | ||
| 984 | // Now configure the bindpoint of the buffer inside the shader | ||
| 985 | glUniformBlockBinding(shader->GetProgramHandle(primitive_mode), | ||
| 986 | shader->GetProgramResourceIndex(used_buffer), | ||
| 987 | current_bindpoint + bindpoint); | ||
| 988 | |||
| 989 | // Prepare values for multibind | 971 | // Prepare values for multibind |
| 990 | bind_buffers[bindpoint] = buffer_cache.GetHandle(); | 972 | bind_buffers[bindpoint] = buffer_cache.GetHandle(); |
| 991 | bind_offsets[bindpoint] = const_buffer_offset; | 973 | bind_offsets[bindpoint] = const_buffer_offset; |
| 992 | bind_sizes[bindpoint] = size; | 974 | bind_sizes[bindpoint] = size; |
| 993 | } | 975 | } |
| 994 | 976 | ||
| 995 | glBindBuffersRange(GL_UNIFORM_BUFFER, current_bindpoint, static_cast<GLsizei>(entries.size()), | 977 | // The first binding is reserved for emulation values |
| 978 | const GLuint ubo_base_binding = base_bindings.cbuf + 1; | ||
| 979 | glBindBuffersRange(GL_UNIFORM_BUFFER, ubo_base_binding, static_cast<GLsizei>(entries.size()), | ||
| 996 | bind_buffers.data(), bind_offsets.data(), bind_sizes.data()); | 980 | bind_buffers.data(), bind_offsets.data(), bind_sizes.data()); |
| 997 | |||
| 998 | return current_bindpoint + static_cast<u32>(entries.size()); | ||
| 999 | } | 981 | } |
| 1000 | 982 | ||
| 1001 | u32 RasterizerOpenGL::SetupGlobalRegions(Maxwell::ShaderStage stage, Shader& shader, | 983 | void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, |
| 1002 | GLenum primitive_mode, u32 current_bindpoint) { | 984 | const Shader& shader, GLenum primitive_mode, |
| 1003 | for (const auto& global_region : shader->GetShaderEntries().global_memory_entries) { | 985 | BaseBindings base_bindings) { |
| 1004 | const auto& region = | 986 | // TODO(Rodrigo): Use ARB_multi_bind here |
| 1005 | global_cache.GetGlobalRegion(global_region, static_cast<Maxwell::ShaderStage>(stage)); | 987 | const auto& entries = shader->GetShaderEntries().global_memory_entries; |
| 1006 | const GLuint block_index{shader->GetProgramResourceIndex(global_region)}; | 988 | |
| 1007 | ASSERT(block_index != GL_INVALID_INDEX); | 989 | for (u32 bindpoint = 0; bindpoint < static_cast<u32>(entries.size()); ++bindpoint) { |
| 990 | const auto& entry = entries[bindpoint]; | ||
| 991 | const u32 current_bindpoint = base_bindings.gmem + bindpoint; | ||
| 992 | const auto& region = global_cache.GetGlobalRegion(entry, stage); | ||
| 1008 | 993 | ||
| 1009 | glBindBufferBase(GL_SHADER_STORAGE_BUFFER, current_bindpoint, region->GetBufferHandle()); | 994 | glBindBufferBase(GL_SHADER_STORAGE_BUFFER, current_bindpoint, region->GetBufferHandle()); |
| 1010 | glShaderStorageBlockBinding(shader->GetProgramHandle(primitive_mode), block_index, | ||
| 1011 | current_bindpoint); | ||
| 1012 | ++current_bindpoint; | ||
| 1013 | } | 995 | } |
| 1014 | |||
| 1015 | return current_bindpoint; | ||
| 1016 | } | 996 | } |
| 1017 | 997 | ||
| 1018 | u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, | 998 | void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& shader, |
| 1019 | GLenum primitive_mode, u32 current_unit) { | 999 | GLuint program_handle, BaseBindings base_bindings) { |
| 1020 | MICROPROFILE_SCOPE(OpenGL_Texture); | 1000 | MICROPROFILE_SCOPE(OpenGL_Texture); |
| 1021 | const auto& gpu = Core::System::GetInstance().GPU(); | 1001 | const auto& gpu = Core::System::GetInstance().GPU(); |
| 1022 | const auto& maxwell3d = gpu.Maxwell3D(); | 1002 | const auto& maxwell3d = gpu.Maxwell3D(); |
| 1023 | const auto& entries = shader->GetShaderEntries().samplers; | 1003 | const auto& entries = shader->GetShaderEntries().samplers; |
| 1024 | 1004 | ||
| 1025 | ASSERT_MSG(current_unit + entries.size() <= std::size(state.texture_units), | 1005 | ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.texture_units), |
| 1026 | "Exceeded the number of active textures."); | 1006 | "Exceeded the number of active textures."); |
| 1027 | 1007 | ||
| 1028 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | 1008 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { |
| 1029 | const auto& entry = entries[bindpoint]; | 1009 | const auto& entry = entries[bindpoint]; |
| 1030 | const u32 current_bindpoint = current_unit + bindpoint; | 1010 | const u32 current_bindpoint = base_bindings.sampler + bindpoint; |
| 1031 | 1011 | auto& unit = state.texture_units[current_bindpoint]; | |
| 1032 | // Bind the uniform to the sampler. | ||
| 1033 | |||
| 1034 | glProgramUniform1i(shader->GetProgramHandle(primitive_mode), | ||
| 1035 | shader->GetUniformLocation(entry), current_bindpoint); | ||
| 1036 | 1012 | ||
| 1037 | const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset()); | 1013 | const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset()); |
| 1038 | |||
| 1039 | if (!texture.enabled) { | 1014 | if (!texture.enabled) { |
| 1040 | state.texture_units[current_bindpoint].texture = 0; | 1015 | unit.texture = 0; |
| 1041 | continue; | 1016 | continue; |
| 1042 | } | 1017 | } |
| 1043 | 1018 | ||
| 1044 | texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); | 1019 | texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); |
| 1020 | |||
| 1045 | Surface surface = res_cache.GetTextureSurface(texture, entry); | 1021 | Surface surface = res_cache.GetTextureSurface(texture, entry); |
| 1046 | if (surface != nullptr) { | 1022 | if (surface != nullptr) { |
| 1047 | const GLuint handle = | 1023 | unit.texture = |
| 1048 | entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; | 1024 | entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; |
| 1049 | const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); | 1025 | unit.target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); |
| 1050 | state.texture_units[current_bindpoint].texture = handle; | 1026 | unit.swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source); |
| 1051 | state.texture_units[current_bindpoint].target = target; | 1027 | unit.swizzle.g = MaxwellToGL::SwizzleSource(texture.tic.y_source); |
| 1052 | state.texture_units[current_bindpoint].swizzle.r = | 1028 | unit.swizzle.b = MaxwellToGL::SwizzleSource(texture.tic.z_source); |
| 1053 | MaxwellToGL::SwizzleSource(texture.tic.x_source); | 1029 | unit.swizzle.a = MaxwellToGL::SwizzleSource(texture.tic.w_source); |
| 1054 | state.texture_units[current_bindpoint].swizzle.g = | ||
| 1055 | MaxwellToGL::SwizzleSource(texture.tic.y_source); | ||
| 1056 | state.texture_units[current_bindpoint].swizzle.b = | ||
| 1057 | MaxwellToGL::SwizzleSource(texture.tic.z_source); | ||
| 1058 | state.texture_units[current_bindpoint].swizzle.a = | ||
| 1059 | MaxwellToGL::SwizzleSource(texture.tic.w_source); | ||
| 1060 | } else { | 1030 | } else { |
| 1061 | // Can occur when texture addr is null or its memory is unmapped/invalid | 1031 | // Can occur when texture addr is null or its memory is unmapped/invalid |
| 1062 | state.texture_units[current_bindpoint].texture = 0; | 1032 | unit.texture = 0; |
| 1063 | } | 1033 | } |
| 1064 | } | 1034 | } |
| 1065 | |||
| 1066 | return current_unit + static_cast<u32>(entries.size()); | ||
| 1067 | } | 1035 | } |
| 1068 | 1036 | ||
| 1069 | void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { | 1037 | void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 57ab2f627..a103692f9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -127,35 +127,18 @@ private: | |||
| 127 | bool using_depth_fb = true, bool preserve_contents = true, | 127 | bool using_depth_fb = true, bool preserve_contents = true, |
| 128 | std::optional<std::size_t> single_color_target = {}); | 128 | std::optional<std::size_t> single_color_target = {}); |
| 129 | 129 | ||
| 130 | /** | 130 | /// Configures the current constbuffers to use for the draw command. |
| 131 | * Configures the current constbuffers to use for the draw command. | 131 | void SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader, |
| 132 | * @param stage The shader stage to configure buffers for. | 132 | GLuint program_handle, BaseBindings base_bindings); |
| 133 | * @param shader The shader object that contains the specified stage. | 133 | |
| 134 | * @param current_bindpoint The offset at which to start counting new buffer bindpoints. | 134 | /// Configures the current global memory entries to use for the draw command. |
| 135 | * @returns The next available bindpoint for use in the next shader stage. | 135 | void SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, |
| 136 | */ | 136 | const Shader& shader, GLenum primitive_mode, |
| 137 | u32 SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, | 137 | BaseBindings base_bindings); |
| 138 | GLenum primitive_mode, u32 current_bindpoint); | 138 | |
| 139 | 139 | /// Configures the current textures to use for the draw command. | |
| 140 | /** | 140 | void SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader, |
| 141 | * Configures the current global memory regions to use for the draw command. | 141 | GLuint program_handle, BaseBindings base_bindings); |
| 142 | * @param stage The shader stage to configure buffers for. | ||
| 143 | * @param shader The shader object that contains the specified stage. | ||
| 144 | * @param current_bindpoint The offset at which to start counting new buffer bindpoints. | ||
| 145 | * @returns The next available bindpoint for use in the next shader stage. | ||
| 146 | */ | ||
| 147 | u32 SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, | ||
| 148 | GLenum primitive_mode, u32 current_bindpoint); | ||
| 149 | |||
| 150 | /** | ||
| 151 | * Configures the current textures to use for the draw command. | ||
| 152 | * @param stage The shader stage to configure textures for. | ||
| 153 | * @param shader The shader object that contains the specified stage. | ||
| 154 | * @param current_unit The offset at which to start counting unused texture units. | ||
| 155 | * @returns The next available bindpoint for use in the next shader stage. | ||
| 156 | */ | ||
| 157 | u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, | ||
| 158 | GLenum primitive_mode, u32 current_unit); | ||
| 159 | 142 | ||
| 160 | /// Syncs the viewport and depth range to match the guest state | 143 | /// Syncs the viewport and depth range to match the guest state |
| 161 | void SyncViewport(OpenGLState& current_state); | 144 | void SyncViewport(OpenGLState& current_state); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 54ec23f3a..90eda7814 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -34,36 +34,25 @@ static ProgramCode GetShaderCode(VAddr addr) { | |||
| 34 | return program_code; | 34 | return program_code; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /// Helper function to set shader uniform block bindings for a single shader stage | 37 | /// Gets the shader type from a Maxwell program type |
| 38 | static void SetShaderUniformBlockBinding(GLuint shader, const char* name, | 38 | constexpr GLenum GetShaderType(Maxwell::ShaderProgram program_type) { |
| 39 | Maxwell::ShaderStage binding, std::size_t expected_size) { | 39 | switch (program_type) { |
| 40 | const GLuint ub_index = glGetUniformBlockIndex(shader, name); | 40 | case Maxwell::ShaderProgram::VertexA: |
| 41 | if (ub_index == GL_INVALID_INDEX) { | 41 | case Maxwell::ShaderProgram::VertexB: |
| 42 | return; | 42 | return GL_VERTEX_SHADER; |
| 43 | case Maxwell::ShaderProgram::Geometry: | ||
| 44 | return GL_GEOMETRY_SHADER; | ||
| 45 | case Maxwell::ShaderProgram::Fragment: | ||
| 46 | return GL_FRAGMENT_SHADER; | ||
| 47 | default: | ||
| 48 | return GL_NONE; | ||
| 43 | } | 49 | } |
| 44 | |||
| 45 | GLint ub_size = 0; | ||
| 46 | glGetActiveUniformBlockiv(shader, ub_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ub_size); | ||
| 47 | ASSERT_MSG(static_cast<std::size_t>(ub_size) == expected_size, | ||
| 48 | "Uniform block size did not match! Got {}, expected {}", ub_size, expected_size); | ||
| 49 | glUniformBlockBinding(shader, ub_index, static_cast<GLuint>(binding)); | ||
| 50 | } | ||
| 51 | |||
| 52 | /// Sets shader uniform block bindings for an entire shader program | ||
| 53 | static void SetShaderUniformBlockBindings(GLuint shader) { | ||
| 54 | SetShaderUniformBlockBinding(shader, "vs_config", Maxwell::ShaderStage::Vertex, | ||
| 55 | sizeof(GLShader::MaxwellUniformData)); | ||
| 56 | SetShaderUniformBlockBinding(shader, "gs_config", Maxwell::ShaderStage::Geometry, | ||
| 57 | sizeof(GLShader::MaxwellUniformData)); | ||
| 58 | SetShaderUniformBlockBinding(shader, "fs_config", Maxwell::ShaderStage::Fragment, | ||
| 59 | sizeof(GLShader::MaxwellUniformData)); | ||
| 60 | } | 50 | } |
| 61 | 51 | ||
| 62 | CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type) | 52 | CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type) |
| 63 | : addr{addr}, program_type{program_type}, setup{GetShaderCode(addr)} { | 53 | : addr{addr}, program_type{program_type}, setup{GetShaderCode(addr)} { |
| 64 | 54 | ||
| 65 | GLShader::ProgramResult program_result; | 55 | GLShader::ProgramResult program_result; |
| 66 | GLenum gl_type{}; | ||
| 67 | 56 | ||
| 68 | switch (program_type) { | 57 | switch (program_type) { |
| 69 | case Maxwell::ShaderProgram::VertexA: | 58 | case Maxwell::ShaderProgram::VertexA: |
| @@ -74,17 +63,14 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type) | |||
| 74 | case Maxwell::ShaderProgram::VertexB: | 63 | case Maxwell::ShaderProgram::VertexB: |
| 75 | CalculateProperties(); | 64 | CalculateProperties(); |
| 76 | program_result = GLShader::GenerateVertexShader(setup); | 65 | program_result = GLShader::GenerateVertexShader(setup); |
| 77 | gl_type = GL_VERTEX_SHADER; | ||
| 78 | break; | 66 | break; |
| 79 | case Maxwell::ShaderProgram::Geometry: | 67 | case Maxwell::ShaderProgram::Geometry: |
| 80 | CalculateProperties(); | 68 | CalculateProperties(); |
| 81 | program_result = GLShader::GenerateGeometryShader(setup); | 69 | program_result = GLShader::GenerateGeometryShader(setup); |
| 82 | gl_type = GL_GEOMETRY_SHADER; | ||
| 83 | break; | 70 | break; |
| 84 | case Maxwell::ShaderProgram::Fragment: | 71 | case Maxwell::ShaderProgram::Fragment: |
| 85 | CalculateProperties(); | 72 | CalculateProperties(); |
| 86 | program_result = GLShader::GenerateFragmentShader(setup); | 73 | program_result = GLShader::GenerateFragmentShader(setup); |
| 87 | gl_type = GL_FRAGMENT_SHADER; | ||
| 88 | break; | 74 | break; |
| 89 | default: | 75 | default: |
| 90 | LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type)); | 76 | LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type)); |
| @@ -92,71 +78,105 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type) | |||
| 92 | return; | 78 | return; |
| 93 | } | 79 | } |
| 94 | 80 | ||
| 81 | code = program_result.first; | ||
| 95 | entries = program_result.second; | 82 | entries = program_result.second; |
| 96 | shader_length = entries.shader_length; | 83 | shader_length = entries.shader_length; |
| 84 | } | ||
| 97 | 85 | ||
| 98 | if (program_type != Maxwell::ShaderProgram::Geometry) { | 86 | std::tuple<GLuint, BaseBindings> CachedShader::GetProgramHandle(GLenum primitive_mode, |
| 99 | OGLShader shader; | 87 | BaseBindings base_bindings) { |
| 100 | shader.Create(program_result.first.c_str(), gl_type); | 88 | GLuint handle{}; |
| 101 | program.Create(true, shader.handle); | 89 | if (program_type == Maxwell::ShaderProgram::Geometry) { |
| 102 | SetShaderUniformBlockBindings(program.handle); | 90 | handle = GetGeometryShader(primitive_mode, base_bindings); |
| 103 | LabelGLObject(GL_PROGRAM, program.handle, addr); | ||
| 104 | } else { | 91 | } else { |
| 105 | // Store shader's code to lazily build it on draw | 92 | const auto [entry, is_cache_miss] = programs.try_emplace(base_bindings); |
| 106 | geometry_programs.code = program_result.first; | 93 | auto& program = entry->second; |
| 94 | if (is_cache_miss) { | ||
| 95 | std::string source = AllocateBindings(base_bindings); | ||
| 96 | source += code; | ||
| 97 | |||
| 98 | OGLShader shader; | ||
| 99 | shader.Create(source.c_str(), GetShaderType(program_type)); | ||
| 100 | program.Create(true, shader.handle); | ||
| 101 | LabelGLObject(GL_PROGRAM, program.handle, addr); | ||
| 102 | } | ||
| 103 | |||
| 104 | handle = program.handle; | ||
| 107 | } | 105 | } |
| 106 | |||
| 107 | // Add const buffer and samplers offset reserved by this shader. One UBO binding is reserved for | ||
| 108 | // emulation values | ||
| 109 | base_bindings.cbuf += static_cast<u32>(entries.const_buffers.size()) + 1; | ||
| 110 | base_bindings.gmem += static_cast<u32>(entries.global_memory_entries.size()); | ||
| 111 | base_bindings.sampler += static_cast<u32>(entries.samplers.size()); | ||
| 112 | |||
| 113 | return {handle, base_bindings}; | ||
| 108 | } | 114 | } |
| 109 | 115 | ||
| 110 | GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { | 116 | std::string CachedShader::AllocateBindings(BaseBindings base_bindings) { |
| 111 | const auto search{cbuf_resource_cache.find(buffer.GetHash())}; | 117 | std::string code = "#version 430 core\n"; |
| 112 | if (search == cbuf_resource_cache.end()) { | 118 | code += fmt::format("#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); |
| 113 | const GLuint index{ | 119 | |
| 114 | glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())}; | 120 | for (const auto& cbuf : entries.const_buffers) { |
| 115 | cbuf_resource_cache[buffer.GetHash()] = index; | 121 | code += fmt::format("#define CBUF_BINDING_{} {}\n", cbuf.GetIndex(), base_bindings.cbuf++); |
| 116 | return index; | ||
| 117 | } | 122 | } |
| 118 | 123 | ||
| 119 | return search->second; | 124 | for (const auto& gmem : entries.global_memory_entries) { |
| 120 | } | 125 | code += fmt::format("#define GMEM_BINDING_{}_{} {}\n", gmem.GetCbufIndex(), |
| 126 | gmem.GetCbufOffset(), base_bindings.gmem++); | ||
| 127 | } | ||
| 121 | 128 | ||
| 122 | GLuint CachedShader::GetProgramResourceIndex(const GLShader::GlobalMemoryEntry& global_mem) { | 129 | for (const auto& sampler : entries.samplers) { |
| 123 | const auto search{gmem_resource_cache.find(global_mem.GetHash())}; | 130 | code += fmt::format("#define SAMPLER_BINDING_{} {}\n", sampler.GetIndex(), |
| 124 | if (search == gmem_resource_cache.end()) { | 131 | base_bindings.sampler++); |
| 125 | const GLuint index{glGetProgramResourceIndex(program.handle, GL_SHADER_STORAGE_BLOCK, | ||
| 126 | global_mem.GetName().c_str())}; | ||
| 127 | gmem_resource_cache[global_mem.GetHash()] = index; | ||
| 128 | return index; | ||
| 129 | } | 132 | } |
| 130 | 133 | ||
| 131 | return search->second; | 134 | return code; |
| 132 | } | 135 | } |
| 133 | 136 | ||
| 134 | GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) { | 137 | GLuint CachedShader::GetGeometryShader(GLenum primitive_mode, BaseBindings base_bindings) { |
| 135 | const auto search{uniform_cache.find(sampler.GetHash())}; | 138 | const auto [entry, is_cache_miss] = geometry_programs.try_emplace(base_bindings); |
| 136 | if (search == uniform_cache.end()) { | 139 | auto& programs = entry->second; |
| 137 | const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())}; | 140 | |
| 138 | uniform_cache[sampler.GetHash()] = index; | 141 | switch (primitive_mode) { |
| 139 | return index; | 142 | case GL_POINTS: |
| 143 | return LazyGeometryProgram(programs.points, base_bindings, "points", 1, "ShaderPoints"); | ||
| 144 | case GL_LINES: | ||
| 145 | case GL_LINE_STRIP: | ||
| 146 | return LazyGeometryProgram(programs.lines, base_bindings, "lines", 2, "ShaderLines"); | ||
| 147 | case GL_LINES_ADJACENCY: | ||
| 148 | case GL_LINE_STRIP_ADJACENCY: | ||
| 149 | return LazyGeometryProgram(programs.lines_adjacency, base_bindings, "lines_adjacency", 4, | ||
| 150 | "ShaderLinesAdjacency"); | ||
| 151 | case GL_TRIANGLES: | ||
| 152 | case GL_TRIANGLE_STRIP: | ||
| 153 | case GL_TRIANGLE_FAN: | ||
| 154 | return LazyGeometryProgram(programs.triangles, base_bindings, "triangles", 3, | ||
| 155 | "ShaderTriangles"); | ||
| 156 | case GL_TRIANGLES_ADJACENCY: | ||
| 157 | case GL_TRIANGLE_STRIP_ADJACENCY: | ||
| 158 | return LazyGeometryProgram(programs.triangles_adjacency, base_bindings, | ||
| 159 | "triangles_adjacency", 6, "ShaderTrianglesAdjacency"); | ||
| 160 | default: | ||
| 161 | UNREACHABLE_MSG("Unknown primitive mode."); | ||
| 162 | return LazyGeometryProgram(programs.points, base_bindings, "points", 1, "ShaderPoints"); | ||
| 140 | } | 163 | } |
| 141 | |||
| 142 | return search->second; | ||
| 143 | } | 164 | } |
| 144 | 165 | ||
| 145 | GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, | 166 | GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, BaseBindings base_bindings, |
| 146 | const std::string& glsl_topology, u32 max_vertices, | 167 | const std::string& glsl_topology, u32 max_vertices, |
| 147 | const std::string& debug_name) { | 168 | const std::string& debug_name) { |
| 148 | if (target_program.handle != 0) { | 169 | if (target_program.handle != 0) { |
| 149 | return target_program.handle; | 170 | return target_program.handle; |
| 150 | } | 171 | } |
| 151 | std::string source = "#version 430 core\n"; | 172 | std::string source = AllocateBindings(base_bindings); |
| 152 | source += "layout (" + glsl_topology + ") in;\n"; | 173 | source += "layout (" + glsl_topology + ") in;\n"; |
| 153 | source += "#define MAX_VERTEX_INPUT " + std::to_string(max_vertices) + '\n'; | 174 | source += "#define MAX_VERTEX_INPUT " + std::to_string(max_vertices) + '\n'; |
| 154 | source += geometry_programs.code; | 175 | source += code; |
| 155 | 176 | ||
| 156 | OGLShader shader; | 177 | OGLShader shader; |
| 157 | shader.Create(source.c_str(), GL_GEOMETRY_SHADER); | 178 | shader.Create(source.c_str(), GL_GEOMETRY_SHADER); |
| 158 | target_program.Create(true, shader.handle); | 179 | target_program.Create(true, shader.handle); |
| 159 | SetShaderUniformBlockBindings(target_program.handle); | ||
| 160 | LabelGLObject(GL_PROGRAM, target_program.handle, addr, debug_name); | 180 | LabelGLObject(GL_PROGRAM, target_program.handle, addr, debug_name); |
| 161 | return target_program.handle; | 181 | return target_program.handle; |
| 162 | }; | 182 | }; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 62b1733b4..904d15dd0 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -7,6 +7,9 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <map> | 8 | #include <map> |
| 9 | #include <memory> | 9 | #include <memory> |
| 10 | #include <tuple> | ||
| 11 | |||
| 12 | #include <glad/glad.h> | ||
| 10 | 13 | ||
| 11 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 12 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| @@ -23,6 +26,16 @@ class RasterizerOpenGL; | |||
| 23 | using Shader = std::shared_ptr<CachedShader>; | 26 | using Shader = std::shared_ptr<CachedShader>; |
| 24 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 27 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 25 | 28 | ||
| 29 | struct BaseBindings { | ||
| 30 | u32 cbuf{}; | ||
| 31 | u32 gmem{}; | ||
| 32 | u32 sampler{}; | ||
| 33 | |||
| 34 | bool operator<(const BaseBindings& rhs) const { | ||
| 35 | return std::tie(cbuf, gmem, sampler) < std::tie(rhs.cbuf, rhs.gmem, rhs.sampler); | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | |||
| 26 | class CachedShader final : public RasterizerCacheObject { | 39 | class CachedShader final : public RasterizerCacheObject { |
| 27 | public: | 40 | public: |
| 28 | CachedShader(VAddr addr, Maxwell::ShaderProgram program_type); | 41 | CachedShader(VAddr addr, Maxwell::ShaderProgram program_type); |
| @@ -44,71 +57,42 @@ public: | |||
| 44 | } | 57 | } |
| 45 | 58 | ||
| 46 | /// Gets the GL program handle for the shader | 59 | /// Gets the GL program handle for the shader |
| 47 | GLuint GetProgramHandle(GLenum primitive_mode) { | 60 | std::tuple<GLuint, BaseBindings> GetProgramHandle(GLenum primitive_mode, |
| 48 | if (program_type != Maxwell::ShaderProgram::Geometry) { | 61 | BaseBindings base_bindings); |
| 49 | return program.handle; | ||
| 50 | } | ||
| 51 | switch (primitive_mode) { | ||
| 52 | case GL_POINTS: | ||
| 53 | return LazyGeometryProgram(geometry_programs.points, "points", 1, "ShaderPoints"); | ||
| 54 | case GL_LINES: | ||
| 55 | case GL_LINE_STRIP: | ||
| 56 | return LazyGeometryProgram(geometry_programs.lines, "lines", 2, "ShaderLines"); | ||
| 57 | case GL_LINES_ADJACENCY: | ||
| 58 | case GL_LINE_STRIP_ADJACENCY: | ||
| 59 | return LazyGeometryProgram(geometry_programs.lines_adjacency, "lines_adjacency", 4, | ||
| 60 | "ShaderLinesAdjacency"); | ||
| 61 | case GL_TRIANGLES: | ||
| 62 | case GL_TRIANGLE_STRIP: | ||
| 63 | case GL_TRIANGLE_FAN: | ||
| 64 | return LazyGeometryProgram(geometry_programs.triangles, "triangles", 3, | ||
| 65 | "ShaderTriangles"); | ||
| 66 | case GL_TRIANGLES_ADJACENCY: | ||
| 67 | case GL_TRIANGLE_STRIP_ADJACENCY: | ||
| 68 | return LazyGeometryProgram(geometry_programs.triangles_adjacency, "triangles_adjacency", | ||
| 69 | 6, "ShaderTrianglesAdjacency"); | ||
| 70 | default: | ||
| 71 | UNREACHABLE_MSG("Unknown primitive mode."); | ||
| 72 | return LazyGeometryProgram(geometry_programs.points, "points", 1, "ShaderPoints"); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | 62 | ||
| 76 | /// Gets the GL program resource location for the specified resource, caching as needed | 63 | private: |
| 77 | GLuint GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer); | 64 | // Geometry programs. These are needed because GLSL needs an input topology but it's not |
| 65 | // declared by the hardware. Workaround this issue by generating a different shader per input | ||
| 66 | // topology class. | ||
| 67 | struct GeometryPrograms { | ||
| 68 | OGLProgram points; | ||
| 69 | OGLProgram lines; | ||
| 70 | OGLProgram lines_adjacency; | ||
| 71 | OGLProgram triangles; | ||
| 72 | OGLProgram triangles_adjacency; | ||
| 73 | }; | ||
| 78 | 74 | ||
| 79 | /// Gets the GL program resource location for the specified resource, caching as needed | 75 | std::string AllocateBindings(BaseBindings base_bindings); |
| 80 | GLuint GetProgramResourceIndex(const GLShader::GlobalMemoryEntry& global_mem); | ||
| 81 | 76 | ||
| 82 | /// Gets the GL uniform location for the specified resource, caching as needed | 77 | GLuint GetGeometryShader(GLenum primitive_mode, BaseBindings base_bindings); |
| 83 | GLint GetUniformLocation(const GLShader::SamplerEntry& sampler); | ||
| 84 | 78 | ||
| 85 | private: | ||
| 86 | /// Generates a geometry shader or returns one that already exists. | 79 | /// Generates a geometry shader or returns one that already exists. |
| 87 | GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology, | 80 | GLuint LazyGeometryProgram(OGLProgram& target_program, BaseBindings base_bindings, |
| 88 | u32 max_vertices, const std::string& debug_name); | 81 | const std::string& glsl_topology, u32 max_vertices, |
| 82 | const std::string& debug_name); | ||
| 89 | 83 | ||
| 90 | void CalculateProperties(); | 84 | void CalculateProperties(); |
| 91 | 85 | ||
| 92 | VAddr addr; | 86 | VAddr addr{}; |
| 93 | std::size_t shader_length; | 87 | std::size_t shader_length{}; |
| 94 | Maxwell::ShaderProgram program_type; | 88 | Maxwell::ShaderProgram program_type{}; |
| 95 | GLShader::ShaderSetup setup; | 89 | GLShader::ShaderSetup setup; |
| 96 | GLShader::ShaderEntries entries; | 90 | GLShader::ShaderEntries entries; |
| 97 | 91 | ||
| 98 | // Non-geometry program. | 92 | std::string code; |
| 99 | OGLProgram program; | ||
| 100 | 93 | ||
| 101 | // Geometry programs. These are needed because GLSL needs an input topology but it's not | 94 | std::map<BaseBindings, OGLProgram> programs; |
| 102 | // declared by the hardware. Workaround this issue by generating a different shader per input | 95 | std::map<BaseBindings, GeometryPrograms> geometry_programs; |
| 103 | // topology class. | ||
| 104 | struct { | ||
| 105 | std::string code; | ||
| 106 | OGLProgram points; | ||
| 107 | OGLProgram lines; | ||
| 108 | OGLProgram lines_adjacency; | ||
| 109 | OGLProgram triangles; | ||
| 110 | OGLProgram triangles_adjacency; | ||
| 111 | } geometry_programs; | ||
| 112 | 96 | ||
| 113 | std::map<u32, GLuint> cbuf_resource_cache; | 97 | std::map<u32, GLuint> cbuf_resource_cache; |
| 114 | std::map<u32, GLuint> gmem_resource_cache; | 98 | std::map<u32, GLuint> gmem_resource_cache; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index e072216f0..004245431 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -374,7 +374,8 @@ private: | |||
| 374 | void DeclareConstantBuffers() { | 374 | void DeclareConstantBuffers() { |
| 375 | for (const auto& entry : ir.GetConstantBuffers()) { | 375 | for (const auto& entry : ir.GetConstantBuffers()) { |
| 376 | const auto [index, size] = entry; | 376 | const auto [index, size] = entry; |
| 377 | code.AddLine("layout (std140) uniform " + GetConstBufferBlock(index) + " {"); | 377 | code.AddLine("layout (std140, binding = CBUF_BINDING_" + std::to_string(index) + |
| 378 | ") uniform " + GetConstBufferBlock(index) + " {"); | ||
| 378 | code.AddLine(" vec4 " + GetConstBuffer(index) + "[MAX_CONSTBUFFER_ELEMENTS];"); | 379 | code.AddLine(" vec4 " + GetConstBuffer(index) + "[MAX_CONSTBUFFER_ELEMENTS];"); |
| 379 | code.AddLine("};"); | 380 | code.AddLine("};"); |
| 380 | code.AddNewLine(); | 381 | code.AddNewLine(); |
| @@ -383,7 +384,10 @@ private: | |||
| 383 | 384 | ||
| 384 | void DeclareGlobalMemory() { | 385 | void DeclareGlobalMemory() { |
| 385 | for (const auto& entry : ir.GetGlobalMemoryBases()) { | 386 | for (const auto& entry : ir.GetGlobalMemoryBases()) { |
| 386 | code.AddLine("layout (std430) buffer " + GetGlobalMemoryBlock(entry) + " {"); | 387 | const std::string binding = |
| 388 | fmt::format("GMEM_BINDING_{}_{}", entry.cbuf_index, entry.cbuf_offset); | ||
| 389 | code.AddLine("layout (std430, binding = " + binding + ") buffer " + | ||
| 390 | GetGlobalMemoryBlock(entry) + " {"); | ||
| 387 | code.AddLine(" float " + GetGlobalMemory(entry) + "[MAX_GLOBALMEMORY_ELEMENTS];"); | 391 | code.AddLine(" float " + GetGlobalMemory(entry) + "[MAX_GLOBALMEMORY_ELEMENTS];"); |
| 388 | code.AddLine("};"); | 392 | code.AddLine("};"); |
| 389 | code.AddNewLine(); | 393 | code.AddNewLine(); |
| @@ -413,7 +417,8 @@ private: | |||
| 413 | if (sampler.IsShadow()) | 417 | if (sampler.IsShadow()) |
| 414 | sampler_type += "Shadow"; | 418 | sampler_type += "Shadow"; |
| 415 | 419 | ||
| 416 | code.AddLine("uniform " + sampler_type + ' ' + GetSampler(sampler) + ';'); | 420 | code.AddLine("layout (binding = SAMPLER_BINDING_" + std::to_string(sampler.GetIndex()) + |
| 421 | ") uniform " + sampler_type + ' ' + GetSampler(sampler) + ';'); | ||
| 417 | } | 422 | } |
| 418 | if (!samplers.empty()) | 423 | if (!samplers.empty()) |
| 419 | code.AddNewLine(); | 424 | code.AddNewLine(); |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h index e47bc3729..0856a1361 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.h +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h | |||
| @@ -38,10 +38,6 @@ public: | |||
| 38 | return index; | 38 | return index; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | u32 GetHash() const { | ||
| 42 | return (static_cast<u32>(stage) << 16) | index; | ||
| 43 | } | ||
| 44 | |||
| 45 | private: | 41 | private: |
| 46 | std::string name; | 42 | std::string name; |
| 47 | Maxwell::ShaderStage stage{}; | 43 | Maxwell::ShaderStage stage{}; |
| @@ -62,10 +58,6 @@ public: | |||
| 62 | return stage; | 58 | return stage; |
| 63 | } | 59 | } |
| 64 | 60 | ||
| 65 | u32 GetHash() const { | ||
| 66 | return (static_cast<u32>(stage) << 16) | static_cast<u32>(GetIndex()); | ||
| 67 | } | ||
| 68 | |||
| 69 | private: | 61 | private: |
| 70 | std::string name; | 62 | std::string name; |
| 71 | Maxwell::ShaderStage stage{}; | 63 | Maxwell::ShaderStage stage{}; |
| @@ -93,10 +85,6 @@ public: | |||
| 93 | return stage; | 85 | return stage; |
| 94 | } | 86 | } |
| 95 | 87 | ||
| 96 | u32 GetHash() const { | ||
| 97 | return (static_cast<u32>(stage) << 24) | (cbuf_index << 16) | cbuf_offset; | ||
| 98 | } | ||
| 99 | |||
| 100 | private: | 88 | private: |
| 101 | u32 cbuf_index{}; | 89 | u32 cbuf_index{}; |
| 102 | u32 cbuf_offset{}; | 90 | u32 cbuf_offset{}; |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 446d1a93f..04e1db911 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -20,15 +20,14 @@ static constexpr u32 PROGRAM_OFFSET{10}; | |||
| 20 | ProgramResult GenerateVertexShader(const ShaderSetup& setup) { | 20 | ProgramResult GenerateVertexShader(const ShaderSetup& setup) { |
| 21 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 21 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 22 | 22 | ||
| 23 | std::string out = "#version 430 core\n"; | 23 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; |
| 24 | out += "#extension GL_ARB_separate_shader_objects : enable\n\n"; | ||
| 25 | out += "// Shader Unique Id: VS" + id + "\n\n"; | 24 | out += "// Shader Unique Id: VS" + id + "\n\n"; |
| 26 | out += GetCommonDeclarations(); | 25 | out += GetCommonDeclarations(); |
| 27 | 26 | ||
| 28 | out += R"( | 27 | out += R"( |
| 29 | layout (location = 0) out vec4 position; | 28 | layout (location = 0) out vec4 position; |
| 30 | 29 | ||
| 31 | layout(std140) uniform vs_config { | 30 | layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { |
| 32 | vec4 viewport_flip; | 31 | vec4 viewport_flip; |
| 33 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding | 32 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding |
| 34 | uvec4 alpha_test; | 33 | uvec4 alpha_test; |
| @@ -78,7 +77,6 @@ void main() { | |||
| 78 | } | 77 | } |
| 79 | 78 | ||
| 80 | ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { | 79 | ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { |
| 81 | // Version is intentionally skipped in shader generation, it's added by the lazy compilation. | ||
| 82 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 80 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 83 | 81 | ||
| 84 | 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"; |
| @@ -89,7 +87,7 @@ ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { | |||
| 89 | layout (location = 0) in vec4 gs_position[]; | 87 | layout (location = 0) in vec4 gs_position[]; |
| 90 | layout (location = 0) out vec4 position; | 88 | layout (location = 0) out vec4 position; |
| 91 | 89 | ||
| 92 | layout (std140) uniform gs_config { | 90 | layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config { |
| 93 | vec4 viewport_flip; | 91 | vec4 viewport_flip; |
| 94 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding | 92 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding |
| 95 | uvec4 alpha_test; | 93 | uvec4 alpha_test; |
| @@ -112,8 +110,7 @@ void main() { | |||
| 112 | ProgramResult GenerateFragmentShader(const ShaderSetup& setup) { | 110 | ProgramResult GenerateFragmentShader(const ShaderSetup& setup) { |
| 113 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); | 111 | const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); |
| 114 | 112 | ||
| 115 | std::string out = "#version 430 core\n"; | 113 | std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; |
| 116 | out += "#extension GL_ARB_separate_shader_objects : enable\n\n"; | ||
| 117 | out += "// Shader Unique Id: FS" + id + "\n\n"; | 114 | out += "// Shader Unique Id: FS" + id + "\n\n"; |
| 118 | out += GetCommonDeclarations(); | 115 | out += GetCommonDeclarations(); |
| 119 | 116 | ||
| @@ -129,7 +126,7 @@ layout (location = 7) out vec4 FragColor7; | |||
| 129 | 126 | ||
| 130 | layout (location = 0) in vec4 position; | 127 | layout (location = 0) in vec4 position; |
| 131 | 128 | ||
| 132 | layout (std140) uniform fs_config { | 129 | layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config { |
| 133 | vec4 viewport_flip; | 130 | vec4 viewport_flip; |
| 134 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding | 131 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding |
| 135 | uvec4 alpha_test; | 132 | uvec4 alpha_test; |