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_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
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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>
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
180
src/core/gpu.h
180
src/core/gpu.h
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 :
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
|
@ -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.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);
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue