nothing works yet

This commit is contained in:
RSDuck 2023-04-08 01:37:32 +02:00
parent f8fdc77e43
commit b11b5bf522
16 changed files with 3472 additions and 176 deletions

View File

@ -66,6 +66,7 @@ if (ENABLE_OGLRENDERER)
GPU_OpenGL.cpp
GPU_OpenGL_shaders.h
GPU3D_OpenGL.cpp
GPU3D_Compute.cpp
GPU3D_OpenGL_shaders.h
OpenGLSupport.cpp)

View File

@ -169,6 +169,7 @@ extern std::unique_ptr<Renderer3D> CurrentRenderer;
#ifdef OGLRENDERER_ENABLED
#include "GPU3D_OpenGL.h"
#include "GPU3D_Compute.h"
#endif
#endif

1451
src/GPU3D_Compute.cpp Normal file

File diff suppressed because it is too large Load Diff

263
src/GPU3D_Compute.h Normal file
View File

@ -0,0 +1,263 @@
/*
Copyright 2016-2022 melonDS team
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_COMPUTE
#define GPU3D_COMPUTE
#include "GPU3D.h"
#include "OpenGLSupport.h"
#include "NonStupidBitfield.h"
#include <unordered_map>
namespace GPU3D
{
class ComputeRenderer : public Renderer3D
{
public:
ComputeRenderer();
~ComputeRenderer() override;
bool Init() override;
void DeInit() override;
void Reset() override;
void SetRenderSettings(GPU::RenderSettings& settings) override;
void VCount144() override;
void RenderFrame() override;
void RestartFrame() override;
u32* GetLine(int line) override;
//dk::Fence FrameReady = {};
//dk::Fence FrameReserveFence = {};
private:
GLuint ShaderInterpXSpans[2];
GLuint ShaderBinCombined;
GLuint ShaderDepthBlend[2];
GLuint ShaderRasteriseNoTexture[2];
GLuint ShaderRasteriseNoTextureToon[2];
GLuint ShaderRasteriseNoTextureHighlight[2];
GLuint ShaderRasteriseUseTextureDecal[2];
GLuint ShaderRasteriseUseTextureModulate[2];
GLuint ShaderRasteriseUseTextureToon[2];
GLuint ShaderRasteriseUseTextureHighlight[2];
GLuint ShaderRasteriseShadowMask[2];
GLuint ShaderClearCoarseBinMask;
GLuint ShaderClearIndirectWorkCount;
GLuint ShaderCalculateWorkListOffset;
GLuint ShaderSortWork;
GLuint ShaderFinalPass[8];
GLuint YSpanIndicesTextureMemory;
GLuint YSpanIndicesTexture;
GLuint YSpanSetupMemory;
GLuint XSpanSetupMemory;
GLuint BinResultMemory;
GLuint RenderPolygonMemory;
GLuint TileMemory;
GLuint FinalTileMemory;
u32 DummyLine[256] = {};
struct SpanSetupY
{
// Attributes
s32 Z0, Z1, W0, W1;
s32 ColorR0, ColorG0, ColorB0;
s32 ColorR1, ColorG1, ColorB1;
s32 TexcoordU0, TexcoordV0;
s32 TexcoordU1, TexcoordV1;
// Interpolator
s32 I0, I1;
s32 Linear;
s32 IRecip;
s32 W0n, W0d, W1d;
// Slope
s32 Increment;
s32 X0, X1, Y0, Y1;
s32 XMin, XMax;
s32 DxInitial;
s32 XCovIncr;
u32 IsDummy, __pad1;
};
struct SpanSetupX
{
s32 X0, X1;
s32 EdgeLenL, EdgeLenR, EdgeCovL, EdgeCovR;
s32 XRecip;
u32 Flags;
s32 Z0, Z1, W0, W1;
s32 ColorR0, ColorG0, ColorB0;
s32 ColorR1, ColorG1, ColorB1;
s32 TexcoordU0, TexcoordV0;
s32 TexcoordU1, TexcoordV1;
s32 CovLInitial, CovRInitial;
};
struct SetupIndices
{
u16 PolyIdx, SpanIdxL, SpanIdxR, Y;
};
struct RenderPolygon
{
u32 FirstXSpan;
s32 YTop, YBot;
s32 XMin, XMax;
s32 XMinY, XMaxY;
u32 Variant;
u32 Attr;
float TextureLayer;
u32 __pad0, __pad1;
};
static const int TileSize = 8;
static const int CoarseTileCountX = 8;
static const int CoarseTileCountY = 4;
static const int CoarseTileW = CoarseTileCountX * TileSize;
static const int CoarseTileH = CoarseTileCountY * TileSize;
static const int TilesPerLine = 256/TileSize;
static const int TileLines = 192/TileSize;
static const int BinStride = 2048/32;
static const int CoarseBinStride = BinStride/32;
static const int MaxWorkTiles = TilesPerLine*TileLines*48;
static const int MaxVariants = 256;
static const int UniformIdxCurVariant = 0;
static const int UniformIdxTextureSize = 1;
struct BinResult
{
u32 VariantWorkCount[MaxVariants*4];
u32 SortedWorkOffset[MaxVariants];
u32 SortWorkWorkCount[4];
u32 UnsortedWorkDescs[MaxWorkTiles*2];
u32 SortedWork[MaxWorkTiles*2];
u32 BinnedMaskCoarse[TilesPerLine*TileLines*CoarseBinStride];
u32 BinnedMask[TilesPerLine*TileLines*BinStride];
u32 WorkOffsets[TilesPerLine*TileLines*BinStride];
};
struct Tiles
{
u32 ColorTiles[MaxWorkTiles*TileSize*TileSize];
u32 DepthTiles[MaxWorkTiles*TileSize*TileSize];
u32 AttrStencilTiles[MaxWorkTiles*TileSize*TileSize];
};
struct FinalTiles
{
u32 ColorResult[256*192*2];
u32 DepthResult[256*192*2];
u32 AttrResult[256*192*2];
};
// eh those are pretty bad guesses
// though real hw shouldn't be eable to render all 2048 polygons on every line either
static const int MaxYSpanIndices = 64*2048;
static const int MaxYSpanSetups = 6144*2;
SetupIndices YSpanIndices[MaxYSpanIndices];
SpanSetupY YSpanSetups[MaxYSpanSetups];
RenderPolygon RenderPolygons[2048];
struct TexArrayEntry
{
u16 TexArrayIdx;
u16 LayerIdx;
};
struct TexArray
{
GLuint Image;
u32 ImageDescriptor;
};
struct TexCacheEntry
{
u32 DescriptorIdx;
u32 LastVariant; // very cheap way to make variant lookup faster
u32 TextureRAMStart[2], TextureRAMSize[2];
u32 TexPalStart, TexPalSize;
u8 WidthLog2, HeightLog2;
TexArrayEntry Texture;
u64 TextureHash[2];
u64 TexPalHash;
};
std::unordered_map<u64, TexCacheEntry> TexCache;
struct MetaUniform
{
u32 NumPolygons;
u32 NumVariants;
u32 AlphaRef;
u32 DispCnt;
u32 ToonTable[4*34];
u32 ClearColor, ClearDepth, ClearAttr;
u32 FogOffset, FogShift, FogColor;
u32 XScroll;
};
GLuint MetaUniformMemory;
static const u32 TexCacheMaxImages = 4096;
u32 FreeImageDescriptorsCount = 0;
u32 FreeImageDescriptors[TexCacheMaxImages];
std::vector<TexArrayEntry> FreeTextures[8][8];
std::vector<TexArray> TexArrays[8][8];
u32 TextureDecodingBuffer[1024*1024];
TexCacheEntry& GetTexture(u32 textureParam, u32 paletteParam);
void SetupAttrs(SpanSetupY* span, Polygon* poly, int from, int to);
void SetupYSpan(int polynum, SpanSetupY* span, Polygon* poly, int from, int to, u32 y, int side);
void SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int vertex, int side);
bool CompileShader(GLuint& shader, const char* source, const std::initializer_list<const char*>& defines);
};
}
#endif

1502
src/GPU3D_Compute_shaders.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -49,25 +49,18 @@ bool GLRenderer::BuildRenderShader(u32 flags, const char* vs, const char* fs)
strcpy(&fsbuf[headerlen], kRenderFSCommon);
strcpy(&fsbuf[headerlen + fsclen], fs);
bool ret = OpenGL::BuildShaderProgram(vsbuf, fsbuf, RenderShader[flags], shadername);
GLuint prog;
bool ret = OpenGL::CompileVertexFragmentProgram(prog,
vsbuf, fsbuf,
shadername,
{{"vPosition", 0}, {"vColor", 1}, {"vTexcoord", 2}, {"vPolygonAttr", 3}},
{{"oColor", 0}, {"oAttr", 1}});
delete[] vsbuf;
delete[] fsbuf;
if (!ret) return false;
GLuint prog = RenderShader[flags][2];
glBindAttribLocation(prog, 0, "vPosition");
glBindAttribLocation(prog, 1, "vColor");
glBindAttribLocation(prog, 2, "vTexcoord");
glBindAttribLocation(prog, 3, "vPolygonAttr");
glBindFragDataLocation(prog, 0, "oColor");
glBindFragDataLocation(prog, 1, "oAttr");
if (!OpenGL::LinkShaderProgram(RenderShader[flags]))
return false;
GLint uni_id = glGetUniformBlockIndex(prog, "uConfig");
glUniformBlockBinding(prog, uni_id, 0);
@ -78,13 +71,15 @@ bool GLRenderer::BuildRenderShader(u32 flags, const char* vs, const char* fs)
uni_id = glGetUniformLocation(prog, "TexPalMem");
glUniform1i(uni_id, 1);
RenderShader[flags] = prog;
return true;
}
void GLRenderer::UseRenderShader(u32 flags)
{
if (CurShaderID == flags) return;
glUseProgram(RenderShader[flags][2]);
glUseProgram(RenderShader[flags]);
CurShaderID = flags;
}
@ -118,21 +113,17 @@ std::unique_ptr<GLRenderer> GLRenderer::New() noexcept
glDepthRange(0, 1);
glClearDepth(1.0);
if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, result->ClearShaderPlain, "ClearShader"))
if (!OpenGL::CompileVertexFragmentProgram(result->ClearShaderPlain,
kClearVS, kClearFS,
"ClearShader",
{{"vPosition", 0}},
{{"oColor", 0}, {"oAttr", 1}}))
return nullptr;
glBindAttribLocation(result->ClearShaderPlain[2], 0, "vPosition");
glBindFragDataLocation(result->ClearShaderPlain[2], 0, "oColor");
glBindFragDataLocation(result->ClearShaderPlain[2], 1, "oAttr");
if (!OpenGL::LinkShaderProgram(result->ClearShaderPlain))
return nullptr;
result->ClearUniformLoc[0] = glGetUniformLocation(result->ClearShaderPlain[2], "uColor");
result->ClearUniformLoc[1] = glGetUniformLocation(result->ClearShaderPlain[2], "uDepth");
result->ClearUniformLoc[2] = glGetUniformLocation(result->ClearShaderPlain[2], "uOpaquePolyID");
result->ClearUniformLoc[3] = glGetUniformLocation(result->ClearShaderPlain[2], "uFogFlag");
result->ClearUniformLoc[0] = glGetUniformLocation(result->ClearShaderPlain, "uColor");
result->ClearUniformLoc[1] = glGetUniformLocation(result->ClearShaderPlain, "uDepth");
result->ClearUniformLoc[2] = glGetUniformLocation(result->ClearShaderPlain, "uOpaquePolyID");
result->ClearUniformLoc[3] = glGetUniformLocation(result->ClearShaderPlain, "uFogFlag");
memset(result->RenderShader, 0, sizeof(RenderShader));
@ -160,42 +151,35 @@ std::unique_ptr<GLRenderer> GLRenderer::New() noexcept
if (!result->BuildRenderShader(RenderFlag_ShadowMask | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WSM))
return nullptr;
if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, result->FinalPassEdgeShader, "FinalPassEdgeShader"))
if (!OpenGL::CompileVertexFragmentProgram(result->FinalPassEdgeShader,
kFinalPassVS, kFinalPassEdgeFS,
"FinalPassEdgeShader",
{{"vPosition", 0}},
{{"oColor", 0}}))
return nullptr;
if (!OpenGL::CompileVertexFragmentProgram(result->FinalPassFogShader,
kFinalPassVS, kFinalPassFogFS,
"FinalPassFogShader",
{{"vPosition", 0}},
{{"oColor", 0}}))
return nullptr;
if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, result->FinalPassFogShader, "FinalPassFogShader"))
return nullptr;
GLuint uni_id = glGetUniformBlockIndex(result->FinalPassEdgeShader, "uConfig");
glUniformBlockBinding(result->FinalPassEdgeShader, uni_id, 0);
glBindAttribLocation(result->FinalPassEdgeShader[2], 0, "vPosition");
glBindFragDataLocation(result->FinalPassEdgeShader[2], 0, "oColor");
if (!OpenGL::LinkShaderProgram(result->FinalPassEdgeShader))
return nullptr;
GLint uni_id = glGetUniformBlockIndex(result->FinalPassEdgeShader[2], "uConfig");
glUniformBlockBinding(result->FinalPassEdgeShader[2], uni_id, 0);
glUseProgram(result->FinalPassEdgeShader[2]);
uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "DepthBuffer");
glUseProgram(result->FinalPassEdgeShader);
uni_id = glGetUniformLocation(result->FinalPassEdgeShader, "DepthBuffer");
glUniform1i(uni_id, 0);
uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "AttrBuffer");
uni_id = glGetUniformLocation(result->FinalPassEdgeShader, "AttrBuffer");
glUniform1i(uni_id, 1);
glBindAttribLocation(result->FinalPassFogShader[2], 0, "vPosition");
glBindFragDataLocation(result->FinalPassFogShader[2], 0, "oColor");
uni_id = glGetUniformBlockIndex(result->FinalPassFogShader, "uConfig");
glUniformBlockBinding(result->FinalPassFogShader, uni_id, 0);
if (!OpenGL::LinkShaderProgram(result->FinalPassFogShader))
return nullptr;
uni_id = glGetUniformBlockIndex(result->FinalPassFogShader[2], "uConfig");
glUniformBlockBinding(result->FinalPassFogShader[2], uni_id, 0);
glUseProgram(result->FinalPassFogShader[2]);
uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "DepthBuffer");
glUseProgram(result->FinalPassFogShader);
uni_id = glGetUniformLocation(result->FinalPassFogShader, "DepthBuffer");
glUniform1i(uni_id, 0);
uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "AttrBuffer");
uni_id = glGetUniformLocation(result->FinalPassFogShader, "AttrBuffer");
glUniform1i(uni_id, 1);
@ -320,8 +304,8 @@ GLRenderer::~GLRenderer()
for (int i = 0; i < 16; i++)
{
if (!RenderShader[i][2]) continue;
OpenGL::DeleteShaderProgram(RenderShader[i]);
if (!RenderShader[i]) continue;
glDeleteProgram(RenderShader[i]);
}
}
@ -1093,7 +1077,7 @@ void GLRenderer::RenderSceneChunk(int y, int h)
// edge marking
// TODO: depth/polyid values at screen edges
glUseProgram(FinalPassEdgeShader[2]);
glUseProgram(FinalPassEdgeShader);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
@ -1104,7 +1088,7 @@ void GLRenderer::RenderSceneChunk(int y, int h)
{
// fog
glUseProgram(FinalPassFogShader[2]);
glUseProgram(FinalPassFogShader);
if (RenderDispCnt & (1<<6))
glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);
@ -1238,7 +1222,7 @@ void GLRenderer::RenderFrame()
// TODO: check whether 'clear polygon ID' affects translucent polyID
// (for example when alpha is 1..30)
{
glUseProgram(ClearShaderPlain[2]);
glUseProgram(ClearShaderPlain);
glDepthFunc(GL_ALWAYS);
u32 r = RenderClearAttr1 & 0x1F;

View File

@ -84,13 +84,13 @@ private:
};
GLuint ClearShaderPlain[3] {};
GLuint ClearShaderPlain {};
GLuint RenderShader[16][3] {};
GLuint RenderShader[16] {};
GLuint CurShaderID = -1;
GLuint FinalPassEdgeShader[3] {};
GLuint FinalPassFogShader[3] {};
GLuint FinalPassEdgeShader {};
GLuint FinalPassFogShader {};
// std140 compliant structure
struct

View File

@ -36,32 +36,27 @@ using namespace OpenGL;
std::unique_ptr<GLCompositor> GLCompositor::New() noexcept
{
assert(glBindAttribLocation != nullptr);
GLuint CompShader {};
std::array<GLuint, 3> CompShader {};
if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, &CompShader[0], "CompositorShader"))
return nullptr;
glBindAttribLocation(CompShader[2], 0, "vPosition");
glBindAttribLocation(CompShader[2], 1, "vTexcoord");
glBindFragDataLocation(CompShader[2], 0, "oColor");
if (!OpenGL::LinkShaderProgram(CompShader.data()))
// OpenGL::LinkShaderProgram already deletes the shader program object
// if linking the shaders together failed.
if (!OpenGL::CompileVertexFragmentProgram(CompShader,
kCompositorVS, kCompositorFS_Nearest,
"CompositorShader",
{{"vPosition", 0}, {"vTexcoord", 1}},
{{"oColor", 0}}))
return nullptr;
return std::unique_ptr<GLCompositor>(new GLCompositor(CompShader));
}
GLCompositor::GLCompositor(std::array<GLuint, 3> compShader) noexcept : CompShader(compShader)
GLCompositor::GLCompositor(GLuint compShader) noexcept : CompShader(compShader)
{
CompScaleLoc = glGetUniformLocation(CompShader[2], "u3DScale");
Comp3DXPosLoc = glGetUniformLocation(CompShader[2], "u3DXPos");
CompScaleLoc = glGetUniformLocation(CompShader, "u3DScale");
Comp3DXPosLoc = glGetUniformLocation(CompShader, "u3DXPos");
glUseProgram(CompShader[2]);
GLuint screenTextureUniform = glGetUniformLocation(CompShader[2], "ScreenTex");
glUseProgram(CompShader);
GLuint screenTextureUniform = glGetUniformLocation(CompShader, "ScreenTex");
glUniform1i(screenTextureUniform, 0);
GLuint _3dTextureUniform = glGetUniformLocation(CompShader[2], "_3DTex");
GLuint _3dTextureUniform = glGetUniformLocation(CompShader, "_3DTex");
glUniform1i(_3dTextureUniform, 1);
// all this mess is to prevent bleeding
@ -136,7 +131,7 @@ GLCompositor::~GLCompositor()
glDeleteVertexArrays(1, &CompVertexArrayID);
glDeleteBuffers(1, &CompVertexBufferID);
OpenGL::DeleteShaderProgram(CompShader.data());
glDeleteProgram(CompShader);
}
void GLCompositor::Reset()
@ -200,7 +195,7 @@ void GLCompositor::RenderFrame()
glClear(GL_COLOR_BUFFER_BIT);
// TODO: select more shaders (filtering, etc)
OpenGL::UseShaderProgram(CompShader.data());
glUseProgram(CompShader);
glUniform1ui(CompScaleLoc, Scale);
// TODO: support setting this midframe, if ever needed

View File

@ -44,12 +44,12 @@ public:
void RenderFrame();
void BindOutputTexture(int buf);
private:
GLCompositor(std::array<GLuint, 3> CompShader) noexcept;
GLCompositor(GLuint CompShader) noexcept;
int Scale;
int ScreenH, ScreenW;
std::array<GLuint, 3> CompShader;
GLuint CompShader;
GLuint CompScaleLoc;
GLuint Comp3DXPosLoc;

View File

@ -26,6 +26,32 @@
#include <initializer_list>
#include <algorithm>
inline u64 GetRangedBitMask(u32 idx, u32 startBit, u32 bitsCount)
{
u32 startEntry = startBit >> 6;
u64 entriesCount = ((startBit + bitsCount + 0x3F) >> 6) - startEntry;
if (entriesCount > 1)
{
if (idx == startEntry)
return 0xFFFFFFFFFFFFFFFF << (startBit & 0x3F);
if (((startBit + bitsCount) & 0x3F) && idx == startEntry + entriesCount - 1)
return ~(0xFFFFFFFFFFFFFFFF << ((startBit + bitsCount) & 0x3F));
else
return 0xFFFFFFFFFFFFFFFF;
return 0xFFFFFFFFFFFFFFFF;
}
else if (idx == startEntry)
{
return ((1ULL << bitsCount) - 1) << (startBit & 0x3F);
}
else
{
return 0;
}
}
// like std::bitset but less stupid and optimised for
// our use case (keeping track of memory invalidations)
@ -164,6 +190,11 @@ struct NonStupidBitField
return Ref{*this, idx};
}
bool operator[](u32 idx) const
{
return Data[idx >> 6] & (1ULL << (idx & 0x3F));
}
void SetRange(u32 startBit, u32 bitsCount)
{
u32 startEntry = startBit >> 6;
@ -185,6 +216,26 @@ struct NonStupidBitField
}
}
int Min() const
{
for (int i = 0; i < DataLength; i++)
{
if (Data[i])
return i * 64 + __builtin_ctzll(Data[i]);
}
return -1;
}
int Max() const
{
for (int i = DataLength - 1; i >= 0; i--)
{
if (Data[i])
return i * 64 + (63 - __builtin_clzll(Data[i]));
}
return -1;
}
NonStupidBitField& operator|=(const NonStupidBitField<Size>& other)
{
for (u32 i = 0; i < DataLength; i++)
@ -193,6 +244,7 @@ struct NonStupidBitField
}
return *this;
}
NonStupidBitField& operator&=(const NonStupidBitField<Size>& other)
{
for (u32 i = 0; i < DataLength; i++)
@ -201,6 +253,20 @@ struct NonStupidBitField
}
return *this;
}
operator bool() const
{
for (int i = 0; i < DataLength - 1; i++)
{
if (Data[i])
return true;
}
if (Data[DataLength-1] & ((Size&0x3F) ? ~(0xFFFFFFFFFFFFFFFF << (Size&0x3F)) : 0xFFFFFFFFFFFFFFFF))
{
return true;
}
return false;
}
};

View File

@ -24,7 +24,9 @@ using Platform::LogLevel;
namespace OpenGL
{
bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name)
#define checkGLError() if (glGetError() != GL_NO_ERROR) printf("error %d\n", __LINE__)
bool CompilerShader(GLuint& id, const char* source, const char* name, const char* type)
{
int len;
int res;
@ -35,61 +37,31 @@ bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char*
return false;
}
ids[0] = glCreateShader(GL_VERTEX_SHADER);
len = strlen(vs);
glShaderSource(ids[0], 1, &vs, &len);
glCompileShader(ids[0]);
len = strlen(source);
glShaderSource(id, 1, &source, &len);
checkGLError();
glCompileShader(id);
checkGLError();
glGetShaderiv(ids[0], GL_COMPILE_STATUS, &res);
glGetShaderiv(id, GL_COMPILE_STATUS, &res);
checkGLError();
if (res != GL_TRUE)
{
glGetShaderiv(ids[0], GL_INFO_LOG_LENGTH, &res);
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &res);
if (res < 1) res = 1024;
char* log = new char[res+1];
glGetShaderInfoLog(ids[0], res+1, NULL, log);
Log(LogLevel::Error, "OpenGL: failed to compile vertex shader %s: %s\n", name, log);
Log(LogLevel::Debug, "shader source:\n--\n%s\n--\n", vs);
glGetShaderInfoLog(id, res+1, NULL, log);
Log(LogLevel::Error, "OpenGL: failed to compile %s shader %s: %s\n", type, name, log);
Log(LogLevel::Debug, "shader source:\n--\n%s\n--\n", source);
delete[] log;
glDeleteShader(ids[0]);
return false;
}
ids[1] = glCreateShader(GL_FRAGMENT_SHADER);
len = strlen(fs);
glShaderSource(ids[1], 1, &fs, &len);
glCompileShader(ids[1]);
glGetShaderiv(ids[1], GL_COMPILE_STATUS, &res);
if (res != GL_TRUE)
{
glGetShaderiv(ids[1], GL_INFO_LOG_LENGTH, &res);
if (res < 1) res = 1024;
char* log = new char[res+1];
glGetShaderInfoLog(ids[1], res+1, NULL, log);
Log(LogLevel::Error, "OpenGL: failed to compile fragment shader %s: %s\n", name, log);
//printf("shader source:\n--\n%s\n--\n", fs);
delete[] log;
FILE* logf = fopen("shaderfail.log", "w");
fwrite(fs, len+1, 1, logf);
fclose(logf);
glDeleteShader(ids[0]);
glDeleteShader(ids[1]);
return false;
}
ids[2] = glCreateProgram();
glAttachShader(ids[2], ids[0]);
glAttachShader(ids[2], ids[1]);
return true;
}
bool LinkShaderProgram(GLuint* ids)
bool LinkProgram(GLuint& result, GLuint* ids, int numIds)
{
int res;
@ -99,46 +71,100 @@ bool LinkShaderProgram(GLuint* ids)
return false;
}
glLinkProgram(ids[2]);
for (int i = 0; i < numIds; i++)
{
glAttachShader(result, ids[i]);
checkGLError();
}
glDetachShader(ids[2], ids[0]);
glDetachShader(ids[2], ids[1]);
glLinkProgram(result);
glDeleteShader(ids[0]);
glDeleteShader(ids[1]);
for (int i = 0; i < numIds; i++)
glDetachShader(result, ids[i]);
glGetProgramiv(ids[2], GL_LINK_STATUS, &res);
glGetProgramiv(result, GL_LINK_STATUS, &res);
if (res != GL_TRUE)
{
glGetProgramiv(ids[2], GL_INFO_LOG_LENGTH, &res);
glGetProgramiv(result, GL_INFO_LOG_LENGTH, &res);
if (res < 1) res = 1024;
char* log = new char[res+1];
glGetProgramInfoLog(ids[2], res+1, NULL, log);
glGetProgramInfoLog(result, res+1, NULL, log);
Log(LogLevel::Error, "OpenGL: failed to link shader program: %s\n", log);
delete[] log;
glDeleteProgram(ids[2]);
return false;
}
return true;
}
void DeleteShaderProgram(GLuint* ids)
bool CompileComputeProgram(GLuint& result, const char* source, const char* name)
{
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
bool linkingSucess = false;
if (glDeleteProgram)
{ // If OpenGL isn't loaded, then there's no shader program to delete
glDeleteProgram(ids[2]);
goto error;
}
result = glCreateProgram();
printf("compiling %s", name);
if (!CompilerShader(shader, source, name, "compute"))
goto error;
linkingSucess = LinkProgram(result, &shader, 1);
error:
glDeleteShader(shader);
if (!linkingSucess)
glDeleteProgram(result);
return linkingSucess;
}
void UseShaderProgram(GLuint* ids)
bool CompileVertexFragmentProgram(GLuint& result,
const char* vs, const char* fs,
const char* name,
const std::initializer_list<AttributeTarget>& vertexInAttrs,
const std::initializer_list<AttributeTarget>& fragmentOutAttrs)
{
if (glUseProgram)
{ // If OpenGL isn't loaded, then there's no shader program to use
glUseProgram(ids[2]);
GLuint shaders[2] =
{
glCreateShader(GL_VERTEX_SHADER),
glCreateShader(GL_FRAGMENT_SHADER)
};
result = glCreateProgram();
bool linkingSucess = false;
if (!CompilerShader(shaders[0], vs, name, "vertex"))
goto error;
if (!CompilerShader(shaders[1], fs, name, "fragment"))
goto error;
for (const AttributeTarget& target : vertexInAttrs)
{
glBindAttribLocation(result, target.Location, target.Name);
}
for (const AttributeTarget& target : fragmentOutAttrs)
{
glBindFragDataLocation(result, target.Location, target.Name);
}
linkingSucess = LinkProgram(result, shaders, 2);
error:
glDeleteShader(shaders[1]);
glDeleteShader(shaders[0]);
if (!linkingSucess)
glDeleteProgram(result);
return linkingSucess;
}
}

View File

@ -29,10 +29,19 @@
namespace OpenGL
{
bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name);
bool LinkShaderProgram(GLuint* ids);
void DeleteShaderProgram(GLuint* ids);
void UseShaderProgram(GLuint* ids);
struct AttributeTarget
{
const char* Name;
u32 Location;
};
bool CompileVertexFragmentProgram(GLuint& result,
const char* vs, const char* fs,
const char* name,
const std::initializer_list<AttributeTarget>& vertexInAttrs,
const std::initializer_list<AttributeTarget>& fragmentOutAttrs);
bool CompileComputeProgram(GLuint& result, const char* source, const char* name);
}

View File

@ -24,6 +24,7 @@ set(SOURCES_QT_SDL
ROMInfoDialog.cpp
RAMInfoDialog.cpp
TitleManagerDialog.cpp
RTCSettingsDialog.cpp
Input.cpp
LAN_PCap.cpp
LAN_Socket.cpp

View File

@ -57,7 +57,7 @@ struct Item
std::deque<Item> ItemQueue;
GLuint Shader[3];
GLuint Shader;
GLint uScreenSize, uOSDPos, uOSDSize;
GLfloat uScaleFactor;
GLuint OSDVertexArray;
@ -70,20 +70,19 @@ bool Init(bool openGL)
{
if (openGL)
{
OpenGL::BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, Shader, "OSDShader");
OpenGL::CompileVertexFragmentProgram(Shader,
kScreenVS_OSD, kScreenFS_OSD,
"OSDShader",
{{"vPosition", 0}},
{{"oColor", 0}});
GLuint pid = Shader[2];
glBindAttribLocation(pid, 0, "vPosition");
glBindFragDataLocation(pid, 0, "oColor");
glUseProgram(Shader);
glUniform1i(glGetUniformLocation(Shader, "OSDTex"), 0);
OpenGL::LinkShaderProgram(Shader);
glUseProgram(pid);
glUniform1i(glGetUniformLocation(pid, "OSDTex"), 0);
uScreenSize = glGetUniformLocation(pid, "uScreenSize");
uOSDPos = glGetUniformLocation(pid, "uOSDPos");
uOSDSize = glGetUniformLocation(pid, "uOSDSize");
uScaleFactor = glGetUniformLocation(pid, "uScaleFactor");
uScreenSize = glGetUniformLocation(Shader, "uScreenSize");
uOSDPos = glGetUniformLocation(Shader, "uOSDPos");
uOSDSize = glGetUniformLocation(Shader, "uOSDSize");
uScaleFactor = glGetUniformLocation(Shader, "uScaleFactor");
float vertices[6*2] =
{
@ -425,7 +424,7 @@ void DrawGL(float w, float h)
u32 y = kOSDMargin;
glUseProgram(Shader[2]);
glUseProgram(Shader);
glUniform2f(uScreenSize, w, h);
glUniform1f(uScaleFactor, mainWindow->devicePixelRatioF());

View File

@ -228,19 +228,17 @@ void EmuThread::initOpenGL()
oglContext = windowctx;
oglContext->MakeCurrent();
OpenGL::BuildShaderProgram(kScreenVS, kScreenFS, screenShaderProgram, "ScreenShader");
GLuint pid = screenShaderProgram[2];
glBindAttribLocation(pid, 0, "vPosition");
glBindAttribLocation(pid, 1, "vTexcoord");
glBindFragDataLocation(pid, 0, "oColor");
OpenGL::CompileVertexFragmentProgram(screenShaderProgram,
kScreenVS, kScreenFS,
"ScreenShader",
{{"vPosition", 0}, {"vTexcoord", 1}},
{{"oColor", 0}});
OpenGL::LinkShaderProgram(screenShaderProgram);
glUseProgram(screenShaderProgram);
glUniform1i(glGetUniformLocation(screenShaderProgram, "ScreenTex"), 0);
glUseProgram(pid);
glUniform1i(glGetUniformLocation(pid, "ScreenTex"), 0);
screenShaderScreenSizeULoc = glGetUniformLocation(pid, "uScreenSize");
screenShaderTransformULoc = glGetUniformLocation(pid, "uTransform");
screenShaderScreenSizeULoc = glGetUniformLocation(screenShaderProgram, "uScreenSize");
screenShaderTransformULoc = glGetUniformLocation(screenShaderProgram, "uTransform");
// to prevent bleeding between both parts of the screen
// with bilinear filtering enabled
@ -300,7 +298,7 @@ void EmuThread::deinitOpenGL()
glDeleteVertexArrays(1, &screenVertexArray);
glDeleteBuffers(1, &screenVertexBuffer);
OpenGL::DeleteShaderProgram(screenShaderProgram);
glDeleteProgram(screenShaderProgram);
OSD::DeInit();
@ -749,7 +747,7 @@ void EmuThread::drawScreenGL()
glViewport(0, 0, w, h);
glUseProgram(screenShaderProgram[2]);
glUseProgram(screenShaderProgram);
glUniform2f(screenShaderScreenSizeULoc, w / factor, h / factor);
int frontbuf = FrontBuffer;

View File

@ -121,7 +121,7 @@ private:
GL::Context* oglContext = nullptr;
GLuint screenVertexBuffer, screenVertexArray;
GLuint screenTexture;
GLuint screenShaderProgram[3];
GLuint screenShaderProgram;
GLuint screenShaderTransformULoc, screenShaderScreenSizeULoc;
QMutex screenSettingsLock;