Просмотр исходного кода

gl_rasterizer: use texture buffer for fog LUT

wwylele 9 лет назад
Родитель
Сommit
8978ecb09c

+ 8 - 0
src/video_core/pica_state.h

@@ -111,6 +111,14 @@ struct State {
 
             BitField<0, 13, s32> difference; // 1.1.11 fixed point
             BitField<13, 11, u32> value;     // 0.0.11 fixed point
+
+            float ToFloat() const {
+                return static_cast<float>(value) / 2047.0f;
+            }
+
+            float DiffToFloat() const {
+                return static_cast<float>(difference) / 2047.0f;
+            }
         };
 
         std::array<LutEntry, 128> lut;

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

@@ -106,16 +106,14 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
     glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, lighting_lut_buffer.handle);
 
     // Setup the LUT for the fog
-    {
-        fog_lut.Create();
-        state.fog_lut.texture_1d = fog_lut.handle;
-    }
+    fog_lut.Create();
+    state.fog_lut.texture_buffer = fog_lut.handle;
     state.Apply();
-
+    fog_lut_buffer.Create();
+    glBindBuffer(GL_TEXTURE_BUFFER, fog_lut_buffer.handle);
+    glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW);
     glActiveTexture(TextureUnits::FogLUT.Enum());
-    glTexImage1D(GL_TEXTURE_1D, 0, GL_R32UI, 128, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr);
-    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, fog_lut_buffer.handle);
 
     // Setup the noise LUT for proctex
     proctex_noise_lut.Create();
@@ -1356,16 +1354,17 @@ void RasterizerOpenGL::SyncFogColor() {
 }
 
 void RasterizerOpenGL::SyncFogLUT() {
-    std::array<GLuint, 128> new_data;
+    std::array<GLvec2, 128> new_data;
 
     std::transform(Pica::g_state.fog.lut.begin(), Pica::g_state.fog.lut.end(), new_data.begin(),
-                   [](const auto& entry) { return entry.raw; });
+                   [](const auto& entry) {
+                       return GLvec2{entry.ToFloat(), entry.DiffToFloat()};
+                   });
 
     if (new_data != fog_lut_data) {
         fog_lut_data = new_data;
-        glActiveTexture(TextureUnits::FogLUT.Enum());
-        glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 128, GL_RED_INTEGER, GL_UNSIGNED_INT,
-                        fog_lut_data.data());
+        glBindBuffer(GL_TEXTURE_BUFFER, fog_lut_buffer.handle);
+        glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec2), new_data.data());
     }
 }
 

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

@@ -283,8 +283,9 @@ private:
     OGLTexture lighting_lut;
     std::array<std::array<GLvec2, 256>, Pica::LightingRegs::NumLightingSampler> lighting_lut_data{};
 
+    OGLBuffer fog_lut_buffer;
     OGLTexture fog_lut;
-    std::array<GLuint, 128> fog_lut_data{};
+    std::array<GLvec2, 128> fog_lut_data{};
 
     OGLTexture proctex_noise_lut;
     std::array<GLvec2, 128> proctex_noise_lut_data{};

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

@@ -1052,7 +1052,7 @@ layout (std140) uniform shader_data {
 
 uniform sampler2D tex[3];
 uniform samplerBuffer lighting_lut;
-uniform usampler1D fog_lut;
+uniform samplerBuffer fog_lut;
 uniform sampler1D proctex_noise_lut;
 uniform sampler1D proctex_color_map;
 uniform sampler1D proctex_alpha_map;
@@ -1145,12 +1145,8 @@ 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";
         out += "float fog_f = fog_index - fog_i;\n";
-        out += "uint fog_lut_entry = texelFetch(fog_lut, int(fog_i), 0).r;\n";
-        out += "float fog_lut_entry_difference = float(int((fog_lut_entry & 0x1FFFU) << 19U) >> "
-               "19);\n"; // Extract signed difference
-        out += "float fog_lut_entry_value = float((fog_lut_entry >> 13U) & 0x7FFU);\n";
-        out += "float fog_factor = (fog_lut_entry_value + fog_lut_entry_difference * fog_f) / "
-               "2047.0;\n";
+        out += "vec2 fog_lut_entry = texelFetch(fog_lut, int(fog_i)).rg;\n";
+        out += "float fog_factor = fog_lut_entry.r + fog_lut_entry.g * fog_f;\n";
         out += "fog_factor = clamp(fog_factor, 0.0, 1.0);\n";
 
         // Blend the fog

+ 5 - 5
src/video_core/renderer_opengl/gl_state.cpp

@@ -54,7 +54,7 @@ OpenGLState::OpenGLState() {
 
     lighting_lut.texture_buffer = 0;
 
-    fog_lut.texture_1d = 0;
+    fog_lut.texture_buffer = 0;
 
     proctex_lut.texture_1d = 0;
     proctex_diff_lut.texture_1d = 0;
@@ -198,9 +198,9 @@ void OpenGLState::Apply() const {
     }
 
     // Fog LUT
-    if (fog_lut.texture_1d != cur_state.fog_lut.texture_1d) {
+    if (fog_lut.texture_buffer != cur_state.fog_lut.texture_buffer) {
         glActiveTexture(TextureUnits::FogLUT.Enum());
-        glBindTexture(GL_TEXTURE_1D, fog_lut.texture_1d);
+        glBindTexture(GL_TEXTURE_BUFFER, fog_lut.texture_buffer);
     }
 
     // ProcTex Noise LUT
@@ -272,8 +272,8 @@ void OpenGLState::ResetTexture(GLuint handle) {
     }
     if (cur_state.lighting_lut.texture_buffer == handle)
         cur_state.lighting_lut.texture_buffer = 0;
-    if (cur_state.fog_lut.texture_1d == handle)
-        cur_state.fog_lut.texture_1d = 0;
+    if (cur_state.fog_lut.texture_buffer == handle)
+        cur_state.fog_lut.texture_buffer = 0;
     if (cur_state.proctex_noise_lut.texture_1d == handle)
         cur_state.proctex_noise_lut.texture_1d = 0;
     if (cur_state.proctex_color_map.texture_1d == handle)

+ 1 - 1
src/video_core/renderer_opengl/gl_state.h

@@ -91,7 +91,7 @@ public:
     } lighting_lut;
 
     struct {
-        GLuint texture_1d; // GL_TEXTURE_BINDING_1D
+        GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
     } fog_lut;
 
     struct {

+ 1 - 2
src/video_core/swrasterizer/rasterizer.cpp

@@ -584,8 +584,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
                 float fog_i = MathUtil::Clamp(floorf(fog_index), 0.0f, 127.0f);
                 float fog_f = fog_index - fog_i;
                 const auto& fog_lut_entry = g_state.fog.lut[static_cast<unsigned int>(fog_i)];
-                float fog_factor = (fog_lut_entry.value + fog_lut_entry.difference * fog_f) /
-                                   2047.0f; // This is signed fixed point 1.11
+                float fog_factor = fog_lut_entry.ToFloat() + fog_lut_entry.DiffToFloat() * fog_f;
                 fog_factor = MathUtil::Clamp(fog_factor, 0.0f, 1.0f);
 
                 // Blend the fog