mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-04-26 04:45:18 -06:00
Merge eb48b871d8 into b2c34fb1df
This commit is contained in:
commit
00442e7e99
@ -73,8 +73,8 @@ add_definitions(-DEMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH})
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# enable link time optimization for release builds
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)
|
||||
#set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)#
|
||||
#set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)#
|
||||
|
||||
if (MSVC)
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT CemuBin)
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "util/helpers/StringParser.h"
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "Cafe/GameProfile/GameProfile.h"
|
||||
#include "HW/Latte/Renderer/OpenGL/RendererShaderGL.h"
|
||||
#include "util/containers/flat_hash_map.hpp"
|
||||
#if ENABLE_METAL
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||
@ -360,23 +361,15 @@ void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compil
|
||||
}
|
||||
|
||||
// create shader
|
||||
shader->shader = g_renderer->shader_create(shaderType, shader->baseHash, shader->auxHash, shaderSrc, true, shader->isCustomShader);
|
||||
shader->shader = g_renderer->shader_create(shaderType, shader->baseHash, shader->auxHash, std::move(shaderSrc), true, shader->isCustomShader);
|
||||
if (shader->shader == nullptr)
|
||||
shader->hasError = true;
|
||||
// after renderer shader creation we can throw away any intermediate info
|
||||
LatteShader_CleanupAfterCompile(shader);
|
||||
}
|
||||
|
||||
void LatteShader_FinishCompilation(LatteDecompilerShader* shader)
|
||||
{
|
||||
if (shader->hasError)
|
||||
if (g_renderer->GetType() == RendererAPI::OpenGL)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "LatteShader_finishCompilation(): Skipped because of error in shader {:x}", shader->baseHash);
|
||||
return;
|
||||
RendererShaderGL* shaderGL = static_cast<RendererShaderGL*>(shader->shader);
|
||||
shaderGL->SetDecompilerShader(shader);
|
||||
}
|
||||
shader->shader->WaitForCompiled();
|
||||
|
||||
LatteShader_prepareSeparableUniforms(shader);
|
||||
// after renderer shader creation we can throw away any intermediate info
|
||||
LatteShader_CleanupAfterCompile(shader);
|
||||
}
|
||||
|
||||
@ -845,13 +838,6 @@ LatteDecompilerShader* LatteShader_CompileSeparableVertexShader(uint64 baseHash,
|
||||
LatteShader_CreateRendererShader(vertexShader, false);
|
||||
performanceMonitor.numCompiledVS++;
|
||||
|
||||
if (g_renderer->GetType() == RendererAPI::OpenGL)
|
||||
{
|
||||
if (vertexShader->shader)
|
||||
vertexShader->shader->PreponeCompilation(true);
|
||||
LatteShader_FinishCompilation(vertexShader);
|
||||
}
|
||||
|
||||
LatteSHRC_RegisterShader(vertexShader, vertexShader->baseHash, vertexShader->auxHash);
|
||||
return vertexShader;
|
||||
}
|
||||
@ -874,13 +860,6 @@ LatteDecompilerShader* LatteShader_CompileSeparableGeometryShader(uint64 baseHas
|
||||
LatteShader_CreateRendererShader(geometryShader, false);
|
||||
performanceMonitor.numCompiledGS++;
|
||||
|
||||
if (g_renderer->GetType() == RendererAPI::OpenGL)
|
||||
{
|
||||
if (geometryShader->shader)
|
||||
geometryShader->shader->PreponeCompilation(true);
|
||||
LatteShader_FinishCompilation(geometryShader);
|
||||
}
|
||||
|
||||
LatteSHRC_RegisterShader(geometryShader, geometryShader->baseHash, geometryShader->auxHash);
|
||||
return geometryShader;
|
||||
}
|
||||
@ -903,13 +882,6 @@ LatteDecompilerShader* LatteShader_CompileSeparablePixelShader(uint64 baseHash,
|
||||
LatteShaderCache_writeSeparablePixelShader(_shaderBaseHash_ps, psAuxHash, pixelShaderPtr, pixelShaderSize, LatteGPUState.contextRegister, usesGeometryShader);
|
||||
}
|
||||
|
||||
if (g_renderer->GetType() == RendererAPI::OpenGL)
|
||||
{
|
||||
if (pixelShader->shader)
|
||||
pixelShader->shader->PreponeCompilation(true);
|
||||
LatteShader_FinishCompilation(pixelShader);
|
||||
}
|
||||
|
||||
LatteSHRC_RegisterShader(pixelShader, _shaderBaseHash_ps, psAuxHash);
|
||||
return pixelShader;
|
||||
}
|
||||
|
||||
@ -100,7 +100,6 @@ void LatteShader_GetDecompilerOptions(struct LatteDecompilerOptions& options, La
|
||||
LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompilerOutput_t& decompilerOutput, uint64 baseHash, bool calculateAuxHash, uint64 optionalAuxHash, uint32* contextRegister);
|
||||
|
||||
void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compileAsync);
|
||||
void LatteShader_FinishCompilation(LatteDecompilerShader* shader);
|
||||
|
||||
void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader);
|
||||
|
||||
|
||||
@ -106,13 +106,24 @@ void LatteShaderCache_removeFromCompileQueue(sint32 index)
|
||||
*/
|
||||
void LatteShaderCache_updateCompileQueue(sint32 maxRemainingEntries)
|
||||
{
|
||||
// remove any shaders that are already done
|
||||
for (size_t i = 0; i < shaderCompileQueue.count; i++)
|
||||
{
|
||||
auto shaderEntry = shaderCompileQueue.entry[i].shader;
|
||||
if (!shaderEntry)
|
||||
continue;
|
||||
if (shaderEntry->shader->IsCompiled())
|
||||
{
|
||||
LatteShaderCache_removeFromCompileQueue(i);
|
||||
}
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
if (shaderCompileQueue.count <= maxRemainingEntries)
|
||||
break;
|
||||
auto shader = shaderCompileQueue.entry[0].shader;
|
||||
if (shader)
|
||||
LatteShader_FinishCompilation(shader);
|
||||
shader->shader->PreponeCompilation();
|
||||
LatteShaderCache_removeFromCompileQueue(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ bool gxShader_checkIfSuccessfullyLinked(GLuint glProgram)
|
||||
|
||||
void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader)
|
||||
{
|
||||
if (g_renderer->GetType() != RendererAPI::OpenGL)
|
||||
if(shader->hasError)
|
||||
return;
|
||||
|
||||
auto shaderGL = (RendererShaderGL*)shader->shader;
|
||||
|
||||
@ -176,8 +176,8 @@ static RendererShaderMtl* rectsEmulationGS_generate(MetalRenderer* metalRenderer
|
||||
|
||||
gsSrc.append("}\r\n");
|
||||
|
||||
auto mtlShader = new RendererShaderMtl(metalRenderer, RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc);
|
||||
mtlShader->PreponeCompilation(true);
|
||||
auto mtlShader = new RendererShaderMtl(metalRenderer, RendererShader::ShaderType::kGeometry, 0, 0, false, false, std::move(gsSrc));
|
||||
mtlShader->PreponeCompilation();
|
||||
|
||||
return mtlShader;
|
||||
}
|
||||
@ -321,11 +321,11 @@ bool MetalPipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool
|
||||
{
|
||||
// if some shader stages are not compiled yet, compile them now
|
||||
if (m_vertexShaderMtl && !m_vertexShaderMtl->IsCompiled())
|
||||
m_vertexShaderMtl->PreponeCompilation(isRenderThread);
|
||||
m_vertexShaderMtl->PreponeCompilation();
|
||||
if (m_geometryShaderMtl && !m_geometryShaderMtl->IsCompiled())
|
||||
m_geometryShaderMtl->PreponeCompilation(isRenderThread);
|
||||
m_geometryShaderMtl->PreponeCompilation();
|
||||
if (m_pixelShaderMtl && !m_pixelShaderMtl->IsCompiled())
|
||||
m_pixelShaderMtl->PreponeCompilation(isRenderThread);
|
||||
m_pixelShaderMtl->PreponeCompilation();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -996,9 +996,9 @@ void MetalRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType,
|
||||
m_state.m_uniformBufferOffsets[GetMtlGeneralShaderType(shaderType)][bufferIndex] = offset;
|
||||
}
|
||||
|
||||
RendererShader* MetalRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader)
|
||||
RendererShader* MetalRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, std::string&& source, bool isGameShader, bool isGfxPackShader)
|
||||
{
|
||||
return new RendererShaderMtl(this, type, baseHash, auxHash, isGameShader, isGfxPackShader, source);
|
||||
return new RendererShaderMtl(this, type, baseHash, auxHash, isGameShader, isGfxPackShader, std::move(source));
|
||||
}
|
||||
|
||||
void MetalRenderer::streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize)
|
||||
|
||||
@ -241,7 +241,7 @@ public:
|
||||
void buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size) override;
|
||||
|
||||
// shader
|
||||
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool compileAsync, bool isGfxPackSource) override;
|
||||
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, std::string&& source, bool compileAsync, bool isGfxPackSource) override;
|
||||
|
||||
// streamout
|
||||
void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override;
|
||||
|
||||
@ -213,8 +213,8 @@ void RendererShaderMtl::Shutdown()
|
||||
shaderMtlThreadPool.StopThreads();
|
||||
}
|
||||
|
||||
RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode)
|
||||
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_mtlr{mtlRenderer}, m_mslCode{mslCode}
|
||||
RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, std::string&& mslCode)
|
||||
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_mtlr{mtlRenderer}, m_mslCode{std::move(mslCode)}
|
||||
{
|
||||
// start async compilation
|
||||
shaderMtlThreadPool.s_compilationQueueMutex.lock();
|
||||
@ -231,7 +231,7 @@ RendererShaderMtl::~RendererShaderMtl()
|
||||
m_function->release();
|
||||
}
|
||||
|
||||
void RendererShaderMtl::PreponeCompilation(bool isRenderThread)
|
||||
void RendererShaderMtl::PreponeCompilation()
|
||||
{
|
||||
shaderMtlThreadPool.s_compilationQueueMutex.lock();
|
||||
bool isStillQueued = m_compilationState.hasState(COMPILATION_STATE::QUEUED);
|
||||
|
||||
@ -28,7 +28,7 @@ public:
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
|
||||
RendererShaderMtl(class MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode);
|
||||
RendererShaderMtl(class MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, std::string&& mslCode);
|
||||
virtual ~RendererShaderMtl();
|
||||
|
||||
MTL::Function* GetFunction() const
|
||||
@ -36,7 +36,7 @@ public:
|
||||
return m_function;
|
||||
}
|
||||
|
||||
void PreponeCompilation(bool isRenderThread) override;
|
||||
void PreponeCompilation() override;
|
||||
bool IsCompiled() override;
|
||||
bool WaitForCompiled() override;
|
||||
|
||||
|
||||
@ -1306,9 +1306,9 @@ void OpenGLRenderer::attributeStream_unbindVertexBuffer()
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
RendererShader* OpenGLRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader)
|
||||
RendererShader* OpenGLRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, std::string&& source, bool isGameShader, bool isGfxPackShader)
|
||||
{
|
||||
return new RendererShaderGL(type, baseHash, auxHash, isGameShader, isGfxPackShader, source);
|
||||
return new RendererShaderGL(type, baseHash, auxHash, isGameShader, isGfxPackShader, std::move(source));
|
||||
}
|
||||
|
||||
void OpenGLRenderer::shader_bind(RendererShader* shader)
|
||||
|
||||
@ -145,7 +145,7 @@ public:
|
||||
void uniformData_update();
|
||||
|
||||
// shader
|
||||
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader) override;
|
||||
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, std::string&& source, bool isGameShader, bool isGfxPackShader) override;
|
||||
void shader_bind(RendererShader* shader);
|
||||
void shader_unbind(RendererShader::ShaderType shaderType);
|
||||
|
||||
|
||||
@ -867,8 +867,8 @@ RendererShaderGL* rectsEmulationGS_generateShaderGL(LatteDecompilerShader* verte
|
||||
|
||||
gsSrc.append("}\r\n");
|
||||
|
||||
auto glShader = new RendererShaderGL(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc);
|
||||
glShader->PreponeCompilation(true);
|
||||
auto glShader = new RendererShaderGL(RendererShader::ShaderType::kGeometry, 0, 0, false, false, std::move(gsSrc));
|
||||
glShader->PreponeCompilation();
|
||||
|
||||
return glShader;
|
||||
}
|
||||
@ -912,9 +912,20 @@ void OpenGLRenderer::draw_genericDrawHandler(uint32 baseVertex, uint32 baseInsta
|
||||
{
|
||||
beginPerfMonProfiling(performanceMonitor.gpuTime_dcStageShaderAndUniformMgr);
|
||||
LatteSHRC_UpdateActiveShaders();
|
||||
LatteDecompilerShader* vs = (LatteDecompilerShader*)LatteSHRC_GetActiveVertexShader();
|
||||
LatteDecompilerShader* gs = (LatteDecompilerShader*)LatteSHRC_GetActiveGeometryShader();
|
||||
LatteDecompilerShader* ps = (LatteDecompilerShader*)LatteSHRC_GetActivePixelShader();
|
||||
LatteDecompilerShader* vs = LatteSHRC_GetActiveVertexShader();
|
||||
LatteDecompilerShader* gs = LatteSHRC_GetActiveGeometryShader();
|
||||
LatteDecompilerShader* ps = LatteSHRC_GetActivePixelShader();
|
||||
|
||||
for (auto& i : {vs, gs, ps})
|
||||
{
|
||||
if (!i)
|
||||
continue;
|
||||
if (!i->shader->IsCompiled())
|
||||
{
|
||||
i->shader->WaitForCompiled();
|
||||
}
|
||||
}
|
||||
|
||||
if (vs)
|
||||
shader_bind(vs->shader);
|
||||
else
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h"
|
||||
|
||||
#include "Cemu/FileCache/FileCache.h"
|
||||
#include "HW/Latte/Core/LatteShader.h"
|
||||
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "config/LaunchSettings.h"
|
||||
@ -42,7 +43,7 @@ bool RendererShaderGL::loadBinary()
|
||||
m_program = 0;
|
||||
return false;
|
||||
}
|
||||
m_isCompiled = true;
|
||||
m_binaryLoaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -73,8 +74,8 @@ void RendererShaderGL::storeBinary()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, std::string&& glslSource)
|
||||
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_glslSource(std::move(glslSource))
|
||||
{
|
||||
GLenum glShaderType;
|
||||
switch (type)
|
||||
@ -109,19 +110,8 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH
|
||||
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);
|
||||
cemuLog_log(LogType::Force, "Error/Warning in shader:");
|
||||
cemuLog_log(LogType::Force, log);
|
||||
}
|
||||
|
||||
// set debug name
|
||||
if (LaunchSettings::NSightModeEnabled())
|
||||
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());
|
||||
@ -134,12 +124,6 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH
|
||||
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();
|
||||
@ -157,7 +141,7 @@ RendererShaderGL::~RendererShaderGL()
|
||||
glDeleteProgram(m_program);
|
||||
}
|
||||
|
||||
void RendererShaderGL::PreponeCompilation(bool isRenderThread)
|
||||
void RendererShaderGL::PreponeCompilation()
|
||||
{
|
||||
// the logic for initiating compilation is currently in the constructor
|
||||
// here we only guarantee that it is finished before we return
|
||||
@ -168,47 +152,74 @@ void RendererShaderGL::PreponeCompilation(bool isRenderThread)
|
||||
|
||||
bool RendererShaderGL::IsCompiled()
|
||||
{
|
||||
cemu_assert_debug(false);
|
||||
return true;
|
||||
if(m_isCompiled)
|
||||
return true;
|
||||
|
||||
if(!glMaxShaderCompilerThreadsARB || m_binaryLoaded)
|
||||
{
|
||||
WaitForCompiled();
|
||||
return true;
|
||||
}
|
||||
|
||||
GLint isShaderComplete = 0, isProgramComplete = 0;
|
||||
glGetShaderiv(m_shader_object, GL_COMPLETION_STATUS_ARB, &isShaderComplete);
|
||||
if(!isShaderComplete)
|
||||
return false;
|
||||
glGetProgramiv(m_program, GL_COMPLETION_STATUS_ARB, &isProgramComplete);
|
||||
if (isProgramComplete)
|
||||
WaitForCompiled(); // since COMPLETION_STATUS == true, this should be very fast
|
||||
return m_isCompiled;
|
||||
}
|
||||
|
||||
bool RendererShaderGL::WaitForCompiled()
|
||||
{
|
||||
char infoLog[8 * 1024];
|
||||
if (m_isCompiled)
|
||||
return true;
|
||||
if (m_binaryLoaded)
|
||||
{
|
||||
LatteShader_prepareSeparableUniforms(m_decompilerShader);
|
||||
m_isCompiled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
char infoLog[8 * 1024];
|
||||
GLint log_length;
|
||||
|
||||
// count shader compilation
|
||||
if (!s_isLoadingShaders)
|
||||
++g_compiled_shaders_total;
|
||||
|
||||
// check if compilation was successful
|
||||
GLint compileStatus = GL_FALSE;
|
||||
glGetShaderiv(m_shader_object, GL_COMPILE_STATUS, &compileStatus);
|
||||
if (compileStatus == 0)
|
||||
if (compileStatus == GL_FALSE)
|
||||
{
|
||||
uint32 infoLogLength, tempLength;
|
||||
glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength);
|
||||
if (infoLogLength != 0)
|
||||
glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length > 0)
|
||||
{
|
||||
tempLength = sizeof(infoLog) - 1;
|
||||
glGetShaderInfoLog(m_shader_object, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
|
||||
infoLog[tempLength] = '\0';
|
||||
cemuLog_log(LogType::Force, "Compile error in shader. Log:");
|
||||
glGetShaderInfoLog(m_shader_object, sizeof(infoLog), &log_length, infoLog);
|
||||
cemuLog_log(LogType::Force, "Error/Warning in shader:");
|
||||
cemuLog_log(LogType::Force, infoLog);
|
||||
}
|
||||
|
||||
if (m_shader_object != 0)
|
||||
glDeleteShader(m_shader_object);
|
||||
if (m_program != 0)
|
||||
glDeleteProgram(m_program);
|
||||
m_program = m_shader_object = 0;
|
||||
m_isCompiled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// get shader binary
|
||||
GLint linkStatus = GL_FALSE;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus == 0)
|
||||
if (linkStatus == GL_FALSE)
|
||||
{
|
||||
uint32 infoLogLength, tempLength;
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength);
|
||||
if (infoLogLength != 0)
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&log_length);
|
||||
if (log_length != 0)
|
||||
{
|
||||
tempLength = sizeof(infoLog) - 1;
|
||||
glGetProgramInfoLog(m_program, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
|
||||
infoLog[tempLength] = '\0';
|
||||
glGetProgramInfoLog(m_program, sizeof(infoLog), &log_length, (GLcharARB*)infoLog);
|
||||
cemuLog_log(LogType::Force, "Link error in shader. Log:");
|
||||
cemuLog_log(LogType::Force, infoLog);
|
||||
}
|
||||
@ -216,9 +227,19 @@ bool RendererShaderGL::WaitForCompiled()
|
||||
return false;
|
||||
}
|
||||
|
||||
/*glDetachShader(m_program, m_shader_object);
|
||||
m_shader_attached = false;*/
|
||||
glDetachShader(m_program, m_shader_object);
|
||||
m_shader_attached = false;
|
||||
glDeleteShader(m_shader_object);
|
||||
m_shader_object = 0;
|
||||
|
||||
storeBinary();
|
||||
|
||||
m_isCompiled = true;
|
||||
if (m_decompilerShader)
|
||||
{
|
||||
LatteShader_prepareSeparableUniforms(m_decompilerShader);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -246,6 +267,10 @@ void RendererShaderGL::SetUniform4iv(sint32 location, void* data, sint32 count)
|
||||
{
|
||||
glProgramUniform4iv(m_program, location, count, (const GLint*)data);
|
||||
}
|
||||
void RendererShaderGL::SetDecompilerShader(LatteDecompilerShader* decompilerShader)
|
||||
{
|
||||
m_decompilerShader = decompilerShader;
|
||||
}
|
||||
|
||||
void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId)
|
||||
{
|
||||
@ -276,8 +301,8 @@ void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId)
|
||||
{
|
||||
const uint32 cacheMagic = GeneratePrecompiledCacheId();
|
||||
const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId);
|
||||
s_programBinaryCache = FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic);
|
||||
if (s_programBinaryCache == nullptr)
|
||||
s_programBinaryCache.reset(FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic));
|
||||
if (!s_programBinaryCache)
|
||||
cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename);
|
||||
}
|
||||
s_isLoadingShaders = true;
|
||||
@ -290,13 +315,10 @@ void RendererShaderGL::ShaderCacheLoading_end()
|
||||
|
||||
void RendererShaderGL::ShaderCacheLoading_Close()
|
||||
{
|
||||
if(s_programBinaryCache)
|
||||
{
|
||||
delete s_programBinaryCache;
|
||||
s_programBinaryCache = nullptr;
|
||||
}
|
||||
s_programBinaryCache.reset();
|
||||
g_compiled_shaders_total = 0;
|
||||
g_compiled_shaders_async = 0;
|
||||
}
|
||||
|
||||
FileCache* RendererShaderGL::s_programBinaryCache{};
|
||||
|
||||
std::unique_ptr<class FileCache> RendererShaderGL::s_programBinaryCache{};
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
class RendererShaderGL : public RendererShader
|
||||
{
|
||||
public:
|
||||
RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslSource);
|
||||
RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, std::string&& glslSource);
|
||||
|
||||
virtual ~RendererShaderGL();
|
||||
|
||||
void PreponeCompilation(bool isRenderThread) override;
|
||||
void PreponeCompilation() override;
|
||||
bool IsCompiled() override;
|
||||
bool WaitForCompiled() override;
|
||||
|
||||
@ -24,6 +24,8 @@ public:
|
||||
void SetUniform2fv(sint32 location, void* data, sint32 count);
|
||||
void SetUniform4iv(sint32 location, void* data, sint32 count);
|
||||
|
||||
void SetDecompilerShader(class LatteDecompilerShader* decompilerShader);
|
||||
|
||||
static void ShaderCacheLoading_begin(uint64 cacheTitleId);
|
||||
static void ShaderCacheLoading_end();
|
||||
static void ShaderCacheLoading_Close();
|
||||
@ -31,6 +33,7 @@ public:
|
||||
private:
|
||||
GLuint m_program;
|
||||
GLuint m_shader_object;
|
||||
LatteDecompilerShader* m_decompilerShader = nullptr;
|
||||
|
||||
bool loadBinary();
|
||||
void storeBinary();
|
||||
@ -39,7 +42,8 @@ private:
|
||||
|
||||
bool m_shader_attached{ false };
|
||||
bool m_isCompiled{ false };
|
||||
bool m_binaryLoaded { false };
|
||||
|
||||
static class FileCache* s_programBinaryCache;
|
||||
static std::unique_ptr<class FileCache> s_programBinaryCache;
|
||||
};
|
||||
|
||||
|
||||
@ -131,7 +131,7 @@ public:
|
||||
virtual void buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size) = 0;
|
||||
|
||||
// shader
|
||||
virtual RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool compileAsync, bool isGfxPackSource) = 0;
|
||||
virtual RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, std::string&& source, bool compileAsync, bool isGfxPackSource) = 0;
|
||||
|
||||
// streamout
|
||||
virtual void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) = 0;
|
||||
|
||||
@ -251,11 +251,11 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con
|
||||
else
|
||||
finalFragmentSrc = PrependFragmentPreamble(fragment_source);
|
||||
|
||||
m_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false));
|
||||
m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false));
|
||||
m_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, std::string(vertex_source), false, false));
|
||||
m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, std::string(finalFragmentSrc), false, false));
|
||||
|
||||
m_vertex_shader->PreponeCompilation(true);
|
||||
m_fragment_shader->PreponeCompilation(true);
|
||||
m_vertex_shader->PreponeCompilation();
|
||||
m_fragment_shader->PreponeCompilation();
|
||||
|
||||
if (!m_vertex_shader->WaitForCompiled())
|
||||
throw std::exception();
|
||||
|
||||
@ -14,7 +14,7 @@ public:
|
||||
|
||||
ShaderType GetType() const { return m_type; }
|
||||
|
||||
virtual void PreponeCompilation(bool isRenderThread) = 0; // if shader not yet compiled, compile it synchronously (if possible) or alternatively wait for compilation. After this function IsCompiled() is guaranteed to be true
|
||||
virtual void PreponeCompilation() = 0; // if shader not yet compiled, compile it synchronously (if possible) or alternatively wait for compilation. After this function IsCompiled() is guaranteed to be true
|
||||
virtual bool IsCompiled() = 0;
|
||||
virtual bool WaitForCompiled() = 0;
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ public:
|
||||
job->m_compilationState.setValue(RendererShaderVk::COMPILATION_STATE::COMPILING);
|
||||
s_compilationQueueMutex.unlock();
|
||||
// compile
|
||||
job->CompileInternal(false);
|
||||
job->CompileInternal();
|
||||
++g_compiled_shaders_async;
|
||||
// mark as compiled
|
||||
cemu_assert_debug(job->m_compilationState.getValue() == RendererShaderVk::COMPILATION_STATE::COMPILING);
|
||||
@ -195,8 +195,8 @@ private:
|
||||
std::atomic<bool> m_threadsActive;
|
||||
}ShaderVkThreadPool;
|
||||
|
||||
RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslCode)
|
||||
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_glslCode(glslCode)
|
||||
RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, std::string&& glslCode)
|
||||
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_glslCode(std::move(glslCode))
|
||||
{
|
||||
// start async compilation
|
||||
ShaderVkThreadPool.s_compilationQueueMutex.lock();
|
||||
@ -264,7 +264,7 @@ void RendererShaderVk::FinishCompilation()
|
||||
m_glslCode.shrink_to_fit();
|
||||
}
|
||||
|
||||
void RendererShaderVk::CompileInternal(bool isRenderThread)
|
||||
void RendererShaderVk::CompileInternal()
|
||||
{
|
||||
const bool compileWithDebugInfo = ((VulkanRenderer*)g_renderer.get())->IsTracingToolEnabled();
|
||||
|
||||
@ -393,7 +393,7 @@ void RendererShaderVk::CompileInternal(bool isRenderThread)
|
||||
FinishCompilation();
|
||||
}
|
||||
|
||||
void RendererShaderVk::PreponeCompilation(bool isRenderThread)
|
||||
void RendererShaderVk::PreponeCompilation()
|
||||
{
|
||||
ShaderVkThreadPool.s_compilationQueueMutex.lock();
|
||||
bool isStillQueued = m_compilationState.hasState(COMPILATION_STATE::QUEUED);
|
||||
@ -413,7 +413,7 @@ void RendererShaderVk::PreponeCompilation(bool isRenderThread)
|
||||
else
|
||||
{
|
||||
// compile synchronously
|
||||
CompileInternal(isRenderThread);
|
||||
CompileInternal();
|
||||
m_compilationState.setValue(COMPILATION_STATE::DONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ public:
|
||||
static void ShaderCacheLoading_end();
|
||||
static void ShaderCacheLoading_Close();
|
||||
|
||||
RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslCode);
|
||||
RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, std::string&& glslCode);
|
||||
virtual ~RendererShaderVk();
|
||||
|
||||
static void Init();
|
||||
@ -49,12 +49,12 @@ public:
|
||||
s_dependencyLock.unlock();
|
||||
}
|
||||
|
||||
void PreponeCompilation(bool isRenderThread) override;
|
||||
void PreponeCompilation() override;
|
||||
bool IsCompiled() override;
|
||||
bool WaitForCompiled() override;
|
||||
|
||||
private:
|
||||
void CompileInternal(bool isRenderThread);
|
||||
void CompileInternal();
|
||||
|
||||
void FinishCompilation();
|
||||
|
||||
|
||||
@ -157,8 +157,8 @@ RendererShaderVk* rectsEmulationGS_generate(LatteDecompilerShader* vertexShader,
|
||||
|
||||
gsSrc.append("}\r\n");
|
||||
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc);
|
||||
vkShader->PreponeCompilation(true);
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kGeometry, 0, 0, false, false, std::move(gsSrc));
|
||||
vkShader->PreponeCompilation();
|
||||
return vkShader;
|
||||
}
|
||||
|
||||
@ -964,11 +964,11 @@ bool PipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool show
|
||||
{
|
||||
// if some shader stages are not compiled yet, compile them now
|
||||
if (m_vkVertexShader && m_vkVertexShader->IsCompiled() == false)
|
||||
m_vkVertexShader->PreponeCompilation(isRenderThread);
|
||||
m_vkVertexShader->PreponeCompilation();
|
||||
if (m_vkPixelShader && m_vkPixelShader->IsCompiled() == false)
|
||||
m_vkPixelShader->PreponeCompilation(isRenderThread);
|
||||
m_vkPixelShader->PreponeCompilation();
|
||||
if (m_vkGeometryShader && m_vkGeometryShader->IsCompiled() == false)
|
||||
m_vkGeometryShader->PreponeCompilation(isRenderThread);
|
||||
m_vkGeometryShader->PreponeCompilation();
|
||||
}
|
||||
|
||||
if (shaderStages.empty())
|
||||
|
||||
@ -1293,9 +1293,9 @@ VkDeviceCreateInfo VulkanRenderer::CreateDeviceCreateInfo(const std::vector<VkDe
|
||||
return createInfo;
|
||||
}
|
||||
|
||||
RendererShader* VulkanRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader)
|
||||
RendererShader* VulkanRenderer::shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, std::string&& source, bool isGameShader, bool isGfxPackShader)
|
||||
{
|
||||
return new RendererShaderVk(type, baseHash, auxHash, isGameShader, isGfxPackShader, source);
|
||||
return new RendererShaderVk(type, baseHash, auxHash, isGameShader, isGfxPackShader, std::move(source));
|
||||
}
|
||||
|
||||
VulkanRenderer::QueueFamilyIndices VulkanRenderer::FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device)
|
||||
|
||||
@ -330,7 +330,7 @@ public:
|
||||
std::pair<VkBuffer, uint32> buffer_genStrideWorkaroundVertexBuffer(MPTR buffer, uint32 size, uint32 oldStride);
|
||||
void buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size) override;
|
||||
|
||||
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader) override;
|
||||
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, std::string&& source, bool isGameShader, bool isGfxPackShader) override;
|
||||
|
||||
IndexAllocation indexData_reserveIndexMemory(uint32 size) override;
|
||||
void indexData_releaseIndexMemory(IndexAllocation& allocation) override;
|
||||
|
||||
@ -180,8 +180,8 @@ RendererShaderVk* _vkGenSurfaceCopyShader_vs()
|
||||
"}\r\n";
|
||||
|
||||
std::string shaderStr(vsShaderSrc);
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kVertex, 0, 0, false, false, shaderStr);
|
||||
vkShader->PreponeCompilation(true);
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kVertex, 0, 0, false, false, std::move(shaderStr));
|
||||
vkShader->PreponeCompilation();
|
||||
return vkShader;
|
||||
}
|
||||
|
||||
@ -198,8 +198,8 @@ RendererShaderVk* _vkGenSurfaceCopyShader_ps_colorToDepth()
|
||||
"}\r\n";
|
||||
|
||||
std::string shaderStr(psShaderSrc);
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr);
|
||||
vkShader->PreponeCompilation(true);
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, std::move(shaderStr));
|
||||
vkShader->PreponeCompilation();
|
||||
return vkShader;
|
||||
}
|
||||
|
||||
@ -217,8 +217,8 @@ RendererShaderVk* _vkGenSurfaceCopyShader_ps_depthToColor()
|
||||
"}\r\n";
|
||||
|
||||
std::string shaderStr(psShaderSrc);
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr);
|
||||
vkShader->PreponeCompilation(true);
|
||||
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, std::move(shaderStr));
|
||||
vkShader->PreponeCompilation();
|
||||
return vkShader;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user