GPU: Base work for hardware renderer
This commit is contained in:
parent
c0853de6a6
commit
4706a906d5
241
src/pse/gpu.cpp
241
src/pse/gpu.cpp
|
@ -4,14 +4,6 @@
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
Log_SetChannel(GPU);
|
Log_SetChannel(GPU);
|
||||||
|
|
||||||
static constexpr s32 S11ToS32(u32 value)
|
|
||||||
{
|
|
||||||
if (value & (UINT16_C(1) << 10))
|
|
||||||
return static_cast<s32>(UINT32_C(0xFFFFF800) | value);
|
|
||||||
else
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
GPU::GPU() = default;
|
GPU::GPU() = default;
|
||||||
|
|
||||||
GPU::~GPU() = default;
|
GPU::~GPU() = default;
|
||||||
|
@ -109,96 +101,92 @@ u32 GPU::ReadGPUREAD()
|
||||||
|
|
||||||
void GPU::WriteGP0(u32 value)
|
void GPU::WriteGP0(u32 value)
|
||||||
{
|
{
|
||||||
Assert(m_GP0_command_length < MAX_GP0_COMMAND_LENGTH);
|
m_GP0_command.push_back(value);
|
||||||
|
Assert(m_GP0_command.size() <= 128);
|
||||||
m_GP0_command[m_GP0_command_length++] = value;
|
|
||||||
|
|
||||||
const u8 command = Truncate8(m_GP0_command[0] >> 24);
|
const u8 command = Truncate8(m_GP0_command[0] >> 24);
|
||||||
const u32 param = m_GP0_command[0] & UINT32_C(0x00FFFFFF);
|
const u32 param = m_GP0_command[0] & UINT32_C(0x00FFFFFF);
|
||||||
switch (command)
|
|
||||||
|
if (command >= 0x20 && command <= 0x7F)
|
||||||
{
|
{
|
||||||
case 0x00: // NOP
|
// Draw polygon
|
||||||
|
if (!HandleRenderCommand())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case 0x00: // NOP
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xE1: // Set draw mode
|
||||||
|
{
|
||||||
|
// 0..10 bits match GPUSTAT
|
||||||
|
const u32 MASK = ((UINT32_C(1) << 11) - 1);
|
||||||
|
m_GPUSTAT.bits = (m_GPUSTAT.bits & ~MASK) | param & MASK;
|
||||||
|
m_GPUSTAT.texture_disable = (param & (UINT32_C(1) << 11)) != 0;
|
||||||
|
m_texture_config.x_flip = (param & (UINT32_C(1) << 12)) != 0;
|
||||||
|
m_texture_config.y_flip = (param & (UINT32_C(1) << 13)) != 0;
|
||||||
|
Log_DebugPrintf("Set draw mode %08X", param);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE1: // Set draw mode
|
case 0xE2: // set texture window
|
||||||
{
|
|
||||||
// 0..10 bits match GPUSTAT
|
|
||||||
const u32 MASK = ((UINT32_C(1) << 11) - 1);
|
|
||||||
m_GPUSTAT.bits = (m_GPUSTAT.bits & ~MASK) | param & MASK;
|
|
||||||
m_GPUSTAT.texture_disable = (param & (UINT32_C(1) << 11)) != 0;
|
|
||||||
m_texture_config.x_flip = (param & (UINT32_C(1) << 12)) != 0;
|
|
||||||
m_texture_config.y_flip = (param & (UINT32_C(1) << 13)) != 0;
|
|
||||||
Log_DebugPrintf("Set draw mode %08X", param);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xE2: // set texture window
|
|
||||||
{
|
|
||||||
m_texture_config.window_mask_x = param & UINT32_C(0x1F);
|
|
||||||
m_texture_config.window_mask_y = (param >> 5) & UINT32_C(0x1F);
|
|
||||||
m_texture_config.window_offset_x = (param >> 10) & UINT32_C(0x1F);
|
|
||||||
m_texture_config.window_offset_y = (param >> 15) & UINT32_C(0x1F);
|
|
||||||
Log_DebugPrintf("Set texture window %02X %02X %02X %02X", m_texture_config.window_mask_x,
|
|
||||||
m_texture_config.window_mask_y, m_texture_config.window_offset_x,
|
|
||||||
m_texture_config.window_offset_y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xE3: // Set drawing area top left
|
|
||||||
{
|
|
||||||
m_drawing_area.top_left_x = param & UINT32_C(0x3FF);
|
|
||||||
m_drawing_area.top_left_y = (param >> 10) & UINT32_C(0x1FF);
|
|
||||||
Log_DebugPrintf("Set drawing area top-left: (%u, %u)", m_drawing_area.top_left_x, m_drawing_area.top_left_y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xE4: // Set drawing area bottom right
|
|
||||||
{
|
|
||||||
m_drawing_area.bottom_right_x = param & UINT32_C(0x3FF);
|
|
||||||
m_drawing_area.bottom_right_y = (param >> 10) & UINT32_C(0x1FF);
|
|
||||||
Log_DebugPrintf("Set drawing area bottom-right: (%u, %u)", m_drawing_area.bottom_right_x,
|
|
||||||
m_drawing_area.bottom_right_y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xE5: // Set drawing offset
|
|
||||||
{
|
|
||||||
m_drawing_offset.x = S11ToS32(param & UINT32_C(0x7FF));
|
|
||||||
m_drawing_offset.y = S11ToS32((param >> 11) & UINT32_C(0x7FF));
|
|
||||||
Log_DebugPrintf("Set drawing offset (%d, %d)", m_drawing_offset.x, m_drawing_offset.y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xE6: // Mask bit setting
|
|
||||||
{
|
|
||||||
m_GPUSTAT.draw_set_mask_bit = (param & UINT32_C(0x01)) != 0;
|
|
||||||
m_GPUSTAT.draw_to_masked_pixels = (param & UINT32_C(0x01)) != 0;
|
|
||||||
Log_DebugPrintf("Set mask bit %u %u", BoolToUInt32(m_GPUSTAT.draw_set_mask_bit),
|
|
||||||
BoolToUInt32(m_GPUSTAT.draw_to_masked_pixels));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (command < 0x20)
|
|
||||||
{
|
{
|
||||||
|
m_texture_config.window_mask_x = param & UINT32_C(0x1F);
|
||||||
|
m_texture_config.window_mask_y = (param >> 5) & UINT32_C(0x1F);
|
||||||
|
m_texture_config.window_offset_x = (param >> 10) & UINT32_C(0x1F);
|
||||||
|
m_texture_config.window_offset_y = (param >> 15) & UINT32_C(0x1F);
|
||||||
|
Log_DebugPrintf("Set texture window %02X %02X %02X %02X", m_texture_config.window_mask_x,
|
||||||
|
m_texture_config.window_mask_y, m_texture_config.window_offset_x,
|
||||||
|
m_texture_config.window_offset_y);
|
||||||
}
|
}
|
||||||
else if (command < 0x40)
|
break;
|
||||||
|
|
||||||
|
case 0xE3: // Set drawing area top left
|
||||||
{
|
{
|
||||||
// Draw polygon
|
m_drawing_area.top_left_x = param & UINT32_C(0x3FF);
|
||||||
if (!HandleRenderPolygonCommand())
|
m_drawing_area.top_left_y = (param >> 10) & UINT32_C(0x1FF);
|
||||||
return;
|
Log_DebugPrintf("Set drawing area top-left: (%u, %u)", m_drawing_area.top_left_x, m_drawing_area.top_left_y);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
Log_ErrorPrintf("Unimplemented GP0 command 0x%02X", command);
|
case 0xE4: // Set drawing area bottom right
|
||||||
|
{
|
||||||
|
m_drawing_area.bottom_right_x = param & UINT32_C(0x3FF);
|
||||||
|
m_drawing_area.bottom_right_y = (param >> 10) & UINT32_C(0x1FF);
|
||||||
|
Log_DebugPrintf("Set drawing area bottom-right: (%u, %u)", m_drawing_area.bottom_right_x,
|
||||||
|
m_drawing_area.bottom_right_y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xE5: // Set drawing offset
|
||||||
|
{
|
||||||
|
m_drawing_offset.x = S11ToS32(param & UINT32_C(0x7FF));
|
||||||
|
m_drawing_offset.y = S11ToS32((param >> 11) & UINT32_C(0x7FF));
|
||||||
|
Log_DebugPrintf("Set drawing offset (%d, %d)", m_drawing_offset.x, m_drawing_offset.y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xE6: // Mask bit setting
|
||||||
|
{
|
||||||
|
m_GPUSTAT.draw_set_mask_bit = (param & UINT32_C(0x01)) != 0;
|
||||||
|
m_GPUSTAT.draw_to_masked_pixels = (param & UINT32_C(0x01)) != 0;
|
||||||
|
Log_DebugPrintf("Set mask bit %u %u", BoolToUInt32(m_GPUSTAT.draw_set_mask_bit),
|
||||||
|
BoolToUInt32(m_GPUSTAT.draw_to_masked_pixels));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Unimplemented GP0 command 0x%02X", command);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_GP0_command.fill(UINT32_C(0));
|
m_GP0_command.clear();
|
||||||
m_GP0_command_length = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::WriteGP1(u32 value)
|
void GPU::WriteGP1(u32 value)
|
||||||
|
@ -221,25 +209,84 @@ void GPU::WriteGP1(u32 value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU::HandleRenderPolygonCommand()
|
bool GPU::HandleRenderCommand()
|
||||||
{
|
{
|
||||||
const u8 command = Truncate8(m_GP0_command[0] >> 24);
|
const u8 command = Truncate8(m_GP0_command[0] >> 24);
|
||||||
const bool semi_transparent = !!(command & 0x02);
|
|
||||||
const bool textured = !!(command & 0x04);
|
|
||||||
const bool four_points = !!(command & 0x08);
|
|
||||||
const bool shaded = !!(command & 0x10);
|
|
||||||
|
|
||||||
// shaded vertices use the colour from the first word for the first vertex
|
const RenderCommand rc{m_GP0_command[0]};
|
||||||
const u8 words_per_vertex = 1 + BoolToUInt8(textured) + BoolToUInt8(shaded);
|
u8 words_per_vertex;
|
||||||
const u8 num_vertices = four_points ? 4 : 3;
|
u32 num_vertices;
|
||||||
const u8 total_words = words_per_vertex * num_vertices + BoolToUInt8(!shaded);
|
u32 total_words;
|
||||||
if (m_GP0_command_length < total_words)
|
switch (rc.primitive)
|
||||||
|
{
|
||||||
|
case Primitive::Polygon:
|
||||||
|
{
|
||||||
|
// shaded vertices use the colour from the first word for the first vertex
|
||||||
|
words_per_vertex = 1 + BoolToUInt8(rc.texture_enable) + BoolToUInt8(rc.shading_enable);
|
||||||
|
num_vertices = rc.quad_polygon ? 4 : 3;
|
||||||
|
total_words = words_per_vertex * num_vertices + BoolToUInt8(!rc.shading_enable);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Primitive::Line:
|
||||||
|
{
|
||||||
|
words_per_vertex = 1 + BoolToUInt8(rc.shading_enable);
|
||||||
|
if (rc.polyline)
|
||||||
|
{
|
||||||
|
// polyline goes until we hit the termination code
|
||||||
|
num_vertices = 0;
|
||||||
|
bool found_terminator = false;
|
||||||
|
for (size_t pos = 0; pos < m_GP0_command.size(); pos += words_per_vertex)
|
||||||
|
{
|
||||||
|
if (m_GP0_command[pos] == 0x55555555)
|
||||||
|
{
|
||||||
|
found_terminator = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_vertices++;
|
||||||
|
}
|
||||||
|
if (!found_terminator)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num_vertices = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_words = words_per_vertex * num_vertices + BoolToUInt8(!rc.shading_enable);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Primitive::Rectangle:
|
||||||
|
{
|
||||||
|
words_per_vertex =
|
||||||
|
1 + BoolToUInt8(rc.texture_enable) + BoolToUInt8(rc.rectangle_size == DrawRectangleSize::Variable);
|
||||||
|
num_vertices = 1;
|
||||||
|
total_words = words_per_vertex;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UnreachableCode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_GP0_command.size() < total_words)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Log_DebugPrintf("Render %s %s %s %s polygon (%u verts, %u words per vert)",
|
static constexpr std::array<const char*, 4> primitive_names = {{"", "polygon", "line", "rectangle"}};
|
||||||
four_points ? "four-point" : "three-point", semi_transparent ? "semi-transparent" : "opaque",
|
|
||||||
textured ? "textured" : "non-textured", shaded ? "shaded" : "monochrome", ZeroExtend32(num_vertices),
|
Log_DebugPrintf("Render %s %s %s %s %s (%u verts, %u words per vert)", rc.quad_polygon ? "four-point" : "three-point",
|
||||||
|
rc.transparency_enable ? "semi-transparent" : "opaque",
|
||||||
|
rc.texture_enable ? "textured" : "non-textured", rc.shading_enable ? "shaded" : "monochrome",
|
||||||
|
primitive_names[static_cast<u8>(rc.primitive.GetValue())], ZeroExtend32(num_vertices),
|
||||||
ZeroExtend32(words_per_vertex));
|
ZeroExtend32(words_per_vertex));
|
||||||
|
|
||||||
|
DispatchRenderCommand(rc, num_vertices);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) {}
|
||||||
|
|
||||||
|
void GPU::FlushRender() {}
|
|
@ -10,10 +10,10 @@ class GPU
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPU();
|
GPU();
|
||||||
~GPU();
|
virtual ~GPU();
|
||||||
|
|
||||||
bool Initialize(Bus* bus, DMA* dma);
|
virtual bool Initialize(Bus* bus, DMA* dma);
|
||||||
void Reset();
|
virtual void Reset();
|
||||||
|
|
||||||
u32 ReadRegister(u32 offset);
|
u32 ReadRegister(u32 offset);
|
||||||
void WriteRegister(u32 offset, u32 value);
|
void WriteRegister(u32 offset, u32 value);
|
||||||
|
@ -22,8 +22,21 @@ public:
|
||||||
u32 DMARead();
|
u32 DMARead();
|
||||||
void DMAWrite(u32 value);
|
void DMAWrite(u32 value);
|
||||||
|
|
||||||
private:
|
// gpu_hw_opengl.cpp
|
||||||
static constexpr u32 MAX_GP0_COMMAND_LENGTH = 12;
|
static std::unique_ptr<GPU> CreateHardwareOpenGLRenderer();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static constexpr u32 VRAM_WIDTH = 1024;
|
||||||
|
static constexpr u32 VRAM_HEIGHT = 512;
|
||||||
|
static constexpr u32 VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16);
|
||||||
|
|
||||||
|
static constexpr s32 S11ToS32(u32 value)
|
||||||
|
{
|
||||||
|
if (value & (UINT16_C(1) << 10))
|
||||||
|
return static_cast<s32>(UINT32_C(0xFFFFF800) | value);
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
enum class DMADirection : u32
|
enum class DMADirection : u32
|
||||||
{
|
{
|
||||||
|
@ -33,6 +46,48 @@ private:
|
||||||
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
|
||||||
|
};
|
||||||
|
|
||||||
|
union RenderCommand
|
||||||
|
{
|
||||||
|
u32 bits;
|
||||||
|
|
||||||
|
BitField<u32, u32, 0, 23> color_for_first_vertex;
|
||||||
|
BitField<u32, bool, 24, 1> texture_enable; // not valid for lines
|
||||||
|
BitField<u32, bool, 25, 1> transparency_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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Use BitField to do sign extending instead
|
||||||
|
union VertexPosition
|
||||||
|
{
|
||||||
|
u32 bits;
|
||||||
|
|
||||||
|
BitField<u32, u32, 0, 11> x_s11;
|
||||||
|
BitField<u32, u32, 16, 11> y_s11;
|
||||||
|
|
||||||
|
u32 x() const { return S11ToS32(x_s11); }
|
||||||
|
u32 y() const { return S11ToS32(y_s11); }
|
||||||
|
};
|
||||||
|
|
||||||
void SoftReset();
|
void SoftReset();
|
||||||
void UpdateDMARequest();
|
void UpdateDMARequest();
|
||||||
u32 ReadGPUREAD();
|
u32 ReadGPUREAD();
|
||||||
|
@ -40,7 +95,11 @@ private:
|
||||||
void WriteGP1(u32 value);
|
void WriteGP1(u32 value);
|
||||||
|
|
||||||
// Rendering commands, returns false if not enough data is provided
|
// Rendering commands, returns false if not enough data is provided
|
||||||
bool HandleRenderPolygonCommand();
|
bool HandleRenderCommand();
|
||||||
|
|
||||||
|
// Rendering in the backend
|
||||||
|
virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices);
|
||||||
|
virtual void FlushRender();
|
||||||
|
|
||||||
Bus* m_bus = nullptr;
|
Bus* m_bus = nullptr;
|
||||||
DMA* m_dma = nullptr;
|
DMA* m_dma = nullptr;
|
||||||
|
@ -97,6 +156,5 @@ private:
|
||||||
s32 y;
|
s32 y;
|
||||||
} m_drawing_offset = {};
|
} m_drawing_offset = {};
|
||||||
|
|
||||||
std::array<u32, MAX_GP0_COMMAND_LENGTH> m_GP0_command = {};
|
std::vector<u32> m_GP0_command;
|
||||||
u32 m_GP0_command_length = 0;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "gpu_hw.h"
|
||||||
|
#include "YBaseLib/Assert.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
GPU_HW::GPU_HW() = default;
|
||||||
|
|
||||||
|
GPU_HW::~GPU_HW() = default;
|
||||||
|
|
||||||
|
void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices)
|
||||||
|
{
|
||||||
|
switch (rc.primitive)
|
||||||
|
{
|
||||||
|
case Primitive::Polygon:
|
||||||
|
{
|
||||||
|
const u32 first_colour = m_GP0_command[0] & UINT32_C(0x00FFFFFF);
|
||||||
|
const bool shaded = rc.shading_enable;
|
||||||
|
const bool textured = rc.texture_enable;
|
||||||
|
|
||||||
|
// if we're drawing quads, we need to create a degenerate triangle to restart the triangle strip
|
||||||
|
if (rc.quad_polygon && !m_vertex_staging.empty())
|
||||||
|
m_vertex_staging.push_back(m_vertex_staging.back());
|
||||||
|
|
||||||
|
u32 buffer_pos = 1;
|
||||||
|
for (u32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
HWVertex hw_vert;
|
||||||
|
hw_vert.color = (shaded && i > 0) ? (m_GP0_command[buffer_pos++] & UINT32_C(0x00FFFFFF)) : first_colour;
|
||||||
|
|
||||||
|
const VertexPosition vp{m_GP0_command[buffer_pos++]};
|
||||||
|
hw_vert.x = vp.x();
|
||||||
|
hw_vert.y = vp.y();
|
||||||
|
|
||||||
|
if (textured)
|
||||||
|
hw_vert.texcoord = (m_GP0_command[buffer_pos++] & UINT32_C(0x0000FFFF));
|
||||||
|
|
||||||
|
m_vertex_staging.push_back(hw_vert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UnreachableCode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GPU_HW::GenerateVertexShader(bool textured)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "#version 330 core\n";
|
||||||
|
if (textured)
|
||||||
|
ss << "#define TEXTURED 1\n";
|
||||||
|
else
|
||||||
|
ss << "/* #define TEXTURED 0 */\n";
|
||||||
|
|
||||||
|
ss << R"(
|
||||||
|
in uivec2 a_position;
|
||||||
|
in uint a_texcoord;
|
||||||
|
in vec4 a_color;
|
||||||
|
|
||||||
|
out vec4 v_color;
|
||||||
|
#if TEXTURED
|
||||||
|
out vec2 v_texcoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// -1024..+1023 -> -1..1
|
||||||
|
float gl_x = (a_position.x < 0) ? (float(a_position.x) / 1024.0) : (float(a_position.x) / 1023.0);
|
||||||
|
float gl_y = (a_position.y < 0) ? -(float(a_position.y) / 1024.0) : -(float(a_position.y) / 1023.0);
|
||||||
|
gl_Position = vec4(gl_x, gl_y, 0.0, 1.0);
|
||||||
|
|
||||||
|
v_color = a_color;
|
||||||
|
#if TEXTURED
|
||||||
|
v_texcoord = a_texcoord;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GPU_HW::GenerateFragmentShader(bool textured)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "#version 330 core\n";
|
||||||
|
if (textured)
|
||||||
|
ss << "#define TEXTURED 1\n";
|
||||||
|
else
|
||||||
|
ss << "/* #define TEXTURED 0 */\n";
|
||||||
|
|
||||||
|
ss << R"(
|
||||||
|
in vec4 v_color;
|
||||||
|
#if TEXTURED
|
||||||
|
in vec2 v_texcoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out vec4 ocol0;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//ocol0 = v_color;
|
||||||
|
ocol0 = vec4(1.0, 0.5, 0.5, 1.0);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
#include "gpu.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GPU_HW : public GPU
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GPU_HW();
|
||||||
|
virtual ~GPU_HW();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct HWVertex
|
||||||
|
{
|
||||||
|
s32 x;
|
||||||
|
s32 y;
|
||||||
|
u32 color;
|
||||||
|
u32 texcoord;
|
||||||
|
};
|
||||||
|
|
||||||
|
void LoadVertices(RenderCommand rc, u32 num_vertices);
|
||||||
|
|
||||||
|
std::string GenerateVertexShader(bool textured);
|
||||||
|
std::string GenerateFragmentShader(bool textured);
|
||||||
|
|
||||||
|
std::vector<HWVertex> m_vertex_staging;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
#include "gpu_hw_opengl.h"
|
||||||
|
#include "YBaseLib/Assert.h"
|
||||||
|
#include "YBaseLib/Log.h"
|
||||||
|
Log_SetChannel(GPU_HW_OpenGL);
|
||||||
|
|
||||||
|
GPU_HW_OpenGL::GPU_HW_OpenGL() : GPU_HW() {}
|
||||||
|
|
||||||
|
GPU_HW_OpenGL::~GPU_HW_OpenGL()
|
||||||
|
{
|
||||||
|
DestroyFramebuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_HW_OpenGL::Initialize(Bus* bus, DMA* dma)
|
||||||
|
{
|
||||||
|
if (!GPU_HW::Initialize(bus, dma))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CreateFramebuffer();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_HW_OpenGL::Reset()
|
||||||
|
{
|
||||||
|
GPU_HW::Reset();
|
||||||
|
|
||||||
|
ClearFramebuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_HW_OpenGL::CreateFramebuffer()
|
||||||
|
{
|
||||||
|
glGenTextures(1, &m_framebuffer_texture_id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_framebuffer_texture_id);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, VRAM_WIDTH, VRAM_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &m_framebuffer_fbo_id);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_framebuffer_texture_id, 0);
|
||||||
|
Assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_HW_OpenGL::ClearFramebuffer()
|
||||||
|
{
|
||||||
|
// TODO: get rid of the FBO switches
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_HW_OpenGL::DestroyFramebuffer()
|
||||||
|
{
|
||||||
|
glDeleteFramebuffers(1, &m_framebuffer_fbo_id);
|
||||||
|
m_framebuffer_fbo_id = 0;
|
||||||
|
|
||||||
|
glDeleteTextures(1, &m_framebuffer_texture_id);
|
||||||
|
m_framebuffer_texture_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_HW_OpenGL::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
||||||
|
{
|
||||||
|
LoadVertices(rc, num_vertices);
|
||||||
|
if (m_vertex_staging.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id);
|
||||||
|
|
||||||
|
if (rc.texture_enable)
|
||||||
|
m_texture_program.Bind();
|
||||||
|
else
|
||||||
|
m_color_program.Bind();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizei>(sizeof(HWVertex) * m_vertex_staging.size()),
|
||||||
|
m_vertex_staging.data(), GL_STREAM_DRAW);
|
||||||
|
glDrawArrays(rc.quad_polygon ? GL_TRIANGLE_STRIP : GL_TRIANGLES, 0, static_cast<GLsizei>(m_vertex_staging.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_HW_OpenGL::FlushRender()
|
||||||
|
{
|
||||||
|
if (m_vertex_staging.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_vertex_staging.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPU> GPU::CreateHardwareOpenGLRenderer()
|
||||||
|
{
|
||||||
|
return std::make_unique<GPU_HW_OpenGL>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_HW_OpenGL::Program::Bind()
|
||||||
|
{
|
||||||
|
glUseProgram(program_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint CompileShader(GLenum type, const std::string& source)
|
||||||
|
{
|
||||||
|
GLuint id = glCreateShader(type);
|
||||||
|
|
||||||
|
std::array<const GLchar*, 1> sources = {{source.c_str()}};
|
||||||
|
std::array<GLint, 1> source_lengths = {{static_cast<GLint>(source.size())}};
|
||||||
|
glShaderSource(id, static_cast<GLsizei>(source.size()), sources.data(), source_lengths.data());
|
||||||
|
|
||||||
|
GLint status = GL_FALSE;
|
||||||
|
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
|
||||||
|
|
||||||
|
GLint info_log_length = 0;
|
||||||
|
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||||
|
|
||||||
|
if (status == GL_FALSE || info_log_length > 0)
|
||||||
|
{
|
||||||
|
std::string info_log;
|
||||||
|
info_log.resize(info_log_length + 1);
|
||||||
|
glGetShaderInfoLog(id, info_log_length, &info_log_length, info_log.data());
|
||||||
|
|
||||||
|
if (status == GL_TRUE)
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Shader compiled with warnings:\n%s", info_log.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Shader failed to compile:\n%s", info_log.c_str());
|
||||||
|
glDeleteShader(id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_HW_OpenGL::Program::Compile(const std::string& vertex_shader, const std::string& fragment_shader)
|
||||||
|
{
|
||||||
|
GLuint vertex_shader_id = CompileShader(GL_VERTEX_SHADER, vertex_shader);
|
||||||
|
if (vertex_shader_id == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
GLuint fragment_shader_id = CompileShader(GL_FRAGMENT_SHADER, fragment_shader);
|
||||||
|
if (fragment_shader_id == 0)
|
||||||
|
{
|
||||||
|
glDeleteShader(vertex_shader_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
program_id = glCreateProgram();
|
||||||
|
glAttachShader(program_id, vertex_shader_id);
|
||||||
|
glAttachShader(program_id, fragment_shader_id);
|
||||||
|
|
||||||
|
glBindAttribLocation(program_id, 0, "a_position");
|
||||||
|
glBindAttribLocation(program_id, 1, "a_texcoord");
|
||||||
|
glBindAttribLocation(program_id, 2, "a_color");
|
||||||
|
glBindFragDataLocation(program_id, 0, "ocol0");
|
||||||
|
|
||||||
|
glLinkProgram(program_id);
|
||||||
|
|
||||||
|
glDeleteShader(vertex_shader_id);
|
||||||
|
glDeleteShader(fragment_shader_id);
|
||||||
|
|
||||||
|
GLint status = GL_FALSE;
|
||||||
|
glGetProgramiv(program_id, GL_LINK_STATUS, &status);
|
||||||
|
|
||||||
|
GLint info_log_length = 0;
|
||||||
|
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||||
|
|
||||||
|
if (status == GL_FALSE || info_log_length > 0)
|
||||||
|
{
|
||||||
|
std::string info_log;
|
||||||
|
info_log.resize(info_log_length + 1);
|
||||||
|
glGetProgramInfoLog(program_id, info_log_length, &info_log_length, info_log.data());
|
||||||
|
|
||||||
|
if (status == GL_TRUE)
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Program linked with warnings:\n%s", info_log.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("Program failed to link:\n%s", info_log.c_str());
|
||||||
|
glDeleteProgram(program_id);
|
||||||
|
program_id = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
#include "gpu_hw.h"
|
||||||
|
#include "glad.h"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
class GPU_HW_OpenGL : public GPU_HW
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GPU_HW_OpenGL();
|
||||||
|
~GPU_HW_OpenGL() override;
|
||||||
|
|
||||||
|
bool Initialize(Bus* bus, DMA* dma) override;
|
||||||
|
void Reset() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices) override;
|
||||||
|
virtual void FlushRender() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateFramebuffer();
|
||||||
|
void ClearFramebuffer();
|
||||||
|
void DestroyFramebuffer();
|
||||||
|
|
||||||
|
void CreateVertexBuffer();
|
||||||
|
|
||||||
|
GLuint m_framebuffer_texture_id = 0;
|
||||||
|
GLuint m_framebuffer_fbo_id = 0;
|
||||||
|
|
||||||
|
GLuint m_vertex_buffer = 0;
|
||||||
|
GLuint m_vao_id = 0;
|
||||||
|
|
||||||
|
struct Program
|
||||||
|
{
|
||||||
|
GLuint program_id = 0;
|
||||||
|
|
||||||
|
bool IsValid() const { return program_id != 0; }
|
||||||
|
void Bind();
|
||||||
|
bool Compile(const std::string& vertex_shader, const std::string& fragment_shader);
|
||||||
|
};
|
||||||
|
|
||||||
|
Program m_texture_program;
|
||||||
|
Program m_color_program;
|
||||||
|
};
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
<ClCompile Include="cpu_disasm.cpp" />
|
<ClCompile Include="cpu_disasm.cpp" />
|
||||||
<ClCompile Include="dma.cpp" />
|
<ClCompile Include="dma.cpp" />
|
||||||
<ClCompile Include="gpu.cpp" />
|
<ClCompile Include="gpu.cpp" />
|
||||||
|
<ClCompile Include="gpu_hw.cpp" />
|
||||||
|
<ClCompile Include="gpu_hw_opengl.cpp" />
|
||||||
<ClCompile Include="system.cpp" />
|
<ClCompile Include="system.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -49,6 +51,8 @@
|
||||||
<ClInclude Include="cpu_types.h" />
|
<ClInclude Include="cpu_types.h" />
|
||||||
<ClInclude Include="dma.h" />
|
<ClInclude Include="dma.h" />
|
||||||
<ClInclude Include="gpu.h" />
|
<ClInclude Include="gpu.h" />
|
||||||
|
<ClInclude Include="gpu_hw.h" />
|
||||||
|
<ClInclude Include="gpu_hw_opengl.h" />
|
||||||
<ClInclude Include="save_state_version.h" />
|
<ClInclude Include="save_state_version.h" />
|
||||||
<ClInclude Include="system.h" />
|
<ClInclude Include="system.h" />
|
||||||
<ClInclude Include="types.h" />
|
<ClInclude Include="types.h" />
|
||||||
|
@ -211,7 +215,7 @@
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
@ -232,7 +236,7 @@
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
@ -253,7 +257,7 @@
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
@ -276,7 +280,7 @@
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
@ -298,7 +302,7 @@
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
@ -320,7 +324,7 @@
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
@ -343,7 +347,7 @@
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
@ -365,7 +369,7 @@
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\xbyak\xbyak;$(SolutionDir)dep\softfloat\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\inih\cpp;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
<ClCompile Include="bus.cpp" />
|
<ClCompile Include="bus.cpp" />
|
||||||
<ClCompile Include="dma.cpp" />
|
<ClCompile Include="dma.cpp" />
|
||||||
<ClCompile Include="gpu.cpp" />
|
<ClCompile Include="gpu.cpp" />
|
||||||
|
<ClCompile Include="gpu_hw_opengl.cpp" />
|
||||||
|
<ClCompile Include="gpu_hw.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="types.h" />
|
<ClInclude Include="types.h" />
|
||||||
|
@ -18,6 +20,8 @@
|
||||||
<ClInclude Include="bus.h" />
|
<ClInclude Include="bus.h" />
|
||||||
<ClInclude Include="dma.h" />
|
<ClInclude Include="dma.h" />
|
||||||
<ClInclude Include="gpu.h" />
|
<ClInclude Include="gpu.h" />
|
||||||
|
<ClInclude Include="gpu_hw_opengl.h" />
|
||||||
|
<ClInclude Include="gpu_hw.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="cpu_core.inl" />
|
<None Include="cpu_core.inl" />
|
||||||
|
|
|
@ -1,21 +1,32 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "bus.h"
|
||||||
|
#include "cpu_core.h"
|
||||||
|
#include "dma.h"
|
||||||
|
#include "gpu.h"
|
||||||
|
|
||||||
System::System() = default;
|
System::System()
|
||||||
|
{
|
||||||
|
m_cpu = std::make_unique<CPU::Core>();
|
||||||
|
m_bus = std::make_unique<Bus>();
|
||||||
|
m_dma = std::make_unique<DMA>();
|
||||||
|
m_gpu = std::make_unique<GPU>();
|
||||||
|
// m_gpu = GPU::CreateHardwareOpenGLRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
System::~System() = default;
|
System::~System() = default;
|
||||||
|
|
||||||
bool System::Initialize()
|
bool System::Initialize()
|
||||||
{
|
{
|
||||||
if (!m_cpu.Initialize(&m_bus))
|
if (!m_cpu->Initialize(m_bus.get()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_bus.Initialize(this, &m_dma, &m_gpu))
|
if (!m_bus->Initialize(this, m_dma.get(), m_gpu.get()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_dma.Initialize(&m_bus, &m_gpu))
|
if (!m_dma->Initialize(m_bus.get(), m_gpu.get()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_gpu.Initialize(&m_bus, &m_dma))
|
if (!m_gpu->Initialize(m_bus.get(), m_dma.get()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -23,13 +34,13 @@ bool System::Initialize()
|
||||||
|
|
||||||
void System::Reset()
|
void System::Reset()
|
||||||
{
|
{
|
||||||
m_cpu.Reset();
|
m_cpu->Reset();
|
||||||
m_bus.Reset();
|
m_bus->Reset();
|
||||||
m_dma.Reset();
|
m_dma->Reset();
|
||||||
m_gpu.Reset();
|
m_gpu->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::RunFrame()
|
void System::RunFrame()
|
||||||
{
|
{
|
||||||
m_cpu.Execute();
|
m_cpu->Execute();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "bus.h"
|
|
||||||
#include "dma.h"
|
|
||||||
#include "gpu.h"
|
|
||||||
#include "cpu_core.h"
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
namespace CPU
|
||||||
|
{
|
||||||
|
class Core;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bus;
|
||||||
|
class DMA;
|
||||||
|
class GPU;
|
||||||
|
|
||||||
class System
|
class System
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -17,8 +22,8 @@ public:
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CPU::Core m_cpu;
|
std::unique_ptr<CPU::Core> m_cpu;
|
||||||
Bus m_bus;
|
std::unique_ptr<Bus> m_bus;
|
||||||
DMA m_dma;
|
std::unique_ptr<DMA> m_dma;
|
||||||
GPU m_gpu;
|
std::unique_ptr<GPU> m_gpu;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue