GPU: Move enums/types into separate file

This commit is contained in:
Connor McLaughlin 2020-10-22 19:31:28 +10:00
parent d3d881aa6b
commit 03d4f80883
19 changed files with 343 additions and 287 deletions

View File

@ -41,6 +41,7 @@ add_library(core
gpu_hw_vulkan.h
gpu_sw.cpp
gpu_sw.h
gpu_types.h
gte.cpp
gte.h
gte_types.h

View File

@ -189,6 +189,7 @@
<ClInclude Include="gpu_hw_shadergen.h" />
<ClInclude Include="gpu_hw_vulkan.h" />
<ClInclude Include="gpu_sw.h" />
<ClInclude Include="gpu_types.h" />
<ClInclude Include="gte.h" />
<ClInclude Include="cpu_types.h" />
<ClInclude Include="dma.h" />

View File

@ -104,5 +104,6 @@
<ClInclude Include="shadergen.h" />
<ClInclude Include="memory_card_image.h" />
<ClInclude Include="analog_joystick.h" />
<ClInclude Include="gpu_types.h" />
</ItemGroup>
</Project>
</Project>

View File

@ -1306,18 +1306,18 @@ void GPU::FlushRender() {}
void GPU::SetDrawMode(u16 value)
{
DrawMode::Reg new_mode_reg{static_cast<u16>(value & DrawMode::Reg::MASK)};
GPUDrawModeReg new_mode_reg{static_cast<u16>(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;
}
@ -1328,7 +1328,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;
}

View File

@ -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 <algorithm>
@ -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<u32, u32, 0, 24> color_for_first_vertex;
BitField<u32, bool, 24, 1> raw_texture_enable; // not valid for lines
BitField<u32, bool, 25, 1> transparency_enable;
BitField<u32, bool, 26, 1> texture_enable;
BitField<u32, DrawRectangleSize, 27, 2> rectangle_size; // only for rectangles
BitField<u32, bool, 27, 1> quad_polygon; // only for polygons
BitField<u32, bool, 27, 1> polyline; // only for lines
BitField<u32, bool, 28, 1> shading_enable; // 0 - flat, 1 = gouroud
BitField<u32, Primitive, 29, 21> 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<u32, s32, 0, 11> x;
BitField<u32, s32, 16, 11> 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<u32, u8, 0, 4> texture_page_x_base;
BitField<u32, u8, 4, 1> texture_page_y_base;
BitField<u32, TransparencyMode, 5, 2> semi_transparency_mode;
BitField<u32, TextureMode, 7, 2> texture_color_mode;
BitField<u32, GPUTransparencyMode, 5, 2> semi_transparency_mode;
BitField<u32, GPUTextureMode, 7, 2> texture_color_mode;
BitField<u32, bool, 9, 1> dither_enable;
BitField<u32, bool, 10, 1> draw_to_displayed_field;
BitField<u32, bool, 11, 1> 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<u16, u8, 0, 4> texture_page_x_base;
BitField<u16, u8, 4, 1> texture_page_y_base;
BitField<u16, TransparencyMode, 5, 2> transparency_mode;
BitField<u16, TextureMode, 7, 2> texture_mode;
BitField<u16, bool, 9, 1> dither_enable;
BitField<u16, bool, 10, 1> draw_to_displayed_field;
BitField<u16, bool, 11, 1> texture_disable;
BitField<u16, bool, 12, 1> texture_x_flip;
BitField<u16, bool, 13, 1> 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;
@ -614,33 +473,6 @@ protected:
bool texture_page_changed;
bool texture_window_changed;
/// Returns the texture/palette rendering mode.
TextureMode GetTextureMode() const { return mode_reg.texture_mode; }
/// Returns the semi-transparency mode when enabled.
TransparencyMode 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; }
/// Returns a rectangle comprising the texture page area.
Common::Rectangle<u32> GetTexturePageRectangle() const
{
static constexpr std::array<u32, 4> texture_page_widths = {
{TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH}};
return Common::Rectangle<u32>::FromExtents(texture_page_x, texture_page_y,
texture_page_widths[static_cast<u8>(mode_reg.texture_mode.GetValue())],
TEXTURE_PAGE_HEIGHT);
}
/// Returns a rectangle comprising the texture palette area.
Common::Rectangle<u32> GetTexturePaletteRectangle() const
{
static constexpr std::array<u32, 4> palette_widths = {{16, 256, 0, 0}};
return Common::Rectangle<u32>::FromExtents(texture_palette_x, texture_palette_y,
palette_widths[static_cast<u8>(mode_reg.texture_mode.GetValue())], 1);
}
bool IsTexturePageChanged() const { return texture_page_changed; }
void SetTexturePageChanged() { texture_page_changed = true; }
void ClearTexturePageChangedFlag() { texture_page_changed = false; }
@ -757,7 +589,7 @@ protected:
HeapFIFOQueue<u64, MAX_FIFO_SIZE> m_fifo;
std::vector<u32> 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 +638,4 @@ private:
static const GP0CommandHandlerTable s_GP0_command_handler_table;
};
IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(GPU::TextureMode);
extern std::unique_ptr<GPU> g_gpu;

View File

@ -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);

View File

@ -414,13 +414,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));
@ -437,7 +437,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;
@ -538,12 +538,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);
@ -552,15 +552,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;
@ -632,14 +632,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;
@ -694,7 +694,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;
@ -702,7 +702,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;
@ -828,8 +828,8 @@ void GPU_HW::IncludeVRAMDityRectangle(const Common::Rectangle<u32>& rect)
// the vram area can include the texture page, but the game can leave it as-is. in this case, set it as dirty so the
// shadow texture is updated
if (!m_draw_mode.IsTexturePageChanged() &&
(m_draw_mode.GetTexturePageRectangle().Intersects(rect) ||
(m_draw_mode.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(rect))))
(m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(rect) ||
(m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(rect))))
{
m_draw_mode.SetTexturePageChanged();
}
@ -853,13 +853,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;
@ -923,9 +923,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
@ -933,8 +933,9 @@ void GPU_HW::DispatchRenderCommand()
{
m_draw_mode.ClearTexturePageChangedFlag();
if (m_vram_dirty_rect.Valid() &&
(m_draw_mode.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
(m_draw_mode.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
(m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
(m_draw_mode.mode_reg.IsUsingPalette() &&
m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
{
// Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap");
if (!IsFlushed())
@ -944,21 +945,21 @@ void GPU_HW::DispatchRenderCommand()
}
}
texture_mode = m_draw_mode.GetTextureMode();
texture_mode = m_draw_mode.mode_reg.texture_mode;
if (rc.raw_texture_enable)
{
texture_mode =
static_cast<TextureMode>(static_cast<u8>(texture_mode) | static_cast<u8>(TextureMode::RawTextureBit));
static_cast<GPUTextureMode>(static_cast<u8>(texture_mode) | static_cast<u8>(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.mode_reg.transparency_mode : 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)
@ -969,7 +970,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<u32>(transparency_mode)][0];

View File

@ -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;
}
};
@ -233,7 +233,7 @@ protected:
}
/// Returns true if alpha blending should be enabled for drawing the current batch.
ALWAYS_INLINE bool UseAlphaBlending(TransparencyMode transparency_mode, BatchRenderMode render_mode) const
ALWAYS_INLINE bool UseAlphaBlending(GPUTransparencyMode transparency_mode, BatchRenderMode render_mode) const
{
if (m_texture_filtering == GPUTextureFilter::Bilinear || m_texture_filtering == GPUTextureFilter::JINC2 ||
m_texture_filtering == GPUTextureFilter::xBR)
@ -241,7 +241,7 @@ protected:
return true;
}
if (transparency_mode == TransparencyMode::Disabled || render_mode == BatchRenderMode::OnlyOpaque)
if (transparency_mode == GPUTransparencyMode::Disabled || render_mode == BatchRenderMode::OnlyOpaque)
return false;
return true;

View File

@ -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<u8>(TransparencyMode::Disabled) ||
if (transparency_mode != static_cast<u8>(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<u8>(TransparencyMode::BackgroundMinusForeground)) ?
(transparency_mode == static_cast<u8>(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<BatchRenderMode>(render_mode), static_cast<TextureMode>(texture_mode),
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTextureMode>(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<u8>(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);

View File

@ -396,10 +396,10 @@ bool GPU_HW_OpenGL::CompilePrograms()
{
for (u8 interlacing = 0; interlacing < 2; interlacing++)
{
const bool textured = (static_cast<TextureMode>(texture_mode) != TextureMode::Disabled);
const bool textured = (static_cast<GPUTextureMode>(texture_mode) != GPUTextureMode::Disabled);
const std::string batch_vs = shadergen.GenerateBatchVertexShader(textured);
const std::string fs = shadergen.GenerateBatchFragmentShader(
static_cast<BatchRenderMode>(render_mode), static_cast<TextureMode>(texture_mode),
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTextureMode>(texture_mode),
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
const auto link_callback = [this, textured, use_binding_layout](GL::Program& prog) {
@ -592,7 +592,7 @@ void GPU_HW_OpenGL::SetBlendMode()
if (UseAlphaBlending(m_current_transparency_mode, m_current_render_mode))
{
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);

View File

@ -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;
};

View File

@ -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";

View File

@ -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,

View File

@ -642,7 +642,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
for (u8 interlacing = 0; interlacing < 2; interlacing++)
{
const std::string fs = shadergen.GenerateBatchFragmentShader(
static_cast<BatchRenderMode>(render_mode), static_cast<TextureMode>(texture_mode),
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTextureMode>(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<TextureMode>(texture_mode) != TextureMode::Disabled);
const bool textured = (static_cast<GPUTextureMode>(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<TransparencyMode>(transparency_mode) != TransparencyMode::Disabled &&
if ((static_cast<GPUTransparencyMode>(transparency_mode) != GPUTransparencyMode::Disabled &&
(static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
static_cast<BatchRenderMode>(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<TransparencyMode>(transparency_mode) == TransparencyMode::BackgroundMinusForeground &&
(static_cast<GPUTransparencyMode>(transparency_mode) == GPUTransparencyMode::BackgroundMinusForeground &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque) ?
VK_BLEND_OP_REVERSE_SUBTRACT :

View File

@ -532,12 +532,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;
@ -553,7 +553,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;
@ -580,10 +580,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));
@ -591,15 +591,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;
@ -629,7 +629,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;
@ -642,7 +642,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);
@ -653,12 +653,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
@ -710,9 +710,9 @@ void ALWAYS_INLINE_RELEASE GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color
texcoord_y = (texcoord_y & m_draw_mode.texture_window_and_y) | m_draw_mode.texture_window_or_y;
VRAMPixel texture_color;
switch (m_draw_mode.GetTextureMode())
switch (m_draw_mode.mode_reg.texture_mode)
{
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);
@ -722,7 +722,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);
@ -786,18 +786,18 @@ void ALWAYS_INLINE_RELEASE GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color
color.Set(func(bg_color.r.GetValue(), color.r.GetValue()), func(bg_color.g.GetValue(), color.g.GetValue()), \
func(bg_color.b.GetValue(), color.b.GetValue()), color.c.GetValue())
switch (m_draw_mode.GetTransparencyMode())
switch (m_draw_mode.mode_reg.transparency_mode)
{
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:
@ -828,8 +828,8 @@ template<bool texture_enable, bool raw_texture_enable, bool transparency_enable>
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<u32>(std::clamp<s32>(start_x, m_drawing_area.left, m_drawing_area.right));
@ -986,7 +986,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<s32>(m_drawing_area.left))
{
@ -1178,7 +1178,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<s32>(m_drawing_area.top))
break;
@ -1194,7 +1194,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<s32>(m_drawing_area.bottom))
break;

View File

@ -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); }

224
src/core/gpu_types.h Normal file
View File

@ -0,0 +1,224 @@
#pragma once
#include "common/bitfield.h"
#include "common/rectangle.h"
#include "types.h"
#include <array>
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<u32, u32, 0, 24> color_for_first_vertex;
BitField<u32, bool, 24, 1> raw_texture_enable; // not valid for lines
BitField<u32, bool, 25, 1> transparency_enable;
BitField<u32, bool, 26, 1> texture_enable;
BitField<u32, GPUDrawRectangleSize, 27, 2> rectangle_size; // only for rectangles
BitField<u32, bool, 27, 1> quad_polygon; // only for polygons
BitField<u32, bool, 27, 1> polyline; // only for lines
BitField<u32, bool, 28, 1> shading_enable; // 0 - flat, 1 = gouroud
BitField<u32, GPUPrimitive, 29, 21> 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<u32, s32, 0, 11> x;
BitField<u32, s32, 16, 11> 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<u16, u8, 0, 4> texture_page_x_base;
BitField<u16, u8, 4, 1> texture_page_y_base;
BitField<u16, GPUTransparencyMode, 5, 2> transparency_mode;
BitField<u16, GPUTextureMode, 7, 2> texture_mode;
BitField<u16, bool, 9, 1> dither_enable;
BitField<u16, bool, 10, 1> draw_to_displayed_field;
BitField<u16, bool, 11, 1> texture_disable;
BitField<u16, bool, 12, 1> texture_x_flip;
BitField<u16, bool, 13, 1> 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<u32> GetTexturePageRectangle() const
{
static constexpr std::array<u32, 4> texture_page_widths = {
{TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH} };
return Common::Rectangle<u32>::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
texture_page_widths[static_cast<u8>(texture_mode.GetValue())],
TEXTURE_PAGE_HEIGHT);
}
/// Returns a rectangle comprising the texture palette area.
Common::Rectangle<u32> GetTexturePaletteRectangle() const
{
static constexpr std::array<u32, 4> palette_widths = { {16, 256, 0, 0} };
return Common::Rectangle<u32>::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
palette_widths[static_cast<u8>(texture_mode.GetValue())], 1);
}
};
union GPUTexturePaletteReg
{
static constexpr u16 MASK = UINT16_C(0b0111111111111111);
u16 bits;
BitField<u16, u16, 0, 6> x;
BitField<u16, u16, 6, 10> y;
ALWAYS_INLINE u32 GetXBase() const { return static_cast<u32>(x) * 16u; }
ALWAYS_INLINE u32 GetYBase() const { return static_cast<u32>(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

View File

@ -230,8 +230,8 @@ void LibretroHostInterface::GetSystemAVInfo(struct retro_system_av_info* info, b
info->geometry.aspect_ratio = m_last_aspect_ratio;
info->geometry.base_width = 320;
info->geometry.base_height = 240;
info->geometry.max_width = GPU::VRAM_WIDTH * resolution_scale;
info->geometry.max_height = GPU::VRAM_HEIGHT * resolution_scale;
info->geometry.max_width = VRAM_WIDTH * resolution_scale;
info->geometry.max_height = VRAM_HEIGHT * resolution_scale;
info->timing.fps = System::GetThrottleFrequency();
info->timing.sample_rate = static_cast<double>(AUDIO_SAMPLE_RATE);

View File

@ -960,7 +960,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))
{