2019-09-12 02:53:04 +00:00
|
|
|
#pragma once
|
|
|
|
#include "gpu.h"
|
2019-09-13 16:07:31 +00:00
|
|
|
#include <sstream>
|
2019-09-14 06:27:24 +00:00
|
|
|
#include <string>
|
2019-10-03 06:46:13 +00:00
|
|
|
#include <tuple>
|
2019-09-12 02:53:04 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
class GPU_HW : public GPU
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
GPU_HW();
|
|
|
|
virtual ~GPU_HW();
|
|
|
|
|
2019-11-01 15:32:27 +00:00
|
|
|
virtual bool Initialize(System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers) override;
|
2019-10-04 10:33:37 +00:00
|
|
|
virtual void Reset() override;
|
2019-11-01 14:31:25 +00:00
|
|
|
virtual void UpdateSettings() override;
|
2019-10-04 10:33:37 +00:00
|
|
|
|
2019-09-12 02:53:04 +00:00
|
|
|
protected:
|
2019-11-01 11:47:45 +00:00
|
|
|
enum class HWPrimitive : u8
|
|
|
|
{
|
|
|
|
Lines = 0,
|
|
|
|
LineStrip = 1,
|
|
|
|
Triangles = 2,
|
|
|
|
TriangleStrip = 3
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class HWBatchRenderMode : u8
|
|
|
|
{
|
|
|
|
TransparencyDisabled,
|
|
|
|
TransparentAndOpaque,
|
|
|
|
OnlyOpaque,
|
|
|
|
OnlyTransparent
|
|
|
|
};
|
|
|
|
|
2019-09-12 02:53:04 +00:00
|
|
|
struct HWVertex
|
|
|
|
{
|
|
|
|
s32 x;
|
|
|
|
s32 y;
|
|
|
|
u32 color;
|
2019-09-27 11:20:35 +00:00
|
|
|
u32 texpage;
|
2019-11-02 12:21:56 +00:00
|
|
|
u32 texcoord; // 16-bit texcoords are needed for 256 extent rectangles
|
2019-10-29 13:42:08 +00:00
|
|
|
|
2019-11-02 12:21:56 +00:00
|
|
|
ALWAYS_INLINE void Set(s32 x_, s32 y_, u32 color_, u32 texpage_, u16 packed_texcoord)
|
|
|
|
{
|
|
|
|
Set(x_, y_, color_, texpage_, packed_texcoord & 0xFF, (packed_texcoord >> 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
ALWAYS_INLINE void Set(s32 x_, s32 y_, u32 color_, u32 texpage_, u16 texcoord_x, u16 texcoord_y)
|
|
|
|
{
|
|
|
|
x = x_;
|
|
|
|
y = y_;
|
|
|
|
color = color_;
|
|
|
|
texpage = texpage_;
|
|
|
|
texcoord = ZeroExtend32(texcoord_x) | (ZeroExtend32(texcoord_y) << 16);
|
|
|
|
}
|
2019-09-12 02:53:04 +00:00
|
|
|
};
|
|
|
|
|
2019-11-02 12:21:56 +00:00
|
|
|
struct HWBatchConfig
|
2019-09-25 14:15:21 +00:00
|
|
|
{
|
2019-09-26 13:33:20 +00:00
|
|
|
u32 texture_page_x;
|
|
|
|
u32 texture_page_y;
|
|
|
|
u32 texture_palette_x;
|
|
|
|
u32 texture_palette_y;
|
2019-11-01 12:47:32 +00:00
|
|
|
HWPrimitive primitive;
|
|
|
|
TextureMode texture_mode;
|
2019-09-25 14:15:21 +00:00
|
|
|
TransparencyMode transparency_mode;
|
2019-10-05 13:25:06 +00:00
|
|
|
std::array<u8, 4> texture_window_values;
|
2019-11-01 12:47:32 +00:00
|
|
|
bool dithering;
|
2019-09-25 14:15:21 +00:00
|
|
|
|
2019-11-01 11:47:45 +00:00
|
|
|
// We need two-pass rendering when using BG-FG blending and texturing, as the transparency can be enabled
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the render mode for this batch.
|
|
|
|
HWBatchRenderMode GetRenderMode() const
|
|
|
|
{
|
|
|
|
return transparency_mode == TransparencyMode::Disabled ? HWBatchRenderMode::TransparencyDisabled :
|
|
|
|
HWBatchRenderMode::TransparentAndOpaque;
|
|
|
|
}
|
2019-10-06 03:09:03 +00:00
|
|
|
};
|
|
|
|
|
2019-09-14 15:18:58 +00:00
|
|
|
static constexpr u32 VERTEX_BUFFER_SIZE = 1 * 1024 * 1024;
|
2019-11-02 12:21:56 +00:00
|
|
|
static constexpr u32 MIN_BATCH_VERTEX_COUNT = 6;
|
2019-09-14 15:18:58 +00:00
|
|
|
static constexpr u32 MAX_BATCH_VERTEX_COUNT = VERTEX_BUFFER_SIZE / sizeof(HWVertex);
|
2019-09-26 13:33:20 +00:00
|
|
|
static constexpr u32 TEXTURE_TILE_SIZE = 256;
|
|
|
|
static constexpr u32 TEXTURE_TILE_X_COUNT = VRAM_WIDTH / TEXTURE_TILE_SIZE;
|
|
|
|
static constexpr u32 TEXTURE_TILE_Y_COUNT = VRAM_HEIGHT / TEXTURE_TILE_SIZE;
|
|
|
|
static constexpr u32 TEXTURE_TILE_COUNT = TEXTURE_TILE_X_COUNT * TEXTURE_TILE_Y_COUNT;
|
2019-09-14 15:18:58 +00:00
|
|
|
|
2019-09-14 06:43:39 +00:00
|
|
|
static constexpr std::tuple<float, float, float, float> RGBA8ToFloat(u32 rgba)
|
|
|
|
{
|
|
|
|
return std::make_tuple(static_cast<float>(rgba & UINT32_C(0xFF)) * (1.0f / 255.0f),
|
|
|
|
static_cast<float>((rgba >> 16) & UINT32_C(0xFF)) * (1.0f / 255.0f),
|
|
|
|
static_cast<float>((rgba >> 8) & UINT32_C(0xFF)) * (1.0f / 255.0f),
|
|
|
|
static_cast<float>(rgba >> 24) * (1.0f / 255.0f));
|
|
|
|
}
|
|
|
|
|
2019-11-02 12:21:56 +00:00
|
|
|
virtual void InvalidateVRAMReadCache() = 0;
|
|
|
|
|
|
|
|
virtual void MapBatchVertexPointer(u32 required_vertices) = 0;
|
|
|
|
|
|
|
|
u32 GetBatchVertexSpace() const { return static_cast<u32>(m_batch_end_vertex_ptr - m_batch_current_vertex_ptr); }
|
|
|
|
u32 GetBatchVertexCount() const { return static_cast<u32>(m_batch_current_vertex_ptr - m_batch_start_vertex_ptr); }
|
2019-09-13 16:07:31 +00:00
|
|
|
|
2019-11-02 12:21:56 +00:00
|
|
|
bool IsFlushed() const { return m_batch_current_vertex_ptr == m_batch_start_vertex_ptr; }
|
2019-09-13 16:07:31 +00:00
|
|
|
|
2019-10-13 07:33:20 +00:00
|
|
|
void DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32* command_ptr) override;
|
2019-09-12 02:53:04 +00:00
|
|
|
|
2019-09-12 14:18:13 +00:00
|
|
|
void CalcScissorRect(int* left, int* top, int* right, int* bottom);
|
|
|
|
|
2019-10-03 06:46:13 +00:00
|
|
|
std::tuple<s32, s32> ScaleVRAMCoordinates(s32 x, s32 y) const
|
|
|
|
{
|
|
|
|
return std::make_tuple(x * s32(m_resolution_scale), y * s32(m_resolution_scale));
|
|
|
|
}
|
|
|
|
|
2019-09-12 02:53:04 +00:00
|
|
|
std::string GenerateVertexShader(bool textured);
|
2019-11-01 12:47:32 +00:00
|
|
|
std::string GenerateFragmentShader(HWBatchRenderMode transparency, TextureMode texture_mode, bool dithering);
|
2019-09-13 16:07:31 +00:00
|
|
|
std::string GenerateScreenQuadVertexShader();
|
2019-09-14 06:43:39 +00:00
|
|
|
std::string GenerateFillFragmentShader();
|
2019-10-23 05:36:37 +00:00
|
|
|
std::string GenerateDisplayFragmentShader(bool depth_24bit, bool interlaced);
|
2019-09-12 02:53:04 +00:00
|
|
|
|
2019-11-02 12:21:56 +00:00
|
|
|
HWBatchConfig m_batch = {};
|
|
|
|
|
|
|
|
HWVertex* m_batch_start_vertex_ptr = nullptr;
|
|
|
|
HWVertex* m_batch_end_vertex_ptr = nullptr;
|
|
|
|
HWVertex* m_batch_current_vertex_ptr = nullptr;
|
|
|
|
u32 m_batch_base_vertex = 0;
|
|
|
|
|
2019-11-01 15:32:27 +00:00
|
|
|
u32 m_resolution_scale = 1;
|
|
|
|
u32 m_max_resolution_scale = 1;
|
2019-11-01 14:31:25 +00:00
|
|
|
bool m_true_color = false;
|
2019-09-13 16:07:31 +00:00
|
|
|
|
|
|
|
private:
|
2019-11-01 11:47:45 +00:00
|
|
|
static HWPrimitive GetPrimitiveForCommand(RenderCommand rc);
|
2019-09-25 14:15:21 +00:00
|
|
|
|
2019-09-13 16:07:31 +00:00
|
|
|
void GenerateShaderHeader(std::stringstream& ss);
|
|
|
|
|
2019-10-13 07:33:20 +00:00
|
|
|
void LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command_ptr);
|
2019-11-02 12:21:56 +00:00
|
|
|
void AddDuplicateVertex();
|
2019-09-12 02:53:04 +00:00
|
|
|
};
|