mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-22 22:37:04 +00:00
Add all the files
This commit is contained in:
parent
e3db07a16a
commit
d60742f52b
1445 changed files with 430238 additions and 0 deletions
295
src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp
Normal file
295
src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||
#include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h"
|
||||
|
||||
#include "Cemu/FileCache/FileCache.h"
|
||||
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "config/LaunchSettings.h"
|
||||
|
||||
extern std::atomic_int g_compiled_shaders_total;
|
||||
extern std::atomic_int g_compiled_shaders_async;
|
||||
|
||||
bool s_isLoadingShaders{false};
|
||||
|
||||
bool RendererShaderGL::loadBinary()
|
||||
{
|
||||
if (!g_programBinaryCache)
|
||||
return false;
|
||||
if (m_isGameShader == false || m_isGfxPackShader)
|
||||
return false; // only non-custom
|
||||
if (!glProgramBinary)
|
||||
return false; // OpenGL program binaries not supported
|
||||
|
||||
cemu_assert_debug(m_baseHash != 0);
|
||||
uint64 h1, h2;
|
||||
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
|
||||
sint32 fileSize = 0;
|
||||
std::vector<uint8> cacheFileData;
|
||||
if (!g_programBinaryCache->GetFile({ h1, h2 }, cacheFileData))
|
||||
return false;
|
||||
if (fileSize < sizeof(uint32))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 shaderBinFormat = *(uint32*)(cacheFileData.data() + 0);
|
||||
|
||||
m_program = glCreateProgram();
|
||||
glProgramBinary(m_program, shaderBinFormat, cacheFileData.data()+4, cacheFileData.size()-4);
|
||||
|
||||
int status = -1;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &status);
|
||||
if (status != GL_TRUE)
|
||||
{
|
||||
glDeleteProgram(m_program);
|
||||
m_program = 0;
|
||||
return false;
|
||||
}
|
||||
m_isCompiled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RendererShaderGL::storeBinary()
|
||||
{
|
||||
if (!g_programBinaryCache)
|
||||
return;
|
||||
if (!glGetProgramBinary)
|
||||
return;
|
||||
if (m_program == 0)
|
||||
return;
|
||||
if (!m_isGameShader || m_isGfxPackShader)
|
||||
return;
|
||||
|
||||
GLint binaryLength = 0;
|
||||
glGetProgramiv(m_program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
|
||||
if (binaryLength > 0)
|
||||
{
|
||||
uint64 h1, h2;
|
||||
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
|
||||
// build stored shader data (4 byte format + binary data)
|
||||
std::vector<uint8> storedBinary(binaryLength+sizeof(uint32), 0);
|
||||
GLenum binaryFormat = 0;
|
||||
glGetProgramBinary(m_program, binaryLength, NULL, &binaryFormat, storedBinary.data()+sizeof(uint32));
|
||||
*(uint32*)(storedBinary.data() + 0) = binaryFormat;
|
||||
// store
|
||||
g_programBinaryCache->AddFileAsync({ h1, h2 }, storedBinary.data(), storedBinary.size());
|
||||
}
|
||||
}
|
||||
|
||||
RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslSource)
|
||||
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_glslSource(glslSource)
|
||||
{
|
||||
GLenum glShaderType;
|
||||
switch (type)
|
||||
{
|
||||
case ShaderType::kVertex:
|
||||
glShaderType = GL_VERTEX_SHADER;
|
||||
break;
|
||||
case ShaderType::kFragment:
|
||||
glShaderType = GL_FRAGMENT_SHADER;
|
||||
break;
|
||||
case ShaderType::kGeometry:
|
||||
glShaderType = GL_GEOMETRY_SHADER;
|
||||
break;
|
||||
default:
|
||||
cemu_assert_debug(false);
|
||||
}
|
||||
|
||||
if (s_isLoadingShaders)
|
||||
{
|
||||
if (loadBinary())
|
||||
{
|
||||
m_glslSource.clear();
|
||||
m_glslSource.shrink_to_fit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_shader_object = glCreateShader(glShaderType);
|
||||
|
||||
const char *c_str = m_glslSource.c_str();
|
||||
const GLint size = (GLint)m_glslSource.size();
|
||||
glShaderSource(m_shader_object, 1, &c_str, &size);
|
||||
glCompileShader(m_shader_object);
|
||||
|
||||
GLint log_length;
|
||||
glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length > 0)
|
||||
{
|
||||
char log[2048]{};
|
||||
GLsizei log_size;
|
||||
glGetShaderInfoLog(m_shader_object, std::min<uint32>(log_length, sizeof(log) - 1), &log_size, log);
|
||||
forceLog_printf("Error/Warning in shader:");
|
||||
forceLog_printf("%s", log);
|
||||
}
|
||||
|
||||
// set debug name
|
||||
if (LaunchSettings::NSightModeEnabled())
|
||||
{
|
||||
auto objNameStr = fmt::format("shader_{:016x}_{:016x}", m_baseHash, m_auxHash);
|
||||
glObjectLabel(GL_SHADER, m_shader_object, objNameStr.size(), objNameStr.c_str());
|
||||
}
|
||||
|
||||
m_program = glCreateProgram();
|
||||
glProgramParameteri(m_program, GL_PROGRAM_SEPARABLE, GL_TRUE);
|
||||
glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
glAttachShader(m_program, m_shader_object);
|
||||
m_shader_attached = true;
|
||||
glLinkProgram(m_program);
|
||||
|
||||
storeBinary();
|
||||
|
||||
// count shader compilation
|
||||
if (!s_isLoadingShaders)
|
||||
++g_compiled_shaders_total;
|
||||
|
||||
// we can throw away the GLSL code to conserve RAM
|
||||
m_glslSource.clear();
|
||||
m_glslSource.shrink_to_fit();
|
||||
}
|
||||
|
||||
RendererShaderGL::~RendererShaderGL()
|
||||
{
|
||||
if (m_shader_object != 0 && m_shader_attached)
|
||||
glDetachShader(m_program, m_shader_object);
|
||||
|
||||
if (m_shader_object != 0)
|
||||
glDeleteShader(m_shader_object);
|
||||
|
||||
if (m_program != 0)
|
||||
glDeleteProgram(m_program);
|
||||
}
|
||||
|
||||
void RendererShaderGL::PreponeCompilation(bool isRenderThread)
|
||||
{
|
||||
// the logic for initiating compilation is currently in the constructor
|
||||
// here we only guarantee that it is finished before we return
|
||||
if (m_isCompiled)
|
||||
return;
|
||||
WaitForCompiled();
|
||||
}
|
||||
|
||||
bool RendererShaderGL::IsCompiled()
|
||||
{
|
||||
cemu_assert_debug(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RendererShaderGL::WaitForCompiled()
|
||||
{
|
||||
char infoLog[8 * 1024];
|
||||
if (m_isCompiled)
|
||||
return true;
|
||||
// check if compilation was successful
|
||||
GLint compileStatus = GL_FALSE;
|
||||
glGetShaderiv(m_shader_object, GL_COMPILE_STATUS, &compileStatus);
|
||||
if (compileStatus == 0)
|
||||
{
|
||||
uint32 infoLogLength, tempLength;
|
||||
glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength);
|
||||
if (infoLogLength != 0)
|
||||
{
|
||||
tempLength = sizeof(infoLog) - 1;
|
||||
glGetShaderInfoLog(m_shader_object, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
|
||||
infoLog[tempLength] = '\0';
|
||||
forceLog_printf("Compile error in shader. Log:", infoLog);
|
||||
cafeLog_logLine(LOG_TYPE_FORCE, infoLog);
|
||||
}
|
||||
if (m_shader_object != 0)
|
||||
glDeleteShader(m_shader_object);
|
||||
m_isCompiled = true;
|
||||
return false;
|
||||
}
|
||||
// get shader binary
|
||||
GLint linkStatus = GL_FALSE;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus == 0)
|
||||
{
|
||||
uint32 infoLogLength, tempLength;
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength);
|
||||
if (infoLogLength != 0)
|
||||
{
|
||||
tempLength = sizeof(infoLog) - 1;
|
||||
glGetProgramInfoLog(m_program, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
|
||||
infoLog[tempLength] = '\0';
|
||||
forceLog_printf("Link error in shader. Log:", infoLog);
|
||||
cafeLog_logLine(LOG_TYPE_FORCE, infoLog);
|
||||
}
|
||||
m_isCompiled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*glDetachShader(m_program, m_shader_object);
|
||||
m_shader_attached = false;*/
|
||||
m_isCompiled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
sint32 RendererShaderGL::GetUniformLocation(const char* name)
|
||||
{
|
||||
return glGetUniformLocation(m_program, name);
|
||||
}
|
||||
|
||||
void RendererShaderGL::SetUniform1iv(sint32 location, void* data, sint32 count)
|
||||
{
|
||||
glProgramUniform1iv(m_program, location, count, (const GLint*)data);
|
||||
}
|
||||
|
||||
void RendererShaderGL::SetUniform2fv(sint32 location, void* data, sint32 count)
|
||||
{
|
||||
glProgramUniform2fv(m_program, location, count, (const GLfloat*)data);
|
||||
}
|
||||
|
||||
void RendererShaderGL::SetUniform4iv(sint32 location, void* data, sint32 count)
|
||||
{
|
||||
glProgramUniform4iv(m_program, location, count, (const GLint*)data);
|
||||
}
|
||||
|
||||
void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId)
|
||||
{
|
||||
if (g_programBinaryCache)
|
||||
{
|
||||
delete g_programBinaryCache;
|
||||
g_programBinaryCache = nullptr;
|
||||
}
|
||||
|
||||
// determine if cache is enabled
|
||||
bool usePrecompiled = false;
|
||||
switch (ActiveSettings::GetPrecompiledShadersOption())
|
||||
{
|
||||
case PrecompiledShaderOption::Auto:
|
||||
if (g_renderer->GetVendor() == GfxVendor::Nvidia)
|
||||
usePrecompiled = false;
|
||||
else
|
||||
usePrecompiled = true;
|
||||
break;
|
||||
case PrecompiledShaderOption::Enable:
|
||||
usePrecompiled = true;
|
||||
break;
|
||||
case PrecompiledShaderOption::Disable:
|
||||
usePrecompiled = false;
|
||||
break;
|
||||
default:
|
||||
__assume(false);
|
||||
}
|
||||
|
||||
forceLog_printf("Using precompiled shaders: %s", usePrecompiled ? "true" : "false");
|
||||
|
||||
if (usePrecompiled)
|
||||
{
|
||||
const uint32 cacheMagic = GeneratePrecompiledCacheId();
|
||||
const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId);
|
||||
const std::wstring cachePath = ActiveSettings::GetPath("shaderCache/precompiled/{}", cacheFilename).generic_wstring();
|
||||
g_programBinaryCache = FileCache::Open(cachePath, true, cacheMagic);
|
||||
if (g_programBinaryCache == nullptr)
|
||||
cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename);
|
||||
}
|
||||
s_isLoadingShaders = true;
|
||||
}
|
||||
|
||||
void RendererShaderGL::ShaderCacheLoading_end()
|
||||
{
|
||||
s_isLoadingShaders = false;
|
||||
}
|
||||
|
||||
FileCache* RendererShaderGL::g_programBinaryCache{};
|
||||
Loading…
Add table
Add a link
Reference in a new issue