diff options
| -rw-r--r-- | src/video_core/pica.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 65 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 7 | 
4 files changed, 67 insertions, 16 deletions
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index b82ecf68a..aad9effdc 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -1216,7 +1216,7 @@ struct State {              }          }; -        std::array<LutEntry, 256> luts[24]; +        std::array<std::array<LutEntry, 256>, 24> luts;      } lighting;      /// Current Pica command list diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 1e51a7655..80693fa29 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -162,6 +162,13 @@ void RasterizerOpenGL::DrawTriangles() {          state.draw.shader_dirty = false;      } +    for (unsigned index = 0; index < Pica::g_state.lighting.luts.size(); index++) { +        if (uniform_block_data.lut_dirty[index]) { +            SyncLightingLUT(index); +            uniform_block_data.lut_dirty[index] = false; +        } +    } +      if (uniform_block_data.dirty) {          glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW);          uniform_block_data.dirty = false; @@ -381,6 +388,21 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {          SyncGlobalAmbient();          break; +    // Fragment lighting lookup tables +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[0], 0x1c8): +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[1], 0x1c9): +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[2], 0x1ca): +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[3], 0x1cb): +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[4], 0x1cc): +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[5], 0x1cd): +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[6], 0x1ce): +    case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[7], 0x1cf): +    { +        auto& lut_config = regs.lighting.lut_config; +        uniform_block_data.lut_dirty[lut_config.type] = true; +        break; +    } +      }  } @@ -593,20 +615,23 @@ void RasterizerOpenGL::SetShader() {          unsigned int block_index = glGetUniformBlockIndex(current_shader->shader.handle, "shader_data");          glUniformBlockBinding(current_shader->shader.handle, block_index, 0); -    } -    // Update uniforms -    SyncAlphaTest(); -    SyncCombinerColor(); -    auto& tev_stages = Pica::g_state.regs.GetTevStages(); -    for (int index = 0; index < tev_stages.size(); ++index) -        SyncTevConstColor(index, tev_stages[index]); - -    SyncGlobalAmbient(); -    for (int light_index = 0; light_index < 8; light_index++) { -        SyncLightDiffuse(light_index); -        SyncLightAmbient(light_index); -        SyncLightPosition(light_index); +        // Update uniforms +        SyncAlphaTest(); +        SyncCombinerColor(); +        auto& tev_stages = Pica::g_state.regs.GetTevStages(); +        for (int index = 0; index < tev_stages.size(); ++index) +            SyncTevConstColor(index, tev_stages[index]); + +        for (unsigned index = 0; index < Pica::g_state.lighting.luts.size(); ++index) +            SyncLightingLUT(index); + +        SyncGlobalAmbient(); +        for (int light_index = 0; light_index < 8; light_index++) { +            SyncLightDiffuse(light_index); +            SyncLightAmbient(light_index); +            SyncLightPosition(light_index); +        }      }  } @@ -796,6 +821,20 @@ void RasterizerOpenGL::SyncGlobalAmbient() {      }  } +void RasterizerOpenGL::SyncLightingLUT(unsigned lut_index) { +    auto& lut = uniform_block_data.data.lighting_lut[lut_index / 4]; +    std::array<std::array<GLfloat, 4>, 256> new_lut; + +    for (int offset = 0; offset < new_lut.size(); ++offset) { +        new_lut[offset][lut_index & 3] = Pica::g_state.lighting.luts[lut_index][offset].ToFloat(); +    } + +    if (new_lut != lut) { +        lut = new_lut; +        uniform_block_data.dirty = true; +    } +} +  void RasterizerOpenGL::SyncLightDiffuse(int light_index) {      auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);      if (color != uniform_block_data.data.light_src[light_index].diffuse) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 698ca5c4c..fa4a78cb1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -242,10 +242,11 @@ private:          std::array<GLfloat, 3> lighting_global_ambient;          INSERT_PADDING_WORDS(1);          LightSrc light_src[8]; +        std::array<std::array<std::array<GLfloat, 4>, 256>, 6> lighting_lut;      }; -    static_assert(sizeof(UniformData) == 0x210, "The size of the UniformData structure has changed, update the structure in the shader"); -    static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec"); +    static_assert(sizeof(UniformData) == 0x6210, "The size of the UniformData structure has changed, update the structure in the shader"); +    static_assert(sizeof(UniformData) < 32768, "UniformData structure must be less than 32kb");      /// Reconfigure the OpenGL color texture to use the given format and dimensions      void ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height); @@ -295,6 +296,9 @@ private:      /// Syncs the lighting global ambient color to match the PICA register      void SyncGlobalAmbient(); +    /// Syncs the lighting lookup tables +    void SyncLightingLUT(unsigned index); +      /// Syncs the specified light's diffuse color to match the PICA register      void SyncLightDiffuse(int light_index); @@ -346,6 +350,7 @@ private:      struct {          UniformData data; +        bool lut_dirty[24];          bool dirty;      } uniform_block_data; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 5bc588b0b..4e02671dd 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -324,6 +324,7 @@ std::string GenerateFragmentShader(const PicaShaderConfig& config) {  #version 330 core  #define NUM_TEV_STAGES 6  #define NUM_LIGHTS 8 +#define LIGHTING_LUT_SIZE 256  in vec4 primary_color;  in vec2 texcoord[3]; @@ -345,6 +346,12 @@ layout (std140) uniform shader_data {      float depth_offset;      vec3 lighting_global_ambient;      LightSrc light_src[NUM_LIGHTS]; +    vec4 lighting_lut_0[LIGHTING_LUT_SIZE]; +    vec4 lighting_lut_1[LIGHTING_LUT_SIZE]; +    vec4 lighting_lut_2[LIGHTING_LUT_SIZE]; +    vec4 lighting_lut_3[LIGHTING_LUT_SIZE]; +    vec4 lighting_lut_4[LIGHTING_LUT_SIZE]; +    vec4 lighting_lut_5[LIGHTING_LUT_SIZE];  };  uniform sampler2D tex[3];  | 
