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_hw_vulkan.h
gpu_sw.cpp gpu_sw.cpp
gpu_sw.h gpu_sw.h
gpu_types.h
gte.cpp gte.cpp
gte.h gte.h
gte_types.h gte_types.h

View File

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

View File

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

View File

@ -1306,18 +1306,18 @@ void GPU::FlushRender() {}
void GPU::SetDrawMode(u16 value) 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) if (!m_set_texture_disable_mask)
new_mode_reg.texture_disable = false; new_mode_reg.texture_disable = false;
if (new_mode_reg.bits == m_draw_mode.mode_reg.bits) if (new_mode_reg.bits == m_draw_mode.mode_reg.bits)
return; return;
if ((new_mode_reg.bits & DrawMode::Reg::TEXTURE_PAGE_MASK) != if ((new_mode_reg.bits & GPUDrawModeReg::TEXTURE_PAGE_MASK) !=
(m_draw_mode.mode_reg.bits & DrawMode::Reg::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_x = new_mode_reg.GetTexturePageBaseX();
m_draw_mode.texture_page_y = new_mode_reg.GetTexturePageYBase(); m_draw_mode.texture_page_y = new_mode_reg.GetTexturePageBaseY();
m_draw_mode.texture_page_changed = true; 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. // Bits 0..10 are returned in the GPU status register.
m_GPUSTAT.bits = 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; m_GPUSTAT.texture_disable = m_draw_mode.mode_reg.texture_disable;
} }

View File

@ -2,6 +2,7 @@
#include "common/bitfield.h" #include "common/bitfield.h"
#include "common/fifo_queue.h" #include "common/fifo_queue.h"
#include "common/rectangle.h" #include "common/rectangle.h"
#include "gpu_types.h"
#include "timers.h" #include "timers.h"
#include "types.h" #include "types.h"
#include <algorithm> #include <algorithm>
@ -37,66 +38,12 @@ public:
GPUREADtoCPU = 3 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 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, MAX_FIFO_SIZE = 4096,
TEXTURE_PAGE_WIDTH = 256,
TEXTURE_PAGE_HEIGHT = 256,
MAX_PRIMITIVE_WIDTH = 1024,
MAX_PRIMITIVE_HEIGHT = 512,
DOT_TIMER_INDEX = 0, DOT_TIMER_INDEX = 0,
HBLANK_TIMER_INDEX = 1, HBLANK_TIMER_INDEX = 1,
MAX_RESOLUTION_SCALE = 16, MAX_RESOLUTION_SCALE = 16,
DITHER_MATRIX_SIZE = 4
}; };
enum : u16 enum : u16
@ -109,12 +56,6 @@ public:
PAL_TOTAL_LINES = 314, 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. // Base class constructor.
GPU(); GPU();
virtual ~GPU(); virtual ~GPU();
@ -264,60 +205,6 @@ protected:
static bool DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer, static bool DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer,
bool remove_alpha); 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 union VRAMPixel
{ {
u16 bits; u16 bits;
@ -508,8 +395,8 @@ protected:
u32 bits; u32 bits;
BitField<u32, u8, 0, 4> texture_page_x_base; BitField<u32, u8, 0, 4> texture_page_x_base;
BitField<u32, u8, 4, 1> texture_page_y_base; BitField<u32, u8, 4, 1> texture_page_y_base;
BitField<u32, TransparencyMode, 5, 2> semi_transparency_mode; BitField<u32, GPUTransparencyMode, 5, 2> semi_transparency_mode;
BitField<u32, TextureMode, 7, 2> texture_color_mode; BitField<u32, GPUTextureMode, 7, 2> texture_color_mode;
BitField<u32, bool, 9, 1> dither_enable; BitField<u32, bool, 9, 1> dither_enable;
BitField<u32, bool, 10, 1> draw_to_displayed_field; BitField<u32, bool, 10, 1> draw_to_displayed_field;
BitField<u32, bool, 11, 1> set_mask_while_drawing; BitField<u32, bool, 11, 1> set_mask_while_drawing;
@ -567,36 +454,8 @@ protected:
static constexpr u16 PALETTE_MASK = UINT16_C(0b0111111111111111); static constexpr u16 PALETTE_MASK = UINT16_C(0b0111111111111111);
static constexpr u32 TEXTURE_WINDOW_MASK = UINT32_C(0b11111111111111111111); 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 // original values
Reg mode_reg; GPUDrawModeReg mode_reg;
u16 palette_reg; // from vertex u16 palette_reg; // from vertex
u32 texture_window_value; u32 texture_window_value;
@ -614,33 +473,6 @@ protected:
bool texture_page_changed; bool texture_page_changed;
bool texture_window_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; } bool IsTexturePageChanged() const { return texture_page_changed; }
void SetTexturePageChanged() { texture_page_changed = true; } void SetTexturePageChanged() { texture_page_changed = true; }
void ClearTexturePageChangedFlag() { texture_page_changed = false; } void ClearTexturePageChangedFlag() { texture_page_changed = false; }
@ -757,7 +589,7 @@ protected:
HeapFIFOQueue<u64, MAX_FIFO_SIZE> m_fifo; HeapFIFOQueue<u64, MAX_FIFO_SIZE> m_fifo;
std::vector<u32> m_blit_buffer; std::vector<u32> m_blit_buffer;
u32 m_blit_remaining_words; 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 FifoPop() { return Truncate32(m_fifo.Pop()); }
ALWAYS_INLINE u32 FifoPeek() { return Truncate32(m_fifo.Peek()); } ALWAYS_INLINE u32 FifoPeek() { return Truncate32(m_fifo.Peek()); }
@ -806,6 +638,4 @@ private:
static const GP0CommandHandlerTable s_GP0_command_handler_table; static const GP0CommandHandlerTable s_GP0_command_handler_table;
}; };
IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(GPU::TextureMode);
extern std::unique_ptr<GPU> g_gpu; extern std::unique_ptr<GPU> g_gpu;

View File

@ -132,16 +132,16 @@ GPU::GP0CommandHandlerTable GPU::GenerateGP0CommandHandlerTable()
table[0x1F] = &GPU::HandleInterruptRequestCommand; table[0x1F] = &GPU::HandleInterruptRequestCommand;
for (u32 i = 0x20; i <= 0x7F; i++) for (u32 i = 0x20; i <= 0x7F; i++)
{ {
const RenderCommand rc{i << 24}; const GPURenderCommand rc{i << 24};
switch (rc.primitive) switch (rc.primitive)
{ {
case Primitive::Polygon: case GPUPrimitive::Polygon:
table[i] = &GPU::HandleRenderPolygonCommand; table[i] = &GPU::HandleRenderPolygonCommand;
break; break;
case Primitive::Line: case GPUPrimitive::Line:
table[i] = rc.polyline ? &GPU::HandleRenderPolyLineCommand : &GPU::HandleRenderLineCommand; table[i] = rc.polyline ? &GPU::HandleRenderPolyLineCommand : &GPU::HandleRenderLineCommand;
break; break;
case Primitive::Rectangle: case GPUPrimitive::Rectangle:
table[i] = &GPU::HandleRenderRectangleCommand; table[i] = &GPU::HandleRenderRectangleCommand;
break; break;
default: default:
@ -314,7 +314,7 @@ bool GPU::HandleSetMaskBitCommand()
bool GPU::HandleRenderPolygonCommand() 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 // 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); 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) if (rc.texture_enable)
{ {
const u16 texpage_attribute = Truncate16((rc.shading_enable ? FifoPeek(5) : FifoPeek(4)) >> 16); const u16 texpage_attribute = Truncate16((rc.shading_enable ? FifoPeek(5) : FifoPeek(4)) >> 16);
SetDrawMode((texpage_attribute & DrawMode::Reg::POLYGON_TEXPAGE_MASK) | SetDrawMode((texpage_attribute & GPUDrawModeReg::POLYGON_TEXPAGE_MASK) |
(m_draw_mode.mode_reg.bits & ~DrawMode::Reg::POLYGON_TEXPAGE_MASK)); (m_draw_mode.mode_reg.bits & ~GPUDrawModeReg::POLYGON_TEXPAGE_MASK));
SetTexturePalette(Truncate16(FifoPeek(2) >> 16)); SetTexturePalette(Truncate16(FifoPeek(2) >> 16));
} }
@ -358,9 +358,9 @@ bool GPU::HandleRenderPolygonCommand()
bool GPU::HandleRenderRectangleCommand() bool GPU::HandleRenderRectangleCommand()
{ {
const RenderCommand rc{FifoPeek(0)}; const GPURenderCommand rc{FifoPeek(0)};
const u32 total_words = 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); CHECK_COMMAND_SIZE(total_words);
@ -390,7 +390,7 @@ bool GPU::HandleRenderRectangleCommand()
bool GPU::HandleRenderLineCommand() bool GPU::HandleRenderLineCommand()
{ {
const RenderCommand rc{FifoPeek(0)}; const GPURenderCommand rc{FifoPeek(0)};
const u32 total_words = rc.shading_enable ? 4 : 3; const u32 total_words = rc.shading_enable ? 4 : 3;
CHECK_COMMAND_SIZE(total_words); CHECK_COMMAND_SIZE(total_words);
@ -413,7 +413,7 @@ bool GPU::HandleRenderLineCommand()
bool GPU::HandleRenderPolyLineCommand() bool GPU::HandleRenderPolyLineCommand()
{ {
// always read the first two vertices, we test for the terminator after that // 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; const u32 min_words = rc.shading_enable ? 3 : 4;
CHECK_COMMAND_SIZE(min_words); CHECK_COMMAND_SIZE(min_words);

View File

@ -414,13 +414,13 @@ void GPU_HW::LoadVertices()
if (m_GPUSTAT.check_mask_before_draw) if (m_GPUSTAT.check_mask_before_draw)
m_current_depth++; 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 u32 texpage = ZeroExtend32(m_draw_mode.mode_reg.bits) | (ZeroExtend32(m_draw_mode.palette_reg) << 16);
const float depth = GetCurrentNormalizedVertexDepth(); const float depth = GetCurrentNormalizedVertexDepth();
switch (rc.primitive) switch (rc.primitive)
{ {
case Primitive::Polygon: case GPUPrimitive::Polygon:
{ {
DebugAssert(GetBatchVertexSpace() >= (rc.quad_polygon ? 6u : 3u)); 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 u32 color = (shaded && i > 0) ? (FifoPop() & UINT32_C(0x00FFFFFF)) : first_color;
const u64 maddr_and_pos = m_fifo.Pop(); 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 u16 texcoord = textured ? Truncate16(FifoPop()) : 0;
const s32 native_x = m_drawing_offset.x + vp.x; const s32 native_x = m_drawing_offset.x + vp.x;
const s32 native_y = m_drawing_offset.y + vp.y; const s32 native_y = m_drawing_offset.y + vp.y;
@ -538,12 +538,12 @@ void GPU_HW::LoadVertices()
} }
break; break;
case Primitive::Rectangle: case GPUPrimitive::Rectangle:
{ {
const u32 color = rc.color_for_first_vertex; const u32 color = rc.color_for_first_vertex;
const VertexPosition vp{FifoPop()}; const GPUVertexPosition vp{FifoPop()};
const s32 pos_x = TruncateVertexPosition(m_drawing_offset.x + vp.x); const s32 pos_x = TruncateGPUVertexPosition(m_drawing_offset.x + vp.x);
const s32 pos_y = TruncateVertexPosition(m_drawing_offset.y + vp.y); const s32 pos_y = TruncateGPUVertexPosition(m_drawing_offset.y + vp.y);
const auto [texcoord_x, texcoord_y] = UnpackTexcoord(rc.texture_enable ? Truncate16(FifoPop()) : 0); const auto [texcoord_x, texcoord_y] = UnpackTexcoord(rc.texture_enable ? Truncate16(FifoPop()) : 0);
u16 orig_tex_left = ZeroExtend16(texcoord_x); u16 orig_tex_left = ZeroExtend16(texcoord_x);
@ -552,15 +552,15 @@ void GPU_HW::LoadVertices()
s32 rectangle_height; s32 rectangle_height;
switch (rc.rectangle_size) switch (rc.rectangle_size)
{ {
case DrawRectangleSize::R1x1: case GPUDrawRectangleSize::R1x1:
rectangle_width = 1; rectangle_width = 1;
rectangle_height = 1; rectangle_height = 1;
break; break;
case DrawRectangleSize::R8x8: case GPUDrawRectangleSize::R8x8:
rectangle_width = 8; rectangle_width = 8;
rectangle_height = 8; rectangle_height = 8;
break; break;
case DrawRectangleSize::R16x16: case GPUDrawRectangleSize::R16x16:
rectangle_width = 16; rectangle_width = 16;
rectangle_height = 16; rectangle_height = 16;
break; break;
@ -632,14 +632,14 @@ void GPU_HW::LoadVertices()
} }
break; break;
case Primitive::Line: case GPUPrimitive::Line:
{ {
if (!rc.polyline) if (!rc.polyline)
{ {
DebugAssert(GetBatchVertexSpace() >= 2); DebugAssert(GetBatchVertexSpace() >= 2);
u32 start_color, end_color; u32 start_color, end_color;
VertexPosition start_pos, end_pos; GPUVertexPosition start_pos, end_pos;
if (rc.shading_enable) if (rc.shading_enable)
{ {
start_color = rc.color_for_first_vertex; start_color = rc.color_for_first_vertex;
@ -694,7 +694,7 @@ void GPU_HW::LoadVertices()
const bool shaded = rc.shading_enable; const bool shaded = rc.shading_enable;
u32 buffer_pos = 0; 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_x = start_vp.x + m_drawing_offset.x;
s32 start_y = start_vp.y + m_drawing_offset.y; s32 start_y = start_vp.y + m_drawing_offset.y;
u32 start_color = rc.color_for_first_vertex; u32 start_color = rc.color_for_first_vertex;
@ -702,7 +702,7 @@ void GPU_HW::LoadVertices()
for (u32 i = 1; i < num_vertices; i++) for (u32 i = 1; i < num_vertices; i++)
{ {
const u32 end_color = shaded ? (m_blit_buffer[buffer_pos++] & UINT32_C(0x00FFFFFF)) : start_color; 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_x = m_drawing_offset.x + vp.x;
const s32 end_y = m_drawing_offset.y + vp.y; 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 // 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 // shadow texture is updated
if (!m_draw_mode.IsTexturePageChanged() && if (!m_draw_mode.IsTexturePageChanged() &&
(m_draw_mode.GetTexturePageRectangle().Intersects(rect) || (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(rect) ||
(m_draw_mode.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(rect)))) (m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(rect))))
{ {
m_draw_mode.SetTexturePageChanged(); m_draw_mode.SetTexturePageChanged();
} }
@ -853,13 +853,13 @@ void GPU_HW::EnsureVertexBufferSpaceForCurrentCommand()
u32 required_vertices; u32 required_vertices;
switch (m_render_command.primitive) switch (m_render_command.primitive)
{ {
case Primitive::Polygon: case GPUPrimitive::Polygon:
required_vertices = m_render_command.quad_polygon ? 6 : 3; required_vertices = m_render_command.quad_polygon ? 6 : 3;
break; break;
case Primitive::Rectangle: case GPUPrimitive::Rectangle:
required_vertices = MAX_VERTICES_FOR_RECTANGLE; required_vertices = MAX_VERTICES_FOR_RECTANGLE;
break; break;
case Primitive::Line: case GPUPrimitive::Line:
default: default:
required_vertices = m_render_command.polyline ? (GetPolyLineVertexCount() * 6u) : 6u; required_vertices = m_render_command.polyline ? (GetPolyLineVertexCount() * 6u) : 6u;
break; 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() 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()) if (rc.IsTexturingEnabled())
{ {
// texture page changed - check that the new page doesn't intersect the drawing area // 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(); m_draw_mode.ClearTexturePageChangedFlag();
if (m_vram_dirty_rect.Valid() && if (m_vram_dirty_rect.Valid() &&
(m_draw_mode.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) || (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
(m_draw_mode.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().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"); // Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap");
if (!IsFlushed()) 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) if (rc.raw_texture_enable)
{ {
texture_mode = 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 else
{ {
texture_mode = TextureMode::Disabled; texture_mode = GPUTextureMode::Disabled;
} }
// has any state changed which requires a new batch? // has any state changed which requires a new batch?
const TransparencyMode transparency_mode = const GPUTransparencyMode transparency_mode =
rc.transparency_enable ? m_draw_mode.GetTransparencyMode() : TransparencyMode::Disabled; 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; 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 || if (m_batch.texture_mode != texture_mode || m_batch.transparency_mode != transparency_mode ||
dithering_enable != m_batch.dithering) dithering_enable != m_batch.dithering)
@ -969,7 +970,7 @@ void GPU_HW::DispatchRenderCommand()
EnsureVertexBufferSpaceForCurrentCommand(); EnsureVertexBufferSpaceForCurrentCommand();
// transparency mode change // 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}}; 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]; 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 struct BatchConfig
{ {
TextureMode texture_mode; GPUTextureMode texture_mode;
TransparencyMode transparency_mode; GPUTransparencyMode transparency_mode;
bool dithering; bool dithering;
bool interlacing; bool interlacing;
bool set_mask_while_drawing; 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. // on a per-pixel basis, and the opaque pixels shouldn't be blended at all.
bool NeedsTwoPassRendering() const bool NeedsTwoPassRendering() const
{ {
return transparency_mode == GPU::TransparencyMode::BackgroundMinusForeground && return transparency_mode == GPUTransparencyMode::BackgroundMinusForeground &&
texture_mode != TextureMode::Disabled; texture_mode != GPUTextureMode::Disabled;
} }
// Returns the render mode for this batch. // Returns the render mode for this batch.
BatchRenderMode GetRenderMode() const BatchRenderMode GetRenderMode() const
{ {
return transparency_mode == TransparencyMode::Disabled ? BatchRenderMode::TransparencyDisabled : return transparency_mode == GPUTransparencyMode::Disabled ? BatchRenderMode::TransparencyDisabled :
BatchRenderMode::TransparentAndOpaque; BatchRenderMode::TransparentAndOpaque;
} }
}; };
@ -233,7 +233,7 @@ protected:
} }
/// Returns true if alpha blending should be enabled for drawing the current batch. /// 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 || if (m_texture_filtering == GPUTextureFilter::Bilinear || m_texture_filtering == GPUTextureFilter::JINC2 ||
m_texture_filtering == GPUTextureFilter::xBR) m_texture_filtering == GPUTextureFilter::xBR)
@ -241,7 +241,7 @@ protected:
return true; return true;
} }
if (transparency_mode == TransparencyMode::Disabled || render_mode == BatchRenderMode::OnlyOpaque) if (transparency_mode == GPUTransparencyMode::Disabled || render_mode == BatchRenderMode::OnlyOpaque)
return false; return false;
return true; return true;

View File

@ -347,7 +347,7 @@ bool GPU_HW_D3D11::CreateStateObjects()
for (u8 transparency_mode = 0; transparency_mode < 5; transparency_mode++) for (u8 transparency_mode = 0; transparency_mode < 5; transparency_mode++)
{ {
bl_desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); 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) m_texture_filtering != GPUTextureFilter::Nearest)
{ {
bl_desc.RenderTarget[0].BlendEnable = TRUE; 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].SrcBlendAlpha = D3D11_BLEND_ONE;
bl_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; bl_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
bl_desc.RenderTarget[0].BlendOp = 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_REV_SUBTRACT :
D3D11_BLEND_OP_ADD; D3D11_BLEND_OP_ADD;
bl_desc.RenderTarget[0].BlendOpAlpha = 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++) for (u8 interlacing = 0; interlacing < 2; interlacing++)
{ {
const std::string ps = shadergen.GenerateBatchFragmentShader( 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)); ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
m_batch_pixel_shaders[render_mode][texture_mode][dithering][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) 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); 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(), .Get(),
nullptr, 0); nullptr, 0);
const TransparencyMode transparency_mode = const GPUTransparencyMode transparency_mode =
(render_mode == BatchRenderMode::OnlyOpaque) ? TransparencyMode::Disabled : m_batch.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->OMSetBlendState(m_batch_blend_states[static_cast<u8>(transparency_mode)].Get(), nullptr, 0xFFFFFFFFu);
m_context->OMSetDepthStencilState( m_context->OMSetDepthStencilState(
m_batch.check_mask_before_draw ? m_depth_test_less_state.Get() : m_depth_test_always_state.Get(), 0); 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++) 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 batch_vs = shadergen.GenerateBatchVertexShader(textured);
const std::string fs = shadergen.GenerateBatchFragmentShader( 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)); ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
const auto link_callback = [this, textured, use_binding_layout](GL::Program& prog) { 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)) if (UseAlphaBlending(m_current_transparency_mode, m_current_render_mode))
{ {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendEquationSeparate(m_current_transparency_mode == TransparencyMode::BackgroundMinusForeground ? glBlendEquationSeparate(m_current_transparency_mode == GPUTransparencyMode::BackgroundMinusForeground ?
GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT :
GL_FUNC_ADD, GL_FUNC_ADD,
GL_FUNC_ADD); GL_FUNC_ADD);

View File

@ -99,6 +99,6 @@ private:
bool m_use_ssbo_for_vram_writes = false; bool m_use_ssbo_for_vram_writes = false;
bool m_current_check_mask_before_draw = 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; 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()); DefineMacro(ss, "MULTISAMPLING", UsingMSAA());
ss << "CONSTANT uint RESOLUTION_SCALE = " << m_resolution_scale << "u;\n"; 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 float2 RCP_VRAM_SIZE = float2(1.0, 1.0) / float2(VRAM_SIZE);\n";
ss << "CONSTANT uint MULTISAMPLES = " << m_multisamples << "u;\n"; ss << "CONSTANT uint MULTISAMPLES = " << m_multisamples << "u;\n";
ss << "CONSTANT bool PER_SAMPLE_SHADING = " << (m_per_sample_shading ? "true" : "false") << ";\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, std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency,
GPU::TextureMode texture_mode, bool dithering, GPUTextureMode texture_mode, bool dithering, bool interlacing)
bool interlacing)
{ {
const GPU::TextureMode actual_texture_mode = texture_mode & ~GPU::TextureMode::RawTextureBit; const GPUTextureMode actual_texture_mode = texture_mode & ~GPUTextureMode::RawTextureBit;
const bool raw_texture = (texture_mode & GPU::TextureMode::RawTextureBit) == GPU::TextureMode::RawTextureBit; const bool raw_texture = (texture_mode & GPUTextureMode::RawTextureBit) == GPUTextureMode::RawTextureBit;
const bool textured = (texture_mode != GPU::TextureMode::Disabled); const bool textured = (texture_mode != GPUTextureMode::Disabled);
const bool use_dual_source = const bool use_dual_source =
m_supports_dual_source_blend && ((transparency != GPU_HW::BatchRenderMode::TransparencyDisabled && m_supports_dual_source_blend && ((transparency != GPU_HW::BatchRenderMode::TransparencyDisabled &&
transparency != GPU_HW::BatchRenderMode::OnlyOpaque) || 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, "TRANSPARENCY_ONLY_TRANSPARENT", transparency == GPU_HW::BatchRenderMode::OnlyTransparent);
DefineMacro(ss, "TEXTURED", textured); DefineMacro(ss, "TEXTURED", textured);
DefineMacro(ss, "PALETTE", DefineMacro(ss, "PALETTE",
actual_texture_mode == GPU::TextureMode::Palette4Bit || actual_texture_mode == GPUTextureMode::Palette4Bit || actual_texture_mode == GPUTextureMode::Palette8Bit);
actual_texture_mode == GPU::TextureMode::Palette8Bit); DefineMacro(ss, "PALETTE_4_BIT", actual_texture_mode == GPUTextureMode::Palette4Bit);
DefineMacro(ss, "PALETTE_4_BIT", actual_texture_mode == GPU::TextureMode::Palette4Bit); DefineMacro(ss, "PALETTE_8_BIT", actual_texture_mode == GPUTextureMode::Palette8Bit);
DefineMacro(ss, "PALETTE_8_BIT", actual_texture_mode == GPU::TextureMode::Palette8Bit);
DefineMacro(ss, "RAW_TEXTURE", raw_texture); DefineMacro(ss, "RAW_TEXTURE", raw_texture);
DefineMacro(ss, "DITHERING", dithering); DefineMacro(ss, "DITHERING", dithering);
DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering); DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering);
@ -693,7 +691,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod
{ {
if (i > 0) if (i > 0)
ss << ", "; ss << ", ";
ss << GPU::DITHER_MATRIX[i / 4][i % 4]; ss << DITHER_MATRIX[i / 4][i % 4];
} }
if (m_glsl) if (m_glsl)
ss << " );\n"; ss << " );\n";

View File

@ -11,7 +11,7 @@ public:
~GPU_HW_ShaderGen(); ~GPU_HW_ShaderGen();
std::string GenerateBatchVertexShader(bool textured); 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); bool dithering, bool interlacing);
std::string GenerateInterlacedFillFragmentShader(); std::string GenerateInterlacedFillFragmentShader();
std::string GenerateDisplayFragmentShader(bool depth_24bit, GPU_HW::InterlacedRenderMode interlace_mode, 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++) for (u8 interlacing = 0; interlacing < 2; interlacing++)
{ {
const std::string fs = shadergen.GenerateBatchFragmentShader( 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)); ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
VkShaderModule shader = g_vulkan_shader_cache->GetFragmentShader(fs); VkShaderModule shader = g_vulkan_shader_cache->GetFragmentShader(fs);
@ -671,7 +671,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
{ {
for (u8 interlacing = 0; interlacing < 2; interlacing++) 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.SetPipelineLayout(m_batch_pipeline_layout);
gpbuilder.SetRenderPass(m_vram_render_pass, 0); gpbuilder.SetRenderPass(m_vram_render_pass, 0);
@ -697,7 +697,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
gpbuilder.SetNoBlendingState(); gpbuilder.SetNoBlendingState();
gpbuilder.SetMultisamples(m_multisamples, m_per_sample_shading); 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::TransparencyDisabled &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque)) || static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque)) ||
m_texture_filtering != GPUTextureFilter::Nearest) m_texture_filtering != GPUTextureFilter::Nearest)
@ -705,7 +705,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
gpbuilder.SetBlendAttachment( gpbuilder.SetBlendAttachment(
0, true, VK_BLEND_FACTOR_ONE, 0, true, VK_BLEND_FACTOR_ONE,
m_supports_dual_source_blend ? VK_BLEND_FACTOR_SRC1_ALPHA : VK_BLEND_FACTOR_SRC_ALPHA, 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::TransparencyDisabled &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque) ? static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque) ?
VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_REVERSE_SUBTRACT :

View File

@ -532,12 +532,12 @@ void GPU_SW::UpdateDisplay()
void GPU_SW::DispatchRenderCommand() 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; const bool dithering_enable = rc.IsDitheringEnabled() && m_GPUSTAT.dither_enable;
switch (rc.primitive) switch (rc.primitive)
{ {
case Primitive::Polygon: case GPUPrimitive::Polygon:
{ {
const u32 first_color = rc.color_for_first_vertex; const u32 first_color = rc.color_for_first_vertex;
const bool shaded = rc.shading_enable; const bool shaded = rc.shading_enable;
@ -553,7 +553,7 @@ void GPU_SW::DispatchRenderCommand()
vert.g = Truncate8(color_rgb >> 8); vert.g = Truncate8(color_rgb >> 8);
vert.b = Truncate8(color_rgb >> 16); vert.b = Truncate8(color_rgb >> 16);
const VertexPosition vp{FifoPop()}; const GPUVertexPosition vp{FifoPop()};
vert.x = m_drawing_offset.x + vp.x; vert.x = m_drawing_offset.x + vp.x;
vert.y = m_drawing_offset.y + vp.y; vert.y = m_drawing_offset.y + vp.y;
@ -580,10 +580,10 @@ void GPU_SW::DispatchRenderCommand()
} }
break; break;
case Primitive::Rectangle: case GPUPrimitive::Rectangle:
{ {
const auto [r, g, b] = UnpackColorRGB24(rc.color_for_first_vertex); 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 u32 texcoord_and_palette = rc.texture_enable ? FifoPop() : 0;
const auto [texcoord_x, texcoord_y] = UnpackTexcoord(Truncate16(texcoord_and_palette)); const auto [texcoord_x, texcoord_y] = UnpackTexcoord(Truncate16(texcoord_and_palette));
@ -591,15 +591,15 @@ void GPU_SW::DispatchRenderCommand()
u32 height; u32 height;
switch (rc.rectangle_size) switch (rc.rectangle_size)
{ {
case DrawRectangleSize::R1x1: case GPUDrawRectangleSize::R1x1:
width = 1; width = 1;
height = 1; height = 1;
break; break;
case DrawRectangleSize::R8x8: case GPUDrawRectangleSize::R8x8:
width = 8; width = 8;
height = 8; height = 8;
break; break;
case DrawRectangleSize::R16x16: case GPUDrawRectangleSize::R16x16:
width = 16; width = 16;
height = 16; height = 16;
break; break;
@ -629,7 +629,7 @@ void GPU_SW::DispatchRenderCommand()
} }
break; break;
case Primitive::Line: case GPUPrimitive::Line:
{ {
const u32 first_color = rc.color_for_first_vertex; const u32 first_color = rc.color_for_first_vertex;
const bool shaded = rc.shading_enable; const bool shaded = rc.shading_enable;
@ -642,7 +642,7 @@ void GPU_SW::DispatchRenderCommand()
// first vertex // first vertex
SWVertex* p0 = &vertices[0]; SWVertex* p0 = &vertices[0];
SWVertex* p1 = &vertices[1]; 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); m_drawing_offset.x, m_drawing_offset.y);
p0->SetColorRGB24(first_color); p0->SetColorRGB24(first_color);
@ -653,12 +653,12 @@ void GPU_SW::DispatchRenderCommand()
if (rc.polyline) if (rc.polyline)
{ {
p1->SetColorRGB24(shaded ? (m_blit_buffer[buffer_pos++] & UINT32_C(0x00FFFFFF)) : first_color); 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 else
{ {
p1->SetColorRGB24(shaded ? (FifoPop() & UINT32_C(0x00FFFFFF)) : first_color); 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 // 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; texcoord_y = (texcoord_y & m_draw_mode.texture_window_and_y) | m_draw_mode.texture_window_or_y;
VRAMPixel texture_color; 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, 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); (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; 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, 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); (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()), \ 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()) 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); BLEND_RGB(BLEND_AVERAGE);
break; break;
case GPU::TransparencyMode::BackgroundPlusForeground: case GPUTransparencyMode::BackgroundPlusForeground:
BLEND_RGB(BLEND_ADD); BLEND_RGB(BLEND_ADD);
break; break;
case GPU::TransparencyMode::BackgroundMinusForeground: case GPUTransparencyMode::BackgroundMinusForeground:
BLEND_RGB(BLEND_SUBTRACT); BLEND_RGB(BLEND_SUBTRACT);
break; break;
case GPU::TransparencyMode::BackgroundPlusQuarterForeground: case GPUTransparencyMode::BackgroundPlusQuarterForeground:
BLEND_RGB(BLEND_QUARTER); BLEND_RGB(BLEND_QUARTER);
break; break;
default: 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, 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) u8 origin_texcoord_y)
{ {
const s32 start_x = TruncateVertexPosition(m_drawing_offset.x + origin_x); const s32 start_x = TruncateGPUVertexPosition(m_drawing_offset.x + origin_x);
const s32 start_y = TruncateVertexPosition(m_drawing_offset.y + origin_y); 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)); 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 x_ig_adjust = x_start;
s32 w = x_bound - 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)) 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; lc -= ls;
rc -= rs; rc -= rs;
s32 y = TruncateVertexPosition(yi); s32 y = TruncateGPUVertexPosition(yi);
if (y < static_cast<s32>(m_drawing_area.top)) if (y < static_cast<s32>(m_drawing_area.top))
break; break;
@ -1194,7 +1194,7 @@ void GPU_SW::DrawTriangle(const SWVertex* v0, const SWVertex* v1, const SWVertex
{ {
while (yi < yb) while (yi < yb)
{ {
s32 y = TruncateVertexPosition(yi); s32 y = TruncateGPUVertexPosition(yi);
if (y > static_cast<s32>(m_drawing_area.bottom)) if (y > static_cast<s32>(m_drawing_area.bottom))
break; break;

View File

@ -36,10 +36,10 @@ protected:
u8 r, g, b; u8 r, g, b;
u8 u, v; 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); x = TruncateGPUVertexPosition(offset_x + p.x);
y = TruncateVertexPosition(offset_y + p.y); y = TruncateGPUVertexPosition(offset_y + p.y);
} }
ALWAYS_INLINE void SetColorRGB24(u32 color) { std::tie(r, g, b) = UnpackColorRGB24(color); } 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.aspect_ratio = m_last_aspect_ratio;
info->geometry.base_width = 320; info->geometry.base_width = 320;
info->geometry.base_height = 240; info->geometry.base_height = 240;
info->geometry.max_width = GPU::VRAM_WIDTH * resolution_scale; info->geometry.max_width = VRAM_WIDTH * resolution_scale;
info->geometry.max_height = GPU::VRAM_HEIGHT * resolution_scale; info->geometry.max_height = VRAM_HEIGHT * resolution_scale;
info->timing.fps = System::GetThrottleFrequency(); info->timing.fps = System::GetThrottleFrequency();
info->timing.sample_rate = static_cast<double>(AUDIO_SAMPLE_RATE); 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++) for (u32 scale = 1; scale <= GPU::MAX_RESOLUTION_SCALE; scale++)
{ {
char buf[32]; 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)) if (ImGui::MenuItem(buf, nullptr, current_internal_resolution == scale))
{ {