GPU: Move enums/types into separate file
This commit is contained in:
parent
d3d881aa6b
commit
03d4f80883
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
180
src/core/gpu.h
180
src/core/gpu.h
|
@ -2,6 +2,7 @@
|
|||
#include "common/bitfield.h"
|
||||
#include "common/fifo_queue.h"
|
||||
#include "common/rectangle.h"
|
||||
#include "gpu_types.h"
|
||||
#include "timers.h"
|
||||
#include "types.h"
|
||||
#include <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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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,14 +105,14 @@ 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 :
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue