| 
									
										
										
										
											2015-05-24 06:55:12 +02:00
										 |  |  | // Copyright 2008 Dolphin Emulator Project
 | 
					
						
							| 
									
										
										
										
											2015-05-18 01:08:10 +02:00
										 |  |  | // Licensed under GPLv2+
 | 
					
						
							| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-21 19:10:00 -06:00
										 |  |  | #include <cstddef>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-07 20:06:58 -05:00
										 |  |  | #include "Common/CommonTypes.h"
 | 
					
						
							| 
									
										
										
										
											2018-06-09 11:34:43 -04:00
										 |  |  | #include "Common/Compiler.h"
 | 
					
						
							| 
									
										
										
										
											2016-01-17 16:54:31 -05:00
										 |  |  | #include "Common/Logging/Log.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "VideoCommon/IndexGenerator.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-08 16:53:18 -07:00
										 |  |  | #include "VideoCommon/OpcodeDecoding.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "VideoCommon/VideoConfig.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | // Init
 | 
					
						
							|  |  |  | u16* IndexGenerator::index_buffer_current; | 
					
						
							|  |  |  | u16* IndexGenerator::BASEIptr; | 
					
						
							| 
									
										
										
										
											2014-01-16 14:30:17 +01:00
										 |  |  | u32 IndexGenerator::base_index; | 
					
						
							| 
									
										
										
										
											2009-10-06 14:24:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-07 04:16:02 -07:00
										 |  |  | static const u16 s_primitive_restart = UINT16_MAX; | 
					
						
							| 
									
										
										
										
											2013-04-08 17:58:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 14:30:17 +01:00
										 |  |  | static u16* (*primitive_table[8])(u16*, u32, u32); | 
					
						
							| 
									
										
										
										
											2013-04-08 19:39:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void IndexGenerator::Init() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (g_Config.backend_info.bSupportsPrimitiveRestart) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<true>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<true>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<true>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<true>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<true>; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<false>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<false>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<false>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<false>; | 
					
						
							|  |  |  |     primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<false>; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |   primitive_table[OpcodeDecoder::GX_DRAW_LINES] = &AddLineList; | 
					
						
							|  |  |  |   primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = &AddLineStrip; | 
					
						
							|  |  |  |   primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = &AddPoints; | 
					
						
							| 
									
										
										
										
											2013-04-08 19:39:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-15 21:44:46 +01:00
										 |  |  | void IndexGenerator::Start(u16* Indexptr) | 
					
						
							| 
									
										
										
										
											2010-06-16 10:12:57 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   index_buffer_current = Indexptr; | 
					
						
							|  |  |  |   BASEIptr = Indexptr; | 
					
						
							|  |  |  |   base_index = 0; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-02-21 19:10:00 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | void IndexGenerator::AddIndices(int primitive, u32 numVerts) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   index_buffer_current = primitive_table[primitive](index_buffer_current, numVerts, base_index); | 
					
						
							|  |  |  |   base_index += numVerts; | 
					
						
							| 
									
										
										
										
											2013-02-21 19:10:00 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | // Triangles
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | template <bool pr> | 
					
						
							| 
									
										
										
										
											2018-06-09 11:47:01 -04:00
										 |  |  | DOLPHIN_FORCE_INLINE u16* IndexGenerator::WriteTriangle(u16* Iptr, u32 index1, u32 index2, | 
					
						
							|  |  |  |                                                         u32 index3) | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   *Iptr++ = index1; | 
					
						
							|  |  |  |   *Iptr++ = index2; | 
					
						
							|  |  |  |   *Iptr++ = index3; | 
					
						
							|  |  |  |   if (pr) | 
					
						
							|  |  |  |     *Iptr++ = s_primitive_restart; | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2013-02-21 19:10:00 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | template <bool pr> | 
					
						
							|  |  |  | u16* IndexGenerator::AddList(u16* Iptr, u32 const numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2013-02-21 21:01:53 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   for (u32 i = 2; i < numVerts; i += 3) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Iptr = WriteTriangle<pr>(Iptr, index + i - 2, index + i - 1, index + i); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | template <bool pr> | 
					
						
							|  |  |  | u16* IndexGenerator::AddStrip(u16* Iptr, u32 const numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (pr) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     for (u32 i = 0; i < numVerts; ++i) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       *Iptr++ = index + i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *Iptr++ = s_primitive_restart; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     bool wind = false; | 
					
						
							|  |  |  |     for (u32 i = 2; i < numVerts; ++i) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Iptr = WriteTriangle<pr>(Iptr, index + i - 2, index + i - !wind, index + i - wind); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       wind ^= true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-02-21 19:10:00 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * FAN simulator: | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  *   2---3 | 
					
						
							|  |  |  |  *  / \ / \ | 
					
						
							|  |  |  |  * 1---0---4 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  * would generate this triangles: | 
					
						
							|  |  |  |  * 012, 023, 034 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  * rotated (for better striping): | 
					
						
							|  |  |  |  * 120, 302, 034 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  * as odd ones have to winded, following strip is fine: | 
					
						
							|  |  |  |  * 12034 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  * so we use 6 indices for 3 triangles | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | template <bool pr> | 
					
						
							|  |  |  | u16* IndexGenerator::AddFan(u16* Iptr, u32 numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u32 i = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (pr) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     for (; i + 3 <= numVerts; i += 3) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       *Iptr++ = index + i - 1; | 
					
						
							|  |  |  |       *Iptr++ = index + i + 0; | 
					
						
							|  |  |  |       *Iptr++ = index; | 
					
						
							|  |  |  |       *Iptr++ = index + i + 1; | 
					
						
							|  |  |  |       *Iptr++ = index + i + 2; | 
					
						
							|  |  |  |       *Iptr++ = s_primitive_restart; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (; i + 2 <= numVerts; i += 2) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       *Iptr++ = index + i - 1; | 
					
						
							|  |  |  |       *Iptr++ = index + i + 0; | 
					
						
							|  |  |  |       *Iptr++ = index; | 
					
						
							|  |  |  |       *Iptr++ = index + i + 1; | 
					
						
							|  |  |  |       *Iptr++ = s_primitive_restart; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (; i < numVerts; ++i) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Iptr = WriteTriangle<pr>(Iptr, index, index + i - 1, index + i); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QUAD simulator | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  * 0---1   4---5 | 
					
						
							|  |  |  |  * |\  |   |\  | | 
					
						
							|  |  |  |  * | \ |   | \ | | 
					
						
							|  |  |  |  * |  \|   |  \| | 
					
						
							|  |  |  |  * 3---2   7---6 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  * 012,023, 456,467 ... | 
					
						
							|  |  |  |  * or 120,302, 564,746 | 
					
						
							|  |  |  |  * or as strip: 1203, 5647 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Warning: | 
					
						
							| 
									
										
										
										
											2013-04-10 12:45:44 +02:00
										 |  |  |  * A simple triangle has to be rendered for three vertices. | 
					
						
							|  |  |  |  * ZWW do this for sun rays | 
					
						
							| 
									
										
										
										
											2013-04-08 17:22:16 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | template <bool pr> | 
					
						
							|  |  |  | u16* IndexGenerator::AddQuads(u16* Iptr, u32 numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u32 i = 3; | 
					
						
							|  |  |  |   for (; i < numVerts; i += 4) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (pr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       *Iptr++ = index + i - 2; | 
					
						
							|  |  |  |       *Iptr++ = index + i - 1; | 
					
						
							|  |  |  |       *Iptr++ = index + i - 3; | 
					
						
							|  |  |  |       *Iptr++ = index + i - 0; | 
					
						
							|  |  |  |       *Iptr++ = s_primitive_restart; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Iptr = WriteTriangle<pr>(Iptr, index + i - 3, index + i - 2, index + i - 1); | 
					
						
							|  |  |  |       Iptr = WriteTriangle<pr>(Iptr, index + i - 3, index + i - 1, index + i - 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // three vertices remaining, so render a triangle
 | 
					
						
							|  |  |  |   if (i == numVerts) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Iptr = | 
					
						
							|  |  |  |         WriteTriangle<pr>(Iptr, index + numVerts - 3, index + numVerts - 2, index + numVerts - 1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | template <bool pr> | 
					
						
							|  |  |  | u16* IndexGenerator::AddQuads_nonstandard(u16* Iptr, u32 numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2014-05-17 11:55:32 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   WARN_LOG(VIDEO, "Non-standard primitive drawing command GL_DRAW_QUADS_2"); | 
					
						
							|  |  |  |   return AddQuads<pr>(Iptr, numVerts, index); | 
					
						
							| 
									
										
										
										
											2014-05-17 11:55:32 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-21 19:10:00 -06:00
										 |  |  | // Lines
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | u16* IndexGenerator::AddLineList(u16* Iptr, u32 numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   for (u32 i = 1; i < numVerts; i += 2) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     *Iptr++ = index + i - 1; | 
					
						
							|  |  |  |     *Iptr++ = index + i; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-08 17:58:23 +02:00
										 |  |  | // shouldn't be used as strips as LineLists are much more common
 | 
					
						
							|  |  |  | // so converting them to lists
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | u16* IndexGenerator::AddLineStrip(u16* Iptr, u32 numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   for (u32 i = 1; i < numVerts; ++i) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     *Iptr++ = index + i - 1; | 
					
						
							|  |  |  |     *Iptr++ = index + i; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-21 19:10:00 -06:00
										 |  |  | // Points
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | u16* IndexGenerator::AddPoints(u16* Iptr, u32 numVerts, u32 index) | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   for (u32 i = 0; i != numVerts; ++i) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     *Iptr++ = index + i; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return Iptr; | 
					
						
							| 
									
										
										
										
											2009-09-29 18:27:41 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-03-23 00:18:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | u32 IndexGenerator::GetRemainingIndices() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u32 max_index = 65534;  // -1 is reserved for primitive restart (ogl + dx11)
 | 
					
						
							|  |  |  |   return max_index - base_index; | 
					
						
							| 
									
										
										
										
											2013-03-23 00:18:35 +01:00
										 |  |  | } |