Ver Fonte

renderer_opengl: Implement HW fragment lighting LUTs within our default UBO.

bunnei há 10 anos atrás
pai
commit
e9af70eaf3

+ 1 - 1
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;
     } lighting;
 
 
     /// Current Pica command list
     /// Current Pica command list

+ 52 - 13
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -162,6 +162,13 @@ void RasterizerOpenGL::DrawTriangles() {
         state.draw.shader_dirty = false;
         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) {
     if (uniform_block_data.dirty) {
         glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW);
         glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW);
         uniform_block_data.dirty = false;
         uniform_block_data.dirty = false;
@@ -381,6 +388,21 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
         SyncGlobalAmbient();
         SyncGlobalAmbient();
         break;
         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");
         unsigned int block_index = glGetUniformBlockIndex(current_shader->shader.handle, "shader_data");
         glUniformBlockBinding(current_shader->shader.handle, block_index, 0);
         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) {
 void RasterizerOpenGL::SyncLightDiffuse(int light_index) {
     auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
     auto color = PicaToGL::LightColor(Pica::g_state.regs.lighting.light[light_index].diffuse);
     if (color != uniform_block_data.data.light_src[light_index].diffuse) {
     if (color != uniform_block_data.data.light_src[light_index].diffuse) {

+ 7 - 2
src/video_core/renderer_opengl/gl_rasterizer.h

@@ -242,10 +242,11 @@ private:
         std::array<GLfloat, 3> lighting_global_ambient;
         std::array<GLfloat, 3> lighting_global_ambient;
         INSERT_PADDING_WORDS(1);
         INSERT_PADDING_WORDS(1);
         LightSrc light_src[8];
         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
     /// Reconfigure the OpenGL color texture to use the given format and dimensions
     void ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height);
     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
     /// Syncs the lighting global ambient color to match the PICA register
     void SyncGlobalAmbient();
     void SyncGlobalAmbient();
 
 
+    /// Syncs the lighting lookup tables
+    void SyncLightingLUT(unsigned index);
+
     /// Syncs the specified light's diffuse color to match the PICA register
     /// Syncs the specified light's diffuse color to match the PICA register
     void SyncLightDiffuse(int light_index);
     void SyncLightDiffuse(int light_index);
 
 
@@ -346,6 +350,7 @@ private:
 
 
     struct {
     struct {
         UniformData data;
         UniformData data;
+        bool lut_dirty[24];
         bool dirty;
         bool dirty;
     } uniform_block_data;
     } uniform_block_data;
 
 

+ 7 - 0
src/video_core/renderer_opengl/gl_shader_gen.cpp

@@ -324,6 +324,7 @@ std::string GenerateFragmentShader(const PicaShaderConfig& config) {
 #version 330 core
 #version 330 core
 #define NUM_TEV_STAGES 6
 #define NUM_TEV_STAGES 6
 #define NUM_LIGHTS 8
 #define NUM_LIGHTS 8
+#define LIGHTING_LUT_SIZE 256
 
 
 in vec4 primary_color;
 in vec4 primary_color;
 in vec2 texcoord[3];
 in vec2 texcoord[3];
@@ -345,6 +346,12 @@ layout (std140) uniform shader_data {
     float depth_offset;
     float depth_offset;
     vec3 lighting_global_ambient;
     vec3 lighting_global_ambient;
     LightSrc light_src[NUM_LIGHTS];
     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];
 uniform sampler2D tex[3];