mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	gl_rasterizer: use texture buffer for proctex LUT
This commit is contained in:
		
							parent
							
								
									56d718b2a1
								
							
						
					
					
						commit
						8482933db8
					
				
					 5 changed files with 80 additions and 70 deletions
				
			
		|  | @ -117,48 +117,53 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 
 | ||||
|     // Setup the noise LUT for proctex
 | ||||
|     proctex_noise_lut.Create(); | ||||
|     state.proctex_noise_lut.texture_1d = proctex_noise_lut.handle; | ||||
|     state.proctex_noise_lut.texture_buffer = proctex_noise_lut.handle; | ||||
|     state.Apply(); | ||||
|     proctex_noise_lut_buffer.Create(); | ||||
|     glBindBuffer(GL_TEXTURE_BUFFER, proctex_noise_lut_buffer.handle); | ||||
|     glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW); | ||||
|     glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum()); | ||||
|     glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, 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, proctex_noise_lut_buffer.handle); | ||||
| 
 | ||||
|     // Setup the color map for proctex
 | ||||
|     proctex_color_map.Create(); | ||||
|     state.proctex_color_map.texture_1d = proctex_color_map.handle; | ||||
|     state.proctex_color_map.texture_buffer = proctex_color_map.handle; | ||||
|     state.Apply(); | ||||
|     proctex_color_map_buffer.Create(); | ||||
|     glBindBuffer(GL_TEXTURE_BUFFER, proctex_color_map_buffer.handle); | ||||
|     glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW); | ||||
|     glActiveTexture(TextureUnits::ProcTexColorMap.Enum()); | ||||
|     glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, 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, proctex_color_map_buffer.handle); | ||||
| 
 | ||||
|     // Setup the alpha map for proctex
 | ||||
|     proctex_alpha_map.Create(); | ||||
|     state.proctex_alpha_map.texture_1d = proctex_alpha_map.handle; | ||||
|     state.proctex_alpha_map.texture_buffer = proctex_alpha_map.handle; | ||||
|     state.Apply(); | ||||
|     proctex_alpha_map_buffer.Create(); | ||||
|     glBindBuffer(GL_TEXTURE_BUFFER, proctex_alpha_map_buffer.handle); | ||||
|     glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW); | ||||
|     glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum()); | ||||
|     glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, 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, proctex_alpha_map_buffer.handle); | ||||
| 
 | ||||
|     // Setup the LUT for proctex
 | ||||
|     proctex_lut.Create(); | ||||
|     state.proctex_lut.texture_1d = proctex_lut.handle; | ||||
|     state.proctex_lut.texture_buffer = proctex_lut.handle; | ||||
|     state.Apply(); | ||||
|     proctex_lut_buffer.Create(); | ||||
|     glBindBuffer(GL_TEXTURE_BUFFER, proctex_lut_buffer.handle); | ||||
|     glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 4 * 256, nullptr, GL_DYNAMIC_DRAW); | ||||
|     glActiveTexture(TextureUnits::ProcTexLUT.Enum()); | ||||
|     glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, 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_RGBA32F, proctex_lut_buffer.handle); | ||||
| 
 | ||||
|     // Setup the difference LUT for proctex
 | ||||
|     proctex_diff_lut.Create(); | ||||
|     state.proctex_diff_lut.texture_1d = proctex_diff_lut.handle; | ||||
|     state.proctex_diff_lut.texture_buffer = proctex_diff_lut.handle; | ||||
|     state.Apply(); | ||||
|     proctex_diff_lut_buffer.Create(); | ||||
|     glBindBuffer(GL_TEXTURE_BUFFER, proctex_diff_lut_buffer.handle); | ||||
|     glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 4 * 256, nullptr, GL_DYNAMIC_DRAW); | ||||
|     glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); | ||||
|     glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, 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_RGBA32F, proctex_diff_lut_buffer.handle); | ||||
| 
 | ||||
|     // Sync fixed function OpenGL state
 | ||||
|     SyncCullMode(); | ||||
|  | @ -1387,7 +1392,7 @@ void RasterizerOpenGL::SyncProcTexNoise() { | |||
| 
 | ||||
| // helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap
 | ||||
| static void SyncProcTexValueLUT(const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut, | ||||
|                                 std::array<GLvec2, 128>& lut_data, GLenum texture) { | ||||
|                                 std::array<GLvec2, 128>& lut_data, GLuint buffer) { | ||||
|     std::array<GLvec2, 128> new_data; | ||||
|     std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) { | ||||
|         return GLvec2{entry.ToFloat(), entry.DiffToFloat()}; | ||||
|  | @ -1395,24 +1400,24 @@ static void SyncProcTexValueLUT(const std::array<Pica::State::ProcTex::ValueEntr | |||
| 
 | ||||
|     if (new_data != lut_data) { | ||||
|         lut_data = new_data; | ||||
|         glActiveTexture(texture); | ||||
|         glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 128, GL_RG, GL_FLOAT, lut_data.data()); | ||||
|         glBindBuffer(GL_TEXTURE_BUFFER, buffer); | ||||
|         glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec2), new_data.data()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncProcTexNoiseLUT() { | ||||
|     SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, | ||||
|                         TextureUnits::ProcTexNoiseLUT.Enum()); | ||||
|                         proctex_noise_lut_buffer.handle); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncProcTexColorMap() { | ||||
|     SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data, | ||||
|                         TextureUnits::ProcTexColorMap.Enum()); | ||||
|                         proctex_color_map_buffer.handle); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncProcTexAlphaMap() { | ||||
|     SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, | ||||
|                         TextureUnits::ProcTexAlphaMap.Enum()); | ||||
|                         proctex_alpha_map_buffer.handle); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncProcTexLUT() { | ||||
|  | @ -1427,8 +1432,8 @@ void RasterizerOpenGL::SyncProcTexLUT() { | |||
| 
 | ||||
|     if (new_data != proctex_lut_data) { | ||||
|         proctex_lut_data = new_data; | ||||
|         glActiveTexture(TextureUnits::ProcTexLUT.Enum()); | ||||
|         glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_lut_data.data()); | ||||
|         glBindBuffer(GL_TEXTURE_BUFFER, proctex_lut_buffer.handle); | ||||
|         glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec4), new_data.data()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1444,8 +1449,8 @@ void RasterizerOpenGL::SyncProcTexDiffLUT() { | |||
| 
 | ||||
|     if (new_data != proctex_diff_lut_data) { | ||||
|         proctex_diff_lut_data = new_data; | ||||
|         glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); | ||||
|         glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_diff_lut_data.data()); | ||||
|         glBindBuffer(GL_TEXTURE_BUFFER, proctex_diff_lut_buffer.handle); | ||||
|         glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec4), new_data.data()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -287,18 +287,23 @@ private: | |||
|     OGLTexture fog_lut; | ||||
|     std::array<GLvec2, 128> fog_lut_data{}; | ||||
| 
 | ||||
|     OGLBuffer proctex_noise_lut_buffer; | ||||
|     OGLTexture proctex_noise_lut; | ||||
|     std::array<GLvec2, 128> proctex_noise_lut_data{}; | ||||
| 
 | ||||
|     OGLBuffer proctex_color_map_buffer; | ||||
|     OGLTexture proctex_color_map; | ||||
|     std::array<GLvec2, 128> proctex_color_map_data{}; | ||||
| 
 | ||||
|     OGLBuffer proctex_alpha_map_buffer; | ||||
|     OGLTexture proctex_alpha_map; | ||||
|     std::array<GLvec2, 128> proctex_alpha_map_data{}; | ||||
| 
 | ||||
|     OGLBuffer proctex_lut_buffer; | ||||
|     OGLTexture proctex_lut; | ||||
|     std::array<GLvec4, 256> proctex_lut_data{}; | ||||
| 
 | ||||
|     OGLBuffer proctex_diff_lut_buffer; | ||||
|     OGLTexture proctex_diff_lut; | ||||
|     std::array<GLvec4, 256> proctex_diff_lut_data{}; | ||||
| }; | ||||
|  |  | |||
|  | @ -886,12 +886,12 @@ void AppendProcTexSampler(std::string& out, const PicaShaderConfig& config) { | |||
|     // coord=1.0 is lut[127]+lut_diff[127]. For other indices, the result is interpolated using
 | ||||
|     // value entries and difference entries.
 | ||||
|     out += R"( | ||||
| float ProcTexLookupLUT(sampler1D lut, float coord) { | ||||
| float ProcTexLookupLUT(samplerBuffer lut, float coord) { | ||||
|     coord *= 128; | ||||
|     float index_i = clamp(floor(coord), 0.0, 127.0); | ||||
|     float index_f = coord - index_i; // fract() cannot be used here because 128.0 needs to be
 | ||||
|                                      // extracted as index_i = 127.0 and index_f = 1.0
 | ||||
|     vec2 entry = texelFetch(lut, int(index_i), 0).rg; | ||||
|     vec2 entry = texelFetch(lut, int(index_i)).rg; | ||||
|     return clamp(entry.r + entry.g * index_f, 0.0, 1.0); | ||||
| } | ||||
|     )"; | ||||
|  | @ -979,14 +979,14 @@ float ProcTexNoiseCoef(vec2 x) { | |||
|         out += "int lut_index_i = int(lut_coord) + " + | ||||
|                std::to_string(config.state.proctex.lut_offset) + ";\n"; | ||||
|         out += "float lut_index_f = fract(lut_coord);\n"; | ||||
|         out += "vec4 final_color = texelFetch(proctex_lut, lut_index_i, 0) + lut_index_f * " | ||||
|                "texelFetch(proctex_diff_lut, lut_index_i, 0);\n"; | ||||
|         out += "vec4 final_color = texelFetch(proctex_lut, lut_index_i) + lut_index_f * " | ||||
|                "texelFetch(proctex_diff_lut, lut_index_i);\n"; | ||||
|         break; | ||||
|     case ProcTexFilter::Nearest: | ||||
|     case ProcTexFilter::NearestMipmapLinear: | ||||
|     case ProcTexFilter::NearestMipmapNearest: | ||||
|         out += "lut_coord += " + std::to_string(config.state.proctex.lut_offset) + ";\n"; | ||||
|         out += "vec4 final_color = texelFetch(proctex_lut, int(round(lut_coord)), 0);\n"; | ||||
|         out += "vec4 final_color = texelFetch(proctex_lut, int(round(lut_coord)));\n"; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1053,11 +1053,11 @@ layout (std140) uniform shader_data { | |||
| uniform sampler2D tex[3]; | ||||
| uniform samplerBuffer lighting_lut; | ||||
| uniform samplerBuffer fog_lut; | ||||
| uniform sampler1D proctex_noise_lut; | ||||
| uniform sampler1D proctex_color_map; | ||||
| uniform sampler1D proctex_alpha_map; | ||||
| uniform sampler1D proctex_lut; | ||||
| uniform sampler1D proctex_diff_lut; | ||||
| uniform samplerBuffer proctex_noise_lut; | ||||
| uniform samplerBuffer proctex_color_map; | ||||
| uniform samplerBuffer proctex_alpha_map; | ||||
| uniform samplerBuffer proctex_lut; | ||||
| uniform samplerBuffer proctex_diff_lut; | ||||
| 
 | ||||
| // Rotate the vector v by the quaternion q
 | ||||
| vec3 quaternion_rotate(vec4 q, vec3 v) { | ||||
|  |  | |||
|  | @ -56,11 +56,11 @@ OpenGLState::OpenGLState() { | |||
| 
 | ||||
|     fog_lut.texture_buffer = 0; | ||||
| 
 | ||||
|     proctex_lut.texture_1d = 0; | ||||
|     proctex_diff_lut.texture_1d = 0; | ||||
|     proctex_color_map.texture_1d = 0; | ||||
|     proctex_alpha_map.texture_1d = 0; | ||||
|     proctex_noise_lut.texture_1d = 0; | ||||
|     proctex_lut.texture_buffer = 0; | ||||
|     proctex_diff_lut.texture_buffer = 0; | ||||
|     proctex_color_map.texture_buffer = 0; | ||||
|     proctex_alpha_map.texture_buffer = 0; | ||||
|     proctex_noise_lut.texture_buffer = 0; | ||||
| 
 | ||||
|     draw.read_framebuffer = 0; | ||||
|     draw.draw_framebuffer = 0; | ||||
|  | @ -204,33 +204,33 @@ void OpenGLState::Apply() const { | |||
|     } | ||||
| 
 | ||||
|     // ProcTex Noise LUT
 | ||||
|     if (proctex_noise_lut.texture_1d != cur_state.proctex_noise_lut.texture_1d) { | ||||
|     if (proctex_noise_lut.texture_buffer != cur_state.proctex_noise_lut.texture_buffer) { | ||||
|         glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum()); | ||||
|         glBindTexture(GL_TEXTURE_1D, proctex_noise_lut.texture_1d); | ||||
|         glBindTexture(GL_TEXTURE_BUFFER, proctex_noise_lut.texture_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // ProcTex Color Map
 | ||||
|     if (proctex_color_map.texture_1d != cur_state.proctex_color_map.texture_1d) { | ||||
|     if (proctex_color_map.texture_buffer != cur_state.proctex_color_map.texture_buffer) { | ||||
|         glActiveTexture(TextureUnits::ProcTexColorMap.Enum()); | ||||
|         glBindTexture(GL_TEXTURE_1D, proctex_color_map.texture_1d); | ||||
|         glBindTexture(GL_TEXTURE_BUFFER, proctex_color_map.texture_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // ProcTex Alpha Map
 | ||||
|     if (proctex_alpha_map.texture_1d != cur_state.proctex_alpha_map.texture_1d) { | ||||
|     if (proctex_alpha_map.texture_buffer != cur_state.proctex_alpha_map.texture_buffer) { | ||||
|         glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum()); | ||||
|         glBindTexture(GL_TEXTURE_1D, proctex_alpha_map.texture_1d); | ||||
|         glBindTexture(GL_TEXTURE_BUFFER, proctex_alpha_map.texture_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // ProcTex LUT
 | ||||
|     if (proctex_lut.texture_1d != cur_state.proctex_lut.texture_1d) { | ||||
|     if (proctex_lut.texture_buffer != cur_state.proctex_lut.texture_buffer) { | ||||
|         glActiveTexture(TextureUnits::ProcTexLUT.Enum()); | ||||
|         glBindTexture(GL_TEXTURE_1D, proctex_lut.texture_1d); | ||||
|         glBindTexture(GL_TEXTURE_BUFFER, proctex_lut.texture_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // ProcTex Diff LUT
 | ||||
|     if (proctex_diff_lut.texture_1d != cur_state.proctex_diff_lut.texture_1d) { | ||||
|     if (proctex_diff_lut.texture_buffer != cur_state.proctex_diff_lut.texture_buffer) { | ||||
|         glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); | ||||
|         glBindTexture(GL_TEXTURE_1D, proctex_diff_lut.texture_1d); | ||||
|         glBindTexture(GL_TEXTURE_BUFFER, proctex_diff_lut.texture_buffer); | ||||
|     } | ||||
| 
 | ||||
|     // Framebuffer
 | ||||
|  | @ -274,16 +274,16 @@ void OpenGLState::ResetTexture(GLuint handle) { | |||
|         cur_state.lighting_lut.texture_buffer = 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) | ||||
|         cur_state.proctex_color_map.texture_1d = 0; | ||||
|     if (cur_state.proctex_alpha_map.texture_1d == handle) | ||||
|         cur_state.proctex_alpha_map.texture_1d = 0; | ||||
|     if (cur_state.proctex_lut.texture_1d == handle) | ||||
|         cur_state.proctex_lut.texture_1d = 0; | ||||
|     if (cur_state.proctex_diff_lut.texture_1d == handle) | ||||
|         cur_state.proctex_diff_lut.texture_1d = 0; | ||||
|     if (cur_state.proctex_noise_lut.texture_buffer == handle) | ||||
|         cur_state.proctex_noise_lut.texture_buffer = 0; | ||||
|     if (cur_state.proctex_color_map.texture_buffer == handle) | ||||
|         cur_state.proctex_color_map.texture_buffer = 0; | ||||
|     if (cur_state.proctex_alpha_map.texture_buffer == handle) | ||||
|         cur_state.proctex_alpha_map.texture_buffer = 0; | ||||
|     if (cur_state.proctex_lut.texture_buffer == handle) | ||||
|         cur_state.proctex_lut.texture_buffer = 0; | ||||
|     if (cur_state.proctex_diff_lut.texture_buffer == handle) | ||||
|         cur_state.proctex_diff_lut.texture_buffer = 0; | ||||
| } | ||||
| 
 | ||||
| void OpenGLState::ResetSampler(GLuint handle) { | ||||
|  |  | |||
|  | @ -95,23 +95,23 @@ public: | |||
|     } fog_lut; | ||||
| 
 | ||||
|     struct { | ||||
|         GLuint texture_1d; // GL_TEXTURE_BINDING_1D
 | ||||
|         GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
 | ||||
|     } proctex_noise_lut; | ||||
| 
 | ||||
|     struct { | ||||
|         GLuint texture_1d; // GL_TEXTURE_BINDING_1D
 | ||||
|         GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
 | ||||
|     } proctex_color_map; | ||||
| 
 | ||||
|     struct { | ||||
|         GLuint texture_1d; // GL_TEXTURE_BINDING_1D
 | ||||
|         GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
 | ||||
|     } proctex_alpha_map; | ||||
| 
 | ||||
|     struct { | ||||
|         GLuint texture_1d; // GL_TEXTURE_BINDING_1D
 | ||||
|         GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
 | ||||
|     } proctex_lut; | ||||
| 
 | ||||
|     struct { | ||||
|         GLuint texture_1d; // GL_TEXTURE_BINDING_1D
 | ||||
|         GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
 | ||||
|     } proctex_diff_lut; | ||||
| 
 | ||||
|     struct { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue