diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index bc2fc30bc..f441faa74 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -39,6 +39,7 @@ add_library(core
gpu_hw_vulkan.h
gpu_sw.cpp
gpu_sw.h
+ gpu_types.h
gte.cpp
gte.h
gte_types.h
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 9e07f3d86..128b5f78f 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -134,6 +134,7 @@
+
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 84d774ca5..9f6508c1b 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -101,5 +101,6 @@
+
\ No newline at end of file
diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp
index 39e840171..b3f76ef48 100644
--- a/src/core/gpu.cpp
+++ b/src/core/gpu.cpp
@@ -1305,18 +1305,18 @@ void GPU::FlushRender() {}
void GPU::SetDrawMode(u16 value)
{
- DrawMode::Reg new_mode_reg{static_cast(value & DrawMode::Reg::MASK)};
+ GPUDrawModeReg new_mode_reg{static_cast(value & GPUDrawModeReg::MASK)};
if (!m_set_texture_disable_mask)
new_mode_reg.texture_disable = false;
if (new_mode_reg.bits == m_draw_mode.mode_reg.bits)
return;
- if ((new_mode_reg.bits & DrawMode::Reg::TEXTURE_PAGE_MASK) !=
- (m_draw_mode.mode_reg.bits & DrawMode::Reg::TEXTURE_PAGE_MASK))
+ if ((new_mode_reg.bits & GPUDrawModeReg::TEXTURE_PAGE_MASK) !=
+ (m_draw_mode.mode_reg.bits & GPUDrawModeReg::TEXTURE_PAGE_MASK))
{
- m_draw_mode.texture_page_x = new_mode_reg.GetTexturePageXBase();
- m_draw_mode.texture_page_y = new_mode_reg.GetTexturePageYBase();
+ m_draw_mode.texture_page_x = new_mode_reg.GetTexturePageBaseX();
+ m_draw_mode.texture_page_y = new_mode_reg.GetTexturePageBaseY();
m_draw_mode.texture_page_changed = true;
}
@@ -1327,7 +1327,7 @@ void GPU::SetDrawMode(u16 value)
// Bits 0..10 are returned in the GPU status register.
m_GPUSTAT.bits =
- (m_GPUSTAT.bits & ~(DrawMode::Reg::GPUSTAT_MASK)) | (ZeroExtend32(new_mode_reg.bits) & DrawMode::Reg::GPUSTAT_MASK);
+ (m_GPUSTAT.bits & ~(GPUDrawModeReg::GPUSTAT_MASK)) | (ZeroExtend32(new_mode_reg.bits) & GPUDrawModeReg::GPUSTAT_MASK);
m_GPUSTAT.texture_disable = m_draw_mode.mode_reg.texture_disable;
}
diff --git a/src/core/gpu.h b/src/core/gpu.h
index ee217670e..e2b5efe92 100644
--- a/src/core/gpu.h
+++ b/src/core/gpu.h
@@ -2,6 +2,7 @@
#include "common/bitfield.h"
#include "common/fifo_queue.h"
#include "common/rectangle.h"
+#include "gpu_types.h"
#include "timers.h"
#include "types.h"
#include
@@ -37,66 +38,12 @@ public:
GPUREADtoCPU = 3
};
- enum class Primitive : u8
- {
- Reserved = 0,
- Polygon = 1,
- Line = 2,
- Rectangle = 3
- };
-
- enum class DrawRectangleSize : u8
- {
- Variable = 0,
- R1x1 = 1,
- R8x8 = 2,
- R16x16 = 3
- };
-
- enum class TextureMode : u8
- {
- Palette4Bit = 0,
- Palette8Bit = 1,
- Direct16Bit = 2,
- Reserved_Direct16Bit = 3,
-
- // Not register values.
- RawTextureBit = 4,
- RawPalette4Bit = RawTextureBit | Palette4Bit,
- RawPalette8Bit = RawTextureBit | Palette8Bit,
- RawDirect16Bit = RawTextureBit | Direct16Bit,
- Reserved_RawDirect16Bit = RawTextureBit | Reserved_Direct16Bit,
-
- Disabled = 8 // Not a register value
- };
-
- enum class TransparencyMode : u8
- {
- HalfBackgroundPlusHalfForeground = 0,
- BackgroundPlusForeground = 1,
- BackgroundMinusForeground = 2,
- BackgroundPlusQuarterForeground = 3,
-
- Disabled = 4 // Not a register value
- };
-
enum : u32
{
- VRAM_WIDTH = 1024,
- VRAM_HEIGHT = 512,
- VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16),
- VRAM_WIDTH_MASK = VRAM_WIDTH - 1,
- VRAM_HEIGHT_MASK = VRAM_HEIGHT - 1,
- VRAM_COORD_MASK = 0x3FF,
MAX_FIFO_SIZE = 4096,
- TEXTURE_PAGE_WIDTH = 256,
- TEXTURE_PAGE_HEIGHT = 256,
- MAX_PRIMITIVE_WIDTH = 1024,
- MAX_PRIMITIVE_HEIGHT = 512,
DOT_TIMER_INDEX = 0,
HBLANK_TIMER_INDEX = 1,
MAX_RESOLUTION_SCALE = 16,
- DITHER_MATRIX_SIZE = 4
};
enum : u16
@@ -109,12 +56,6 @@ public:
PAL_TOTAL_LINES = 314,
};
- // 4x4 dither matrix.
- static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = {{-4, +0, -3, +1}, // row 0
- {+2, -2, +3, -1}, // row 1
- {-3, +1, -4, +0}, // row 2
- {+4, -1, +2, -2}}; // row 3
-
// Base class constructor.
GPU();
virtual ~GPU();
@@ -264,60 +205,6 @@ protected:
static bool DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer,
bool remove_alpha);
- union RenderCommand
- {
- u32 bits;
-
- BitField color_for_first_vertex;
- BitField raw_texture_enable; // not valid for lines
- BitField transparency_enable;
- BitField texture_enable;
- BitField rectangle_size; // only for rectangles
- BitField quad_polygon; // only for polygons
- BitField polyline; // only for lines
- BitField shading_enable; // 0 - flat, 1 = gouroud
- BitField primitive;
-
- /// Returns true if texturing should be enabled. Depends on the primitive type.
- bool IsTexturingEnabled() const { return (primitive != Primitive::Line) ? texture_enable : false; }
-
- /// Returns true if dithering should be enabled. Depends on the primitive type.
- bool IsDitheringEnabled() const
- {
- switch (primitive)
- {
- case Primitive::Polygon:
- return shading_enable || (texture_enable && !raw_texture_enable);
-
- case Primitive::Line:
- return true;
-
- case Primitive::Rectangle:
- default:
- return false;
- }
- }
- };
-
- union VertexPosition
- {
- u32 bits;
-
- BitField x;
- BitField y;
- };
-
- // Sprites/rectangles should be clipped to 12 bits before drawing.
- static constexpr s32 TruncateVertexPosition(s32 x) { return SignExtendN<11, s32>(x); }
-
- struct NativeVertex
- {
- s16 x;
- s16 y;
- u32 color;
- u16 texcoord;
- };
-
union VRAMPixel
{
u16 bits;
@@ -508,8 +395,8 @@ protected:
u32 bits;
BitField texture_page_x_base;
BitField texture_page_y_base;
- BitField semi_transparency_mode;
- BitField texture_color_mode;
+ BitField semi_transparency_mode;
+ BitField texture_color_mode;
BitField dither_enable;
BitField draw_to_displayed_field;
BitField set_mask_while_drawing;
@@ -567,36 +454,8 @@ protected:
static constexpr u16 PALETTE_MASK = UINT16_C(0b0111111111111111);
static constexpr u32 TEXTURE_WINDOW_MASK = UINT32_C(0b11111111111111111111);
- // bits in GP0(E1h) or texpage part of polygon
- union Reg
- {
- static constexpr u16 MASK = 0b1111111111111;
- static constexpr u16 TEXTURE_PAGE_MASK = UINT16_C(0b0000000000011111);
-
- // Polygon texpage commands only affect bits 0-8, 11
- static constexpr u16 POLYGON_TEXPAGE_MASK = 0b0000100111111111;
-
- // Bits 0..5 are returned in the GPU status register, latched at E1h/polygon draw time.
- static constexpr u32 GPUSTAT_MASK = 0b11111111111;
-
- u16 bits;
-
- BitField texture_page_x_base;
- BitField texture_page_y_base;
- BitField transparency_mode;
- BitField texture_mode;
- BitField dither_enable;
- BitField draw_to_displayed_field;
- BitField texture_disable;
- BitField texture_x_flip;
- BitField texture_y_flip;
-
- u32 GetTexturePageXBase() const { return ZeroExtend32(texture_page_x_base.GetValue()) * 64; }
- u32 GetTexturePageYBase() const { return ZeroExtend32(texture_page_y_base.GetValue()) * 256; }
- };
-
// original values
- Reg mode_reg;
+ GPUDrawModeReg mode_reg;
u16 palette_reg; // from vertex
u32 texture_window_value;
@@ -615,10 +474,10 @@ protected:
bool texture_window_changed;
/// Returns the texture/palette rendering mode.
- TextureMode GetTextureMode() const { return mode_reg.texture_mode; }
+ GPUTextureMode GetTextureMode() const { return mode_reg.texture_mode; }
/// Returns the semi-transparency mode when enabled.
- TransparencyMode GetTransparencyMode() const { return mode_reg.transparency_mode; }
+ GPUTransparencyMode GetTransparencyMode() const { return mode_reg.transparency_mode; }
/// Returns true if the texture mode requires a palette.
bool IsUsingPalette() const { return (mode_reg.bits & (2 << 7)) == 0; }
@@ -757,7 +616,7 @@ protected:
HeapFIFOQueue m_fifo;
std::vector m_blit_buffer;
u32 m_blit_remaining_words;
- RenderCommand m_render_command{};
+ GPURenderCommand m_render_command{};
ALWAYS_INLINE u32 FifoPop() { return Truncate32(m_fifo.Pop()); }
ALWAYS_INLINE u32 FifoPeek() { return Truncate32(m_fifo.Peek()); }
@@ -806,6 +665,4 @@ private:
static const GP0CommandHandlerTable s_GP0_command_handler_table;
};
-IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(GPU::TextureMode);
-
extern std::unique_ptr g_gpu;
diff --git a/src/core/gpu_commands.cpp b/src/core/gpu_commands.cpp
index 4db537e43..bdf324069 100644
--- a/src/core/gpu_commands.cpp
+++ b/src/core/gpu_commands.cpp
@@ -132,16 +132,16 @@ GPU::GP0CommandHandlerTable GPU::GenerateGP0CommandHandlerTable()
table[0x1F] = &GPU::HandleInterruptRequestCommand;
for (u32 i = 0x20; i <= 0x7F; i++)
{
- const RenderCommand rc{i << 24};
+ const GPURenderCommand rc{i << 24};
switch (rc.primitive)
{
- case Primitive::Polygon:
+ case GPUPrimitive::Polygon:
table[i] = &GPU::HandleRenderPolygonCommand;
break;
- case Primitive::Line:
+ case GPUPrimitive::Line:
table[i] = rc.polyline ? &GPU::HandleRenderPolyLineCommand : &GPU::HandleRenderLineCommand;
break;
- case Primitive::Rectangle:
+ case GPUPrimitive::Rectangle:
table[i] = &GPU::HandleRenderRectangleCommand;
break;
default:
@@ -314,7 +314,7 @@ bool GPU::HandleSetMaskBitCommand()
bool GPU::HandleRenderPolygonCommand()
{
- const RenderCommand rc{FifoPeek(0)};
+ const GPURenderCommand rc{FifoPeek(0)};
// shaded vertices use the colour from the first word for the first vertex
const u32 words_per_vertex = 1 + BoolToUInt32(rc.texture_enable) + BoolToUInt32(rc.shading_enable);
@@ -341,8 +341,8 @@ bool GPU::HandleRenderPolygonCommand()
if (rc.texture_enable)
{
const u16 texpage_attribute = Truncate16((rc.shading_enable ? FifoPeek(5) : FifoPeek(4)) >> 16);
- SetDrawMode((texpage_attribute & DrawMode::Reg::POLYGON_TEXPAGE_MASK) |
- (m_draw_mode.mode_reg.bits & ~DrawMode::Reg::POLYGON_TEXPAGE_MASK));
+ SetDrawMode((texpage_attribute & GPUDrawModeReg::POLYGON_TEXPAGE_MASK) |
+ (m_draw_mode.mode_reg.bits & ~GPUDrawModeReg::POLYGON_TEXPAGE_MASK));
SetTexturePalette(Truncate16(FifoPeek(2) >> 16));
}
@@ -358,9 +358,9 @@ bool GPU::HandleRenderPolygonCommand()
bool GPU::HandleRenderRectangleCommand()
{
- const RenderCommand rc{FifoPeek(0)};
+ const GPURenderCommand rc{FifoPeek(0)};
const u32 total_words =
- 2 + BoolToUInt32(rc.texture_enable) + BoolToUInt32(rc.rectangle_size == DrawRectangleSize::Variable);
+ 2 + BoolToUInt32(rc.texture_enable) + BoolToUInt32(rc.rectangle_size == GPUDrawRectangleSize::Variable);
CHECK_COMMAND_SIZE(total_words);
@@ -390,7 +390,7 @@ bool GPU::HandleRenderRectangleCommand()
bool GPU::HandleRenderLineCommand()
{
- const RenderCommand rc{FifoPeek(0)};
+ const GPURenderCommand rc{FifoPeek(0)};
const u32 total_words = rc.shading_enable ? 4 : 3;
CHECK_COMMAND_SIZE(total_words);
@@ -413,7 +413,7 @@ bool GPU::HandleRenderLineCommand()
bool GPU::HandleRenderPolyLineCommand()
{
// always read the first two vertices, we test for the terminator after that
- const RenderCommand rc{FifoPeek(0)};
+ const GPURenderCommand rc{FifoPeek(0)};
const u32 min_words = rc.shading_enable ? 3 : 4;
CHECK_COMMAND_SIZE(min_words);
diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp
index 0e6c152d1..078e33ac5 100644
--- a/src/core/gpu_hw.cpp
+++ b/src/core/gpu_hw.cpp
@@ -403,13 +403,13 @@ void GPU_HW::LoadVertices()
if (m_GPUSTAT.check_mask_before_draw)
m_current_depth++;
- const RenderCommand rc{m_render_command.bits};
+ const GPURenderCommand rc{m_render_command.bits};
const u32 texpage = ZeroExtend32(m_draw_mode.mode_reg.bits) | (ZeroExtend32(m_draw_mode.palette_reg) << 16);
const float depth = GetCurrentNormalizedVertexDepth();
switch (rc.primitive)
{
- case Primitive::Polygon:
+ case GPUPrimitive::Polygon:
{
DebugAssert(GetBatchVertexSpace() >= (rc.quad_polygon ? 6u : 3u));
@@ -426,7 +426,7 @@ void GPU_HW::LoadVertices()
{
const u32 color = (shaded && i > 0) ? (FifoPop() & UINT32_C(0x00FFFFFF)) : first_color;
const u64 maddr_and_pos = m_fifo.Pop();
- const VertexPosition vp{Truncate32(maddr_and_pos)};
+ const GPUVertexPosition vp{Truncate32(maddr_and_pos)};
const u16 texcoord = textured ? Truncate16(FifoPop()) : 0;
const s32 native_x = m_drawing_offset.x + vp.x;
const s32 native_y = m_drawing_offset.y + vp.y;
@@ -527,12 +527,12 @@ void GPU_HW::LoadVertices()
}
break;
- case Primitive::Rectangle:
+ case GPUPrimitive::Rectangle:
{
const u32 color = rc.color_for_first_vertex;
- const VertexPosition vp{FifoPop()};
- const s32 pos_x = TruncateVertexPosition(m_drawing_offset.x + vp.x);
- const s32 pos_y = TruncateVertexPosition(m_drawing_offset.y + vp.y);
+ const GPUVertexPosition vp{FifoPop()};
+ const s32 pos_x = TruncateGPUVertexPosition(m_drawing_offset.x + vp.x);
+ const s32 pos_y = TruncateGPUVertexPosition(m_drawing_offset.y + vp.y);
const auto [texcoord_x, texcoord_y] = UnpackTexcoord(rc.texture_enable ? Truncate16(FifoPop()) : 0);
u16 orig_tex_left = ZeroExtend16(texcoord_x);
@@ -541,15 +541,15 @@ void GPU_HW::LoadVertices()
s32 rectangle_height;
switch (rc.rectangle_size)
{
- case DrawRectangleSize::R1x1:
+ case GPUDrawRectangleSize::R1x1:
rectangle_width = 1;
rectangle_height = 1;
break;
- case DrawRectangleSize::R8x8:
+ case GPUDrawRectangleSize::R8x8:
rectangle_width = 8;
rectangle_height = 8;
break;
- case DrawRectangleSize::R16x16:
+ case GPUDrawRectangleSize::R16x16:
rectangle_width = 16;
rectangle_height = 16;
break;
@@ -621,14 +621,14 @@ void GPU_HW::LoadVertices()
}
break;
- case Primitive::Line:
+ case GPUPrimitive::Line:
{
if (!rc.polyline)
{
DebugAssert(GetBatchVertexSpace() >= 2);
u32 start_color, end_color;
- VertexPosition start_pos, end_pos;
+ GPUVertexPosition start_pos, end_pos;
if (rc.shading_enable)
{
start_color = rc.color_for_first_vertex;
@@ -683,7 +683,7 @@ void GPU_HW::LoadVertices()
const bool shaded = rc.shading_enable;
u32 buffer_pos = 0;
- const VertexPosition start_vp{m_blit_buffer[buffer_pos++]};
+ const GPUVertexPosition start_vp{m_blit_buffer[buffer_pos++]};
s32 start_x = start_vp.x + m_drawing_offset.x;
s32 start_y = start_vp.y + m_drawing_offset.y;
u32 start_color = rc.color_for_first_vertex;
@@ -691,7 +691,7 @@ void GPU_HW::LoadVertices()
for (u32 i = 1; i < num_vertices; i++)
{
const u32 end_color = shaded ? (m_blit_buffer[buffer_pos++] & UINT32_C(0x00FFFFFF)) : start_color;
- const VertexPosition vp{m_blit_buffer[buffer_pos++]};
+ const GPUVertexPosition vp{m_blit_buffer[buffer_pos++]};
const s32 end_x = m_drawing_offset.x + vp.x;
const s32 end_y = m_drawing_offset.y + vp.y;
@@ -842,13 +842,13 @@ void GPU_HW::EnsureVertexBufferSpaceForCurrentCommand()
u32 required_vertices;
switch (m_render_command.primitive)
{
- case Primitive::Polygon:
+ case GPUPrimitive::Polygon:
required_vertices = m_render_command.quad_polygon ? 6 : 3;
break;
- case Primitive::Rectangle:
+ case GPUPrimitive::Rectangle:
required_vertices = MAX_VERTICES_FOR_RECTANGLE;
break;
- case Primitive::Line:
+ case GPUPrimitive::Line:
default:
required_vertices = m_render_command.polyline ? (GetPolyLineVertexCount() * 6u) : 6u;
break;
@@ -912,9 +912,9 @@ void GPU_HW::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32
void GPU_HW::DispatchRenderCommand()
{
- const RenderCommand rc{m_render_command.bits};
+ const GPURenderCommand rc{m_render_command.bits};
- TextureMode texture_mode;
+ GPUTextureMode texture_mode;
if (rc.IsTexturingEnabled())
{
// texture page changed - check that the new page doesn't intersect the drawing area
@@ -937,17 +937,17 @@ void GPU_HW::DispatchRenderCommand()
if (rc.raw_texture_enable)
{
texture_mode =
- static_cast(static_cast(texture_mode) | static_cast(TextureMode::RawTextureBit));
+ static_cast(static_cast(texture_mode) | static_cast(GPUTextureMode::RawTextureBit));
}
}
else
{
- texture_mode = TextureMode::Disabled;
+ texture_mode = GPUTextureMode::Disabled;
}
// has any state changed which requires a new batch?
- const TransparencyMode transparency_mode =
- rc.transparency_enable ? m_draw_mode.GetTransparencyMode() : TransparencyMode::Disabled;
+ const GPUTransparencyMode transparency_mode =
+ rc.transparency_enable ? m_draw_mode.GetTransparencyMode() : GPUTransparencyMode::Disabled;
const bool dithering_enable = (!m_true_color && rc.IsDitheringEnabled()) ? m_GPUSTAT.dither_enable : false;
if (m_batch.texture_mode != texture_mode || m_batch.transparency_mode != transparency_mode ||
dithering_enable != m_batch.dithering)
@@ -958,7 +958,7 @@ void GPU_HW::DispatchRenderCommand()
EnsureVertexBufferSpaceForCurrentCommand();
// transparency mode change
- if (m_batch.transparency_mode != transparency_mode && transparency_mode != TransparencyMode::Disabled)
+ if (m_batch.transparency_mode != transparency_mode && transparency_mode != GPUTransparencyMode::Disabled)
{
static constexpr float transparent_alpha[4][2] = {{0.5f, 0.5f}, {1.0f, 1.0f}, {1.0f, 1.0f}, {0.25f, 1.0f}};
m_batch_ubo_data.u_src_alpha_factor = transparent_alpha[static_cast(transparency_mode)][0];
diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h
index 2bd162845..b8c691dec 100644
--- a/src/core/gpu_hw.h
+++ b/src/core/gpu_hw.h
@@ -94,8 +94,8 @@ protected:
struct BatchConfig
{
- TextureMode texture_mode;
- TransparencyMode transparency_mode;
+ GPUTextureMode texture_mode;
+ GPUTransparencyMode transparency_mode;
bool dithering;
bool interlacing;
bool set_mask_while_drawing;
@@ -105,15 +105,15 @@ protected:
// on a per-pixel basis, and the opaque pixels shouldn't be blended at all.
bool NeedsTwoPassRendering() const
{
- return transparency_mode == GPU::TransparencyMode::BackgroundMinusForeground &&
- texture_mode != TextureMode::Disabled;
+ return transparency_mode == GPUTransparencyMode::BackgroundMinusForeground &&
+ texture_mode != GPUTextureMode::Disabled;
}
// Returns the render mode for this batch.
BatchRenderMode GetRenderMode() const
{
- return transparency_mode == TransparencyMode::Disabled ? BatchRenderMode::TransparencyDisabled :
- BatchRenderMode::TransparentAndOpaque;
+ return transparency_mode == GPUTransparencyMode::Disabled ? BatchRenderMode::TransparencyDisabled :
+ BatchRenderMode::TransparentAndOpaque;
}
};
diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp
index c209a8a1c..ba46706dd 100644
--- a/src/core/gpu_hw_d3d11.cpp
+++ b/src/core/gpu_hw_d3d11.cpp
@@ -347,7 +347,7 @@ bool GPU_HW_D3D11::CreateStateObjects()
for (u8 transparency_mode = 0; transparency_mode < 5; transparency_mode++)
{
bl_desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
- if (transparency_mode != static_cast(TransparencyMode::Disabled) ||
+ if (transparency_mode != static_cast(GPUTransparencyMode::Disabled) ||
m_texture_filtering != GPUTextureFilter::Nearest)
{
bl_desc.RenderTarget[0].BlendEnable = TRUE;
@@ -356,7 +356,7 @@ bool GPU_HW_D3D11::CreateStateObjects()
bl_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
bl_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
bl_desc.RenderTarget[0].BlendOp =
- (transparency_mode == static_cast(TransparencyMode::BackgroundMinusForeground)) ?
+ (transparency_mode == static_cast(GPUTransparencyMode::BackgroundMinusForeground)) ?
D3D11_BLEND_OP_REV_SUBTRACT :
D3D11_BLEND_OP_ADD;
bl_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
@@ -462,7 +462,7 @@ bool GPU_HW_D3D11::CompileShaders()
for (u8 interlacing = 0; interlacing < 2; interlacing++)
{
const std::string ps = shadergen.GenerateBatchFragmentShader(
- static_cast(render_mode), static_cast(texture_mode),
+ static_cast(render_mode), static_cast(texture_mode),
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
m_batch_pixel_shaders[render_mode][texture_mode][dithering][interlacing] =
@@ -610,7 +610,7 @@ void GPU_HW_D3D11::DrawUtilityShader(ID3D11PixelShader* shader, const void* unif
void GPU_HW_D3D11::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices)
{
- const bool textured = (m_batch.texture_mode != TextureMode::Disabled);
+ const bool textured = (m_batch.texture_mode != GPUTextureMode::Disabled);
m_context->VSSetShader(m_batch_vertex_shaders[BoolToUInt8(textured)].Get(), nullptr, 0);
@@ -619,8 +619,8 @@ void GPU_HW_D3D11::DrawBatchVertices(BatchRenderMode render_mode, u32 base_verte
.Get(),
nullptr, 0);
- const TransparencyMode transparency_mode =
- (render_mode == BatchRenderMode::OnlyOpaque) ? TransparencyMode::Disabled : m_batch.transparency_mode;
+ const GPUTransparencyMode transparency_mode =
+ (render_mode == BatchRenderMode::OnlyOpaque) ? GPUTransparencyMode::Disabled : m_batch.transparency_mode;
m_context->OMSetBlendState(m_batch_blend_states[static_cast(transparency_mode)].Get(), nullptr, 0xFFFFFFFFu);
m_context->OMSetDepthStencilState(
m_batch.check_mask_before_draw ? m_depth_test_less_state.Get() : m_depth_test_always_state.Get(), 0);
diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp
index 1ea2c2a6f..c4b702b57 100644
--- a/src/core/gpu_hw_opengl.cpp
+++ b/src/core/gpu_hw_opengl.cpp
@@ -395,10 +395,10 @@ bool GPU_HW_OpenGL::CompilePrograms()
{
for (u8 interlacing = 0; interlacing < 2; interlacing++)
{
- const bool textured = (static_cast(texture_mode) != TextureMode::Disabled);
+ const bool textured = (static_cast(texture_mode) != GPUTextureMode::Disabled);
const std::string batch_vs = shadergen.GenerateBatchVertexShader(textured);
const std::string fs = shadergen.GenerateBatchFragmentShader(
- static_cast(render_mode), static_cast(texture_mode),
+ static_cast(render_mode), static_cast(texture_mode),
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
const auto link_callback = [this, textured, use_binding_layout](GL::Program& prog) {
@@ -588,7 +588,7 @@ void GPU_HW_OpenGL::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vert
void GPU_HW_OpenGL::SetBlendMode()
{
- if (m_texture_filtering == GPUTextureFilter::Nearest && (m_current_transparency_mode == TransparencyMode::Disabled ||
+ if (m_texture_filtering == GPUTextureFilter::Nearest && (m_current_transparency_mode == GPUTransparencyMode::Disabled ||
m_current_render_mode == BatchRenderMode::OnlyOpaque))
{
glDisable(GL_BLEND);
@@ -596,7 +596,7 @@ void GPU_HW_OpenGL::SetBlendMode()
else
{
glEnable(GL_BLEND);
- glBlendEquationSeparate(m_current_transparency_mode == TransparencyMode::BackgroundMinusForeground ?
+ glBlendEquationSeparate(m_current_transparency_mode == GPUTransparencyMode::BackgroundMinusForeground ?
GL_FUNC_REVERSE_SUBTRACT :
GL_FUNC_ADD,
GL_FUNC_ADD);
diff --git a/src/core/gpu_hw_opengl.h b/src/core/gpu_hw_opengl.h
index 7b748a69c..d9528d706 100644
--- a/src/core/gpu_hw_opengl.h
+++ b/src/core/gpu_hw_opengl.h
@@ -99,6 +99,6 @@ private:
bool m_use_ssbo_for_vram_writes = false;
bool m_current_check_mask_before_draw = false;
- TransparencyMode m_current_transparency_mode = TransparencyMode::Disabled;
+ GPUTransparencyMode m_current_transparency_mode = GPUTransparencyMode::Disabled;
BatchRenderMode m_current_render_mode = BatchRenderMode::TransparencyDisabled;
};
diff --git a/src/core/gpu_hw_shadergen.cpp b/src/core/gpu_hw_shadergen.cpp
index c6d6de5f8..59c2414b6 100644
--- a/src/core/gpu_hw_shadergen.cpp
+++ b/src/core/gpu_hw_shadergen.cpp
@@ -19,7 +19,7 @@ void GPU_HW_ShaderGen::WriteCommonFunctions(std::stringstream& ss)
DefineMacro(ss, "MULTISAMPLING", UsingMSAA());
ss << "CONSTANT uint RESOLUTION_SCALE = " << m_resolution_scale << "u;\n";
- ss << "CONSTANT uint2 VRAM_SIZE = uint2(" << GPU::VRAM_WIDTH << ", " << GPU::VRAM_HEIGHT << ") * RESOLUTION_SCALE;\n";
+ ss << "CONSTANT uint2 VRAM_SIZE = uint2(" << VRAM_WIDTH << ", " << VRAM_HEIGHT << ") * RESOLUTION_SCALE;\n";
ss << "CONSTANT float2 RCP_VRAM_SIZE = float2(1.0, 1.0) / float2(VRAM_SIZE);\n";
ss << "CONSTANT uint MULTISAMPLES = " << m_multisamples << "u;\n";
ss << "CONSTANT bool PER_SAMPLE_SHADING = " << (m_per_sample_shading ? "true" : "false") << ";\n";
@@ -650,12 +650,11 @@ void FilteredSampleFromVRAM(uint4 texpage, float2 coords, float4 uv_limits,
}
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency,
- GPU::TextureMode texture_mode, bool dithering,
- bool interlacing)
+ GPUTextureMode texture_mode, bool dithering, bool interlacing)
{
- const GPU::TextureMode actual_texture_mode = texture_mode & ~GPU::TextureMode::RawTextureBit;
- const bool raw_texture = (texture_mode & GPU::TextureMode::RawTextureBit) == GPU::TextureMode::RawTextureBit;
- const bool textured = (texture_mode != GPU::TextureMode::Disabled);
+ const GPUTextureMode actual_texture_mode = texture_mode & ~GPUTextureMode::RawTextureBit;
+ const bool raw_texture = (texture_mode & GPUTextureMode::RawTextureBit) == GPUTextureMode::RawTextureBit;
+ const bool textured = (texture_mode != GPUTextureMode::Disabled);
const bool use_dual_source =
m_supports_dual_source_blend && ((transparency != GPU_HW::BatchRenderMode::TransparencyDisabled &&
transparency != GPU_HW::BatchRenderMode::OnlyOpaque) ||
@@ -668,10 +667,9 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod
DefineMacro(ss, "TRANSPARENCY_ONLY_TRANSPARENT", transparency == GPU_HW::BatchRenderMode::OnlyTransparent);
DefineMacro(ss, "TEXTURED", textured);
DefineMacro(ss, "PALETTE",
- actual_texture_mode == GPU::TextureMode::Palette4Bit ||
- actual_texture_mode == GPU::TextureMode::Palette8Bit);
- DefineMacro(ss, "PALETTE_4_BIT", actual_texture_mode == GPU::TextureMode::Palette4Bit);
- DefineMacro(ss, "PALETTE_8_BIT", actual_texture_mode == GPU::TextureMode::Palette8Bit);
+ actual_texture_mode == GPUTextureMode::Palette4Bit || actual_texture_mode == GPUTextureMode::Palette8Bit);
+ DefineMacro(ss, "PALETTE_4_BIT", actual_texture_mode == GPUTextureMode::Palette4Bit);
+ DefineMacro(ss, "PALETTE_8_BIT", actual_texture_mode == GPUTextureMode::Palette8Bit);
DefineMacro(ss, "RAW_TEXTURE", raw_texture);
DefineMacro(ss, "DITHERING", dithering);
DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering);
@@ -693,7 +691,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod
{
if (i > 0)
ss << ", ";
- ss << GPU::DITHER_MATRIX[i / 4][i % 4];
+ ss << DITHER_MATRIX[i / 4][i % 4];
}
if (m_glsl)
ss << " );\n";
diff --git a/src/core/gpu_hw_shadergen.h b/src/core/gpu_hw_shadergen.h
index 998d53d96..b041908e7 100644
--- a/src/core/gpu_hw_shadergen.h
+++ b/src/core/gpu_hw_shadergen.h
@@ -11,7 +11,7 @@ public:
~GPU_HW_ShaderGen();
std::string GenerateBatchVertexShader(bool textured);
- std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency, GPU::TextureMode texture_mode,
+ std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency, GPUTextureMode texture_mode,
bool dithering, bool interlacing);
std::string GenerateInterlacedFillFragmentShader();
std::string GenerateDisplayFragmentShader(bool depth_24bit, GPU_HW::InterlacedRenderMode interlace_mode,
diff --git a/src/core/gpu_hw_vulkan.cpp b/src/core/gpu_hw_vulkan.cpp
index 2d77fdd2b..90724b8bc 100644
--- a/src/core/gpu_hw_vulkan.cpp
+++ b/src/core/gpu_hw_vulkan.cpp
@@ -642,7 +642,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
for (u8 interlacing = 0; interlacing < 2; interlacing++)
{
const std::string fs = shadergen.GenerateBatchFragmentShader(
- static_cast(render_mode), static_cast(texture_mode),
+ static_cast(render_mode), static_cast(texture_mode),
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
VkShaderModule shader = g_vulkan_shader_cache->GetFragmentShader(fs);
@@ -671,7 +671,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
{
for (u8 interlacing = 0; interlacing < 2; interlacing++)
{
- const bool textured = (static_cast(texture_mode) != TextureMode::Disabled);
+ const bool textured = (static_cast(texture_mode) != GPUTextureMode::Disabled);
gpbuilder.SetPipelineLayout(m_batch_pipeline_layout);
gpbuilder.SetRenderPass(m_vram_render_pass, 0);
@@ -697,7 +697,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
gpbuilder.SetNoBlendingState();
gpbuilder.SetMultisamples(m_multisamples, m_per_sample_shading);
- if ((static_cast(transparency_mode) != TransparencyMode::Disabled &&
+ if ((static_cast(transparency_mode) != GPUTransparencyMode::Disabled &&
(static_cast(render_mode) != BatchRenderMode::TransparencyDisabled &&
static_cast(render_mode) != BatchRenderMode::OnlyOpaque)) ||
m_texture_filtering != GPUTextureFilter::Nearest)
@@ -705,7 +705,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
gpbuilder.SetBlendAttachment(
0, true, VK_BLEND_FACTOR_ONE,
m_supports_dual_source_blend ? VK_BLEND_FACTOR_SRC1_ALPHA : VK_BLEND_FACTOR_SRC_ALPHA,
- (static_cast(transparency_mode) == TransparencyMode::BackgroundMinusForeground &&
+ (static_cast(transparency_mode) == GPUTransparencyMode::BackgroundMinusForeground &&
static_cast(render_mode) != BatchRenderMode::TransparencyDisabled &&
static_cast(render_mode) != BatchRenderMode::OnlyOpaque) ?
VK_BLEND_OP_REVERSE_SUBTRACT :
diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp
index f514e8994..59785e4f1 100644
--- a/src/core/gpu_sw.cpp
+++ b/src/core/gpu_sw.cpp
@@ -536,12 +536,12 @@ void GPU_SW::UpdateDisplay()
void GPU_SW::DispatchRenderCommand()
{
- const RenderCommand rc{m_render_command.bits};
+ const GPURenderCommand rc{m_render_command.bits};
const bool dithering_enable = rc.IsDitheringEnabled() && m_GPUSTAT.dither_enable;
switch (rc.primitive)
{
- case Primitive::Polygon:
+ case GPUPrimitive::Polygon:
{
const u32 first_color = rc.color_for_first_vertex;
const bool shaded = rc.shading_enable;
@@ -557,7 +557,7 @@ void GPU_SW::DispatchRenderCommand()
vert.g = Truncate8(color_rgb >> 8);
vert.b = Truncate8(color_rgb >> 16);
- const VertexPosition vp{FifoPop()};
+ const GPUVertexPosition vp{FifoPop()};
vert.x = m_drawing_offset.x + vp.x;
vert.y = m_drawing_offset.y + vp.y;
@@ -584,10 +584,10 @@ void GPU_SW::DispatchRenderCommand()
}
break;
- case Primitive::Rectangle:
+ case GPUPrimitive::Rectangle:
{
const auto [r, g, b] = UnpackColorRGB24(rc.color_for_first_vertex);
- const VertexPosition vp{FifoPop()};
+ const GPUVertexPosition vp{FifoPop()};
const u32 texcoord_and_palette = rc.texture_enable ? FifoPop() : 0;
const auto [texcoord_x, texcoord_y] = UnpackTexcoord(Truncate16(texcoord_and_palette));
@@ -595,15 +595,15 @@ void GPU_SW::DispatchRenderCommand()
u32 height;
switch (rc.rectangle_size)
{
- case DrawRectangleSize::R1x1:
+ case GPUDrawRectangleSize::R1x1:
width = 1;
height = 1;
break;
- case DrawRectangleSize::R8x8:
+ case GPUDrawRectangleSize::R8x8:
width = 8;
height = 8;
break;
- case DrawRectangleSize::R16x16:
+ case GPUDrawRectangleSize::R16x16:
width = 16;
height = 16;
break;
@@ -633,7 +633,7 @@ void GPU_SW::DispatchRenderCommand()
}
break;
- case Primitive::Line:
+ case GPUPrimitive::Line:
{
const u32 first_color = rc.color_for_first_vertex;
const bool shaded = rc.shading_enable;
@@ -646,7 +646,7 @@ void GPU_SW::DispatchRenderCommand()
// first vertex
SWVertex* p0 = &vertices[0];
SWVertex* p1 = &vertices[1];
- p0->SetPosition(VertexPosition{rc.polyline ? m_blit_buffer[buffer_pos++] : Truncate32(FifoPop())},
+ p0->SetPosition(GPUVertexPosition{rc.polyline ? m_blit_buffer[buffer_pos++] : Truncate32(FifoPop())},
m_drawing_offset.x, m_drawing_offset.y);
p0->SetColorRGB24(first_color);
@@ -657,12 +657,12 @@ void GPU_SW::DispatchRenderCommand()
if (rc.polyline)
{
p1->SetColorRGB24(shaded ? (m_blit_buffer[buffer_pos++] & UINT32_C(0x00FFFFFF)) : first_color);
- p1->SetPosition(VertexPosition{m_blit_buffer[buffer_pos++]}, m_drawing_offset.x, m_drawing_offset.y);
+ p1->SetPosition(GPUVertexPosition{m_blit_buffer[buffer_pos++]}, m_drawing_offset.x, m_drawing_offset.y);
}
else
{
p1->SetColorRGB24(shaded ? (FifoPop() & UINT32_C(0x00FFFFFF)) : first_color);
- p1->SetPosition(VertexPosition{Truncate32(FifoPop())}, m_drawing_offset.x, m_drawing_offset.y);
+ p1->SetPosition(GPUVertexPosition{Truncate32(FifoPop())}, m_drawing_offset.x, m_drawing_offset.y);
}
// down here because of the FIFO pops
@@ -716,7 +716,7 @@ void ALWAYS_INLINE_RELEASE GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color
VRAMPixel texture_color;
switch (m_draw_mode.GetTextureMode())
{
- case GPU::TextureMode::Palette4Bit:
+ case GPUTextureMode::Palette4Bit:
{
const u16 palette_value = GetPixel((m_draw_mode.texture_page_x + ZeroExtend32(texcoord_x / 4)) % VRAM_WIDTH,
(m_draw_mode.texture_page_y + ZeroExtend32(texcoord_y)) % VRAM_HEIGHT);
@@ -726,7 +726,7 @@ void ALWAYS_INLINE_RELEASE GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color
}
break;
- case GPU::TextureMode::Palette8Bit:
+ case GPUTextureMode::Palette8Bit:
{
const u16 palette_value = GetPixel((m_draw_mode.texture_page_x + ZeroExtend32(texcoord_x / 2)) % VRAM_WIDTH,
(m_draw_mode.texture_page_y + ZeroExtend32(texcoord_y)) % VRAM_HEIGHT);
@@ -792,16 +792,16 @@ void ALWAYS_INLINE_RELEASE GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color
switch (m_draw_mode.GetTransparencyMode())
{
- case GPU::TransparencyMode::HalfBackgroundPlusHalfForeground:
+ case GPUTransparencyMode::HalfBackgroundPlusHalfForeground:
BLEND_RGB(BLEND_AVERAGE);
break;
- case GPU::TransparencyMode::BackgroundPlusForeground:
+ case GPUTransparencyMode::BackgroundPlusForeground:
BLEND_RGB(BLEND_ADD);
break;
- case GPU::TransparencyMode::BackgroundMinusForeground:
+ case GPUTransparencyMode::BackgroundMinusForeground:
BLEND_RGB(BLEND_SUBTRACT);
break;
- case GPU::TransparencyMode::BackgroundPlusQuarterForeground:
+ case GPUTransparencyMode::BackgroundPlusQuarterForeground:
BLEND_RGB(BLEND_QUARTER);
break;
default:
@@ -832,8 +832,8 @@ template
void GPU_SW::DrawRectangle(s32 origin_x, s32 origin_y, u32 width, u32 height, u8 r, u8 g, u8 b, u8 origin_texcoord_x,
u8 origin_texcoord_y)
{
- const s32 start_x = TruncateVertexPosition(m_drawing_offset.x + origin_x);
- const s32 start_y = TruncateVertexPosition(m_drawing_offset.y + origin_y);
+ const s32 start_x = TruncateGPUVertexPosition(m_drawing_offset.x + origin_x);
+ const s32 start_y = TruncateGPUVertexPosition(m_drawing_offset.y + origin_y);
{
const u32 clip_left = static_cast(std::clamp(start_x, m_drawing_area.left, m_drawing_area.right));
@@ -990,7 +990,7 @@ void GPU_SW::DrawSpan(s32 y, s32 x_start, s32 x_bound, i_group ig, const i_delta
s32 x_ig_adjust = x_start;
s32 w = x_bound - x_start;
- s32 x = TruncateVertexPosition(x_start);
+ s32 x = TruncateGPUVertexPosition(x_start);
if (x < static_cast(m_drawing_area.left))
{
@@ -1182,7 +1182,7 @@ void GPU_SW::DrawTriangle(const SWVertex* v0, const SWVertex* v1, const SWVertex
lc -= ls;
rc -= rs;
- s32 y = TruncateVertexPosition(yi);
+ s32 y = TruncateGPUVertexPosition(yi);
if (y < static_cast(m_drawing_area.top))
break;
@@ -1198,7 +1198,7 @@ void GPU_SW::DrawTriangle(const SWVertex* v0, const SWVertex* v1, const SWVertex
{
while (yi < yb)
{
- s32 y = TruncateVertexPosition(yi);
+ s32 y = TruncateGPUVertexPosition(yi);
if (y > static_cast(m_drawing_area.bottom))
break;
diff --git a/src/core/gpu_sw.h b/src/core/gpu_sw.h
index d8ad4f463..0b9326db4 100644
--- a/src/core/gpu_sw.h
+++ b/src/core/gpu_sw.h
@@ -36,10 +36,10 @@ protected:
u8 r, g, b;
u8 u, v;
- ALWAYS_INLINE void SetPosition(VertexPosition p, s32 offset_x, s32 offset_y)
+ ALWAYS_INLINE void SetPosition(GPUVertexPosition p, s32 offset_x, s32 offset_y)
{
- x = TruncateVertexPosition(offset_x + p.x);
- y = TruncateVertexPosition(offset_y + p.y);
+ x = TruncateGPUVertexPosition(offset_x + p.x);
+ y = TruncateGPUVertexPosition(offset_y + p.y);
}
ALWAYS_INLINE void SetColorRGB24(u32 color) { std::tie(r, g, b) = UnpackColorRGB24(color); }
diff --git a/src/core/gpu_types.h b/src/core/gpu_types.h
new file mode 100644
index 000000000..a87827423
--- /dev/null
+++ b/src/core/gpu_types.h
@@ -0,0 +1,410 @@
+#pragma once
+#include "common/bitfield.h"
+#include "common/rectangle.h"
+#include "types.h"
+#include
+
+enum : u32
+{
+ VRAM_WIDTH = 1024,
+ VRAM_HEIGHT = 512,
+ VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16),
+ VRAM_WIDTH_MASK = VRAM_WIDTH - 1,
+ VRAM_HEIGHT_MASK = VRAM_HEIGHT - 1,
+ VRAM_COORD_MASK = 0x3FF,
+ TEXTURE_PAGE_WIDTH = 256,
+ TEXTURE_PAGE_HEIGHT = 256,
+ MAX_PRIMITIVE_WIDTH = 1024,
+ MAX_PRIMITIVE_HEIGHT = 512,
+ DITHER_MATRIX_SIZE = 4
+};
+
+enum class GPUPrimitive : u8
+{
+ Reserved = 0,
+ Polygon = 1,
+ Line = 2,
+ Rectangle = 3
+};
+
+enum class GPUDrawRectangleSize : u8
+{
+ Variable = 0,
+ R1x1 = 1,
+ R8x8 = 2,
+ R16x16 = 3
+};
+
+enum class GPUTextureMode : u8
+{
+ Palette4Bit = 0,
+ Palette8Bit = 1,
+ Direct16Bit = 2,
+ Reserved_Direct16Bit = 3,
+
+ // Not register values.
+ RawTextureBit = 4,
+ RawPalette4Bit = RawTextureBit | Palette4Bit,
+ RawPalette8Bit = RawTextureBit | Palette8Bit,
+ RawDirect16Bit = RawTextureBit | Direct16Bit,
+ Reserved_RawDirect16Bit = RawTextureBit | Reserved_Direct16Bit,
+
+ Disabled = 8 // Not a register value
+};
+
+IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(GPUTextureMode);
+
+enum class GPUTransparencyMode : u8
+{
+ HalfBackgroundPlusHalfForeground = 0,
+ BackgroundPlusForeground = 1,
+ BackgroundMinusForeground = 2,
+ BackgroundPlusQuarterForeground = 3,
+
+ Disabled = 4 // Not a register value
+};
+
+enum class GPUInterlacedDisplayMode : u8
+{
+ None,
+ InterleavedFields,
+ SeparateFields
+};
+
+union GPURenderCommand
+{
+ u32 bits;
+
+ BitField color_for_first_vertex;
+ BitField raw_texture_enable; // not valid for lines
+ BitField transparency_enable;
+ BitField texture_enable;
+ BitField rectangle_size; // only for rectangles
+ BitField quad_polygon; // only for polygons
+ BitField polyline; // only for lines
+ BitField shading_enable; // 0 - flat, 1 = gouroud
+ BitField primitive;
+
+ /// Returns true if texturing should be enabled. Depends on the primitive type.
+ ALWAYS_INLINE bool IsTexturingEnabled() const { return (primitive != GPUPrimitive::Line) ? texture_enable : false; }
+
+ /// Returns true if dithering should be enabled. Depends on the primitive type.
+ ALWAYS_INLINE bool IsDitheringEnabled() const
+ {
+ switch (primitive)
+ {
+ case GPUPrimitive::Polygon:
+ return shading_enable || (texture_enable && !raw_texture_enable);
+
+ case GPUPrimitive::Line:
+ return true;
+
+ case GPUPrimitive::Rectangle:
+ default:
+ return false;
+ }
+ }
+};
+
+// Helper/format conversion functions.
+static constexpr u32 RGBA5551ToRGBA8888(u16 color)
+{
+ u8 r = Truncate8(color & 31);
+ u8 g = Truncate8((color >> 5) & 31);
+ u8 b = Truncate8((color >> 10) & 31);
+ u8 a = Truncate8((color >> 15) & 1);
+
+ // 00012345 -> 1234545
+ b = (b << 3) | (b & 0b111);
+ g = (g << 3) | (g & 0b111);
+ r = (r << 3) | (r & 0b111);
+ a = a ? 255 : 0;
+
+ return ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16) | (ZeroExtend32(a) << 24);
+}
+
+static constexpr u16 RGBA8888ToRGBA5551(u32 color)
+{
+ const u16 r = Truncate16((color >> 3) & 0x1Fu);
+ const u16 g = Truncate16((color >> 11) & 0x1Fu);
+ const u16 b = Truncate16((color >> 19) & 0x1Fu);
+ const u16 a = Truncate16((color >> 31) & 0x01u);
+
+ return r | (g << 5) | (b << 10) | (a << 15);
+}
+
+union GPUVertexPosition
+{
+ u32 bits;
+
+ BitField x;
+ BitField y;
+};
+
+// Sprites/rectangles should be clipped to 12 bits before drawing.
+static constexpr s32 TruncateGPUVertexPosition(s32 x)
+{
+ return SignExtendN<11, s32>(x);
+}
+
+// bits in GP0(E1h) or texpage part of polygon
+union GPUDrawModeReg
+{
+ static constexpr u16 MASK = 0b1111111111111;
+ static constexpr u16 TEXTURE_PAGE_MASK = UINT16_C(0b0000000000011111);
+
+ // Polygon texpage commands only affect bits 0-8, 11
+ static constexpr u16 POLYGON_TEXPAGE_MASK = 0b0000100111111111;
+
+ // Bits 0..5 are returned in the GPU status register, latched at E1h/polygon draw time.
+ static constexpr u32 GPUSTAT_MASK = 0b11111111111;
+
+ u16 bits;
+
+ BitField texture_page_x_base;
+ BitField texture_page_y_base;
+ BitField transparency_mode;
+ BitField texture_mode;
+ BitField dither_enable;
+ BitField draw_to_displayed_field;
+ BitField texture_disable;
+ BitField texture_x_flip;
+ BitField texture_y_flip;
+
+ ALWAYS_INLINE u16 GetTexturePageBaseX() const { return ZeroExtend16(texture_page_x_base.GetValue()) * 64; }
+ ALWAYS_INLINE u16 GetTexturePageBaseY() const { return ZeroExtend16(texture_page_y_base.GetValue()) * 256; }
+
+ /// Returns true if the texture mode requires a palette.
+ bool IsUsingPalette() const { return (bits & (2 << 7)) == 0; }
+
+ /// Returns a rectangle comprising the texture page area.
+ Common::Rectangle GetTexturePageRectangle() const
+ {
+ static constexpr std::array texture_page_widths = {
+ {TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH} };
+ return Common::Rectangle::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
+ texture_page_widths[static_cast(texture_mode.GetValue())],
+ TEXTURE_PAGE_HEIGHT);
+ }
+
+ /// Returns a rectangle comprising the texture palette area.
+ Common::Rectangle GetTexturePaletteRectangle() const
+ {
+ static constexpr std::array palette_widths = { {16, 256, 0, 0} };
+ return Common::Rectangle::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
+ palette_widths[static_cast(texture_mode.GetValue())], 1);
+ }
+};
+
+union GPUTexturePaletteReg
+{
+ static constexpr u16 MASK = UINT16_C(0b0111111111111111);
+
+ u16 bits;
+
+ BitField x;
+ BitField y;
+
+ ALWAYS_INLINE u32 GetXBase() const { return static_cast(x) * 16u; }
+ ALWAYS_INLINE u32 GetYBase() const { return static_cast(y); }
+};
+
+struct GPUTextureWindow
+{
+ u8 and_x;
+ u8 and_y;
+ u8 or_x;
+ u8 or_y;
+};
+
+// 4x4 dither matrix.
+static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = { {-4, +0, -3, +1}, // row 0
+ {+2, -2, +3, -1}, // row 1
+ {-3, +1, -4, +0}, // row 2
+ {+4, -1, +2, -2} }; // row 3
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union
+#endif
+
+enum class GPUBackendCommandType : u8
+{
+ Sync,
+ FillVRAM,
+ UpdateVRAM,
+ CopyVRAM,
+ SetDrawingArea,
+ DrawPolygon,
+ DrawRectangle,
+ DrawLine,
+ FlushRender
+};
+
+union GPUBackendCommandParameters
+{
+ u8 bits;
+
+ BitField interlaced_rendering;
+
+ /// Returns 0 if the currently-displayed field is on an even line in VRAM, otherwise 1.
+ BitField active_line_lsb;
+
+ BitField set_mask_while_drawing;
+ BitField check_mask_before_draw;
+
+ ALWAYS_INLINE bool IsMaskingEnabled() const { return (bits & 12u) != 0u; }
+
+ // During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or }
+ u16 GetMaskAND() const
+ {
+ // return check_mask_before_draw ? 0x8000 : 0x0000;
+ return Truncate16((bits << 12) & 0x8000);
+ }
+ u16 GetMaskOR() const
+ {
+ // return set_mask_while_drawing ? 0x8000 : 0x0000;
+ return Truncate16((bits << 13) & 0x8000);
+ }
+};
+
+struct GPUBackendCommand
+{
+ GPUBackendCommandType type;
+ GPUBackendCommandParameters params;
+ u32 size;
+};
+
+struct GPUBackendSyncCommand : public GPUBackendCommand
+{
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendSyncCommand); }
+};
+
+struct GPUBackendFillVRAMCommand : public GPUBackendCommand
+{
+ u16 x;
+ u16 y;
+ u16 width;
+ u16 height;
+ u32 color;
+
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendFillVRAMCommand); }
+};
+
+struct GPUBackendUpdateVRAMCommand : public GPUBackendCommand
+{
+ u16 x;
+ u16 y;
+ u16 width;
+ u16 height;
+ u16 data[0];
+
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendUpdateVRAMCommand) + (sizeof(u16) * width * height); }
+};
+
+struct GPUBackendCopyVRAMCommand : public GPUBackendCommand
+{
+ u16 src_x;
+ u16 src_y;
+ u16 dst_x;
+ u16 dst_y;
+ u16 width;
+ u16 height;
+
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendCopyVRAMCommand); }
+};
+
+struct GPUBackendSetDrawingAreaCommand : public GPUBackendCommand
+{
+ Common::Rectangle new_area;
+
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendSetDrawingAreaCommand); }
+};
+
+struct GPUBackendDrawCommand : public GPUBackendCommand
+{
+ GPURenderCommand rc;
+ GPUDrawModeReg draw_mode;
+ GPUTexturePaletteReg palette;
+ GPUTextureWindow window;
+ Common::Rectangle bounds;
+
+ ALWAYS_INLINE bool IsDitheringEnabled() const { return rc.IsDitheringEnabled() && draw_mode.dither_enable; }
+};
+
+struct GPUBackendDrawPolygonCommand : public GPUBackendDrawCommand
+{
+ u16 num_vertices;
+
+ struct Vertex
+ {
+ float precise_x, precise_y, precise_w;
+ s32 x, y;
+ union
+ {
+ struct
+ {
+ u8 r, g, b, a;
+ };
+ u32 color;
+ };
+ union
+ {
+ struct
+ {
+ u8 u, v;
+ };
+ u16 texcoord;
+ };
+ };
+
+ Vertex vertices[0];
+
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendDrawPolygonCommand) + sizeof(Vertex) * num_vertices; }
+};
+
+struct GPUBackendDrawRectangleCommand : public GPUBackendDrawCommand
+{
+ s32 x, y;
+ u16 width, height;
+ u16 texcoord;
+ u32 color;
+
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendDrawRectangleCommand); }
+};
+
+struct GPUBackendDrawLineCommand : public GPUBackendDrawCommand
+{
+ u16 num_vertices;
+
+ struct Vertex
+ {
+ s32 x, y;
+ union
+ {
+ struct
+ {
+ u8 r, g, b, a;
+ };
+ u32 color;
+ };
+ };
+
+ Vertex vertices[0];
+
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendDrawLineCommand) + sizeof(Vertex) * num_vertices; }
+};
+
+struct GPUBackendClearDisplayCommand : public GPUBackendCommand
+{
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendClearDisplayCommand); }
+};
+
+struct GPUBackendFlushRenderCommand : public GPUBackendCommand
+{
+ ALWAYS_INLINE u32 Size() const { return sizeof(GPUBackendFlushRenderCommand); }
+};
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
diff --git a/src/duckstation-sdl/sdl_host_interface.cpp b/src/duckstation-sdl/sdl_host_interface.cpp
index d06c08caa..17b893282 100644
--- a/src/duckstation-sdl/sdl_host_interface.cpp
+++ b/src/duckstation-sdl/sdl_host_interface.cpp
@@ -921,7 +921,7 @@ void SDLHostInterface::DrawQuickSettingsMenu()
for (u32 scale = 1; scale <= GPU::MAX_RESOLUTION_SCALE; scale++)
{
char buf[32];
- std::snprintf(buf, sizeof(buf), "%ux (%ux%u)", scale, scale * GPU::VRAM_WIDTH, scale * GPU::VRAM_HEIGHT);
+ std::snprintf(buf, sizeof(buf), "%ux (%ux%u)", scale, scale * VRAM_WIDTH, scale * VRAM_HEIGHT);
if (ImGui::MenuItem(buf, nullptr, current_internal_resolution == scale))
{