mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 21:37:42 -07:00
nothing works yet
This commit is contained in:
parent
f8fdc77e43
commit
b11b5bf522
@ -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)
|
||||
|
||||
|
@ -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
1451
src/GPU3D_Compute.cpp
Normal file
File diff suppressed because it is too large
Load Diff
263
src/GPU3D_Compute.h
Normal file
263
src/GPU3D_Compute.h
Normal 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
1502
src/GPU3D_Compute_shaders.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ set(SOURCES_QT_SDL
|
||||
ROMInfoDialog.cpp
|
||||
RAMInfoDialog.cpp
|
||||
TitleManagerDialog.cpp
|
||||
RTCSettingsDialog.cpp
|
||||
Input.cpp
|
||||
LAN_PCap.cpp
|
||||
LAN_Socket.cpp
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -121,7 +121,7 @@ private:
|
||||
GL::Context* oglContext = nullptr;
|
||||
GLuint screenVertexBuffer, screenVertexArray;
|
||||
GLuint screenTexture;
|
||||
GLuint screenShaderProgram[3];
|
||||
GLuint screenShaderProgram;
|
||||
GLuint screenShaderTransformULoc, screenShaderScreenSizeULoc;
|
||||
|
||||
QMutex screenSettingsLock;
|
||||
|
Loading…
Reference in New Issue
Block a user