rpcs3/rpcs3/Emu/RSX/Program/SPIRVCommon.cpp
2024-03-27 19:20:21 +02:00

200 lines
6.7 KiB
C++

#include "stdafx.h"
#ifdef _MSC_VER
#pragma warning(push, 0)
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wsuggest-override"
#ifdef __clang__
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
#endif
#endif
#include "3rdparty/glslang/glslang/SPIRV/GlslangToSpv.h"
#ifdef _MSC_VER
#pragma warning(pop)
#else
#pragma GCC diagnostic pop
#endif
#include "SPIRVCommon.h"
#include "GLSLCommon.h"
namespace spirv
{
static TBuiltInResource g_default_config;
void init_default_resources(TBuiltInResource& rsc)
{
rsc.maxLights = 32;
rsc.maxClipPlanes = 6;
rsc.maxTextureUnits = 32;
rsc.maxTextureCoords = 32;
rsc.maxVertexAttribs = 64;
rsc.maxVertexUniformComponents = 4096;
rsc.maxVaryingFloats = 64;
rsc.maxVertexTextureImageUnits = 32;
rsc.maxCombinedTextureImageUnits = 80;
rsc.maxTextureImageUnits = 32;
rsc.maxFragmentUniformComponents = 4096;
rsc.maxDrawBuffers = 32;
rsc.maxVertexUniformVectors = 128;
rsc.maxVaryingVectors = 8;
rsc.maxFragmentUniformVectors = 16;
rsc.maxVertexOutputVectors = 16;
rsc.maxFragmentInputVectors = 15;
rsc.minProgramTexelOffset = -8;
rsc.maxProgramTexelOffset = 7;
rsc.maxClipDistances = 8;
rsc.maxComputeWorkGroupCountX = 65535;
rsc.maxComputeWorkGroupCountY = 65535;
rsc.maxComputeWorkGroupCountZ = 65535;
rsc.maxComputeWorkGroupSizeX = 1024;
rsc.maxComputeWorkGroupSizeY = 1024;
rsc.maxComputeWorkGroupSizeZ = 64;
rsc.maxComputeUniformComponents = 1024;
rsc.maxComputeTextureImageUnits = 16;
rsc.maxComputeImageUniforms = 8;
rsc.maxComputeAtomicCounters = 8;
rsc.maxComputeAtomicCounterBuffers = 1;
rsc.maxVaryingComponents = 60;
rsc.maxVertexOutputComponents = 64;
rsc.maxGeometryInputComponents = 64;
rsc.maxGeometryOutputComponents = 128;
rsc.maxFragmentInputComponents = 128;
rsc.maxImageUnits = 8;
rsc.maxCombinedImageUnitsAndFragmentOutputs = 8;
rsc.maxCombinedShaderOutputResources = 8;
rsc.maxImageSamples = 0;
rsc.maxVertexImageUniforms = 0;
rsc.maxTessControlImageUniforms = 0;
rsc.maxTessEvaluationImageUniforms = 0;
rsc.maxGeometryImageUniforms = 0;
rsc.maxFragmentImageUniforms = 8;
rsc.maxCombinedImageUniforms = 8;
rsc.maxGeometryTextureImageUnits = 16;
rsc.maxGeometryOutputVertices = 256;
rsc.maxGeometryTotalOutputComponents = 1024;
rsc.maxGeometryUniformComponents = 1024;
rsc.maxGeometryVaryingComponents = 64;
rsc.maxTessControlInputComponents = 128;
rsc.maxTessControlOutputComponents = 128;
rsc.maxTessControlTextureImageUnits = 16;
rsc.maxTessControlUniformComponents = 1024;
rsc.maxTessControlTotalOutputComponents = 4096;
rsc.maxTessEvaluationInputComponents = 128;
rsc.maxTessEvaluationOutputComponents = 128;
rsc.maxTessEvaluationTextureImageUnits = 16;
rsc.maxTessEvaluationUniformComponents = 1024;
rsc.maxTessPatchComponents = 120;
rsc.maxPatchVertices = 32;
rsc.maxTessGenLevel = 64;
rsc.maxViewports = 16;
rsc.maxVertexAtomicCounters = 0;
rsc.maxTessControlAtomicCounters = 0;
rsc.maxTessEvaluationAtomicCounters = 0;
rsc.maxGeometryAtomicCounters = 0;
rsc.maxFragmentAtomicCounters = 8;
rsc.maxCombinedAtomicCounters = 8;
rsc.maxAtomicCounterBindings = 1;
rsc.maxVertexAtomicCounterBuffers = 0;
rsc.maxTessControlAtomicCounterBuffers = 0;
rsc.maxTessEvaluationAtomicCounterBuffers = 0;
rsc.maxGeometryAtomicCounterBuffers = 0;
rsc.maxFragmentAtomicCounterBuffers = 1;
rsc.maxCombinedAtomicCounterBuffers = 1;
rsc.maxAtomicCounterBufferSize = 16384;
rsc.maxTransformFeedbackBuffers = 4;
rsc.maxTransformFeedbackInterleavedComponents = 64;
rsc.maxCullDistances = 8;
rsc.maxCombinedClipAndCullDistances = 8;
rsc.maxSamples = 4;
rsc.limits.nonInductiveForLoops = true;
rsc.limits.whileLoops = true;
rsc.limits.doWhileLoops = true;
rsc.limits.generalUniformIndexing = true;
rsc.limits.generalAttributeMatrixVectorIndexing = true;
rsc.limits.generalVaryingIndexing = true;
rsc.limits.generalSamplerIndexing = true;
rsc.limits.generalVariableIndexing = true;
rsc.limits.generalConstantMatrixVectorIndexing = true;
}
bool compile_glsl_to_spv(std::vector<u32>& spv, std::string& shader, ::glsl::program_domain domain, ::glsl::glsl_rules rules)
{
EShLanguage lang = (domain == ::glsl::glsl_fragment_program)
? EShLangFragment
: (domain == ::glsl::glsl_vertex_program)
? EShLangVertex
: EShLangCompute;
glslang::EShClient client;
glslang::EShTargetClientVersion target_version;
EShMessages msg;
if (rules == ::glsl::glsl_rules_vulkan)
{
client = glslang::EShClientVulkan;
target_version = glslang::EShTargetClientVersion::EShTargetVulkan_1_0;
msg = static_cast<EShMessages>(EShMsgVulkanRules | EShMsgSpvRules | EShMsgEnhanced);
}
else
{
client = glslang::EShClientOpenGL;
target_version = glslang::EShTargetClientVersion::EShTargetOpenGL_450;
msg = static_cast<EShMessages>(EShMsgDefault | EShMsgSpvRules | EShMsgEnhanced);
}
glslang::TProgram program;
glslang::TShader shader_object(lang);
shader_object.setEnvInput(glslang::EShSourceGlsl, lang, client, 100);
shader_object.setEnvClient(client, target_version);
shader_object.setEnvTarget(glslang::EshTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_0);
bool success = false;
const char* shader_text = shader.data();
shader_object.setStrings(&shader_text, 1);
if (shader_object.parse(&g_default_config, 430, EProfile::ECoreProfile, false, true, msg))
{
program.addShader(&shader_object);
success = program.link(msg);
if (success)
{
glslang::SpvOptions options;
options.disableOptimizer = true;
options.optimizeSize = true;
glslang::GlslangToSpv(*program.getIntermediate(lang), spv, &options);
// Now we optimize
//spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_0);
//optimizer.RegisterPass(spvtools::CreateUnifyConstantPass()); // Remove duplicate constants
//optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); // Huge savings in vertex interpreter and likely normal vertex shaders
//optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); // Remove dead code
//optimizer.Run(spv.data(), spv.size(), &spv);
}
}
else
{
rsx_log.error("%s", shader_object.getInfoLog());
rsx_log.error("%s", shader_object.getInfoDebugLog());
}
return success;
}
void initialize_compiler_context()
{
glslang::InitializeProcess();
init_default_resources(g_default_config);
}
void finalize_compiler_context()
{
glslang::FinalizeProcess();
}
}