Test parsing of generated OpenGL shaders too (by using glslang).

This commit is contained in:
Henrik Rydgård
2020-10-30 23:29:18 +01:00
parent 44c57d87f4
commit b7d674411e
14 changed files with 138 additions and 98 deletions
+27 -8
View File
@@ -1177,24 +1177,43 @@ EShLanguage FindLanguage(const VkShaderStageFlagBits shader_type) {
// Compile a given string containing GLSL into SPV for use by VK
// Return value of false means an error was encountered.
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type,
const char *pshader,
std::vector<unsigned int> &spirv, std::string *errorMessage) {
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *sourceCode, GLSLVariant variant,
std::vector<unsigned int> &spirv, std::string *errorMessage) {
glslang::TProgram program;
const char *shaderStrings[1];
EProfile profile = ECoreProfile;
int defaultVersion = 450;
TBuiltInResource Resources;
init_resources(Resources);
// Enable SPIR-V and Vulkan rules when parsing GLSL
EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
int defaultVersion;
EShMessages messages;
EProfile profile;
switch (variant) {
case GLSLVariant::VULKAN:
// Enable SPIR-V and Vulkan rules when parsing GLSL
messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
defaultVersion = 450;
profile = ECoreProfile;
break;
case GLSLVariant::GL140:
messages = (EShMessages)(EShMsgDefault);
defaultVersion = 140;
profile = ECompatibilityProfile;
break;
case GLSLVariant::GLES300:
messages = (EShMessages)(EShMsgDefault);
defaultVersion = 300;
profile = EEsProfile;
break;
default:
return false;
}
EShLanguage stage = FindLanguage(shader_type);
glslang::TShader shader(stage);
shaderStrings[0] = pshader;
shaderStrings[0] = sourceCode;
shader.setStrings(shaderStrings, 1);
if (!shader.parse(&Resources, defaultVersion, profile, false, true, messages)) {
+8 -1
View File
@@ -367,7 +367,14 @@ void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, int baseMip, int
// GLSL compiler
void init_glslang();
void finalize_glslang();
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector<uint32_t> &spirv, std::string *errorMessage = nullptr);
enum class GLSLVariant {
VULKAN,
GL140,
GLES300,
};
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *sourceCode, GLSLVariant variant, std::vector<uint32_t> &spirv, std::string *errorMessage);
const char *VulkanResultToString(VkResult res);
std::string FormatDriverVersion(const VkPhysicalDeviceProperties &props);
+3 -1
View File
@@ -215,7 +215,9 @@ bool VKShaderModule::Compile(VulkanContext *vulkan, ShaderLanguage language, con
// We'll need this to free it later.
source_ = (const char *)data;
std::vector<uint32_t> spirv;
if (!GLSLtoSPV(vkstage_, source_.c_str(), spirv)) {
std::string errorMessage;
if (!GLSLtoSPV(vkstage_, source_.c_str(), GLSLVariant::VULKAN, spirv, &errorMessage)) {
INFO_LOG(G3D, "Shader compile to module failed: %s", errorMessage.c_str());
return false;
}
+34 -2
View File
@@ -2,7 +2,6 @@
#undef new
#endif
#include "ext/glslang/SPIRV/GlslangToSpv.h"
#include "ShaderCommon.h"
@@ -102,9 +101,42 @@ void init_resources(TBuiltInResource &Resources) {
Resources.limits.generalConstantMatrixVectorIndexing = 1;
}
void GLSLShaderCompat::SetupForShaderLanguage(ShaderLanguage lang) {
GLSLShaderCompat::GLSLShaderCompat(ShaderLanguage lang) {
shaderLanguage = lang;
switch (lang) {
case GLSL_140:
// Just used in the shader test, and as a basis for the others in DetectShaderLanguage.
glslVersionNumber = 110;
attribute = "attribute";
varying_vs = "varying";
varying_fs = "varying";
fragColor0 = "gl_FragColor";
fragColor1 = "fragColor1";
texture = "texture2D";
texelFetch = nullptr;
bitwiseOps = false;
lastFragData = nullptr;
gles = false;
forceMatrix4x4 = true;
break;
case GLSL_300:
// Just used in the shader test.
glslVersionNumber = 300; // GLSL ES 3.0
varying_vs = "out";
varying_fs = "in";
attribute = "in";
fragColor0 = "fragColor0";
fragColor1 = "fragColor1";
texture = "texture";
texelFetch = nullptr;
bitwiseOps = false;
lastFragData = nullptr;
gles = false;
forceMatrix4x4 = true;
glslES30 = true;
bitwiseOps = true;
texelFetch = "texelFetch";
break;
case GLSL_VULKAN:
fragColor0 = "fragColor0";
fragColor1 = "fragColor1";
+18 -18
View File
@@ -146,25 +146,25 @@ enum DoLightComputation {
};
struct GLSLShaderCompat {
int glslVersionNumber;
ShaderLanguage shaderLanguage;
bool gles;
const char *varying_fs;
const char *varying_vs;
const char *attribute;
const char *fragColor0;
const char *fragColor1;
const char *texture;
const char *texelFetch;
const char *lastFragData;
const char *framebufferFetchExtension;
const char *inPrefix = "";
bool glslES30;
bool bitwiseOps;
bool forceMatrix4x4;
bool coefsFromBuffers;
explicit GLSLShaderCompat(ShaderLanguage lang);
void SetupForShaderLanguage(ShaderLanguage lang);
int glslVersionNumber = 0;
ShaderLanguage shaderLanguage;
bool gles = false;
const char *varying_fs = nullptr;
const char *varying_vs = nullptr;
const char *attribute = nullptr;
const char *fragColor0 = nullptr;
const char *fragColor1 = nullptr;
const char *texture = nullptr;
const char *texelFetch = nullptr;
const char *lastFragData = nullptr;
const char *framebufferFetchExtension = nullptr;
const char *inPrefix = "";
bool glslES30 = false;
bool bitwiseOps = false;
bool forceMatrix4x4 = false;
bool coefsFromBuffers = false;
};
// PSP vertex format.
+1 -1
View File
@@ -16,7 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#ifdef _WIN32
#define SHADERLOG
//#define SHADERLOG
#endif
#include <cmath>
+2 -12
View File
@@ -571,7 +571,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu
}
ShaderManagerGLES::ShaderManagerGLES(Draw::DrawContext *draw)
: ShaderManagerCommon(draw), lastShader_(nullptr), shaderSwitchDirtyUniforms_(0), diskCacheDirty_(false), fsCache_(16), vsCache_(16) {
: ShaderManagerCommon(draw), compat_(GLSL_140), fsCache_(16), vsCache_(16) {
render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
codeBuffer_ = new char[16384];
lastFSID_.set_invalid();
@@ -585,18 +585,8 @@ ShaderManagerGLES::~ShaderManagerGLES() {
void ShaderManagerGLES::DetectShaderLanguage() {
GLSLShaderCompat &compat = compat_;
compat.shaderLanguage = ShaderLanguage::GLSL_140;
compat.attribute = "attribute";
compat.varying_vs = "varying";
compat.varying_fs = "varying";
compat.fragColor0 = "gl_FragColor";
compat.fragColor1 = "fragColor1";
compat.texture = "texture2D";
compat.texelFetch = nullptr;
compat.bitwiseOps = false;
compat.lastFragData = nullptr;
compat.gles = gl_extensions.IsGLES;
compat.forceMatrix4x4 = true;
if (compat.gles) {
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
+4 -4
View File
@@ -196,7 +196,7 @@ private:
typedef std::vector<LinkedShaderCacheEntry> LinkedShaderCache;
GLRenderManager *render_;
GLSLShaderCompat compat_{};
GLSLShaderCompat compat_;
LinkedShaderCache linkedShaderCache_;
bool lastVShaderSame_;
@@ -204,8 +204,8 @@ private:
FShaderID lastFSID_;
VShaderID lastVSID_;
LinkedShader *lastShader_;
u64 shaderSwitchDirtyUniforms_;
LinkedShader *lastShader_ = nullptr;
u64 shaderSwitchDirtyUniforms_ = 0;
char *codeBuffer_;
typedef DenseHashMap<FShaderID, Shader *, nullptr> FSCache;
@@ -214,7 +214,7 @@ private:
typedef DenseHashMap<VShaderID, Shader *, nullptr> VSCache;
VSCache vsCache_;
bool diskCacheDirty_;
bool diskCacheDirty_ = false;
struct {
std::vector<VShaderID> vert;
std::vector<FShaderID> frag;
+2 -2
View File
@@ -99,7 +99,7 @@ static const char * const boneWeightDecl[9] = {
"layout(location = 3) in vec4 w1;\nlayout(location = 4) in vec4 w2;\n",
};
static const char *vulkan_glsl_preamble =
const char *vulkan_glsl_preamble_vs =
"#version 450\n"
"#extension GL_ARB_separate_shader_objects : enable\n"
"#extension GL_ARB_shading_language_420pack : enable\n"
@@ -114,7 +114,7 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, const GLSLShade
char *p = buffer;
if (compat.shaderLanguage == GLSL_VULKAN) {
WRITE(p, "%s", vulkan_glsl_preamble);
WRITE(p, "%s", vulkan_glsl_preamble_vs);
} else {
if (compat.gles) {
// PowerVR needs highp to do the fog in MHU correctly.
+1 -1
View File
@@ -76,7 +76,7 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
break;
case GPUBackend::DIRECT3D9:
ShaderTranslationInit();
presentation_->SetLanguage(HLSL_DX9);
presentation_->SetLanguage(HLSL_D3D9);
break;
case GPUBackend::DIRECT3D11:
ShaderTranslationInit();
+3 -5
View File
@@ -53,7 +53,7 @@ VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id,
OutputDebugStringA(LineNumberString(code).c_str());
#endif
bool success = GLSLtoSPV(VK_SHADER_STAGE_FRAGMENT_BIT, code, spirv, &errorMessage);
bool success = GLSLtoSPV(VK_SHADER_STAGE_FRAGMENT_BIT, code, GLSLVariant::VULKAN, spirv, &errorMessage);
if (!errorMessage.empty()) {
if (success) {
ERROR_LOG(G3D, "Warnings in shader compilation!");
@@ -109,7 +109,7 @@ VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, cons
#ifdef SHADERLOG
OutputDebugStringA(LineNumberString(code).c_str());
#endif
bool success = GLSLtoSPV(VK_SHADER_STAGE_VERTEX_BIT, code, spirv, &errorMessage);
bool success = GLSLtoSPV(VK_SHADER_STAGE_VERTEX_BIT, code, GLSLVariant::VULKAN, spirv, &errorMessage);
if (!errorMessage.empty()) {
if (success) {
ERROR_LOG(G3D, "Warnings in shader compilation!");
@@ -158,7 +158,7 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons
}
ShaderManagerVulkan::ShaderManagerVulkan(Draw::DrawContext *draw, VulkanContext *vulkan)
: ShaderManagerCommon(draw), vulkan_(vulkan), lastVShader_(nullptr), lastFShader_(nullptr), fsCache_(16), vsCache_(16) {
: ShaderManagerCommon(draw), vulkan_(vulkan), compat_(GLSL_VULKAN), fsCache_(16), vsCache_(16) {
codeBuffer_ = new char[16384];
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment;
memset(&ub_base, 0, sizeof(ub_base));
@@ -168,8 +168,6 @@ ShaderManagerVulkan::ShaderManagerVulkan(Draw::DrawContext *draw, VulkanContext
static_assert(sizeof(ub_base) <= 512, "ub_base grew too big");
static_assert(sizeof(ub_lights) <= 512, "ub_lights grew too big");
static_assert(sizeof(ub_bones) <= 384, "ub_bones grew too big");
compat_.SetupForShaderLanguage(ShaderLanguage::GLSL_VULKAN);
}
ShaderManagerVulkan::~ShaderManagerVulkan() {
+3 -3
View File
@@ -131,7 +131,7 @@ private:
void Clear();
VulkanContext *vulkan_;
GLSLShaderCompat compat_{};
GLSLShaderCompat compat_;
typedef DenseHashMap<FShaderID, VulkanFragmentShader *, nullptr> FSCache;
FSCache fsCache_;
@@ -147,8 +147,8 @@ private:
UB_VS_Lights ub_lights;
UB_VS_Bones ub_bones;
VulkanFragmentShader *lastFShader_;
VulkanVertexShader *lastVShader_;
VulkanFragmentShader *lastFShader_ = nullptr;
VulkanVertexShader *lastVShader_ = nullptr;
FShaderID lastFSID_;
VShaderID lastVSID_;
+1 -1
View File
@@ -368,7 +368,7 @@ VkPipeline Vulkan2D::GetPipeline(VkRenderPass rp, VkShaderModule vs, VkShaderMod
VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code, std::string *error) {
std::vector<uint32_t> spirv;
bool success = GLSLtoSPV(stage, code, spirv, error);
bool success = GLSLtoSPV(stage, code, GLSLVariant::VULKAN, spirv, error);
if (!error->empty()) {
if (success) {
ERROR_LOG(G3D, "Warnings in shader compilation!");
+31 -39
View File
@@ -22,6 +22,7 @@
#include "GPU/D3D9/D3D9ShaderCompiler.h"
bool GenerateFShader(FShaderID id, char *buffer, ShaderLanguage lang, std::string *errorString) {
uint64_t uniformMask;
switch (lang) {
case ShaderLanguage::HLSL_D3D11:
return GenerateFragmentShaderHLSL(id, buffer, ShaderLanguage::HLSL_D3D11, errorString);
@@ -29,27 +30,29 @@ bool GenerateFShader(FShaderID id, char *buffer, ShaderLanguage lang, std::strin
return GenerateFragmentShaderHLSL(id, buffer, ShaderLanguage::HLSL_D3D9, errorString);
case ShaderLanguage::GLSL_VULKAN:
{
GLSLShaderCompat compat{};
compat.SetupForShaderLanguage(ShaderLanguage::GLSL_VULKAN);
uint64_t uniformMask;
GLSLShaderCompat compat(ShaderLanguage::GLSL_VULKAN);
return GenerateFragmentShaderGLSL(id, buffer, compat, &uniformMask, errorString);
}
case ShaderLanguage::GLSL_140:
{
GLSLShaderCompat compat(ShaderLanguage::GLSL_140);
return GenerateFragmentShaderGLSL(id, buffer, compat, &uniformMask, errorString);
}
case ShaderLanguage::GLSL_300:
// TODO: Need a device - except that maybe glslang could be used to verify these ....
return false;
{
GLSLShaderCompat compat(ShaderLanguage::GLSL_140);
return GenerateFragmentShaderGLSL(id, buffer, compat, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D9_TEST:
{
GLSLShaderCompat compat{};
compat.SetupForShaderLanguage(ShaderLanguage::HLSL_D3D9);
uint64_t uniformMask;
GLSLShaderCompat compat(ShaderLanguage::HLSL_D3D9);
return GenerateFragmentShaderGLSL(id, buffer, compat, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D11_TEST:
{
GLSLShaderCompat compat{};
compat.SetupForShaderLanguage(ShaderLanguage::HLSL_D3D11);
uint64_t uniformMask;
GLSLShaderCompat compat(ShaderLanguage::HLSL_D3D11);
return GenerateFragmentShaderGLSL(id, buffer, compat, &uniformMask, errorString);
}
default:
@@ -58,34 +61,26 @@ bool GenerateFShader(FShaderID id, char *buffer, ShaderLanguage lang, std::strin
}
bool GenerateVShader(VShaderID id, char *buffer, ShaderLanguage lang, std::string *errorString) {
uint32_t attrMask;
uint64_t uniformMask;
switch (lang) {
case ShaderLanguage::HLSL_D3D11:
return GenerateVertexShaderHLSL(id, buffer, ShaderLanguage::HLSL_D3D11, errorString);
case ShaderLanguage::HLSL_D3D9:
return GenerateVertexShaderHLSL(id, buffer, ShaderLanguage::HLSL_D3D9, errorString);
// return DX9::GenerateFragmentShaderHLSL(id, buffer, ShaderLanguage::HLSL_D3D9);
case ShaderLanguage::GLSL_VULKAN:
{
GLSLShaderCompat compat{};
compat.SetupForShaderLanguage(ShaderLanguage::GLSL_VULKAN);
uint32_t attrMask;
uint64_t uniformMask;
GLSLShaderCompat compat(ShaderLanguage::GLSL_VULKAN);
return GenerateVertexShaderGLSL(id, buffer, compat, &attrMask, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D9_TEST:
{
GLSLShaderCompat compat{};
compat.SetupForShaderLanguage(ShaderLanguage::HLSL_D3D9);
uint32_t attrMask;
uint64_t uniformMask;
GLSLShaderCompat compat(ShaderLanguage::HLSL_D3D9);
return GenerateVertexShaderGLSL(id, buffer, compat, &attrMask, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D11_TEST:
{
GLSLShaderCompat compat{};
compat.SetupForShaderLanguage(ShaderLanguage::HLSL_D3D11);
uint32_t attrMask;
uint64_t uniformMask;
GLSLShaderCompat compat(ShaderLanguage::HLSL_D3D11);
return GenerateVertexShaderGLSL(id, buffer, compat, &attrMask, &uniformMask, errorString);
}
default:
@@ -94,6 +89,7 @@ bool GenerateVShader(VShaderID id, char *buffer, ShaderLanguage lang, std::strin
}
bool TestCompileShader(const char *buffer, ShaderLanguage lang, bool vertex, std::string *errorMessage) {
std::vector<uint32_t> spirv;
switch (lang) {
case ShaderLanguage::HLSL_D3D11:
case ShaderLanguage::HLSL_D3D11_TEST:
@@ -114,19 +110,11 @@ bool TestCompileShader(const char *buffer, ShaderLanguage lang, bool vertex, std
}
case ShaderLanguage::GLSL_VULKAN:
{
std::vector<uint32_t> spirv;
std::string errorMessage;
bool result = GLSLtoSPV(vertex ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT, buffer, spirv, &errorMessage);
if (!result) {
printf("GLSLtoSPV ERROR:\n%s\n\n", errorMessage.c_str());
}
return result;
}
return GLSLtoSPV(vertex ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT, buffer, GLSLVariant::VULKAN, spirv, errorMessage);
case ShaderLanguage::GLSL_140:
return false;
return GLSLtoSPV(vertex ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT, buffer, GLSLVariant::GL140, spirv, errorMessage);
case ShaderLanguage::GLSL_300:
return false;
return GLSLtoSPV(vertex ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT, buffer, GLSLVariant::GLES300, spirv, errorMessage);
default:
return false;
}
@@ -167,8 +155,8 @@ bool TestShaderGenerators() {
ShaderLanguage languages[] = {
ShaderLanguage::HLSL_D3D9_TEST,
ShaderLanguage::HLSL_D3D9,
ShaderLanguage::HLSL_D3D11_TEST,
ShaderLanguage::HLSL_D3D11,
ShaderLanguage::HLSL_D3D9,
ShaderLanguage::GLSL_VULKAN,
ShaderLanguage::GLSL_140,
ShaderLanguage::GLSL_300,
@@ -213,6 +201,7 @@ bool TestShaderGenerators() {
}
// KEEPING FOR REUSE LATER: Defunct temporary test.
/*
if (generateSuccess[0] != generateSuccess[1]) {
printf("mismatching success! %s %s\n", genErrorString[0].c_str(), genErrorString[1].c_str());
printf("%s\n", buffer[0]);
@@ -224,7 +213,11 @@ bool TestShaderGenerators() {
PrintDiff(buffer[0], buffer[1]);
return 1;
}
if (generateSuccess[2] && strcmp(buffer[2], buffer[3])) {
printf("mismatching shaders! a=glsl b=hlsl\n");
PrintDiff(buffer[2], buffer[3]);
return 1;
}*/
// Now that we have the strings ready for easy comparison (buffer,4 in the watch window),
// let's try to compile them.
for (int j = 0; j < numLanguages; j++) {
@@ -262,7 +255,7 @@ bool TestShaderGenerators() {
printf("%s\n", genErrorString[j].c_str());
}
}
/*
// KEEPING FOR REUSE LATER: Defunct temporary test: Compare GLSL-in-Vulkan-mode vs Vulkan
if (generateSuccess[0] != generateSuccess[1]) {
printf("mismatching success! '%s' '%s'\n", genErrorString[0].c_str(), genErrorString[1].c_str());
@@ -275,7 +268,6 @@ bool TestShaderGenerators() {
PrintDiff(buffer[0], buffer[1]);
return false;
}
*/
// Now that we have the strings ready for easy comparison (buffer,4 in the watch window),
// let's try to compile them.