1 // Copyright 2015 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <array> 8 #include <cstddef> 9 #include <cstring> 10 #include <memory> 11 #include <vector> 12 #include <glad/glad.h> 13 #include "common/bit_field.h" 14 #include "common/common_types.h" 15 #include "common/vector_math.h" 16 #include "core/hw/gpu.h" 17 #include "video_core/pica_state.h" 18 #include "video_core/pica_types.h" 19 #include "video_core/rasterizer_interface.h" 20 #include "video_core/regs_framebuffer.h" 21 #include "video_core/regs_lighting.h" 22 #include "video_core/regs_rasterizer.h" 23 #include "video_core/regs_texturing.h" 24 #include "video_core/renderer_opengl/gl_rasterizer_cache.h" 25 #include "video_core/renderer_opengl/gl_resource_manager.h" 26 #include "video_core/renderer_opengl/gl_shader_manager.h" 27 #include "video_core/renderer_opengl/gl_state.h" 28 #include "video_core/renderer_opengl/gl_stream_buffer.h" 29 #include "video_core/renderer_opengl/pica_to_gl.h" 30 #include "video_core/shader/shader.h" 31 32 namespace Frontend { 33 class EmuWindow; 34 } 35 36 namespace OpenGL { 37 class ShaderProgramManager; 38 39 class RasterizerOpenGL : public VideoCore::RasterizerInterface { 40 public: 41 explicit RasterizerOpenGL(); 42 ~RasterizerOpenGL() override; 43 44 void LoadDiskResources(const std::atomic_bool& stop_loading, 45 const VideoCore::DiskResourceLoadCallback& callback) override; 46 47 void AddTriangle(const Pica::Shader::OutputVertex& v0, const Pica::Shader::OutputVertex& v1, 48 const Pica::Shader::OutputVertex& v2) override; 49 void DrawTriangles() override; 50 void NotifyPicaRegisterChanged(u32 id) override; 51 void FlushAll() override; 52 void FlushRegion(PAddr addr, u32 size) override; 53 void InvalidateRegion(PAddr addr, u32 size) override; 54 void FlushAndInvalidateRegion(PAddr addr, u32 size) override; 55 void ClearAll(bool flush) override; 56 bool AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) override; 57 bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override; 58 bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override; 59 bool AccelerateDisplay(const GPU::Regs::FramebufferConfig& config, PAddr framebuffer_addr, 60 u32 pixel_stride, ScreenInfo& screen_info) override; 61 bool AccelerateDrawBatch(bool is_indexed) override; 62 63 /// Syncs entire status to match PICA registers 64 void SyncEntireState() override; 65 66 private: 67 struct SamplerInfo { 68 using TextureConfig = Pica::TexturingRegs::TextureConfig; 69 70 OGLSampler sampler; 71 72 /// Creates the sampler object, initializing its state so that it's in sync with the 73 /// SamplerInfo struct. 74 void Create(); 75 /// Syncs the sampler object with the config, updating any necessary state. 76 void SyncWithConfig(const TextureConfig& config); 77 78 private: 79 TextureConfig::TextureFilter mag_filter; 80 TextureConfig::TextureFilter min_filter; 81 TextureConfig::TextureFilter mip_filter; 82 TextureConfig::WrapMode wrap_s; 83 TextureConfig::WrapMode wrap_t; 84 u32 border_color; 85 u32 lod_min; 86 u32 lod_max; 87 s32 lod_bias; 88 89 // TODO(wwylele): remove this once mipmap for cube is implemented 90 bool supress_mipmap_for_cube = false; 91 }; 92 93 /// Structure that the hardware rendered vertices are composed of 94 struct HardwareVertex { 95 HardwareVertex() = default; HardwareVertexHardwareVertex96 HardwareVertex(const Pica::Shader::OutputVertex& v, bool flip_quaternion) { 97 position[0] = v.pos.x.ToFloat32(); 98 position[1] = v.pos.y.ToFloat32(); 99 position[2] = v.pos.z.ToFloat32(); 100 position[3] = v.pos.w.ToFloat32(); 101 color[0] = v.color.x.ToFloat32(); 102 color[1] = v.color.y.ToFloat32(); 103 color[2] = v.color.z.ToFloat32(); 104 color[3] = v.color.w.ToFloat32(); 105 tex_coord0[0] = v.tc0.x.ToFloat32(); 106 tex_coord0[1] = v.tc0.y.ToFloat32(); 107 tex_coord1[0] = v.tc1.x.ToFloat32(); 108 tex_coord1[1] = v.tc1.y.ToFloat32(); 109 tex_coord2[0] = v.tc2.x.ToFloat32(); 110 tex_coord2[1] = v.tc2.y.ToFloat32(); 111 tex_coord0_w = v.tc0_w.ToFloat32(); 112 normquat[0] = v.quat.x.ToFloat32(); 113 normquat[1] = v.quat.y.ToFloat32(); 114 normquat[2] = v.quat.z.ToFloat32(); 115 normquat[3] = v.quat.w.ToFloat32(); 116 view[0] = v.view.x.ToFloat32(); 117 view[1] = v.view.y.ToFloat32(); 118 view[2] = v.view.z.ToFloat32(); 119 120 if (flip_quaternion) { 121 for (float& x : normquat) { 122 x = -x; 123 } 124 } 125 } 126 127 GLvec4 position; 128 GLvec4 color; 129 GLvec2 tex_coord0; 130 GLvec2 tex_coord1; 131 GLvec2 tex_coord2; 132 GLfloat tex_coord0_w; 133 GLvec4 normquat; 134 GLvec3 view; 135 }; 136 137 /// Syncs the clip enabled status to match the PICA register 138 void SyncClipEnabled(); 139 140 /// Syncs the clip coefficients to match the PICA register 141 void SyncClipCoef(); 142 143 /// Sets the OpenGL shader in accordance with the current PICA register state 144 void SetShader(); 145 146 /// Syncs the cull mode to match the PICA register 147 void SyncCullMode(); 148 149 /// Syncs the depth scale to match the PICA register 150 void SyncDepthScale(); 151 152 /// Syncs the depth offset to match the PICA register 153 void SyncDepthOffset(); 154 155 /// Syncs the blend enabled status to match the PICA register 156 void SyncBlendEnabled(); 157 158 /// Syncs the blend functions to match the PICA register 159 void SyncBlendFuncs(); 160 161 /// Syncs the blend color to match the PICA register 162 void SyncBlendColor(); 163 164 /// Syncs the fog states to match the PICA register 165 void SyncFogColor(); 166 167 /// Sync the procedural texture noise configuration to match the PICA register 168 void SyncProcTexNoise(); 169 170 /// Sync the procedural texture bias configuration to match the PICA register 171 void SyncProcTexBias(); 172 173 /// Syncs the alpha test states to match the PICA register 174 void SyncAlphaTest(); 175 176 /// Syncs the logic op states to match the PICA register 177 void SyncLogicOp(); 178 179 /// Syncs the color write mask to match the PICA register state 180 void SyncColorWriteMask(); 181 182 /// Syncs the stencil write mask to match the PICA register state 183 void SyncStencilWriteMask(); 184 185 /// Syncs the depth write mask to match the PICA register state 186 void SyncDepthWriteMask(); 187 188 /// Syncs the stencil test states to match the PICA register 189 void SyncStencilTest(); 190 191 /// Syncs the depth test states to match the PICA register 192 void SyncDepthTest(); 193 194 /// Syncs the TEV combiner color buffer to match the PICA register 195 void SyncCombinerColor(); 196 197 /// Syncs the TEV constant color to match the PICA register 198 void SyncTevConstColor(std::size_t tev_index, 199 const Pica::TexturingRegs::TevStageConfig& tev_stage); 200 201 /// Syncs the lighting global ambient color to match the PICA register 202 void SyncGlobalAmbient(); 203 204 /// Syncs the specified light's specular 0 color to match the PICA register 205 void SyncLightSpecular0(int light_index); 206 207 /// Syncs the specified light's specular 1 color to match the PICA register 208 void SyncLightSpecular1(int light_index); 209 210 /// Syncs the specified light's diffuse color to match the PICA register 211 void SyncLightDiffuse(int light_index); 212 213 /// Syncs the specified light's ambient color to match the PICA register 214 void SyncLightAmbient(int light_index); 215 216 /// Syncs the specified light's position to match the PICA register 217 void SyncLightPosition(int light_index); 218 219 /// Syncs the specified spot light direcition to match the PICA register 220 void SyncLightSpotDirection(int light_index); 221 222 /// Syncs the specified light's distance attenuation bias to match the PICA register 223 void SyncLightDistanceAttenuationBias(int light_index); 224 225 /// Syncs the specified light's distance attenuation scale to match the PICA register 226 void SyncLightDistanceAttenuationScale(int light_index); 227 228 /// Syncs the shadow rendering bias to match the PICA register 229 void SyncShadowBias(); 230 231 /// Syncs the shadow texture bias to match the PICA register 232 void SyncShadowTextureBias(); 233 234 /// Syncs and uploads the lighting, fog and proctex LUTs 235 void SyncAndUploadLUTs(); 236 void SyncAndUploadLUTsLF(); 237 238 /// Upload the uniform blocks to the uniform buffer object 239 void UploadUniforms(bool accelerate_draw); 240 241 /// Generic draw function for DrawTriangles and AccelerateDrawBatch 242 bool Draw(bool accelerate, bool is_indexed); 243 244 /// Internal implementation for AccelerateDrawBatch 245 bool AccelerateDrawBatchInternal(bool is_indexed); 246 247 struct VertexArrayInfo { 248 u32 vs_input_index_min; 249 u32 vs_input_index_max; 250 u32 vs_input_size; 251 }; 252 253 /// Retrieve the range and the size of the input vertex 254 VertexArrayInfo AnalyzeVertexArray(bool is_indexed); 255 256 /// Setup vertex array for AccelerateDrawBatch 257 void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset, GLuint vs_input_index_min, 258 GLuint vs_input_index_max); 259 260 /// Setup vertex shader for AccelerateDrawBatch 261 bool SetupVertexShader(); 262 263 /// Setup geometry shader for AccelerateDrawBatch 264 bool SetupGeometryShader(); 265 266 bool is_amd; 267 268 OpenGLState state; 269 GLuint default_texture; 270 271 RasterizerCacheOpenGL res_cache; 272 273 std::vector<HardwareVertex> vertex_batch; 274 275 bool shader_dirty = true; 276 277 struct { 278 UniformData data; 279 std::array<bool, Pica::LightingRegs::NumLightingSampler> lighting_lut_dirty; 280 bool lighting_lut_dirty_any; 281 bool fog_lut_dirty; 282 bool proctex_noise_lut_dirty; 283 bool proctex_color_map_dirty; 284 bool proctex_alpha_map_dirty; 285 bool proctex_lut_dirty; 286 bool proctex_diff_lut_dirty; 287 bool dirty; 288 } uniform_block_data = {}; 289 290 std::unique_ptr<ShaderProgramManager> shader_program_manager; 291 292 // They shall be big enough for about one frame. 293 static constexpr std::size_t VERTEX_BUFFER_SIZE = 16 * 1024 * 1024; 294 static constexpr std::size_t INDEX_BUFFER_SIZE = 1 * 1024 * 1024; 295 static constexpr std::size_t UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024; 296 static constexpr std::size_t TEXTURE_BUFFER_SIZE = 1 * 1024 * 1024; 297 298 OGLVertexArray sw_vao; // VAO for software shader draw 299 OGLVertexArray hw_vao; // VAO for hardware shader / accelerate draw 300 std::array<bool, 16> hw_vao_enabled_attributes{}; 301 302 std::array<SamplerInfo, 3> texture_samplers; 303 OGLStreamBuffer vertex_buffer; 304 OGLStreamBuffer uniform_buffer; 305 OGLStreamBuffer index_buffer; 306 OGLStreamBuffer texture_buffer; 307 OGLStreamBuffer texture_lf_buffer; 308 OGLFramebuffer framebuffer; 309 GLint uniform_buffer_alignment; 310 std::size_t uniform_size_aligned_vs; 311 std::size_t uniform_size_aligned_fs; 312 313 SamplerInfo texture_cube_sampler; 314 315 OGLTexture texture_buffer_lut_lf; 316 OGLTexture texture_buffer_lut_rg; 317 OGLTexture texture_buffer_lut_rgba; 318 319 std::array<std::array<GLvec2, 256>, Pica::LightingRegs::NumLightingSampler> lighting_lut_data{}; 320 std::array<GLvec2, 128> fog_lut_data{}; 321 std::array<GLvec2, 128> proctex_noise_lut_data{}; 322 std::array<GLvec2, 128> proctex_color_map_data{}; 323 std::array<GLvec2, 128> proctex_alpha_map_data{}; 324 std::array<GLvec4, 256> proctex_lut_data{}; 325 std::array<GLvec4, 256> proctex_diff_lut_data{}; 326 327 bool allow_shadow; 328 }; 329 330 } // namespace OpenGL 331