mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-16 03:38:30 +12:00
168 lines
6.6 KiB
C++
168 lines
6.6 KiB
C++
#include "Common/GLInclude/GLInclude.h"
|
|
#include "Cafe/HW/Latte/Core/Latte.h"
|
|
#include "Cafe/HW/Latte/Core/LatteDraw.h"
|
|
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
|
|
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h"
|
|
#include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h"
|
|
#include "util/helpers/StringBuf.h"
|
|
|
|
bool gxShader_checkIfSuccessfullyLinked(GLuint glProgram)
|
|
{
|
|
int status = -1;
|
|
glGetProgramiv(glProgram, GL_LINK_STATUS, &status);
|
|
if( status == GL_TRUE )
|
|
return true;
|
|
// in debug mode, get and print shader error log
|
|
char infoLog[48*1024];
|
|
uint32 infoLogLength, tempLength;
|
|
glGetProgramiv(glProgram, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength);
|
|
tempLength = sizeof(infoLog)-1;
|
|
glGetProgramInfoLog(glProgram, std::min(tempLength, infoLogLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
|
|
infoLog[tempLength] = '\0';
|
|
cemuLog_log(LogType::Force, "Link error in raw shader");
|
|
cemuLog_log(LogType::Force, infoLog);
|
|
return false;
|
|
}
|
|
|
|
void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader)
|
|
{
|
|
if (g_renderer->GetType() == RendererAPI::Vulkan)
|
|
return;
|
|
|
|
auto shaderGL = (RendererShaderGL*)shader->shader;
|
|
// setup uniform info
|
|
if (shader->shaderType == LatteConst::ShaderType::Vertex)
|
|
{
|
|
shader->uniform.loc_remapped = glGetUniformLocation(shaderGL->GetProgram(), "uf_remappedVS");
|
|
shader->uniform.loc_uniformRegister = glGetUniformLocation(shaderGL->GetProgram(), "uf_uniformRegisterVS");
|
|
}
|
|
else if (shader->shaderType == LatteConst::ShaderType::Geometry)
|
|
{
|
|
shader->uniform.loc_remapped = glGetUniformLocation(shaderGL->GetProgram(), "uf_remappedGS");
|
|
shader->uniform.loc_uniformRegister = glGetUniformLocation(shaderGL->GetProgram(), "uf_uniformRegisterGS");
|
|
}
|
|
else if (shader->shaderType == LatteConst::ShaderType::Pixel)
|
|
{
|
|
shader->uniform.loc_remapped = glGetUniformLocation(shaderGL->GetProgram(), "uf_remappedPS");
|
|
shader->uniform.loc_uniformRegister = glGetUniformLocation(shaderGL->GetProgram(), "uf_uniformRegisterPS");
|
|
}
|
|
catchOpenGLError();
|
|
shader->uniform.loc_windowSpaceToClipSpaceTransform = glGetUniformLocation(shaderGL->GetProgram(), "uf_windowSpaceToClipSpaceTransform");
|
|
shader->uniform.loc_alphaTestRef = glGetUniformLocation(shaderGL->GetProgram(), "uf_alphaTestRef");
|
|
shader->uniform.loc_pointSize = glGetUniformLocation(shaderGL->GetProgram(), "uf_pointSize");
|
|
shader->uniform.loc_fragCoordScale = glGetUniformLocation(shaderGL->GetProgram(), "uf_fragCoordScale");
|
|
cemu_assert_debug(shader->uniform.list_ufTexRescale.empty());
|
|
for (sint32 t = 0; t < LATTE_NUM_MAX_TEX_UNITS; t++)
|
|
{
|
|
char ufName[64];
|
|
sprintf(ufName, "uf_tex%dScale", t);
|
|
GLint uniformLocation = glGetUniformLocation(shaderGL->GetProgram(), ufName);
|
|
if (uniformLocation >= 0)
|
|
{
|
|
LatteUniformTextureScaleEntry_t entry = { 0 };
|
|
entry.texUnit = t;
|
|
entry.uniformLocation = uniformLocation;
|
|
shader->uniform.list_ufTexRescale.push_back(entry);
|
|
}
|
|
}
|
|
}
|
|
GLuint gpu7ShaderGLDepr_compileShader(const std::string& source, uint32_t type)
|
|
{
|
|
cemu_assert(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER);
|
|
const GLuint shader_object = glCreateShader(type);
|
|
|
|
const char *c_str = source.c_str();
|
|
const GLint size = (GLint)source.size();
|
|
glShaderSource(shader_object, 1, &c_str, &size);
|
|
glCompileShader(shader_object);
|
|
|
|
GLint log_length;
|
|
glGetShaderiv(shader_object, GL_INFO_LOG_LENGTH, &log_length);
|
|
if (log_length > 0)
|
|
{
|
|
char log[2048]{};
|
|
GLsizei log_size;
|
|
glGetShaderInfoLog(shader_object, std::min(log_length, (GLint)sizeof(log) - 1), &log_size, log);
|
|
cemuLog_log(LogType::Force, "Error/Warning in vertex shader:");
|
|
cemuLog_log(LogType::Force, log);
|
|
}
|
|
|
|
return shader_object;
|
|
}
|
|
GLuint gpu7ShaderGLDepr_compileVertexShader(const std::string& source)
|
|
{
|
|
return gpu7ShaderGLDepr_compileShader(source, GL_VERTEX_SHADER);
|
|
}
|
|
|
|
GLuint gpu7ShaderGLDepr_compileFragmentShader(const std::string& source)
|
|
{
|
|
return gpu7ShaderGLDepr_compileShader(source, GL_FRAGMENT_SHADER);
|
|
}
|
|
|
|
GLuint gpu7ShaderGLDepr_compileVertexShader(const char* shaderSource, sint32 shaderSourceLength)
|
|
{
|
|
uint32 shaderObject = glCreateShader(GL_VERTEX_SHADER);
|
|
GLchar* srcPtr = (GLchar*)shaderSource;
|
|
GLint srcLen = shaderSourceLength;
|
|
glShaderSource(shaderObject, 1, &srcPtr, &srcLen);
|
|
glCompileShader(shaderObject);
|
|
uint32 shaderLogLengthInfo, shaderLogLen;
|
|
glGetShaderiv(shaderObject, GL_INFO_LOG_LENGTH, (GLint *)&shaderLogLengthInfo);
|
|
if (shaderLogLengthInfo > 0)
|
|
{
|
|
char messageLog[2048]{};
|
|
glGetShaderInfoLog(shaderObject, std::min<uint32>(shaderLogLengthInfo, sizeof(messageLog) - 1), (GLsizei*)&shaderLogLen, (GLcharARB*)messageLog);
|
|
cemuLog_log(LogType::Force, "Error/Warning in vertex shader:");
|
|
cemuLog_log(LogType::Force, messageLog);
|
|
}
|
|
return shaderObject;
|
|
}
|
|
|
|
GLuint gpu7ShaderGLDepr_compileFragmentShader(const char* shaderSource, sint32 shaderSourceLength)
|
|
{
|
|
uint32 shaderObject = glCreateShader(GL_FRAGMENT_SHADER);
|
|
GLchar* srcPtr = (GLchar*)shaderSource;
|
|
GLint srcLen = shaderSourceLength;
|
|
glShaderSource(shaderObject, 1, &srcPtr, &srcLen);
|
|
glCompileShader(shaderObject);
|
|
uint32 shaderLogLengthInfo, shaderLogLen;
|
|
char messageLog[2048];
|
|
glGetShaderiv(shaderObject, GL_INFO_LOG_LENGTH, (GLint *)&shaderLogLengthInfo);
|
|
if (shaderLogLengthInfo > 0)
|
|
{
|
|
memset(messageLog, 0, sizeof(messageLog));
|
|
glGetShaderInfoLog(shaderObject, std::min<uint32>(shaderLogLengthInfo, sizeof(messageLog) - 1), (GLsizei*)&shaderLogLen, (GLcharARB*)messageLog);
|
|
cemuLog_log(LogType::Force, "Error/Warning in fragment shader:");
|
|
cemuLog_log(LogType::Force, messageLog);
|
|
}
|
|
return shaderObject;
|
|
}
|
|
|
|
GLuint gxShaderDepr_compileRaw(StringBuf* strSourceVS, StringBuf* strSourceFS)
|
|
{
|
|
GLuint glShaderProgram = glCreateProgram();
|
|
GLuint vertexShader = gpu7ShaderGLDepr_compileVertexShader(strSourceVS->c_str(), strSourceVS->getLen());
|
|
glAttachShader(glShaderProgram, vertexShader);
|
|
GLuint fragmentShader = gpu7ShaderGLDepr_compileFragmentShader(strSourceFS->c_str(), strSourceFS->getLen());
|
|
glAttachShader(glShaderProgram, fragmentShader);
|
|
glLinkProgram(glShaderProgram);
|
|
if( gxShader_checkIfSuccessfullyLinked(glShaderProgram) == false )
|
|
{
|
|
return 0;
|
|
}
|
|
return glShaderProgram;
|
|
}
|
|
|
|
GLuint gxShaderDepr_compileRaw(const std::string& vertex_source, const std::string& fragment_source)
|
|
{
|
|
const GLuint programm = glCreateProgram();
|
|
|
|
auto vertex_shader = std::async(std::launch::deferred, gpu7ShaderGLDepr_compileShader, vertex_source, GL_VERTEX_SHADER);
|
|
auto fragment_shader = std::async(std::launch::deferred, gpu7ShaderGLDepr_compileShader, fragment_source, GL_FRAGMENT_SHADER);
|
|
|
|
glAttachShader(programm, vertex_shader.get());
|
|
glAttachShader(programm, fragment_shader.get());
|
|
|
|
glLinkProgram(programm);
|
|
return gxShader_checkIfSuccessfullyLinked(programm) ? programm : 0;
|
|
}
|