| 
									
										
										
										
											2015-05-24 06:32:32 +02:00
										 |  |  | // Copyright 2010 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2+
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-23 11:20:20 -05:00
										 |  |  | #include "VideoCommon/VertexManagerBase.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  | #include <array>
 | 
					
						
							| 
									
										
										
										
											2017-03-03 14:36:51 -08:00
										 |  |  | #include <cmath>
 | 
					
						
							| 
									
										
										
										
											2015-12-20 21:49:49 -05:00
										 |  |  | #include <memory>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 16:54:31 -05:00
										 |  |  | #include "Common/BitSet.h"
 | 
					
						
							|  |  |  | #include "Common/ChunkFile.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-07 20:06:58 -05:00
										 |  |  | #include "Common/CommonTypes.h"
 | 
					
						
							| 
									
										
										
										
											2016-01-17 16:54:31 -05:00
										 |  |  | #include "Common/Logging/Log.h"
 | 
					
						
							| 
									
										
										
										
											2018-01-06 10:50:25 +01:00
										 |  |  | #include "Common/MathUtil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-03 14:36:51 -08:00
										 |  |  | #include "Core/ConfigManager.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-17 16:54:31 -05:00
										 |  |  | #include "VideoCommon/BPMemory.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/DataReader.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "VideoCommon/Debugger.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-14 21:23:13 +01:00
										 |  |  | #include "VideoCommon/GeometryShaderManager.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "VideoCommon/IndexGenerator.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/NativeVertexFormat.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/OpcodeDecoding.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/PerfQueryBase.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/PixelShaderManager.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/RenderBase.h"
 | 
					
						
							| 
									
										
										
										
											2017-09-09 18:30:15 +10:00
										 |  |  | #include "VideoCommon/SamplerCommon.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "VideoCommon/TextureCacheBase.h"
 | 
					
						
							| 
									
										
										
										
											2015-01-24 03:15:09 +13:00
										 |  |  | #include "VideoCommon/VertexLoaderManager.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "VideoCommon/VertexShaderManager.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-23 11:20:20 -05:00
										 |  |  | #include "VideoCommon/VideoBackendBase.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "VideoCommon/VideoConfig.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/XFMemory.h"
 | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-20 21:49:49 -05:00
										 |  |  | std::unique_ptr<VertexManagerBase> g_vertex_manager; | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  | // GX primitive -> RenderState primitive, no primitive restart
 | 
					
						
							| 
									
										
										
										
											2017-11-19 01:47:21 -05:00
										 |  |  | constexpr std::array<PrimitiveType, 8> primitive_from_gx{{ | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  |     PrimitiveType::Triangles,  // GX_DRAW_QUADS
 | 
					
						
							|  |  |  |     PrimitiveType::Triangles,  // GX_DRAW_QUADS_2
 | 
					
						
							|  |  |  |     PrimitiveType::Triangles,  // GX_DRAW_TRIANGLES
 | 
					
						
							|  |  |  |     PrimitiveType::Triangles,  // GX_DRAW_TRIANGLE_STRIP
 | 
					
						
							|  |  |  |     PrimitiveType::Triangles,  // GX_DRAW_TRIANGLE_FAN
 | 
					
						
							|  |  |  |     PrimitiveType::Lines,      // GX_DRAW_LINES
 | 
					
						
							|  |  |  |     PrimitiveType::Lines,      // GX_DRAW_LINE_STRIP
 | 
					
						
							|  |  |  |     PrimitiveType::Points,     // GX_DRAW_POINTS
 | 
					
						
							| 
									
										
										
										
											2017-11-19 01:47:21 -05:00
										 |  |  | }}; | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GX primitive -> RenderState primitive, using primitive restart
 | 
					
						
							| 
									
										
										
										
											2017-11-19 01:47:21 -05:00
										 |  |  | constexpr std::array<PrimitiveType, 8> primitive_from_gx_pr{{ | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  |     PrimitiveType::TriangleStrip,  // GX_DRAW_QUADS
 | 
					
						
							|  |  |  |     PrimitiveType::TriangleStrip,  // GX_DRAW_QUADS_2
 | 
					
						
							|  |  |  |     PrimitiveType::TriangleStrip,  // GX_DRAW_TRIANGLES
 | 
					
						
							|  |  |  |     PrimitiveType::TriangleStrip,  // GX_DRAW_TRIANGLE_STRIP
 | 
					
						
							|  |  |  |     PrimitiveType::TriangleStrip,  // GX_DRAW_TRIANGLE_FAN
 | 
					
						
							|  |  |  |     PrimitiveType::Lines,          // GX_DRAW_LINES
 | 
					
						
							|  |  |  |     PrimitiveType::Lines,          // GX_DRAW_LINE_STRIP
 | 
					
						
							|  |  |  |     PrimitiveType::Points,         // GX_DRAW_POINTS
 | 
					
						
							| 
									
										
										
										
											2017-11-19 01:47:21 -05:00
										 |  |  | }}; | 
					
						
							| 
									
										
										
										
											2014-01-15 21:44:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-03 14:36:51 -08:00
										 |  |  | // Due to the BT.601 standard which the GameCube is based on being a compromise
 | 
					
						
							|  |  |  | // between PAL and NTSC, neither standard gets square pixels. They are each off
 | 
					
						
							|  |  |  | // by ~9% in opposite directions.
 | 
					
						
							|  |  |  | // Just in case any game decides to take this into account, we do both these
 | 
					
						
							|  |  |  | // tests with a large amount of slop.
 | 
					
						
							|  |  |  | static bool AspectIs4_3(float width, float height) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float aspect = fabsf(width / height); | 
					
						
							|  |  |  |   return fabsf(aspect - 4.0f / 3.0f) < 4.0f / 3.0f * 0.11;  // within 11% of 4:3
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool AspectIs16_9(float width, float height) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float aspect = fabsf(width / height); | 
					
						
							|  |  |  |   return fabsf(aspect - 16.0f / 9.0f) < 16.0f / 9.0f * 0.11;  // within 11% of 16:9
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:54:41 +01:00
										 |  |  | VertexManagerBase::VertexManagerBase() | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:54:41 +01:00
										 |  |  | VertexManagerBase::~VertexManagerBase() | 
					
						
							| 
									
										
										
										
											2013-04-24 09:21:54 -04:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  | u32 VertexManagerBase::GetRemainingSize() const | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   return static_cast<u32>(m_end_buffer_pointer - m_cur_buffer_pointer); | 
					
						
							| 
									
										
										
										
											2013-02-26 22:47:50 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, u32 stride, | 
					
						
							|  |  |  |                                                        bool cullall) | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // The SSE vertex loader can write up to 4 bytes past the end
 | 
					
						
							|  |  |  |   u32 const needed_vertex_bytes = count * stride + 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // We can't merge different kinds of primitives, so we have to flush here
 | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  |   PrimitiveType new_primitive_type = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? | 
					
						
							|  |  |  |                                          primitive_from_gx_pr[primitive] : | 
					
						
							|  |  |  |                                          primitive_from_gx[primitive]; | 
					
						
							|  |  |  |   if (m_current_primitive_type != new_primitive_type) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     Flush(); | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Have to update the rasterization state for point/line cull modes.
 | 
					
						
							| 
									
										
										
										
											2018-02-25 01:15:35 +10:00
										 |  |  |     m_current_primitive_type = new_primitive_type; | 
					
						
							|  |  |  |     SetRasterizationStateChanged(); | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Check for size in buffer, if the buffer gets full, call Flush()
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   if (!m_is_flushed && | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || | 
					
						
							|  |  |  |        needed_vertex_bytes > GetRemainingSize())) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Flush(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (count > IndexGenerator::GetRemainingIndices()) | 
					
						
							|  |  |  |       ERROR_LOG(VIDEO, "Too little remaining index values. Use 32-bit or reset them on flush."); | 
					
						
							|  |  |  |     if (count > GetRemainingIndices(primitive)) | 
					
						
							|  |  |  |       ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all indices! " | 
					
						
							|  |  |  |                        "Increase MAXIBUFFERSIZE or we need primitive breaking after all."); | 
					
						
							|  |  |  |     if (needed_vertex_bytes > GetRemainingSize()) | 
					
						
							|  |  |  |       ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all vertices! " | 
					
						
							|  |  |  |                        "Increase MAXVBUFFERSIZE or we need primitive breaking after all."); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   m_cull_all = cullall; | 
					
						
							| 
									
										
										
										
											2016-08-21 23:46:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // need to alloc new buffer
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   if (m_is_flushed) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     g_vertex_manager->ResetBuffer(stride); | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |     m_is_flushed = false; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   return DataReader(m_cur_buffer_pointer, m_end_buffer_pointer); | 
					
						
							| 
									
										
										
										
											2014-12-09 08:35:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:54:41 +01:00
										 |  |  | void VertexManagerBase::FlushData(u32 count, u32 stride) | 
					
						
							| 
									
										
										
										
											2014-12-09 08:35:04 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   m_cur_buffer_pointer += count * stride; | 
					
						
							| 
									
										
										
										
											2013-02-22 01:41:52 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:54:41 +01:00
										 |  |  | u32 VertexManagerBase::GetRemainingIndices(int primitive) | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u32 index_len = MAXIBUFFERSIZE - IndexGenerator::GetIndexLen(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (g_Config.backend_info.bSupportsPrimitiveRestart) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     switch (primitive) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_QUADS: | 
					
						
							|  |  |  |     case OpcodeDecoder::GX_DRAW_QUADS_2: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 5 * 4; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_TRIANGLES: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 4 * 3; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 1 - 1; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_TRIANGLE_FAN: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 6 * 4 + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_LINES: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_LINE_STRIP: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 2 + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_POINTS: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     switch (primitive) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_QUADS: | 
					
						
							|  |  |  |     case OpcodeDecoder::GX_DRAW_QUADS_2: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 6 * 4; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_TRIANGLES: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 3 + 2; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_TRIANGLE_FAN: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 3 + 2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_LINES: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_LINE_STRIP: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len / 2 + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-07 23:11:04 -05:00
										 |  |  |     case OpcodeDecoder::GX_DRAW_POINTS: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       return index_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-03 14:36:51 -08:00
										 |  |  | std::pair<size_t, size_t> VertexManagerBase::ResetFlushAspectRatioCount() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   std::pair<size_t, size_t> val = std::make_pair(m_flush_count_4_3, m_flush_count_anamorphic); | 
					
						
							|  |  |  |   m_flush_count_4_3 = 0; | 
					
						
							|  |  |  |   m_flush_count_anamorphic = 0; | 
					
						
							|  |  |  |   return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 10:50:25 +01:00
										 |  |  | static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex, | 
					
						
							|  |  |  |                             bool has_arbitrary_mips) | 
					
						
							| 
									
										
										
										
											2017-09-09 18:30:15 +10:00
										 |  |  | { | 
					
						
							|  |  |  |   const FourTexUnits& tex = bpmem.tex[index / 4]; | 
					
						
							|  |  |  |   const TexMode0& tm0 = tex.texMode0[index % 4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SamplerState state = {}; | 
					
						
							|  |  |  |   state.Generate(bpmem, index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Force texture filtering config option.
 | 
					
						
							|  |  |  |   if (g_ActiveConfig.bForceFiltering) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     state.min_filter = SamplerState::Filter::Linear; | 
					
						
							|  |  |  |     state.mag_filter = SamplerState::Filter::Linear; | 
					
						
							|  |  |  |     state.mipmap_filter = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? | 
					
						
							|  |  |  |                               SamplerState::Filter::Linear : | 
					
						
							|  |  |  |                               SamplerState::Filter::Point; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Custom textures may have a greater number of mips
 | 
					
						
							|  |  |  |   if (custom_tex) | 
					
						
							|  |  |  |     state.max_lod = 255; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Anisotropic filtering option.
 | 
					
						
							|  |  |  |   if (g_ActiveConfig.iMaxAnisotropy != 0 && !SamplerCommon::IsBpTexMode0PointFiltering(tm0)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
 | 
					
						
							|  |  |  |     // For predictable results on all hardware/drivers, only use one of:
 | 
					
						
							|  |  |  |     //	GL_LINEAR + GL_LINEAR (No Mipmaps [Bilinear])
 | 
					
						
							|  |  |  |     //	GL_LINEAR + GL_LINEAR_MIPMAP_LINEAR (w/ Mipmaps [Trilinear])
 | 
					
						
							|  |  |  |     // Letting the game set other combinations will have varying arbitrary results;
 | 
					
						
							|  |  |  |     // possibly being interpreted as equal to bilinear/trilinear, implicitly
 | 
					
						
							|  |  |  |     // disabling anisotropy, or changing the anisotropic algorithm employed.
 | 
					
						
							|  |  |  |     state.min_filter = SamplerState::Filter::Linear; | 
					
						
							|  |  |  |     state.mag_filter = SamplerState::Filter::Linear; | 
					
						
							|  |  |  |     if (SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0)) | 
					
						
							|  |  |  |       state.mipmap_filter = SamplerState::Filter::Linear; | 
					
						
							|  |  |  |     state.anisotropic_filtering = 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     state.anisotropic_filtering = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-18 02:02:56 -07:00
										 |  |  |   if (has_arbitrary_mips && SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Apply a secondary bias calculated from the IR scale to pull inwards mipmaps
 | 
					
						
							|  |  |  |     // that have arbitrary contents, eg. are used for fog effects where the
 | 
					
						
							|  |  |  |     // distance they kick in at is important to preserve at any resolution.
 | 
					
						
							| 
									
										
										
										
											2018-01-06 10:50:25 +01:00
										 |  |  |     // Correct this with the upscaling factor of custom textures.
 | 
					
						
							|  |  |  |     s64 lod_offset = std::log2(g_renderer->GetEFBScale() / custom_tex_scale) * 256.f; | 
					
						
							|  |  |  |     state.lod_bias = MathUtil::Clamp<s64>(state.lod_bias + lod_offset, -32768, 32767); | 
					
						
							| 
									
										
										
										
											2017-10-18 02:02:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Anisotropic also pushes mips farther away so it cannot be used either
 | 
					
						
							|  |  |  |     state.anisotropic_filtering = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-09 18:30:15 +10:00
										 |  |  |   g_renderer->SetSamplerState(index, state); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:54:41 +01:00
										 |  |  | void VertexManagerBase::Flush() | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   if (m_is_flushed) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // loading a state will invalidate BP, so check for it
 | 
					
						
							|  |  |  |   g_video_backend->CheckInvalidState(); | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-21 10:47:00 +01:00
										 |  |  | #if defined(_DEBUG) || defined(DEBUGFAST)
 | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |   PRIM_LOG("frame%d:\n texgen=%u, numchan=%u, dualtex=%u, ztex=%u, cole=%u, alpe=%u, ze=%u", | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |            g_ActiveConfig.iSaveTargetId, xfmem.numTexGen.numTexGens, xfmem.numChan.numColorChans, | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |            xfmem.dualTexTrans.enabled, bpmem.ztex2.op.Value(), bpmem.blendmode.colorupdate.Value(), | 
					
						
							|  |  |  |            bpmem.blendmode.alphaupdate.Value(), bpmem.zmode.updateenable.Value()); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |   for (u32 i = 0; i < xfmem.numChan.numColorChans; ++i) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     LitChannel* ch = &xfmem.color[i]; | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |     PRIM_LOG("colchan%u: matsrc=%u, light=0x%x, ambsrc=%u, diffunc=%u, attfunc=%u", i, | 
					
						
							|  |  |  |              ch->matsource.Value(), ch->GetFullLightMask(), ch->ambsource.Value(), | 
					
						
							|  |  |  |              ch->diffusefunc.Value(), ch->attnfunc.Value()); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     ch = &xfmem.alpha[i]; | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |     PRIM_LOG("alpchan%u: matsrc=%u, light=0x%x, ambsrc=%u, diffunc=%u, attfunc=%u", i, | 
					
						
							|  |  |  |              ch->matsource.Value(), ch->GetFullLightMask(), ch->ambsource.Value(), | 
					
						
							|  |  |  |              ch->diffusefunc.Value(), ch->attnfunc.Value()); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |   for (u32 i = 0; i < xfmem.numTexGen.numTexGens; ++i) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     TexMtxInfo tinfo = xfmem.texMtxInfo[i]; | 
					
						
							|  |  |  |     if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP) | 
					
						
							|  |  |  |       tinfo.hex &= 0x7ff; | 
					
						
							|  |  |  |     if (tinfo.texgentype != XF_TEXGEN_REGULAR) | 
					
						
							|  |  |  |       tinfo.projection = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |     PRIM_LOG("txgen%u: proj=%u, input=%u, gentype=%u, srcrow=%u, embsrc=%u, emblght=%u, " | 
					
						
							|  |  |  |              "postmtx=%u, postnorm=%u", | 
					
						
							|  |  |  |              i, tinfo.projection.Value(), tinfo.inputform.Value(), tinfo.texgentype.Value(), | 
					
						
							|  |  |  |              tinfo.sourcerow.Value(), tinfo.embosssourceshift.Value(), | 
					
						
							|  |  |  |              tinfo.embosslightshift.Value(), xfmem.postMtxInfo[i].index.Value(), | 
					
						
							|  |  |  |              xfmem.postMtxInfo[i].normalize.Value()); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 22:06:08 +10:00
										 |  |  |   PRIM_LOG("pixel: tev=%u, ind=%u, texgen=%u, dstalpha=%u, alphatest=0x%x", | 
					
						
							|  |  |  |            bpmem.genMode.numtevstages.Value() + 1, bpmem.genMode.numindstages.Value(), | 
					
						
							|  |  |  |            bpmem.genMode.numtexgens.Value(), bpmem.dstalpha.enable.Value(), | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |            (bpmem.alpha_test.hex >> 16) & 0xff); | 
					
						
							| 
									
										
										
										
											2014-01-21 10:47:00 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // If the primitave is marked CullAll. All we need to do is update the vertex constants and
 | 
					
						
							|  |  |  |   // calculate the zfreeze refrence slope
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   if (!m_cull_all) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     BitSet32 usedtextures; | 
					
						
							|  |  |  |     for (u32 i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) | 
					
						
							|  |  |  |       if (bpmem.tevorders[i / 2].getEnable(i & 1)) | 
					
						
							|  |  |  |         usedtextures[bpmem.tevorders[i / 2].getTexMap(i & 1)] = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (bpmem.genMode.numindstages > 0) | 
					
						
							|  |  |  |       for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) | 
					
						
							|  |  |  |         if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) | 
					
						
							|  |  |  |           usedtextures[bpmem.tevindref.getTexMap(bpmem.tevind[i].bt)] = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (unsigned int i : usedtextures) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-09-06 18:57:58 -04:00
										 |  |  |       const auto* tentry = g_texture_cache->Load(i); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (tentry) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2018-01-06 10:50:25 +01:00
										 |  |  |         float custom_tex_scale = tentry->GetWidth() / float(tentry->native_width); | 
					
						
							|  |  |  |         SetSamplerState(i, custom_tex_scale, tentry->is_custom_tex, tentry->has_arbitrary_mips); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |         PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         ERROR_LOG(VIDEO, "error loading texture"); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     g_texture_cache->BindTextures(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // set global vertex constants
 | 
					
						
							|  |  |  |   VertexShaderManager::SetConstants(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-03 14:36:51 -08:00
										 |  |  |   // Track some stats used elsewhere by the anamorphic widescreen heuristic.
 | 
					
						
							|  |  |  |   if (!SConfig::GetInstance().bWii) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     float* rawProjection = xfmem.projection.rawProjection; | 
					
						
							|  |  |  |     bool viewport_is_4_3 = AspectIs4_3(xfmem.viewport.wd, xfmem.viewport.ht); | 
					
						
							|  |  |  |     if (AspectIs16_9(rawProjection[2], rawProjection[0]) && viewport_is_4_3) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // Projection is 16:9 and viewport is 4:3, we are rendering an anamorphic
 | 
					
						
							|  |  |  |       // widescreen picture.
 | 
					
						
							|  |  |  |       m_flush_count_anamorphic++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (AspectIs4_3(rawProjection[2], rawProjection[0]) && viewport_is_4_3) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // Projection and viewports are both 4:3, we are rendering a normal image.
 | 
					
						
							|  |  |  |       m_flush_count_4_3++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // Calculate ZSlope for zfreeze
 | 
					
						
							|  |  |  |   if (!bpmem.genMode.zfreeze) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Must be done after VertexShaderManager::SetConstants()
 | 
					
						
							|  |  |  |     CalculateZSlope(VertexLoaderManager::GetCurrentVertexFormat()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   else if (m_zslope.dirty && !m_cull_all)  // or apply any dirty ZSlopes
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |     PixelShaderManager::SetZSlope(m_zslope.dfdx, m_zslope.dfdy, m_zslope.f0); | 
					
						
							|  |  |  |     m_zslope.dirty = false; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   if (!m_cull_all) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-02-25 01:15:35 +10:00
										 |  |  |     // Update the pipeline, or compile one if needed.
 | 
					
						
							|  |  |  |     UpdatePipelineConfig(); | 
					
						
							|  |  |  |     UpdatePipelineObject(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     // set the rest of the global constants
 | 
					
						
							|  |  |  |     GeometryShaderManager::SetConstants(); | 
					
						
							|  |  |  |     PixelShaderManager::SetConstants(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PerfQueryBase::ShouldEmulate()) | 
					
						
							|  |  |  |       g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:37:41 +01:00
										 |  |  |     g_vertex_manager->vFlush(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     if (PerfQueryBase::ShouldEmulate()) | 
					
						
							|  |  |  |       g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (xfmem.numTexGen.numTexGens != bpmem.genMode.numtexgens) | 
					
						
							|  |  |  |     ERROR_LOG(VIDEO, | 
					
						
							|  |  |  |               "xf.numtexgens (%d) does not match bp.numtexgens (%d). Error in command stream.", | 
					
						
							|  |  |  |               xfmem.numTexGen.numTexGens, bpmem.genMode.numtexgens.Value()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   m_is_flushed = true; | 
					
						
							|  |  |  |   m_cull_all = false; | 
					
						
							| 
									
										
										
										
											2010-10-03 08:20:24 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-10-19 22:24:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:54:41 +01:00
										 |  |  | void VertexManagerBase::DoState(PointerWrap& p) | 
					
						
							| 
									
										
										
										
											2012-01-04 00:42:22 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   p.Do(m_zslope); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   g_vertex_manager->vDoState(p); | 
					
						
							| 
									
										
										
										
											2012-01-04 00:42:22 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-26 01:25:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:54:41 +01:00
										 |  |  | void VertexManagerBase::CalculateZSlope(NativeVertexFormat* format) | 
					
						
							| 
									
										
										
										
											2014-12-26 01:25:24 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   float out[12]; | 
					
						
							|  |  |  |   float viewOffset[2] = {xfmem.viewport.xOrig - bpmem.scissorOffset.x * 2, | 
					
						
							|  |  |  |                          xfmem.viewport.yOrig - bpmem.scissorOffset.y * 2}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  |   if (m_current_primitive_type != PrimitiveType::Triangles && | 
					
						
							|  |  |  |       m_current_primitive_type != PrimitiveType::TriangleStrip) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2017-04-30 18:07:57 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Global matrix ID.
 | 
					
						
							|  |  |  |   u32 mtxIdx = g_main_cp_state.matrix_index_a.PosNormalMtxIdx; | 
					
						
							|  |  |  |   const PortableVertexDeclaration vert_decl = format->GetVertexDeclaration(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Make sure the buffer contains at least 3 vertices.
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   if ((m_cur_buffer_pointer - m_base_buffer_pointer) < (vert_decl.stride * 3)) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Lookup vertices of the last rendered triangle and software-transform them
 | 
					
						
							|  |  |  |   // This allows us to determine the depth slope, which will be used if z-freeze
 | 
					
						
							|  |  |  |   // is enabled in the following flush.
 | 
					
						
							|  |  |  |   for (unsigned int i = 0; i < 3; ++i) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // If this vertex format has per-vertex position matrix IDs, look it up.
 | 
					
						
							|  |  |  |     if (vert_decl.posmtx.enable) | 
					
						
							| 
									
										
										
										
											2016-05-07 09:35:40 +02:00
										 |  |  |       mtxIdx = VertexLoaderManager::position_matrix_index[3 - i]; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (vert_decl.position.components == 2) | 
					
						
							|  |  |  |       VertexLoaderManager::position_cache[2 - i][2] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     VertexShaderManager::TransformToClipSpace(&VertexLoaderManager::position_cache[2 - i][0], | 
					
						
							|  |  |  |                                               &out[i * 4], mtxIdx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Transform to Screenspace
 | 
					
						
							|  |  |  |     float inv_w = 1.0f / out[3 + i * 4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     out[0 + i * 4] = out[0 + i * 4] * inv_w * xfmem.viewport.wd + viewOffset[0]; | 
					
						
							|  |  |  |     out[1 + i * 4] = out[1 + i * 4] * inv_w * xfmem.viewport.ht + viewOffset[1]; | 
					
						
							|  |  |  |     out[2 + i * 4] = out[2 + i * 4] * inv_w * xfmem.viewport.zRange + xfmem.viewport.farZ; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float dx31 = out[8] - out[0]; | 
					
						
							|  |  |  |   float dx12 = out[0] - out[4]; | 
					
						
							|  |  |  |   float dy12 = out[1] - out[5]; | 
					
						
							|  |  |  |   float dy31 = out[9] - out[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float DF31 = out[10] - out[2]; | 
					
						
							|  |  |  |   float DF21 = out[6] - out[2]; | 
					
						
							|  |  |  |   float a = DF31 * -dy12 - DF21 * dy31; | 
					
						
							|  |  |  |   float b = dx31 * DF21 + dx12 * DF31; | 
					
						
							|  |  |  |   float c = -dx12 * dy31 - dx31 * -dy12; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Sometimes we process de-generate triangles. Stop any divide by zeros
 | 
					
						
							|  |  |  |   if (c == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 23:02:37 -04:00
										 |  |  |   m_zslope.dfdx = -a / c; | 
					
						
							|  |  |  |   m_zslope.dfdy = -b / c; | 
					
						
							|  |  |  |   m_zslope.f0 = out[2] - (out[0] * m_zslope.dfdx + out[1] * m_zslope.dfdy); | 
					
						
							|  |  |  |   m_zslope.dirty = true; | 
					
						
							| 
									
										
										
										
											2014-12-26 01:25:24 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-02-25 01:15:35 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | void VertexManagerBase::UpdatePipelineConfig() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   NativeVertexFormat* vertex_format = VertexLoaderManager::GetCurrentVertexFormat(); | 
					
						
							|  |  |  |   if (vertex_format != m_current_pipeline_config.vertex_format) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_current_pipeline_config.vertex_format = vertex_format; | 
					
						
							|  |  |  |     m_current_uber_pipeline_config.vertex_format = | 
					
						
							|  |  |  |         VertexLoaderManager::GetUberVertexFormat(vertex_format->GetVertexDeclaration()); | 
					
						
							|  |  |  |     m_pipeline_config_changed = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VertexShaderUid vs_uid = GetVertexShaderUid(); | 
					
						
							|  |  |  |   if (vs_uid != m_current_pipeline_config.vs_uid) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_current_pipeline_config.vs_uid = vs_uid; | 
					
						
							|  |  |  |     m_current_uber_pipeline_config.vs_uid = UberShader::GetVertexShaderUid(); | 
					
						
							|  |  |  |     m_pipeline_config_changed = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PixelShaderUid ps_uid = GetPixelShaderUid(); | 
					
						
							|  |  |  |   if (ps_uid != m_current_pipeline_config.ps_uid) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_current_pipeline_config.ps_uid = ps_uid; | 
					
						
							|  |  |  |     m_current_uber_pipeline_config.ps_uid = UberShader::GetPixelShaderUid(); | 
					
						
							|  |  |  |     m_pipeline_config_changed = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GeometryShaderUid gs_uid = GetGeometryShaderUid(GetCurrentPrimitiveType()); | 
					
						
							|  |  |  |   if (gs_uid != m_current_pipeline_config.gs_uid) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_current_pipeline_config.gs_uid = gs_uid; | 
					
						
							|  |  |  |     m_current_uber_pipeline_config.gs_uid = gs_uid; | 
					
						
							|  |  |  |     m_pipeline_config_changed = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (m_rasterization_state_changed) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_rasterization_state_changed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     RasterizationState new_rs = {}; | 
					
						
							|  |  |  |     new_rs.Generate(bpmem, m_current_primitive_type); | 
					
						
							|  |  |  |     if (new_rs != m_current_pipeline_config.rasterization_state) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       m_current_pipeline_config.rasterization_state = new_rs; | 
					
						
							|  |  |  |       m_current_uber_pipeline_config.rasterization_state = new_rs; | 
					
						
							|  |  |  |       m_pipeline_config_changed = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (m_depth_state_changed) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_depth_state_changed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DepthState new_ds = {}; | 
					
						
							|  |  |  |     new_ds.Generate(bpmem); | 
					
						
							|  |  |  |     if (new_ds != m_current_pipeline_config.depth_state) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       m_current_pipeline_config.depth_state = new_ds; | 
					
						
							|  |  |  |       m_current_uber_pipeline_config.depth_state = new_ds; | 
					
						
							|  |  |  |       m_pipeline_config_changed = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (m_blending_state_changed) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_blending_state_changed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BlendingState new_bs = {}; | 
					
						
							|  |  |  |     new_bs.Generate(bpmem); | 
					
						
							|  |  |  |     if (new_bs != m_current_pipeline_config.blending_state) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       m_current_pipeline_config.blending_state = new_bs; | 
					
						
							|  |  |  |       m_current_uber_pipeline_config.blending_state = new_bs; | 
					
						
							|  |  |  |       m_pipeline_config_changed = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VertexManagerBase::UpdatePipelineObject() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!m_pipeline_config_changed) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_current_pipeline_object = nullptr; | 
					
						
							|  |  |  |   m_pipeline_config_changed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-16 23:10:22 +10:00
										 |  |  |   switch (g_ActiveConfig.iShaderCompilationMode) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   case ShaderCompilationMode::Synchronous: | 
					
						
							| 
									
										
										
										
											2018-03-01 18:03:24 +10:00
										 |  |  |   { | 
					
						
							|  |  |  |     // Ubershaders disabled? Block and compile the specialized shader.
 | 
					
						
							|  |  |  |     m_current_pipeline_object = g_shader_cache->GetPipelineForUid(m_current_pipeline_config); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-16 23:10:22 +10:00
										 |  |  |   break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   case ShaderCompilationMode::SynchronousUberShaders: | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Exclusive ubershader mode, always use ubershaders.
 | 
					
						
							|  |  |  |     m_current_pipeline_object = | 
					
						
							|  |  |  |         g_shader_cache->GetUberPipelineForUid(m_current_uber_pipeline_config); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   case ShaderCompilationMode::AsynchronousUberShaders: | 
					
						
							|  |  |  |   case ShaderCompilationMode::AsynchronousSkipRendering: | 
					
						
							| 
									
										
										
										
											2018-02-25 01:15:35 +10:00
										 |  |  |   { | 
					
						
							|  |  |  |     // Can we background compile shaders? If so, get the pipeline asynchronously.
 | 
					
						
							| 
									
										
										
										
											2018-03-01 18:03:24 +10:00
										 |  |  |     auto res = g_shader_cache->GetPipelineForUidAsync(m_current_pipeline_config); | 
					
						
							|  |  |  |     if (res) | 
					
						
							| 
									
										
										
										
											2018-02-25 01:15:35 +10:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-03-01 18:03:24 +10:00
										 |  |  |       // Specialized shaders are ready, prefer these.
 | 
					
						
							|  |  |  |       m_current_pipeline_object = *res; | 
					
						
							| 
									
										
										
										
											2018-02-25 01:15:35 +10:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-16 23:10:22 +10:00
										 |  |  |     if (g_ActiveConfig.iShaderCompilationMode == ShaderCompilationMode::AsynchronousUberShaders) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // Specialized shaders not ready, use the ubershaders.
 | 
					
						
							|  |  |  |       m_current_pipeline_object = | 
					
						
							|  |  |  |           g_shader_cache->GetUberPipelineForUid(m_current_uber_pipeline_config); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // Ensure we try again next draw. Otherwise, if no registers change between frames, the
 | 
					
						
							|  |  |  |       // object will never be drawn, even when the shader is ready.
 | 
					
						
							|  |  |  |       m_pipeline_config_changed = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   break; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-02-25 01:15:35 +10:00
										 |  |  | } |