mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	gl_rasterizer: implement texture cube
This commit is contained in:
		
							parent
							
								
									33a0e87ac2
								
							
						
					
					
						commit
						15e8664ef7
					
				
					 7 changed files with 134 additions and 2 deletions
				
			
		|  | @ -40,6 +40,12 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
|         state.texture_units[i].sampler = texture_samplers[i].sampler.handle; | ||||
|     } | ||||
| 
 | ||||
|     // Create cubemap texture and sampler objects
 | ||||
|     texture_cube_sampler.Create(); | ||||
|     state.texture_cube_unit.sampler = texture_cube_sampler.sampler.handle; | ||||
|     texture_cube.Create(); | ||||
|     state.texture_cube_unit.texture_cube = texture_cube.handle; | ||||
| 
 | ||||
|     // Generate VBO, VAO and UBO
 | ||||
|     vertex_buffer.Create(); | ||||
|     vertex_array.Create(); | ||||
|  | @ -352,6 +358,25 @@ void RasterizerOpenGL::DrawTriangles() { | |||
|         const auto& texture = pica_textures[texture_index]; | ||||
| 
 | ||||
|         if (texture.enabled) { | ||||
|             if (texture_index == 0) { | ||||
|                 using TextureType = Pica::TexturingRegs::TextureConfig::TextureType; | ||||
|                 switch (texture.config.type.Value()) { | ||||
|                 case TextureType::TextureCube: | ||||
|                     using CubeFace = Pica::TexturingRegs::CubeFace; | ||||
|                     res_cache.FillTextureCube( | ||||
|                         texture_cube.handle, texture, | ||||
|                         regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveX), | ||||
|                         regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeX), | ||||
|                         regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveY), | ||||
|                         regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeY), | ||||
|                         regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveZ), | ||||
|                         regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeZ)); | ||||
|                     texture_cube_sampler.SyncWithConfig(texture.config); | ||||
|                     state.texture_units[texture_index].texture_2d = 0; | ||||
|                     continue; // Texture unit 0 setup finished. Continue to next unit
 | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             texture_samplers[texture_index].SyncWithConfig(texture.config); | ||||
|             Surface surface = res_cache.GetTextureSurface(texture); | ||||
|             if (surface != nullptr) { | ||||
|  | @ -1225,6 +1250,10 @@ void RasterizerOpenGL::SetShader() { | |||
|         if (uniform_tex != -1) { | ||||
|             glUniform1i(uniform_tex, TextureUnits::PicaTexture(2).id); | ||||
|         } | ||||
|         uniform_tex = glGetUniformLocation(shader->shader.handle, "tex_cube"); | ||||
|         if (uniform_tex != -1) { | ||||
|             glUniform1i(uniform_tex, TextureUnits::TextureCube.id); | ||||
|         } | ||||
| 
 | ||||
|         // Set the texture samplers to correspond to different lookup table texture units
 | ||||
|         GLint uniform_lut = glGetUniformLocation(shader->shader.handle, "lighting_lut"); | ||||
|  |  | |||
|  | @ -287,6 +287,10 @@ private: | |||
|     OGLBuffer uniform_buffer; | ||||
|     OGLFramebuffer framebuffer; | ||||
| 
 | ||||
|     // TODO (wwylele): consider caching texture cube in the rasterizer cache
 | ||||
|     OGLTexture texture_cube; | ||||
|     SamplerInfo texture_cube_sampler; | ||||
| 
 | ||||
|     OGLBuffer lighting_lut_buffer; | ||||
|     OGLTexture lighting_lut; | ||||
|     std::array<std::array<GLvec2, 256>, Pica::LightingRegs::NumLightingSampler> lighting_lut_data{}; | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
| #include <atomic> | ||||
| #include <cstring> | ||||
| #include <iterator> | ||||
|  | @ -1192,10 +1193,14 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& | |||
| } | ||||
| 
 | ||||
| Surface RasterizerCacheOpenGL::GetTextureSurface( | ||||
|     const Pica::TexturingRegs::FullTextureConfig& config) { | ||||
|     const Pica::TexturingRegs::FullTextureConfig& config, PAddr addr_override) { | ||||
|     Pica::Texture::TextureInfo info = | ||||
|         Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format); | ||||
| 
 | ||||
|     if (addr_override != 0) { | ||||
|         info.physical_address = addr_override; | ||||
|     } | ||||
| 
 | ||||
|     SurfaceParams params; | ||||
|     params.addr = info.physical_address; | ||||
|     params.width = info.width; | ||||
|  | @ -1223,6 +1228,70 @@ Surface RasterizerCacheOpenGL::GetTextureSurface( | |||
|     return GetSurface(params, ScaleMatch::Ignore, true); | ||||
| } | ||||
| 
 | ||||
| void RasterizerCacheOpenGL::FillTextureCube(GLuint dest_handle, | ||||
|                                             const Pica::TexturingRegs::FullTextureConfig& config, | ||||
|                                             PAddr px, PAddr nx, PAddr py, PAddr ny, PAddr pz, | ||||
|                                             PAddr nz) { | ||||
|     ASSERT(config.config.width == config.config.height); | ||||
|     struct FaceTuple { | ||||
|         PAddr address; | ||||
|         GLenum gl_face; | ||||
|         Surface surface; | ||||
|     }; | ||||
|     std::array<FaceTuple, 6> faces{{ | ||||
|         {px, GL_TEXTURE_CUBE_MAP_POSITIVE_X}, | ||||
|         {nx, GL_TEXTURE_CUBE_MAP_NEGATIVE_X}, | ||||
|         {py, GL_TEXTURE_CUBE_MAP_POSITIVE_Y}, | ||||
|         {ny, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y}, | ||||
|         {pz, GL_TEXTURE_CUBE_MAP_POSITIVE_Z}, | ||||
|         {nz, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}, | ||||
|     }}; | ||||
| 
 | ||||
|     u16 res_scale = 1; | ||||
|     for (auto& face : faces) { | ||||
|         face.surface = GetTextureSurface(config, face.address); | ||||
|         res_scale = std::max(res_scale, face.surface->res_scale); | ||||
|     } | ||||
| 
 | ||||
|     u32 scaled_size = res_scale * config.config.width; | ||||
| 
 | ||||
|     OpenGLState state = OpenGLState::GetCurState(); | ||||
| 
 | ||||
|     OpenGLState prev_state = state; | ||||
|     SCOPE_EXIT({ prev_state.Apply(); }); | ||||
| 
 | ||||
|     state.texture_cube_unit.texture_cube = dest_handle; | ||||
|     state.Apply(); | ||||
|     glActiveTexture(TextureUnits::TextureCube.Enum()); | ||||
|     FormatTuple format_tuple = GetFormatTuple(faces[0].surface->pixel_format); | ||||
|     for (auto& face : faces) { | ||||
|         glTexImage2D(face.gl_face, 0, format_tuple.internal_format, scaled_size, scaled_size, 0, | ||||
|                      format_tuple.format, format_tuple.type, nullptr); | ||||
|     } | ||||
| 
 | ||||
|     state.draw.read_framebuffer = read_framebuffer.handle; | ||||
|     state.draw.draw_framebuffer = draw_framebuffer.handle; | ||||
|     state.ResetTexture(dest_handle); | ||||
| 
 | ||||
|     for (auto& face : faces) { | ||||
|         state.ResetTexture(face.surface->texture.handle); | ||||
|         state.Apply(); | ||||
|         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | ||||
|                                face.surface->texture.handle, 0); | ||||
|         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||||
|                                0); | ||||
| 
 | ||||
|         glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face.gl_face, dest_handle, | ||||
|                                0); | ||||
|         glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, | ||||
|                                0); | ||||
| 
 | ||||
|         auto src_rect = face.surface->GetScaledRect(); | ||||
|         glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, 0, 0, | ||||
|                           scaled_size, scaled_size, GL_COLOR_BUFFER_BIT, GL_LINEAR); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | ||||
|     bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport_rect) { | ||||
|     const auto& regs = Pica::g_state.regs; | ||||
|  |  | |||
|  | @ -322,7 +322,12 @@ public: | |||
|                                         bool load_if_create); | ||||
| 
 | ||||
|     /// Get a surface based on the texture configuration
 | ||||
|     Surface GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config); | ||||
|     Surface GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config, | ||||
|                               PAddr addr_override = 0); | ||||
| 
 | ||||
|     /// Copy surfaces to a cubemap texture based on the texture configuration
 | ||||
|     void FillTextureCube(GLuint dest_handle, const Pica::TexturingRegs::FullTextureConfig& config, | ||||
|                          PAddr px, PAddr nx, PAddr py, PAddr ny, PAddr pz, PAddr nz); | ||||
| 
 | ||||
|     /// Get the color and depth surfaces based on the framebuffer configuration
 | ||||
|     SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, | ||||
|  |  | |||
|  | @ -202,6 +202,8 @@ static std::string SampleTexture(const PicaShaderConfig& config, unsigned textur | |||
|             return "texture(tex[0], texcoord[0])"; | ||||
|         case TexturingRegs::TextureConfig::Projection2D: | ||||
|             return "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))"; | ||||
|         case TexturingRegs::TextureConfig::TextureCube: | ||||
|             return "texture(tex_cube, vec3(texcoord[0], texcoord0_w))"; | ||||
|         default: | ||||
|             LOG_CRITICAL(HW_GPU, "Unhandled texture type %x", | ||||
|                          static_cast<int>(state.texture0_type)); | ||||
|  | @ -1060,6 +1062,7 @@ in vec4 gl_FragCoord; | |||
| out vec4 color; | ||||
| 
 | ||||
| uniform sampler2D tex[3]; | ||||
| uniform samplerCube tex_cube; | ||||
| uniform samplerBuffer lighting_lut; | ||||
| uniform samplerBuffer fog_lut; | ||||
| uniform samplerBuffer proctex_noise_lut; | ||||
|  |  | |||
|  | @ -52,6 +52,9 @@ OpenGLState::OpenGLState() { | |||
|         texture_unit.sampler = 0; | ||||
|     } | ||||
| 
 | ||||
|     texture_cube_unit.texture_cube = 0; | ||||
|     texture_cube_unit.sampler = 0; | ||||
| 
 | ||||
|     lighting_lut.texture_buffer = 0; | ||||
| 
 | ||||
|     fog_lut.texture_buffer = 0; | ||||
|  | @ -201,6 +204,14 @@ void OpenGLState::Apply() const { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (texture_cube_unit.texture_cube != cur_state.texture_cube_unit.texture_cube) { | ||||
|         glActiveTexture(TextureUnits::TextureCube.Enum()); | ||||
|         glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cube_unit.texture_cube); | ||||
|     } | ||||
|     if (texture_cube_unit.sampler != cur_state.texture_cube_unit.sampler) { | ||||
|         glBindSampler(TextureUnits::TextureCube.id, texture_cube_unit.sampler); | ||||
|     } | ||||
| 
 | ||||
|     // Lighting LUTs
 | ||||
|     if (lighting_lut.texture_buffer != cur_state.lighting_lut.texture_buffer) { | ||||
|         glActiveTexture(TextureUnits::LightingLUT.Enum()); | ||||
|  | @ -311,6 +322,8 @@ OpenGLState& OpenGLState::ResetTexture(GLuint handle) { | |||
|             unit.texture_2d = 0; | ||||
|         } | ||||
|     } | ||||
|     if (texture_cube_unit.texture_cube == handle) | ||||
|         texture_cube_unit.texture_cube = 0; | ||||
|     if (lighting_lut.texture_buffer == handle) | ||||
|         lighting_lut.texture_buffer = 0; | ||||
|     if (fog_lut.texture_buffer == handle) | ||||
|  | @ -334,6 +347,9 @@ OpenGLState& OpenGLState::ResetSampler(GLuint handle) { | |||
|             unit.sampler = 0; | ||||
|         } | ||||
|     } | ||||
|     if (texture_cube_unit.sampler == handle) { | ||||
|         texture_cube_unit.sampler = 0; | ||||
|     } | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ constexpr TextureUnit ProcTexColorMap{6}; | |||
| constexpr TextureUnit ProcTexAlphaMap{7}; | ||||
| constexpr TextureUnit ProcTexLUT{8}; | ||||
| constexpr TextureUnit ProcTexDiffLUT{9}; | ||||
| constexpr TextureUnit TextureCube{10}; | ||||
| 
 | ||||
| } // namespace TextureUnits
 | ||||
| 
 | ||||
|  | @ -87,6 +88,11 @@ public: | |||
|         GLuint sampler;    // GL_SAMPLER_BINDING
 | ||||
|     } texture_units[3]; | ||||
| 
 | ||||
|     struct { | ||||
|         GLuint texture_cube; // GL_TEXTURE_BINDING_CUBE_MAP
 | ||||
|         GLuint sampler;      // GL_SAMPLER_BINDING
 | ||||
|     } texture_cube_unit; | ||||
| 
 | ||||
|     struct { | ||||
|         GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
 | ||||
|     } lighting_lut; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue