diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4097d0cee..61d7ee960 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -52,7 +52,8 @@ RasterizerOpenGL::RasterizerOpenGL() : is_amd(IsVendorAmd()), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd), uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE, false), index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE, false), - texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false) { + texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false), + texture_lf_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false) { allow_shadow = GLAD_GL_ARB_shader_image_load_store && GLAD_GL_ARB_shader_image_size && GLAD_GL_ARB_framebuffer_no_attachments; @@ -149,11 +150,15 @@ RasterizerOpenGL::RasterizerOpenGL() framebuffer.Create(); // Allocate and bind texture buffer lut textures + texture_buffer_lut_lf.Create(); texture_buffer_lut_rg.Create(); texture_buffer_lut_rgba.Create(); + state.texture_buffer_lut_lf.texture_buffer = texture_buffer_lut_lf.handle; state.texture_buffer_lut_rg.texture_buffer = texture_buffer_lut_rg.handle; state.texture_buffer_lut_rgba.texture_buffer = texture_buffer_lut_rgba.handle; state.Apply(); + glActiveTexture(TextureUnits::TextureBufferLUT_LF.Enum()); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, texture_lf_buffer.GetHandle()); glActiveTexture(TextureUnits::TextureBufferLUT_RG.Enum()); glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, texture_buffer.GetHandle()); glActiveTexture(TextureUnits::TextureBufferLUT_RGBA.Enum()); @@ -821,6 +826,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) { // Sync the LUTs within the texture buffer SyncAndUploadLUTs(); + SyncAndUploadLUTsLF(); // Sync the uniform data UploadUniforms(accelerate); @@ -2005,18 +2011,11 @@ void RasterizerOpenGL::SyncShadowTextureBias() { } } -void RasterizerOpenGL::SyncAndUploadLUTs() { - constexpr std::size_t max_size = sizeof(GLvec2) * 256 * Pica::LightingRegs::NumLightingSampler + - sizeof(GLvec2) * 128 + // fog - sizeof(GLvec2) * 128 * 3 + // proctex: noise + color + alpha - sizeof(GLvec4) * 256 + // proctex - sizeof(GLvec4) * 256; // proctex diff +void RasterizerOpenGL::SyncAndUploadLUTsLF() { + constexpr std::size_t max_size = + sizeof(GLvec2) * 256 * Pica::LightingRegs::NumLightingSampler + sizeof(GLvec2) * 128; // fog - if (!uniform_block_data.lighting_lut_dirty_any && !uniform_block_data.fog_lut_dirty && - !uniform_block_data.proctex_noise_lut_dirty && - !uniform_block_data.proctex_color_map_dirty && - !uniform_block_data.proctex_alpha_map_dirty && !uniform_block_data.proctex_lut_dirty && - !uniform_block_data.proctex_diff_lut_dirty) { + if (!uniform_block_data.lighting_lut_dirty_any && !uniform_block_data.fog_lut_dirty) { return; } @@ -2024,8 +2023,8 @@ void RasterizerOpenGL::SyncAndUploadLUTs() { GLintptr offset; bool invalidate; std::size_t bytes_used = 0; - glBindBuffer(GL_TEXTURE_BUFFER, texture_buffer.GetHandle()); - std::tie(buffer, offset, invalidate) = texture_buffer.Map(max_size, sizeof(GLvec4)); + glBindBuffer(GL_TEXTURE_BUFFER, texture_lf_buffer.GetHandle()); + std::tie(buffer, offset, invalidate) = texture_lf_buffer.Map(max_size, sizeof(GLvec4)); // Sync the lighting luts if (uniform_block_data.lighting_lut_dirty_any || invalidate) { @@ -2050,8 +2049,8 @@ void RasterizerOpenGL::SyncAndUploadLUTs() { uniform_block_data.lighting_lut_dirty[index] = false; } } + uniform_block_data.lighting_lut_dirty_any = false; } - uniform_block_data.lighting_lut_dirty_any = false; // Sync the fog lut if (uniform_block_data.fog_lut_dirty || invalidate) { @@ -2073,6 +2072,28 @@ void RasterizerOpenGL::SyncAndUploadLUTs() { uniform_block_data.fog_lut_dirty = false; } + texture_lf_buffer.Unmap(bytes_used); +} + +void RasterizerOpenGL::SyncAndUploadLUTs() { + constexpr std::size_t max_size = sizeof(GLvec2) * 128 * 3 + // proctex: noise + color + alpha + sizeof(GLvec4) * 256 + // proctex + sizeof(GLvec4) * 256; // proctex diff + + if (!uniform_block_data.proctex_noise_lut_dirty && + !uniform_block_data.proctex_color_map_dirty && + !uniform_block_data.proctex_alpha_map_dirty && !uniform_block_data.proctex_lut_dirty && + !uniform_block_data.proctex_diff_lut_dirty) { + return; + } + + u8* buffer; + GLintptr offset; + bool invalidate; + std::size_t bytes_used = 0; + glBindBuffer(GL_TEXTURE_BUFFER, texture_buffer.GetHandle()); + std::tie(buffer, offset, invalidate) = texture_buffer.Map(max_size, sizeof(GLvec4)); + // helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap auto SyncProcTexValueLUT = [this, buffer, offset, invalidate, &bytes_used]( const std::array& lut, diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index a28e9bda1..4748655d5 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -233,6 +233,7 @@ private: /// Syncs and uploads the lighting, fog and proctex LUTs void SyncAndUploadLUTs(); + void SyncAndUploadLUTsLF(); /// Upload the uniform blocks to the uniform buffer object void UploadUniforms(bool accelerate_draw); @@ -303,6 +304,7 @@ private: OGLStreamBuffer uniform_buffer; OGLStreamBuffer index_buffer; OGLStreamBuffer texture_buffer; + OGLStreamBuffer texture_lf_buffer; OGLFramebuffer framebuffer; GLint uniform_buffer_alignment; std::size_t uniform_size_aligned_vs; @@ -310,6 +312,7 @@ private: SamplerInfo texture_cube_sampler; + OGLTexture texture_buffer_lut_lf; OGLTexture texture_buffer_lut_rg; OGLTexture texture_buffer_lut_rgba; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index ee4cea9f2..d8be747f2 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -1244,6 +1244,7 @@ uniform sampler2D tex0; uniform sampler2D tex1; uniform sampler2D tex2; uniform samplerCube tex_cube; +uniform samplerBuffer texture_buffer_lut_lf; uniform samplerBuffer texture_buffer_lut_rg; uniform samplerBuffer texture_buffer_lut_rgba; @@ -1267,7 +1268,7 @@ vec3 quaternion_rotate(vec4 q, vec3 v) { } float LookupLightingLUT(int lut_index, int index, float delta) { - vec2 entry = texelFetch(texture_buffer_lut_rg, lighting_lut_offset[lut_index >> 2][lut_index & 3] + index).rg; + vec2 entry = texelFetch(texture_buffer_lut_lf, lighting_lut_offset[lut_index >> 2][lut_index & 3] + index).rg; return entry.r + entry.g * delta; } @@ -1519,7 +1520,7 @@ vec4 secondary_fragment_color = vec4(0.0); // Generate clamped fog factor from LUT for given fog index out += "float fog_i = clamp(floor(fog_index), 0.0, 127.0);\n" "float fog_f = fog_index - fog_i;\n" - "vec2 fog_lut_entry = texelFetch(texture_buffer_lut_rg, int(fog_i) + " + "vec2 fog_lut_entry = texelFetch(texture_buffer_lut_lf, int(fog_i) + " "fog_lut_offset).rg;\n" "float fog_factor = fog_lut_entry.r + fog_lut_entry.g * fog_f;\n" "fog_factor = clamp(fog_factor, 0.0, 1.0);\n"; diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 8a878b65a..17889f2e5 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -123,6 +123,7 @@ static void SetShaderSamplerBindings(GLuint shader) { SetShaderSamplerBinding(shader, "tex_cube", TextureUnits::TextureCube); // Set the texture samplers to correspond to different lookup table texture units + SetShaderSamplerBinding(shader, "texture_buffer_lut_lf", TextureUnits::TextureBufferLUT_LF); SetShaderSamplerBinding(shader, "texture_buffer_lut_rg", TextureUnits::TextureBufferLUT_RG); SetShaderSamplerBinding(shader, "texture_buffer_lut_rgba", TextureUnits::TextureBufferLUT_RGBA); diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 95ab8525a..364280a08 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -58,6 +58,7 @@ OpenGLState::OpenGLState() { texture_cube_unit.texture_cube = 0; texture_cube_unit.sampler = 0; + texture_buffer_lut_lf.texture_buffer = 0; texture_buffer_lut_rg.texture_buffer = 0; texture_buffer_lut_rgba.texture_buffer = 0; @@ -224,6 +225,12 @@ void OpenGLState::Apply() const { glBindSampler(TextureUnits::TextureCube.id, texture_cube_unit.sampler); } + // Texture buffer LUTs + if (texture_buffer_lut_lf.texture_buffer != cur_state.texture_buffer_lut_lf.texture_buffer) { + glActiveTexture(TextureUnits::TextureBufferLUT_LF.Enum()); + glBindTexture(GL_TEXTURE_BUFFER, texture_buffer_lut_lf.texture_buffer); + } + // Texture buffer LUTs if (texture_buffer_lut_rg.texture_buffer != cur_state.texture_buffer_lut_rg.texture_buffer) { glActiveTexture(TextureUnits::TextureBufferLUT_RG.Enum()); @@ -354,6 +361,8 @@ OpenGLState& OpenGLState::ResetTexture(GLuint handle) { } if (texture_cube_unit.texture_cube == handle) texture_cube_unit.texture_cube = 0; + if (texture_buffer_lut_lf.texture_buffer == handle) + texture_buffer_lut_lf.texture_buffer = 0; if (texture_buffer_lut_rg.texture_buffer == handle) texture_buffer_lut_rg.texture_buffer = 0; if (texture_buffer_lut_rgba.texture_buffer == handle) diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 3fa585b04..e3b85a297 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -22,7 +22,8 @@ constexpr TextureUnit PicaTexture(int unit) { return TextureUnit{unit}; } -constexpr TextureUnit TextureCube{3}; +constexpr TextureUnit TextureCube{6}; +constexpr TextureUnit TextureBufferLUT_LF{3}; constexpr TextureUnit TextureBufferLUT_RG{4}; constexpr TextureUnit TextureBufferLUT_RGBA{5}; @@ -101,6 +102,10 @@ public: GLuint sampler; // GL_SAMPLER_BINDING } texture_cube_unit; + struct { + GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER + } texture_buffer_lut_lf; + struct { GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER } texture_buffer_lut_rg;