Convert OpcodeDecoder::Opcode and OpcodeDecoder::Primitive to enum class

This commit is contained in:
Pokechu22
2021-04-30 14:57:12 -07:00
parent 3fc12431c5
commit 3aaeb2b9ef
13 changed files with 177 additions and 132 deletions

View File

@ -202,25 +202,27 @@ u16* AddPoints(u16* index_ptr, u32 num_verts, u32 index)
void IndexGenerator::Init()
{
using OpcodeDecoder::Primitive;
if (g_Config.backend_info.bSupportsPrimitiveRestart)
{
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<true>;
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<true>;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<true>;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<true>;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<true>;
m_primitive_table[Primitive::GX_DRAW_QUADS] = AddQuads<true>;
m_primitive_table[Primitive::GX_DRAW_QUADS_2] = AddQuads_nonstandard<true>;
m_primitive_table[Primitive::GX_DRAW_TRIANGLES] = AddList<true>;
m_primitive_table[Primitive::GX_DRAW_TRIANGLE_STRIP] = AddStrip<true>;
m_primitive_table[Primitive::GX_DRAW_TRIANGLE_FAN] = AddFan<true>;
}
else
{
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS] = AddQuads<false>;
m_primitive_table[OpcodeDecoder::GX_DRAW_QUADS_2] = AddQuads_nonstandard<false>;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLES] = AddList<false>;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP] = AddStrip<false>;
m_primitive_table[OpcodeDecoder::GX_DRAW_TRIANGLE_FAN] = AddFan<false>;
m_primitive_table[Primitive::GX_DRAW_QUADS] = AddQuads<false>;
m_primitive_table[Primitive::GX_DRAW_QUADS_2] = AddQuads_nonstandard<false>;
m_primitive_table[Primitive::GX_DRAW_TRIANGLES] = AddList<false>;
m_primitive_table[Primitive::GX_DRAW_TRIANGLE_STRIP] = AddStrip<false>;
m_primitive_table[Primitive::GX_DRAW_TRIANGLE_FAN] = AddFan<false>;
}
m_primitive_table[OpcodeDecoder::GX_DRAW_LINES] = AddLineList;
m_primitive_table[OpcodeDecoder::GX_DRAW_LINE_STRIP] = AddLineStrip;
m_primitive_table[OpcodeDecoder::GX_DRAW_POINTS] = AddPoints;
m_primitive_table[Primitive::GX_DRAW_LINES] = AddLineList;
m_primitive_table[Primitive::GX_DRAW_LINE_STRIP] = AddLineStrip;
m_primitive_table[Primitive::GX_DRAW_POINTS] = AddPoints;
}
void IndexGenerator::Start(u16* index_ptr)
@ -230,7 +232,7 @@ void IndexGenerator::Start(u16* index_ptr)
m_base_index = 0;
}
void IndexGenerator::AddIndices(int primitive, u32 num_vertices)
void IndexGenerator::AddIndices(OpcodeDecoder::Primitive primitive, u32 num_vertices)
{
m_index_buffer_current =
m_primitive_table[primitive](m_index_buffer_current, num_vertices, m_base_index);

View File

@ -6,8 +6,9 @@
#pragma once
#include <array>
#include "Common/CommonTypes.h"
#include "Common/EnumMap.h"
#include "VideoCommon/OpcodeDecoding.h"
class IndexGenerator
{
@ -15,7 +16,7 @@ public:
void Init();
void Start(u16* index_ptr);
void AddIndices(int primitive, u32 num_vertices);
void AddIndices(OpcodeDecoder::Primitive primitive, u32 num_vertices);
void AddExternalIndices(const u16* indices, u32 num_indices, u32 num_vertices);
@ -30,5 +31,5 @@ private:
u32 m_base_index = 0;
using PrimitiveFunction = u16* (*)(u16*, u32, u32);
std::array<PrimitiveFunction, 8> m_primitive_table{};
Common::EnumMap<PrimitiveFunction, OpcodeDecoder::Primitive::GX_DRAW_POINTS> m_primitive_table{};
};

View File

@ -102,18 +102,18 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
return finish_up();
const u8 cmd_byte = src.Read<u8>();
switch (cmd_byte)
switch (static_cast<Opcode>(cmd_byte))
{
case GX_NOP:
case Opcode::GX_NOP:
total_cycles += 6; // Hm, this means that we scan over nop streams pretty slowly...
break;
case GX_UNKNOWN_RESET:
case Opcode::GX_UNKNOWN_RESET:
total_cycles += 6; // Datel software uses this command
DEBUG_LOG_FMT(VIDEO, "GX Reset?: {:08x}", cmd_byte);
break;
case GX_LOAD_CP_REG:
case Opcode::GX_LOAD_CP_REG:
{
if (src.size() < 1 + 4)
return finish_up();
@ -128,7 +128,7 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
}
break;
case GX_LOAD_XF_REG:
case Opcode::GX_LOAD_XF_REG:
{
if (src.size() < 4)
return finish_up();
@ -151,10 +151,10 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
}
break;
case GX_LOAD_INDX_A: // Used for position matrices
case GX_LOAD_INDX_B: // Used for normal matrices
case GX_LOAD_INDX_C: // Used for postmatrices
case GX_LOAD_INDX_D: // Used for lights
case Opcode::GX_LOAD_INDX_A: // Used for position matrices
case Opcode::GX_LOAD_INDX_B: // Used for normal matrices
case Opcode::GX_LOAD_INDX_C: // Used for postmatrices
case Opcode::GX_LOAD_INDX_D: // Used for lights
{
if (src.size() < 4)
return finish_up();
@ -175,7 +175,7 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
}
break;
case GX_CMD_CALL_DL:
case Opcode::GX_CMD_CALL_DL:
{
if (src.size() < 8)
return finish_up();
@ -198,18 +198,18 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
}
break;
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after
// that
case Opcode::GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics
// registers after that
total_cycles += 6;
DEBUG_LOG_FMT(VIDEO, "GX 0x44: {:08x}", cmd_byte);
break;
case GX_CMD_INVL_VC: // Invalidate Vertex Cache
case Opcode::GX_CMD_INVL_VC: // Invalidate Vertex Cache
total_cycles += 6;
DEBUG_LOG_FMT(VIDEO, "Invalidate (vertex cache?)");
break;
case GX_LOAD_BP_REG:
case Opcode::GX_LOAD_BP_REG:
// In skipped_frame case: We have to let BP writes through because they set
// tokens and stuff. TODO: Call a much simplified LoadBPReg instead.
{
@ -242,7 +242,8 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
const u16 num_vertices = src.Read<u16>();
const int bytes = VertexLoaderManager::RunVertices(
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, num_vertices, src, is_preprocess);
static_cast<Primitive>((cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT),
num_vertices, src, is_preprocess);
if (bytes < 0)
return finish_up();
@ -267,7 +268,7 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
// Display lists get added directly into the FIFO stream
if constexpr (!is_preprocess)
{
if (g_record_fifo_data && cmd_byte != GX_CMD_CALL_DL)
if (g_record_fifo_data && static_cast<Opcode>(cmd_byte) != Opcode::GX_CMD_CALL_DL)
{
const u8* const opcode_end = src.GetPointer();
FifoRecorder::GetInstance().WriteGPCommand(opcode_start, u32(opcode_end - opcode_start));

View File

@ -4,6 +4,7 @@
#pragma once
#include "Common/CommonTypes.h"
#include "Common/EnumFormatter.h"
class DataReader;
@ -12,7 +13,7 @@ namespace OpcodeDecoder
// Global flag to signal if FifoRecorder is active.
extern bool g_record_fifo_data;
enum
enum class Opcode
{
GX_NOP = 0x00,
GX_UNKNOWN_RESET = 0x01,
@ -27,20 +28,20 @@ enum
GX_CMD_CALL_DL = 0x40,
GX_CMD_UNKNOWN_METRICS = 0x44,
GX_CMD_INVL_VC = 0x48
GX_CMD_INVL_VC = 0x48,
GX_PRIMITIVE_START = 0x80,
GX_PRIMITIVE_END = 0xbf,
};
enum
{
GX_PRIMITIVE_MASK = 0x78,
GX_PRIMITIVE_SHIFT = 3,
GX_VAT_MASK = 0x07
};
constexpr u8 GX_PRIMITIVE_MASK = 0x78;
constexpr u32 GX_PRIMITIVE_SHIFT = 3;
constexpr u8 GX_VAT_MASK = 0x07;
// These values are the values extracted using GX_PRIMITIVE_MASK
// and GX_PRIMITIVE_SHIFT.
// GX_DRAW_QUADS_2 behaves the same way as GX_DRAW_QUADS.
enum
enum class Primitive : u8
{
GX_DRAW_QUADS = 0x0, // 0x80
GX_DRAW_QUADS_2 = 0x1, // 0x88
@ -58,3 +59,16 @@ template <bool is_preprocess = false>
u8* Run(DataReader src, u32* cycles, bool in_display_list);
} // namespace OpcodeDecoder
template <>
struct fmt::formatter<OpcodeDecoder::Primitive>
: EnumFormatter<OpcodeDecoder::Primitive::GX_DRAW_POINTS>
{
static constexpr array_type names = {
"GX_DRAW_QUADS", "GX_DRAW_QUADS_2 (nonstandard)",
"GX_DRAW_TRIANGLES", "GX_DRAW_TRIANGLE_STRIP",
"GX_DRAW_TRIANGLE_FAN", "GX_DRAW_LINES",
"GX_DRAW_LINE_STRIP", "GX_DRAW_POINTS",
};
formatter() : EnumFormatter(names) {}
};

View File

@ -239,7 +239,8 @@ static VertexLoaderBase* RefreshLoader(int vtx_attr_group, bool preprocess = fal
return loader;
}
int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bool is_preprocess)
int RunVertices(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int count, DataReader src,
bool is_preprocess)
{
if (!count)
return 0;
@ -266,7 +267,8 @@ int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bo
// if cull mode is CULL_ALL, tell VertexManager to skip triangles and quads.
// They still need to go through vertex loading, because we need to calculate a zfreeze refrence
// slope.
bool cullall = (bpmem.genMode.cullmode == CullMode::All && primitive < 5);
bool cullall = (bpmem.genMode.cullmode == CullMode::All &&
primitive < OpcodeDecoder::Primitive::GX_DRAW_LINES);
DataReader dst = g_vertex_manager->PrepareForAdditionalData(
primitive, count, loader->m_native_vtx_decl.stride, cullall);

View File

@ -14,6 +14,11 @@ class DataReader;
class NativeVertexFormat;
struct PortableVertexDeclaration;
namespace OpcodeDecoder
{
enum class Primitive : u8;
};
namespace VertexLoaderManager
{
using NativeVertexFormatMap =
@ -35,7 +40,8 @@ NativeVertexFormat* GetOrCreateMatchingFormat(const PortableVertexDeclaration& d
NativeVertexFormat* GetUberVertexFormat(const PortableVertexDeclaration& decl);
// Returns -1 if buf_size is insufficient, else the amount of bytes consumed
int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bool is_preprocess);
int RunVertices(int vtx_attr_group, OpcodeDecoder::Primitive primitive, int count, DataReader src,
bool is_preprocess);
NativeVertexFormat* GetCurrentVertexFormat();

View File

@ -10,6 +10,7 @@
#include "Common/BitSet.h"
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/EnumMap.h"
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
@ -38,8 +39,10 @@
std::unique_ptr<VertexManagerBase> g_vertex_manager;
using OpcodeDecoder::Primitive;
// GX primitive -> RenderState primitive, no primitive restart
constexpr std::array<PrimitiveType, 8> primitive_from_gx{{
constexpr Common::EnumMap<PrimitiveType, Primitive::GX_DRAW_POINTS> primitive_from_gx{
PrimitiveType::Triangles, // GX_DRAW_QUADS
PrimitiveType::Triangles, // GX_DRAW_QUADS_2
PrimitiveType::Triangles, // GX_DRAW_TRIANGLES
@ -48,10 +51,10 @@ constexpr std::array<PrimitiveType, 8> primitive_from_gx{{
PrimitiveType::Lines, // GX_DRAW_LINES
PrimitiveType::Lines, // GX_DRAW_LINE_STRIP
PrimitiveType::Points, // GX_DRAW_POINTS
}};
};
// GX primitive -> RenderState primitive, using primitive restart
constexpr std::array<PrimitiveType, 8> primitive_from_gx_pr{{
constexpr Common::EnumMap<PrimitiveType, Primitive::GX_DRAW_POINTS> primitive_from_gx_pr{
PrimitiveType::TriangleStrip, // GX_DRAW_QUADS
PrimitiveType::TriangleStrip, // GX_DRAW_QUADS_2
PrimitiveType::TriangleStrip, // GX_DRAW_TRIANGLES
@ -60,7 +63,7 @@ constexpr std::array<PrimitiveType, 8> primitive_from_gx_pr{{
PrimitiveType::Lines, // GX_DRAW_LINES
PrimitiveType::Lines, // GX_DRAW_LINE_STRIP
PrimitiveType::Points, // GX_DRAW_POINTS
}};
};
// 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
@ -107,13 +110,13 @@ u32 VertexManagerBase::GetRemainingSize() const
return static_cast<u32>(m_end_buffer_pointer - m_cur_buffer_pointer);
}
void VertexManagerBase::AddIndices(int primitive, u32 num_vertices)
void VertexManagerBase::AddIndices(OpcodeDecoder::Primitive primitive, u32 num_vertices)
{
m_index_generator.AddIndices(primitive, num_vertices);
}
DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, u32 stride,
bool cullall)
DataReader VertexManagerBase::PrepareForAdditionalData(OpcodeDecoder::Primitive primitive,
u32 count, u32 stride, bool cullall)
{
// Flush all EFB pokes. Since the buffer is shared, we can't draw pokes+primitives concurrently.
g_framebuffer_manager->FlushEFBPokes();
@ -185,7 +188,7 @@ void VertexManagerBase::FlushData(u32 count, u32 stride)
m_cur_buffer_pointer += count * stride;
}
u32 VertexManagerBase::GetRemainingIndices(int primitive) const
u32 VertexManagerBase::GetRemainingIndices(OpcodeDecoder::Primitive primitive) const
{
const u32 index_len = MAXIBUFFERSIZE - m_index_generator.GetIndexLen();
@ -193,22 +196,22 @@ u32 VertexManagerBase::GetRemainingIndices(int primitive) const
{
switch (primitive)
{
case OpcodeDecoder::GX_DRAW_QUADS:
case OpcodeDecoder::GX_DRAW_QUADS_2:
case Primitive::GX_DRAW_QUADS:
case Primitive::GX_DRAW_QUADS_2:
return index_len / 5 * 4;
case OpcodeDecoder::GX_DRAW_TRIANGLES:
case Primitive::GX_DRAW_TRIANGLES:
return index_len / 4 * 3;
case OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP:
case Primitive::GX_DRAW_TRIANGLE_STRIP:
return index_len / 1 - 1;
case OpcodeDecoder::GX_DRAW_TRIANGLE_FAN:
case Primitive::GX_DRAW_TRIANGLE_FAN:
return index_len / 6 * 4 + 1;
case OpcodeDecoder::GX_DRAW_LINES:
case Primitive::GX_DRAW_LINES:
return index_len;
case OpcodeDecoder::GX_DRAW_LINE_STRIP:
case Primitive::GX_DRAW_LINE_STRIP:
return index_len / 2 + 1;
case OpcodeDecoder::GX_DRAW_POINTS:
case Primitive::GX_DRAW_POINTS:
return index_len;
default:
@ -219,22 +222,22 @@ u32 VertexManagerBase::GetRemainingIndices(int primitive) const
{
switch (primitive)
{
case OpcodeDecoder::GX_DRAW_QUADS:
case OpcodeDecoder::GX_DRAW_QUADS_2:
case Primitive::GX_DRAW_QUADS:
case Primitive::GX_DRAW_QUADS_2:
return index_len / 6 * 4;
case OpcodeDecoder::GX_DRAW_TRIANGLES:
case Primitive::GX_DRAW_TRIANGLES:
return index_len;
case OpcodeDecoder::GX_DRAW_TRIANGLE_STRIP:
case Primitive::GX_DRAW_TRIANGLE_STRIP:
return index_len / 3 + 2;
case OpcodeDecoder::GX_DRAW_TRIANGLE_FAN:
case Primitive::GX_DRAW_TRIANGLE_FAN:
return index_len / 3 + 2;
case OpcodeDecoder::GX_DRAW_LINES:
case Primitive::GX_DRAW_LINES:
return index_len;
case OpcodeDecoder::GX_DRAW_LINE_STRIP:
case Primitive::GX_DRAW_LINE_STRIP:
return index_len / 2 + 1;
case OpcodeDecoder::GX_DRAW_POINTS:
case Primitive::GX_DRAW_POINTS:
return index_len;
default:

View File

@ -35,6 +35,11 @@ enum TexelBufferFormat : u32
NUM_TEXEL_BUFFER_FORMATS
};
namespace OpcodeDecoder
{
enum class Primitive : u8;
};
class VertexManagerBase
{
private:
@ -93,8 +98,9 @@ public:
virtual bool Initialize();
PrimitiveType GetCurrentPrimitiveType() const { return m_current_primitive_type; }
void AddIndices(int primitive, u32 num_vertices);
DataReader PrepareForAdditionalData(int primitive, u32 count, u32 stride, bool cullall);
void AddIndices(OpcodeDecoder::Primitive primitive, u32 num_vertices);
DataReader PrepareForAdditionalData(OpcodeDecoder::Primitive primitive, u32 count, u32 stride,
bool cullall);
void FlushData(u32 count, u32 stride);
void Flush();
@ -163,7 +169,7 @@ protected:
virtual void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex);
u32 GetRemainingSize() const;
u32 GetRemainingIndices(int primitive) const;
u32 GetRemainingIndices(OpcodeDecoder::Primitive primitive) const;
void CalculateZSlope(NativeVertexFormat* format);
void LoadTextures();