BAHAHAHAHAHAHAHAA

This commit is contained in:
Arisotura 2019-05-16 16:27:45 +02:00
parent f2282e9e32
commit c81bcccadc
11 changed files with 816 additions and 731 deletions

View File

@ -107,6 +107,7 @@
<Unit filename="src/GPU3D.cpp" /> <Unit filename="src/GPU3D.cpp" />
<Unit filename="src/GPU3D.h" /> <Unit filename="src/GPU3D.h" />
<Unit filename="src/GPU3D_OpenGL43.cpp" /> <Unit filename="src/GPU3D_OpenGL43.cpp" />
<Unit filename="src/GPU3D_OpenGL43_shaders.h" />
<Unit filename="src/GPU3D_Soft.cpp" /> <Unit filename="src/GPU3D_Soft.cpp" />
<Unit filename="src/NDS.cpp" /> <Unit filename="src/NDS.cpp" />
<Unit filename="src/NDS.h" /> <Unit filename="src/NDS.h" />

View File

@ -74,6 +74,7 @@ u32 VRAMMap_ARM7[2];
int FrontBuffer; int FrontBuffer;
u32* Framebuffer[2][2]; u32* Framebuffer[2][2];
int FBScale[2]; int FBScale[2];
bool Accelerated;
GPU2D* GPU2D_A; GPU2D* GPU2D_A;
GPU2D* GPU2D_B; GPU2D* GPU2D_B;
@ -88,9 +89,8 @@ bool Init()
FrontBuffer = 0; FrontBuffer = 0;
Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL; Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL;
Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL; Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL;
FBScale[0] = -1; FBScale[1] = -1; FBScale[0] = -1; FBScale[1] = -1; Accelerated = false;
//SetFramebufferScale(1); SetDisplaySettings(0, 0, false);
SetFramebufferScale(1, 1);
return true; return true;
} }
@ -247,13 +247,15 @@ void AssignFramebuffers()
} }
} }
void SetFramebufferScale(int top, int bottom) void SetDisplaySettings(int topscale, int bottomscale, bool accel)
{ {accel=true;
if (top != FBScale[0]) if (topscale != FBScale[0] || accel != Accelerated)
{ {
FBScale[0] = top; FBScale[0] = accel ? 0 : topscale;
int fbsize = (256 * 192) << (FBScale[0] * 2); int fbsize;
if (accel) fbsize = 256*3 * 192;
else fbsize = (256 * 192) << (FBScale[0] * 2);
if (Framebuffer[0][0]) delete[] Framebuffer[0][0]; if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
if (Framebuffer[1][0]) delete[] Framebuffer[1][0]; if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
Framebuffer[0][0] = new u32[fbsize]; Framebuffer[0][0] = new u32[fbsize];
@ -266,21 +268,23 @@ void SetFramebufferScale(int top, int bottom)
if (NDS::PowerControl9 & (1<<15)) if (NDS::PowerControl9 & (1<<15))
{ {
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][0]); GPU2D_A->SetFramebuffer(Framebuffer[backbuf][0]);
GPU2D_A->SetScale(FBScale[0]); GPU2D_A->SetDisplaySettings(FBScale[0], accel);
GPU3D::SetScale(FBScale[0]); GPU3D::SetDisplaySettings(topscale, accel);
} }
else else
{ {
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]); GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
GPU2D_B->SetScale(FBScale[0]); GPU2D_B->SetDisplaySettings(FBScale[0], accel);
} }
} }
if (bottom != FBScale[1]) if (bottomscale != FBScale[1] || accel != Accelerated)
{ {
FBScale[1] = bottom; FBScale[1] = accel ? 0 : bottomscale;
int fbsize = (256 * 192) << (FBScale[1] * 2); int fbsize;
if (accel) fbsize = 256*3 * 192;
else fbsize = (256 * 192) << (FBScale[1] * 2);
if (Framebuffer[0][1]) delete[] Framebuffer[0][1]; if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
if (Framebuffer[1][1]) delete[] Framebuffer[1][1]; if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
Framebuffer[0][1] = new u32[fbsize]; Framebuffer[0][1] = new u32[fbsize];
@ -293,15 +297,17 @@ void SetFramebufferScale(int top, int bottom)
if (NDS::PowerControl9 & (1<<15)) if (NDS::PowerControl9 & (1<<15))
{ {
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][1]); GPU2D_B->SetFramebuffer(Framebuffer[backbuf][1]);
GPU2D_B->SetScale(FBScale[1]); GPU2D_B->SetDisplaySettings(FBScale[1], accel);
} }
else else
{ {
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]); GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
GPU2D_A->SetScale(FBScale[1]); GPU2D_A->SetDisplaySettings(FBScale[1], accel);
GPU3D::SetScale(FBScale[1]); GPU3D::SetDisplaySettings(bottomscale, accel);
} }
} }
Accelerated = accel;
} }

View File

@ -75,7 +75,7 @@ void Stop();
void DoSavestate(Savestate* file); void DoSavestate(Savestate* file);
void SetFramebufferScale(int top, int bottom); void SetDisplaySettings(int topscale, int bottomscale, bool accel);
void MapVRAM_AB(u32 bank, u8 cnt); void MapVRAM_AB(u32 bank, u8 cnt);

View File

@ -82,7 +82,6 @@
GPU2D::GPU2D(u32 num) GPU2D::GPU2D(u32 num)
{ {
Num = num; Num = num;
SetScale(0);
} }
GPU2D::~GPU2D() GPU2D::~GPU2D()
@ -216,12 +215,16 @@ void GPU2D::SetFramebuffer(u32* buf)
Framebuffer = buf; Framebuffer = buf;
} }
void GPU2D::SetScale(int scale) void GPU2D::SetDisplaySettings(int scale, bool accel)
{ {
if (accel) scale = 0;
Accelerated = accel;
LineScale = scale; LineScale = scale;
LineStride = 256 << (scale*2); LineStride = 256 << (scale*2);
if (scale == 1) DrawPixel = DrawPixel_2x; if (Accelerated) DrawPixel = DrawPixel_Accel;
else if (scale == 1) DrawPixel = DrawPixel_2x;
else if (scale == 2) DrawPixel = DrawPixel_4x; else if (scale == 2) DrawPixel = DrawPixel_4x;
else DrawPixel = DrawPixel_1x; else DrawPixel = DrawPixel_1x;
} }
@ -623,7 +626,8 @@ u32 GPU2D::ColorBrightnessDown(u32 val, u32 factor)
void GPU2D::DrawScanline(u32 line) void GPU2D::DrawScanline(u32 line)
{ {
u32* dst = &Framebuffer[LineStride * line]; int stride = Accelerated ? (256*3) : LineStride;
u32* dst = &Framebuffer[stride * line];
int n3dline = line; int n3dline = line;
line = GPU::VCount; line = GPU::VCount;
@ -652,7 +656,7 @@ void GPU2D::DrawScanline(u32 line)
u32 dispmode = DispCnt >> 16; u32 dispmode = DispCnt >> 16;
dispmode &= (Num ? 0x1 : 0x3); dispmode &= (Num ? 0x1 : 0x3);
if (Num == 0) if (Num == 0 && !Accelerated)
_3DLine = GPU3D::GetLine(n3dline); _3DLine = GPU3D::GetLine(n3dline);
// always render regular graphics // always render regular graphics
@ -663,13 +667,13 @@ void GPU2D::DrawScanline(u32 line)
case 0: // screen off case 0: // screen off
{ {
for (int i = 0; i < LineStride; i++) for (int i = 0; i < LineStride; i++)
dst[i] = 0xFF3F3F3F; dst[i] = 0x003F3F3F;
} }
break; break;
case 1: // regular display case 1: // regular display
{ {
for (int i = 0; i < LineStride; i+=2) for (int i = 0; i < stride; i+=2)
*(u64*)&dst[i] = *(u64*)&BGOBJLine[i]; *(u64*)&dst[i] = *(u64*)&BGOBJLine[i];
} }
break; break;
@ -783,6 +787,8 @@ void GPU2D::DrawScanline(u32 line)
DoCapture(line, capwidth); DoCapture(line, capwidth);
} }
if (Accelerated) return;
// master brightness // master brightness
if (dispmode != 0) if (dispmode != 0)
{ {
@ -861,6 +867,8 @@ void GPU2D::DoCapture(u32 line, u32 width)
u16* dst = (u16*)GPU::VRAM[dstvram]; u16* dst = (u16*)GPU::VRAM[dstvram];
u32 dstaddr = (((CaptureCnt >> 18) & 0x3) << 14) + (line * width); u32 dstaddr = (((CaptureCnt >> 18) & 0x3) << 14) + (line * width);
// TODO: handle 3D in accelerated mode!!
u32* srcA; u32* srcA;
if (CaptureCnt & (1<<24)) if (CaptureCnt & (1<<24))
srcA = _3DLine; srcA = _3DLine;
@ -1272,88 +1280,91 @@ void GPU2D::DrawScanline_Mode1(u32 line)
// color special effects // color special effects
// can likely be optimized // can likely be optimized
u32 bldcnteffect = (BlendCnt >> 6) & 0x3; if (!Accelerated)
for (int i = 0; i < LineStride; i++)
{ {
int j = (i >> LineScale) & 0xFF; u32 bldcnteffect = (BlendCnt >> 6) & 0x3;
u32 val1 = BGOBJLine[i]; for (int i = 0; i < LineStride; i++)
u32 val2 = BGOBJLine[4096+i];
u32 coloreffect, eva, evb;
u32 flag1 = val1 >> 24;
u32 flag2 = val2 >> 24;
u32 target2;
if (flag2 & 0x80) target2 = 0x1000;
else if (flag2 & 0x40) target2 = 0x0100;
else target2 = flag2 << 8;
if ((flag1 & 0x80) && (BlendCnt & target2))
{ {
// sprite blending int j = (i >> LineScale) & 0xFF;
coloreffect = 1; u32 val1 = BGOBJLine[i];
u32 val2 = BGOBJLine[4096+i];
if (flag1 & 0x40) u32 coloreffect, eva, evb;
u32 flag1 = val1 >> 24;
u32 flag2 = val2 >> 24;
u32 target2;
if (flag2 & 0x80) target2 = 0x1000;
else if (flag2 & 0x40) target2 = 0x0100;
else target2 = flag2 << 8;
if ((flag1 & 0x80) && (BlendCnt & target2))
{ {
eva = flag1 & 0x1F; // sprite blending
evb = 16 - eva;
}
else
{
eva = EVA;
evb = EVB;
}
}
else if ((flag1 & 0x40) && (BlendCnt & target2))
{
// 3D layer blending
BGOBJLine[i] = ColorBlend5(val1, val2); coloreffect = 1;
continue;
}
else
{
if (flag1 & 0x80) flag1 = 0x10;
else if (flag1 & 0x40) flag1 = 0x01;
if ((BlendCnt & flag1) && (WindowMask[j] & 0x20)) if (flag1 & 0x40)
{ {
if ((bldcnteffect == 1) && (BlendCnt & target2)) eva = flag1 & 0x1F;
evb = 16 - eva;
}
else
{ {
coloreffect = 1;
eva = EVA; eva = EVA;
evb = EVB; evb = EVB;
} }
else if (bldcnteffect >= 2) }
coloreffect = bldcnteffect; else if ((flag1 & 0x40) && (BlendCnt & target2))
{
// 3D layer blending
BGOBJLine[i] = ColorBlend5(val1, val2);
continue;
}
else
{
if (flag1 & 0x80) flag1 = 0x10;
else if (flag1 & 0x40) flag1 = 0x01;
if ((BlendCnt & flag1) && (WindowMask[j] & 0x20))
{
if ((bldcnteffect == 1) && (BlendCnt & target2))
{
coloreffect = 1;
eva = EVA;
evb = EVB;
}
else if (bldcnteffect >= 2)
coloreffect = bldcnteffect;
else
coloreffect = 0;
}
else else
coloreffect = 0; coloreffect = 0;
} }
else
coloreffect = 0;
}
switch (coloreffect) switch (coloreffect)
{ {
case 0: case 0:
BGOBJLine[i] = val1; BGOBJLine[i] = val1;
break; break;
case 1: case 1:
BGOBJLine[i] = ColorBlend4(val1, val2, eva, evb); BGOBJLine[i] = ColorBlend4(val1, val2, eva, evb);
break; break;
case 2: case 2:
BGOBJLine[i] = ColorBrightnessUp(val1, EVY); BGOBJLine[i] = ColorBrightnessUp(val1, EVY);
break; break;
case 3: case 3:
BGOBJLine[i] = ColorBrightnessDown(val1, EVY); BGOBJLine[i] = ColorBrightnessDown(val1, EVY);
break; break;
}
} }
} }
@ -1429,6 +1440,17 @@ void GPU2D::DrawPixel_4x(u32* dst, u16 color, u32 flag)
*(u64*)(dst+3072+2) = val; *(u64*)(dst+3072+2) = val;
} }
void GPU2D::DrawPixel_Accel(u32* dst, u16 color, u32 flag)
{
u8 r = (color & 0x001F) << 1;
u8 g = (color & 0x03E0) >> 4;
u8 b = (color & 0x7C00) >> 9;
*(dst+512) = *(dst+256);
*(dst+256) = *dst;
*dst = r | (g << 8) | (b << 16) | flag;
}
void GPU2D::DrawBG_3D() void GPU2D::DrawBG_3D()
{ {
u16 xoff = BGXPos[0]; u16 xoff = BGXPos[0];
@ -1445,7 +1467,18 @@ void GPU2D::DrawBG_3D()
iend -= (xoff & 0xFF); iend -= (xoff & 0xFF);
} }
if (LineScale == 1) if (Accelerated)
{
for (; i < iend; i++)
{
if (!(WindowMask[i] & 0x01)) continue;
BGOBJLine[i+512] = BGOBJLine[i+256];
BGOBJLine[i+256] = BGOBJLine[i];
BGOBJLine[i] = 0x40000000; // 3D-layer placeholder
}
}
else if (LineScale == 1)
{ {
for (; i < iend; i++) for (; i < iend; i++)
{ {

View File

@ -31,7 +31,7 @@ public:
void SetEnabled(bool enable) { Enabled = enable; } void SetEnabled(bool enable) { Enabled = enable; }
void SetFramebuffer(u32* buf); void SetFramebuffer(u32* buf);
void SetScale(int scale); void SetDisplaySettings(int scale, bool accel);
u8 Read8(u32 addr); u8 Read8(u32 addr);
u16 Read16(u32 addr); u16 Read16(u32 addr);
@ -71,6 +71,7 @@ private:
u32 LineStride; u32 LineStride;
u32 LineScale; u32 LineScale;
bool Accelerated;
u32 BGOBJLine[1024*4 * 2]; u32 BGOBJLine[1024*4 * 2];
u32* _3DLine; u32* _3DLine;
@ -136,6 +137,7 @@ private:
static void DrawPixel_1x(u32* dst, u16 color, u32 flag); static void DrawPixel_1x(u32* dst, u16 color, u32 flag);
static void DrawPixel_2x(u32* dst, u16 color, u32 flag); static void DrawPixel_2x(u32* dst, u16 color, u32 flag);
static void DrawPixel_4x(u32* dst, u16 color, u32 flag); static void DrawPixel_4x(u32* dst, u16 color, u32 flag);
static void DrawPixel_Accel(u32* dst, u16 color, u32 flag);
void (*DrawPixel)(u32* dst, u16 color, u32 flag); void (*DrawPixel)(u32* dst, u16 color, u32 flag);
void DrawBG_3D(); void DrawBG_3D();

View File

@ -607,9 +607,9 @@ void SetEnabled(bool geometry, bool rendering)
if (!rendering) ResetRenderingState(); if (!rendering) ResetRenderingState();
} }
void SetScale(int scale) void SetDisplaySettings(int scale, bool accel)
{ {
GLRenderer43::SetScale(scale); GLRenderer43::SetDisplaySettings(scale, accel);
} }

View File

@ -97,7 +97,7 @@ void Reset();
void DoSavestate(Savestate* file); void DoSavestate(Savestate* file);
void SetEnabled(bool geometry, bool rendering); void SetEnabled(bool geometry, bool rendering);
void SetScale(int scale); void SetDisplaySettings(int scale, bool accel);
void ExecuteCommand(); void ExecuteCommand();
@ -110,6 +110,7 @@ void VCount144();
void VBlank(); void VBlank();
void VCount215(); void VCount215();
u32* GetLine(int line); u32* GetLine(int line);
void SetupAccelFrame();
void WriteToGXFIFO(u32 val); void WriteToGXFIFO(u32 val);
@ -127,13 +128,14 @@ bool Init();
void DeInit(); void DeInit();
void Reset(); void Reset();
void SetScale(int scale); void SetDisplaySettings(int scale, bool accel);
void SetupRenderThread(); void SetupRenderThread();
void VCount144(); void VCount144();
void RenderFrame(); void RenderFrame();
u32* GetLine(int line); u32* GetLine(int line);
void SetupAccelFrame();
} }
@ -144,11 +146,12 @@ bool Init();
void DeInit(); void DeInit();
void Reset(); void Reset();
void SetScale(int scale); void SetDisplaySettings(int scale, bool accel);
void VCount144(); void VCount144();
void RenderFrame(); void RenderFrame();
u32* GetLine(int line); u32* GetLine(int line);
void SetupAccelFrame();
} }

View File

@ -21,6 +21,7 @@
#include "NDS.h" #include "NDS.h"
#include "GPU.h" #include "GPU.h"
#include "OpenGLSupport.h" #include "OpenGLSupport.h"
#include "GPU3D_OpenGL43_shaders.h"
namespace GPU3D namespace GPU3D
{ {
@ -33,631 +34,6 @@ namespace GLRenderer43
// * UBO: 3.1 // * UBO: 3.1
// * glMemoryBarrier: 4.2 // * glMemoryBarrier: 4.2
// TODO: consider other way to handle uniforms (UBO?)
#define kShaderHeader "#version 430"
const char* kClearVS = kShaderHeader R"(
layout(location=0) in vec2 vPosition;
layout(location=1) uniform uint uDepth;
void main()
{
float fdepth = (float(uDepth) / 8388608.0) - 1.0;
gl_Position = vec4(vPosition, fdepth, 1.0);
}
)";
const char* kClearFS = kShaderHeader R"(
layout(location=0) uniform uvec4 uColor;
layout(location=2) uniform uint uOpaquePolyID;
layout(location=3) uniform uint uFogFlag;
layout(location=0) out vec4 oColor;
layout(location=1) out uvec3 oAttr;
void main()
{
oColor = vec4(uColor).bgra / 31.0;
oAttr.r = 0;
oAttr.g = uOpaquePolyID;
oAttr.b = 0;
}
)";
const char* kRenderVSCommon = R"(
layout(std140, binding=0) uniform uConfig
{
vec2 uScreenSize;
uint uDispCnt;
vec4 uToonColors[32];
};
layout(location=0) in uvec4 vPosition;
layout(location=1) in uvec4 vColor;
layout(location=2) in ivec2 vTexcoord;
layout(location=3) in uvec3 vPolygonAttr;
smooth out vec4 fColor;
smooth out vec2 fTexcoord;
flat out uvec3 fPolygonAttr;
)";
const char* kRenderFSCommon = R"(
layout(binding=0) uniform usampler2D TexMem;
layout(binding=1) uniform sampler2D TexPalMem;
layout(std140, binding=0) uniform uConfig
{
vec2 uScreenSize;
uint uDispCnt;
vec4 uToonColors[32];
};
smooth in vec4 fColor;
smooth in vec2 fTexcoord;
flat in uvec3 fPolygonAttr;
layout(location=0) out vec4 oColor;
layout(location=1) out uvec3 oAttr;
int TexcoordWrap(int c, int maxc, uint mode)
{
if ((mode & (1<<0)) != 0)
{
if ((mode & (1<<2)) != 0 && (c & maxc) != 0)
return (maxc-1) - (c & (maxc-1));
else
return (c & (maxc-1));
}
else
return clamp(c, 0, maxc-1);
}
vec4 TextureFetch_A3I5(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x);
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
pixel.a = (pixel.r & 0xE0);
pixel.a = (pixel.a >> 3) + (pixel.a >> 6);
pixel.r &= 0x1F;
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, float(pixel.a)/31.0);
}
vec4 TextureFetch_I2(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x) >> 2;
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
pixel.r >>= (2 * (st.x & 3));
pixel.r &= 0x03;
addr.y = (addr.y << 2) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, max(step(1,pixel.r),alpha0));
}
vec4 TextureFetch_I4(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x) >> 1;
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
if ((st.x & 1) != 0) pixel.r >>= 4;
else pixel.r &= 0x0F;
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, max(step(1,pixel.r),alpha0));
}
vec4 TextureFetch_I8(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x);
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, max(step(1,pixel.r),alpha0));
}
vec4 TextureFetch_Compressed(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y & 0x3FC) * (st.z>>2)) + (st.x & 0x3FC) + (st.y & 0x3);
uvec4 p = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
uint val = (p.r >> (2 * (st.x & 0x3))) & 0x3;
int slot1addr = 0x20000 + ((addr.x & 0x1FFFC) >> 1);
if (addr.x >= 0x40000) slot1addr += 0x10000;
uint palinfo;
p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
palinfo = p.r;
slot1addr++;
p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
palinfo |= (p.r << 8);
addr.y = (addr.y << 3) + ((int(palinfo) & 0x3FFF) << 1);
palinfo >>= 14;
if (val == 0)
{
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
else if (val == 1)
{
addr.y++;
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
else if (val == 2)
{
if (palinfo == 1)
{
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
addr.y++;
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4((color0.rgb + color1.rgb) / 2.0, 1.0);
}
else if (palinfo == 3)
{
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
addr.y++;
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4((color0.rgb*5.0 + color1.rgb*3.0) / 8.0, 1.0);
}
else
{
addr.y += 2;
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
}
else
{
if (palinfo == 2)
{
addr.y += 3;
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
else if (palinfo == 3)
{
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
addr.y++;
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4((color0.rgb*3.0 + color1.rgb*5.0) / 8.0, 1.0);
}
else
{
return vec4(0.0);
}
}
}
vec4 TextureFetch_A5I3(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x);
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
pixel.a = (pixel.r & 0xF8) >> 3;
pixel.r &= 0x07;
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, float(pixel.a)/31.0);
}
vec4 TextureFetch_Direct(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x) << 1;
uvec4 pixelL = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
addr.x++;
uvec4 pixelH = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
vec4 color;
color.r = float(pixelL.r & 0x1F) / 31.0;
color.g = float((pixelL.r >> 5) | ((pixelH.r & 0x03) << 3)) / 31.0;
color.b = float((pixelH.r & 0x7C) >> 2) / 31.0;
color.a = float(pixelH.r >> 7);
return color;
}
vec4 TextureLookup_Nearest(vec2 st)
{
uint attr = fPolygonAttr.y;
uint paladdr = fPolygonAttr.z;
float alpha0;
if ((attr & (1<<29)) != 0) alpha0 = 0.0;
else alpha0 = 1.0;
int tw = 8 << int((attr >> 20) & 0x7);
int th = 8 << int((attr >> 23) & 0x7);
ivec4 st_full = ivec4(ivec2(st), tw, th);
ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
uint wrapmode = attr >> 16;
uint type = (attr >> 26) & 0x7;
if (type == 5) return TextureFetch_Compressed(vramaddr, st_full, wrapmode);
else if (type == 2) return TextureFetch_I2 (vramaddr, st_full, wrapmode, alpha0);
else if (type == 3) return TextureFetch_I4 (vramaddr, st_full, wrapmode, alpha0);
else if (type == 4) return TextureFetch_I8 (vramaddr, st_full, wrapmode, alpha0);
else if (type == 1) return TextureFetch_A3I5 (vramaddr, st_full, wrapmode);
else if (type == 6) return TextureFetch_A5I3 (vramaddr, st_full, wrapmode);
else return TextureFetch_Direct (vramaddr, st_full, wrapmode);
}
vec4 TextureLookup_Linear(vec2 texcoord)
{
ivec2 intpart = ivec2(texcoord);
vec2 fracpart = fract(texcoord);
uint attr = fPolygonAttr.y;
uint paladdr = fPolygonAttr.z;
float alpha0;
if ((attr & (1<<29)) != 0) alpha0 = 0.0;
else alpha0 = 1.0;
int tw = 8 << int((attr >> 20) & 0x7);
int th = 8 << int((attr >> 23) & 0x7);
ivec4 st_full = ivec4(intpart, tw, th);
ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
uint wrapmode = attr >> 16;
vec4 A, B, C, D;
uint type = (attr >> 26) & 0x7;
if (type == 5)
{
A = TextureFetch_Compressed(vramaddr, st_full , wrapmode);
B = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_Compressed(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
else if (type == 2)
{
A = TextureFetch_I2(vramaddr, st_full , wrapmode, alpha0);
B = TextureFetch_I2(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
C = TextureFetch_I2(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
D = TextureFetch_I2(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
}
else if (type == 3)
{
A = TextureFetch_I4(vramaddr, st_full , wrapmode, alpha0);
B = TextureFetch_I4(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
C = TextureFetch_I4(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
D = TextureFetch_I4(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
}
else if (type == 4)
{
A = TextureFetch_I8(vramaddr, st_full , wrapmode, alpha0);
B = TextureFetch_I8(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
C = TextureFetch_I8(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
D = TextureFetch_I8(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
}
else if (type == 1)
{
A = TextureFetch_A3I5(vramaddr, st_full , wrapmode);
B = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_A3I5(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
else if (type == 6)
{
A = TextureFetch_A5I3(vramaddr, st_full , wrapmode);
B = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_A5I3(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
else
{
A = TextureFetch_Direct(vramaddr, st_full , wrapmode);
B = TextureFetch_Direct(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_Direct(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_Direct(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
float fx = fracpart.x;
vec4 AB;
if (A.a < (0.5/31.0) && B.a < (0.5/31.0))
AB = vec4(0);
else
{
//if (A.a < (0.5/31.0) || B.a < (0.5/31.0))
// fx = step(0.5, fx);
AB = mix(A, B, fx);
}
fx = fracpart.x;
vec4 CD;
if (C.a < (0.5/31.0) && D.a < (0.5/31.0))
CD = vec4(0);
else
{
//if (C.a < (0.5/31.0) || D.a < (0.5/31.0))
// fx = step(0.5, fx);
CD = mix(C, D, fx);
}
fx = fracpart.y;
vec4 ret;
if (AB.a < (0.5/31.0) && CD.a < (0.5/31.0))
ret = vec4(0);
else
{
//if (AB.a < (0.5/31.0) || CD.a < (0.5/31.0))
// fx = step(0.5, fx);
ret = mix(AB, CD, fx);
}
return ret;
}
vec4 FinalColor()
{
vec4 col;
vec4 vcol = fColor;
uint blendmode = (fPolygonAttr.x >> 4) & 0x3;
if (blendmode == 2)
{
if ((uDispCnt & (1<<1)) == 0)
{
// toon
vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
vcol.rgb = tooncolor;
}
else
{
// highlight
vcol.rgb = vcol.rrr;
}
}
if ((((fPolygonAttr.y >> 26) & 0x7) == 0) || ((uDispCnt & (1<<0)) == 0))
{
// no texture
col = vcol;
}
else
{
vec4 tcol = TextureLookup_Nearest(fTexcoord);
//vec4 tcol = TextureLookup_Linear(fTexcoord);
if ((blendmode & 1) != 0)
{
// decal
col.rgb = (tcol.rgb * tcol.a) + (vcol.rgb * (1.0-tcol.a));
col.a = vcol.a;
}
else
{
// modulate
col = vcol * tcol;
}
}
if (blendmode == 2)
{
if ((uDispCnt & (1<<1)) != 0)
{
vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
col.rgb = min(col.rgb + tooncolor, 1.0);
}
}
return col.bgra;
}
)";
const char* kRenderVS_Z = R"(
void main()
{
uint attr = vPolygonAttr.x;
uint zshift = (attr >> 16) & 0x1F;
vec4 fpos;
fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
fpos.z = (float(vPosition.z << zshift) / 8388608.0) - 1.0;
fpos.w = float(vPosition.w) / 65536.0f;
fpos.xyz *= fpos.w;
fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
fTexcoord = vec2(vTexcoord) / 16.0;
fPolygonAttr = vPolygonAttr;
gl_Position = fpos;
}
)";
const char* kRenderVS_W = R"(
smooth out float fZ;
void main()
{
uint attr = vPolygonAttr.x;
uint zshift = (attr >> 16) & 0x1F;
vec4 fpos;
fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
fZ = float(vPosition.z << zshift) / 16777216.0;
fpos.w = float(vPosition.w) / 65536.0f;
fpos.xy *= fpos.w;
fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
fTexcoord = vec2(vTexcoord) / 16.0;
fPolygonAttr = vPolygonAttr;
gl_Position = fpos;
}
)";
const char* kRenderFS_ZO = R"(
void main()
{
vec4 col = FinalColor();
if (col.a < 30.5/31) discard;
oColor = col;
oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
}
)";
const char* kRenderFS_WO = R"(
smooth in float fZ;
void main()
{
vec4 col = FinalColor();
if (col.a < 30.5/31) discard;
oColor = col;
oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
gl_FragDepth = fZ;
}
)";
const char* kRenderFS_ZT = R"(
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
oColor = col;
oAttr.g = 0xFF;
}
)";
const char* kRenderFS_WT = R"(
smooth in float fZ;
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
oColor = col;
oAttr.g = 0xFF;
gl_FragDepth = fZ;
}
)";
const char* kRenderFS_ZSM = R"(
void main()
{
oColor = vec4(0,0,0,1);
oAttr.g = 0xFF;
oAttr.b = 1;
}
)";
const char* kRenderFS_WSM = R"(
smooth in float fZ;
void main()
{
oColor = vec4(0,0,0,1);
oAttr.g = 0xFF;
oAttr.b = 1;
gl_FragDepth = fZ;
}
)";
const char* kRenderFS_ZS = R"(
layout(binding=2) uniform usampler2D iAttrTex;
//layout(origin_upper_left) in vec4 gl_FragCoord;
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
if (iAttr.b != 1) discard;
if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
oColor = col;
}
)";
const char* kRenderFS_WS = R"(
layout(binding=2) uniform usampler2D iAttrTex;
//layout(origin_upper_left) in vec4 gl_FragCoord;
smooth in float fZ;
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
if (iAttr.b != 1) discard;
if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
oColor = col;
gl_FragDepth = fZ;
}
)";
enum enum
{ {
@ -721,6 +97,7 @@ GLuint TexMemID;
GLuint TexPalMemID; GLuint TexPalMemID;
int ScaleFactor; int ScaleFactor;
bool Accelerated;
int ScreenW, ScreenH; int ScreenW, ScreenH;
GLuint FramebufferTex[4]; GLuint FramebufferTex[4];
@ -968,9 +345,10 @@ void Reset()
// //
} }
void SetScale(int scale) void SetDisplaySettings(int scale, bool accel)
{ {
ScaleFactor = scale; ScaleFactor = scale;
Accelerated = accel;
// TODO: antialiasing setting // TODO: antialiasing setting
ScreenW = 256 << scale; ScreenW = 256 << scale;
@ -986,10 +364,12 @@ void SetScale(int scale)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW/2, ScreenH/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW/2, ScreenH/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID); glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID);
glBufferData(GL_PIXEL_PACK_BUFFER, ScreenW*ScreenH*4, NULL, GL_DYNAMIC_READ); if (accel) glBufferData(GL_PIXEL_PACK_BUFFER, ScreenW*ScreenH*4, NULL, GL_DYNAMIC_READ);
else glBufferData(GL_PIXEL_PACK_BUFFER, 256*192, NULL, GL_DYNAMIC_READ);
if (Framebuffer) delete[] Framebuffer; if (Framebuffer) delete[] Framebuffer;
Framebuffer = new u32[ScreenW*ScreenH]; if (accel) Framebuffer = new u32[256*192];
else Framebuffer = new u32[ScreenW*ScreenH];
} }
@ -1533,5 +913,10 @@ u32* GetLine(int line)
return &Framebuffer[stride * line]; return &Framebuffer[stride * line];
} }
void SetupAccelFrame()
{
//
}
} }
} }

View File

@ -0,0 +1,645 @@
/*
Copyright 2016-2019 Arisotura
This file is part of melonDS.
melonDS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#ifndef GPU3D_OPENGL43_SHADERS_H
#define GPU3D_OPENGL43_SHADERS_H
#define kShaderHeader "#version 430"
const char* kClearVS = kShaderHeader R"(
layout(location=0) in vec2 vPosition;
layout(location=1) uniform uint uDepth;
void main()
{
float fdepth = (float(uDepth) / 8388608.0) - 1.0;
gl_Position = vec4(vPosition, fdepth, 1.0);
}
)";
const char* kClearFS = kShaderHeader R"(
layout(location=0) uniform uvec4 uColor;
layout(location=2) uniform uint uOpaquePolyID;
layout(location=3) uniform uint uFogFlag;
layout(location=0) out vec4 oColor;
layout(location=1) out uvec3 oAttr;
void main()
{
oColor = vec4(uColor).bgra / 31.0;
oAttr.r = 0;
oAttr.g = uOpaquePolyID;
oAttr.b = 0;
}
)";
const char* kRenderVSCommon = R"(
layout(std140, binding=0) uniform uConfig
{
vec2 uScreenSize;
uint uDispCnt;
vec4 uToonColors[32];
};
layout(location=0) in uvec4 vPosition;
layout(location=1) in uvec4 vColor;
layout(location=2) in ivec2 vTexcoord;
layout(location=3) in uvec3 vPolygonAttr;
smooth out vec4 fColor;
smooth out vec2 fTexcoord;
flat out uvec3 fPolygonAttr;
)";
const char* kRenderFSCommon = R"(
layout(binding=0) uniform usampler2D TexMem;
layout(binding=1) uniform sampler2D TexPalMem;
layout(std140, binding=0) uniform uConfig
{
vec2 uScreenSize;
uint uDispCnt;
vec4 uToonColors[32];
};
smooth in vec4 fColor;
smooth in vec2 fTexcoord;
flat in uvec3 fPolygonAttr;
layout(location=0) out vec4 oColor;
layout(location=1) out uvec3 oAttr;
int TexcoordWrap(int c, int maxc, uint mode)
{
if ((mode & (1<<0)) != 0)
{
if ((mode & (1<<2)) != 0 && (c & maxc) != 0)
return (maxc-1) - (c & (maxc-1));
else
return (c & (maxc-1));
}
else
return clamp(c, 0, maxc-1);
}
vec4 TextureFetch_A3I5(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x);
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
pixel.a = (pixel.r & 0xE0);
pixel.a = (pixel.a >> 3) + (pixel.a >> 6);
pixel.r &= 0x1F;
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, float(pixel.a)/31.0);
}
vec4 TextureFetch_I2(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x) >> 2;
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
pixel.r >>= (2 * (st.x & 3));
pixel.r &= 0x03;
addr.y = (addr.y << 2) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, max(step(1,pixel.r),alpha0));
}
vec4 TextureFetch_I4(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x) >> 1;
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
if ((st.x & 1) != 0) pixel.r >>= 4;
else pixel.r &= 0x0F;
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, max(step(1,pixel.r),alpha0));
}
vec4 TextureFetch_I8(ivec2 addr, ivec4 st, uint wrapmode, float alpha0)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x);
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, max(step(1,pixel.r),alpha0));
}
vec4 TextureFetch_Compressed(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y & 0x3FC) * (st.z>>2)) + (st.x & 0x3FC) + (st.y & 0x3);
uvec4 p = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
uint val = (p.r >> (2 * (st.x & 0x3))) & 0x3;
int slot1addr = 0x20000 + ((addr.x & 0x1FFFC) >> 1);
if (addr.x >= 0x40000) slot1addr += 0x10000;
uint palinfo;
p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
palinfo = p.r;
slot1addr++;
p = texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0);
palinfo |= (p.r << 8);
addr.y = (addr.y << 3) + ((int(palinfo) & 0x3FFF) << 1);
palinfo >>= 14;
if (val == 0)
{
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
else if (val == 1)
{
addr.y++;
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
else if (val == 2)
{
if (palinfo == 1)
{
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
addr.y++;
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4((color0.rgb + color1.rgb) / 2.0, 1.0);
}
else if (palinfo == 3)
{
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
addr.y++;
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4((color0.rgb*5.0 + color1.rgb*3.0) / 8.0, 1.0);
}
else
{
addr.y += 2;
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
}
else
{
if (palinfo == 2)
{
addr.y += 3;
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, 1.0);
}
else if (palinfo == 3)
{
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
addr.y++;
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4((color0.rgb*3.0 + color1.rgb*5.0) / 8.0, 1.0);
}
else
{
return vec4(0.0);
}
}
}
vec4 TextureFetch_A5I3(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x);
uvec4 pixel = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
pixel.a = (pixel.r & 0xF8) >> 3;
pixel.r &= 0x07;
addr.y = (addr.y << 3) + int(pixel.r);
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
return vec4(color.rgb, float(pixel.a)/31.0);
}
vec4 TextureFetch_Direct(ivec2 addr, ivec4 st, uint wrapmode)
{
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
addr.x += ((st.y * st.z) + st.x) << 1;
uvec4 pixelL = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
addr.x++;
uvec4 pixelH = texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0);
vec4 color;
color.r = float(pixelL.r & 0x1F) / 31.0;
color.g = float((pixelL.r >> 5) | ((pixelH.r & 0x03) << 3)) / 31.0;
color.b = float((pixelH.r & 0x7C) >> 2) / 31.0;
color.a = float(pixelH.r >> 7);
return color;
}
vec4 TextureLookup_Nearest(vec2 st)
{
uint attr = fPolygonAttr.y;
uint paladdr = fPolygonAttr.z;
float alpha0;
if ((attr & (1<<29)) != 0) alpha0 = 0.0;
else alpha0 = 1.0;
int tw = 8 << int((attr >> 20) & 0x7);
int th = 8 << int((attr >> 23) & 0x7);
ivec4 st_full = ivec4(ivec2(st), tw, th);
ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
uint wrapmode = attr >> 16;
uint type = (attr >> 26) & 0x7;
if (type == 5) return TextureFetch_Compressed(vramaddr, st_full, wrapmode);
else if (type == 2) return TextureFetch_I2 (vramaddr, st_full, wrapmode, alpha0);
else if (type == 3) return TextureFetch_I4 (vramaddr, st_full, wrapmode, alpha0);
else if (type == 4) return TextureFetch_I8 (vramaddr, st_full, wrapmode, alpha0);
else if (type == 1) return TextureFetch_A3I5 (vramaddr, st_full, wrapmode);
else if (type == 6) return TextureFetch_A5I3 (vramaddr, st_full, wrapmode);
else return TextureFetch_Direct (vramaddr, st_full, wrapmode);
}
vec4 TextureLookup_Linear(vec2 texcoord)
{
ivec2 intpart = ivec2(texcoord);
vec2 fracpart = fract(texcoord);
uint attr = fPolygonAttr.y;
uint paladdr = fPolygonAttr.z;
float alpha0;
if ((attr & (1<<29)) != 0) alpha0 = 0.0;
else alpha0 = 1.0;
int tw = 8 << int((attr >> 20) & 0x7);
int th = 8 << int((attr >> 23) & 0x7);
ivec4 st_full = ivec4(intpart, tw, th);
ivec2 vramaddr = ivec2(int(attr & 0xFFFF) << 3, int(paladdr));
uint wrapmode = attr >> 16;
vec4 A, B, C, D;
uint type = (attr >> 26) & 0x7;
if (type == 5)
{
A = TextureFetch_Compressed(vramaddr, st_full , wrapmode);
B = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_Compressed(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
else if (type == 2)
{
A = TextureFetch_I2(vramaddr, st_full , wrapmode, alpha0);
B = TextureFetch_I2(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
C = TextureFetch_I2(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
D = TextureFetch_I2(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
}
else if (type == 3)
{
A = TextureFetch_I4(vramaddr, st_full , wrapmode, alpha0);
B = TextureFetch_I4(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
C = TextureFetch_I4(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
D = TextureFetch_I4(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
}
else if (type == 4)
{
A = TextureFetch_I8(vramaddr, st_full , wrapmode, alpha0);
B = TextureFetch_I8(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
C = TextureFetch_I8(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
D = TextureFetch_I8(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
}
else if (type == 1)
{
A = TextureFetch_A3I5(vramaddr, st_full , wrapmode);
B = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_A3I5(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
else if (type == 6)
{
A = TextureFetch_A5I3(vramaddr, st_full , wrapmode);
B = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_A5I3(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
else
{
A = TextureFetch_Direct(vramaddr, st_full , wrapmode);
B = TextureFetch_Direct(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
C = TextureFetch_Direct(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
D = TextureFetch_Direct(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
}
float fx = fracpart.x;
vec4 AB;
if (A.a < (0.5/31.0) && B.a < (0.5/31.0))
AB = vec4(0);
else
{
//if (A.a < (0.5/31.0) || B.a < (0.5/31.0))
// fx = step(0.5, fx);
AB = mix(A, B, fx);
}
fx = fracpart.x;
vec4 CD;
if (C.a < (0.5/31.0) && D.a < (0.5/31.0))
CD = vec4(0);
else
{
//if (C.a < (0.5/31.0) || D.a < (0.5/31.0))
// fx = step(0.5, fx);
CD = mix(C, D, fx);
}
fx = fracpart.y;
vec4 ret;
if (AB.a < (0.5/31.0) && CD.a < (0.5/31.0))
ret = vec4(0);
else
{
//if (AB.a < (0.5/31.0) || CD.a < (0.5/31.0))
// fx = step(0.5, fx);
ret = mix(AB, CD, fx);
}
return ret;
}
vec4 FinalColor()
{
vec4 col;
vec4 vcol = fColor;
uint blendmode = (fPolygonAttr.x >> 4) & 0x3;
if (blendmode == 2)
{
if ((uDispCnt & (1<<1)) == 0)
{
// toon
vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
vcol.rgb = tooncolor;
}
else
{
// highlight
vcol.rgb = vcol.rrr;
}
}
if ((((fPolygonAttr.y >> 26) & 0x7) == 0) || ((uDispCnt & (1<<0)) == 0))
{
// no texture
col = vcol;
}
else
{
vec4 tcol = TextureLookup_Nearest(fTexcoord);
//vec4 tcol = TextureLookup_Linear(fTexcoord);
if ((blendmode & 1) != 0)
{
// decal
col.rgb = (tcol.rgb * tcol.a) + (vcol.rgb * (1.0-tcol.a));
col.a = vcol.a;
}
else
{
// modulate
col = vcol * tcol;
}
}
if (blendmode == 2)
{
if ((uDispCnt & (1<<1)) != 0)
{
vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
col.rgb = min(col.rgb + tooncolor, 1.0);
}
}
return col.bgra;
}
)";
const char* kRenderVS_Z = R"(
void main()
{
uint attr = vPolygonAttr.x;
uint zshift = (attr >> 16) & 0x1F;
vec4 fpos;
fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
fpos.z = (float(vPosition.z << zshift) / 8388608.0) - 1.0;
fpos.w = float(vPosition.w) / 65536.0f;
fpos.xyz *= fpos.w;
fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
fTexcoord = vec2(vTexcoord) / 16.0;
fPolygonAttr = vPolygonAttr;
gl_Position = fpos;
}
)";
const char* kRenderVS_W = R"(
smooth out float fZ;
void main()
{
uint attr = vPolygonAttr.x;
uint zshift = (attr >> 16) & 0x1F;
vec4 fpos;
fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
fZ = float(vPosition.z << zshift) / 16777216.0;
fpos.w = float(vPosition.w) / 65536.0f;
fpos.xy *= fpos.w;
fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
fTexcoord = vec2(vTexcoord) / 16.0;
fPolygonAttr = vPolygonAttr;
gl_Position = fpos;
}
)";
const char* kRenderFS_ZO = R"(
void main()
{
vec4 col = FinalColor();
if (col.a < 30.5/31) discard;
oColor = col;
oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
}
)";
const char* kRenderFS_WO = R"(
smooth in float fZ;
void main()
{
vec4 col = FinalColor();
if (col.a < 30.5/31) discard;
oColor = col;
oAttr.g = (fPolygonAttr.x >> 24) & 0x3F;
gl_FragDepth = fZ;
}
)";
const char* kRenderFS_ZT = R"(
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
oColor = col;
oAttr.g = 0xFF;
}
)";
const char* kRenderFS_WT = R"(
smooth in float fZ;
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
oColor = col;
oAttr.g = 0xFF;
gl_FragDepth = fZ;
}
)";
const char* kRenderFS_ZSM = R"(
void main()
{
oColor = vec4(0,0,0,1);
oAttr.g = 0xFF;
oAttr.b = 1;
}
)";
const char* kRenderFS_WSM = R"(
smooth in float fZ;
void main()
{
oColor = vec4(0,0,0,1);
oAttr.g = 0xFF;
oAttr.b = 1;
gl_FragDepth = fZ;
}
)";
const char* kRenderFS_ZS = R"(
layout(binding=2) uniform usampler2D iAttrTex;
//layout(origin_upper_left) in vec4 gl_FragCoord;
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
if (iAttr.b != 1) discard;
if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
oColor = col;
}
)";
const char* kRenderFS_WS = R"(
layout(binding=2) uniform usampler2D iAttrTex;
//layout(origin_upper_left) in vec4 gl_FragCoord;
smooth in float fZ;
void main()
{
vec4 col = FinalColor();
if (col.a < 0.5/31) discard;
if (col.a >= 30.5/31) discard;
uvec4 iAttr = texelFetch(iAttrTex, ivec2(gl_FragCoord.xy), 0);
if (iAttr.b != 1) discard;
if (iAttr.g == ((fPolygonAttr.x >> 24) & 0x3F)) discard;
oColor = col;
gl_FragDepth = fZ;
}
)";
#endif // GPU3D_OPENGL43_SHADERS_H

View File

@ -138,7 +138,7 @@ void Reset()
SetupRenderThread(); SetupRenderThread();
} }
void SetScale(int scale) void SetDisplaySettings(int scale, bool accel)
{ {
printf("SOFT RENDERER SCALE FACTOR: TODO!!!\n"); printf("SOFT RENDERER SCALE FACTOR: TODO!!!\n");
} }
@ -2122,5 +2122,10 @@ u32* GetLine(int line)
return &ColorBuffer[(line * ScanlineWidth) + FirstPixelOffset]; return &ColorBuffer[(line * ScanlineWidth) + FirstPixelOffset];
} }
void SetupAccelFrame()
{
// TODO
}
} }
} }

View File

@ -240,8 +240,8 @@ void GLDrawing_DrawScreen()
x1 = TopScreenRect.X + TopScreenRect.Width; x1 = TopScreenRect.X + TopScreenRect.Width;
y1 = TopScreenRect.Y + TopScreenRect.Height; y1 = TopScreenRect.Y + TopScreenRect.Height;
scwidth = 256 << ScreenScale[0]; scwidth = 256;// << ScreenScale[0];
scheight = 192 << ScreenScale[0]; scheight = 192;// << ScreenScale[0];
switch (ScreenRotation) switch (ScreenRotation)
{ {
@ -286,8 +286,8 @@ void GLDrawing_DrawScreen()
x1 = BottomScreenRect.X + BottomScreenRect.Width; x1 = BottomScreenRect.X + BottomScreenRect.Width;
y1 = BottomScreenRect.Y + BottomScreenRect.Height; y1 = BottomScreenRect.Y + BottomScreenRect.Height;
scwidth = 256 << ScreenScale[1]; scwidth = 256;// << ScreenScale[1];
scheight = 192 << ScreenScale[1]; scheight = 192;// << ScreenScale[1];
switch (ScreenRotation) switch (ScreenRotation)
{ {
@ -349,9 +349,13 @@ void GLDrawing_DrawScreen()
int frontbuf = GPU::FrontBuffer; int frontbuf = GPU::FrontBuffer;
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture); glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256<<ScreenScale[0], 192<<ScreenScale[0], GL_RGBA_INTEGER, /*glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256<<ScreenScale[0], 192<<ScreenScale[0], GL_RGBA_INTEGER,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 768, 256<<ScreenScale[1], 192<<ScreenScale[1], GL_RGBA_INTEGER, glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 768, 256<<ScreenScale[1], 192<<ScreenScale[1], GL_RGBA_INTEGER,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);*/
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3, 192, GL_RGBA_INTEGER,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 768, 256*3, 192, GL_RGBA_INTEGER,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID); glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
@ -633,7 +637,8 @@ int EmuThreadFunc(void* burp)
ScreenScale[0] = ScreenScale[2]; ScreenScale[0] = ScreenScale[2];
ScreenScale[1] = ScreenScale[2]; ScreenScale[1] = ScreenScale[2];
int lastscale[2] = {-1, -1}; int lastscale[2] = {ScreenScale[0], ScreenScale[1]};
GPU::SetDisplaySettings(ScreenScale[0], ScreenScale[1], false);
Touching = false; Touching = false;
KeyInputMask = 0xFFF; KeyInputMask = 0xFFF;
@ -782,7 +787,7 @@ int EmuThreadFunc(void* burp)
if (ScreenScale[0] != lastscale[0] || if (ScreenScale[0] != lastscale[0] ||
ScreenScale[1] != lastscale[1]) ScreenScale[1] != lastscale[1])
{ {
GPU::SetFramebufferScale(ScreenScale[0], ScreenScale[1]); GPU::SetDisplaySettings(ScreenScale[0], ScreenScale[1], false);
ScreenDrawInited = false; ScreenDrawInited = false;
} }