Complete implementation of post shaders for D3D11. All work except 5x scale one which looks wrong.

This commit is contained in:
Henrik Rydgard 2017-02-23 14:51:05 +01:00
parent 731026c199
commit ccef648d3d
2 changed files with 110 additions and 6 deletions

View file

@ -19,6 +19,7 @@
#include <memory>
#include <vector>
#include <sstream>
// DbgNew is not compatible with Glslang
#ifdef DBG_NEW
@ -26,6 +27,8 @@
#endif
#include "base/logging.h"
#include "base/basictypes.h"
#include "base/stringutil.h"
#include "ShaderTranslation.h"
#include "ext/glslang/SPIRV/GlslangToSpv.h"
#include "thin3d/thin3d.h"
@ -58,13 +61,105 @@ void ShaderTranslationShutdown() {
glslang::FinalizeProcess();
}
std::string Preprocess(std::string code, ShaderLanguage lang) {
std::string Preprocess(std::string code, ShaderLanguage lang, Draw::ShaderStage stage) {
// This takes GL up to the version we need.
return code;
}
std::string Postprocess(std::string code, ShaderLanguage lang) {
return code;
struct Builtin {
const char *needle;
const char *replacement;
};
// Workaround for deficiency in SPIRV-Cross
static const Builtin builtins[] = {
{"lessThan",
R"(
bool2 lessThan(float2 a, float2 b) { return bool2(a.x < b.x, a.y < b.y); }
bool3 lessThan(float3 a, float3 b) { return bool3(a.x < b.x, a.y < b.y, a.z < b.z); }
bool4 lessThan(float4 a, float4 b) { return bool4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w); }
)"},
{ "lessThanEqual",
R"(
bool2 lessThanEqual(float2 a, float2 b) { return bool2(a.x <= b.x, a.y <= b.y); }
bool3 lessThanEqual(float3 a, float3 b) { return bool3(a.x <= b.x, a.y <= b.y, a.z <= b.z); }
bool4 lessThanEqual(float4 a, float4 b) { return bool4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w); }
)" },
{ "greaterThan",
R"(
bool2 greaterThan(float2 a, float2 b) { return bool2(a.x > b.x, a.y > b.y); }
bool3 greaterThan(float3 a, float3 b) { return bool3(a.x > b.x, a.y > b.y, a.z > b.z); }
bool4 greaterThan(float4 a, float4 b) { return bool4(a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w); }
)" },
{ "greaterThanEqual",
R"(
bool2 greaterThanEqual(float2 a, float2 b) { return bool2(a.x >= b.x, a.y >= b.y); }
bool3 greaterThanEqual(float3 a, float3 b) { return bool3(a.x >= b.x, a.y >= b.y, a.z >= b.z); }
bool4 greaterThanEqual(float4 a, float4 b) { return bool4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w); }
)" },
{ "equal",
R"(
bool2 equal(float2 a, float2 b) { return bool2(a.x == b.x, a.y == b.y); }
bool3 equal(float3 a, float3 b) { return bool3(a.x == b.x, a.y == b.y, a.z == b.z); }
bool4 equal(float4 a, float4 b) { return bool4(a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w); }
)" },
{ "notEqual",
R"(
bool2 notEqual(float2 a, float2 b) { return bool2(a.x != b.x, a.y != b.y); }
bool3 notEqual(float3 a, float3 b) { return bool3(a.x != b.x, a.y != b.y, a.z != b.z); }
bool4 notEqual(float4 a, float4 b) { return bool4(a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w); }
)" },
};
static const Builtin replacements[] = {
{ "mix(", "lerp(" },
};
static const char *cbufferDecl = R"(
cbuffer data : register(b0) {
float2 u_texelDelta;
float2 u_pixelDelta;
float4 u_time;
};
)";
// SPIRV-Cross' HLSL output has some deficiencies we need to work around.
// Also we need to rip out single uniforms and replace them with blocks.
// Should probably do it in the source shader instead and then back translate to old style GLSL, but
// SPIRV-Cross currently won't compile with the Android NDK so I can't be bothered.
std::string Postprocess(std::string code, ShaderLanguage lang, Draw::ShaderStage stage) {
if (lang != HLSL_D3D11)
return code;
std::stringstream out;
// Output the uniform buffer.
out << cbufferDecl;
// Add the builtins if required.
for (int i = 0; i < ARRAY_SIZE(builtins); i++) {
if (!builtins[i].needle)
continue;
if (code.find(builtins[i].needle) != std::string::npos) {
out << builtins[i].replacement;
}
}
// Perform some replacements
for (int i = 0; i < ARRAY_SIZE(replacements); i++) {
code = ReplaceAll(code, replacements[i].needle, replacements[i].replacement);
}
// Alright, now let's go through it line by line and zap the single uniforms.
std::string line;
std::stringstream instream(code);
while (std::getline(instream, line)) {
if (line.find("uniform float") != std::string::npos)
continue;
out << line << "\n";
}
std::string output = out.str();
return output;
}
bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShaderMetadata *destMetadata, std::string src, ShaderLanguage srcLang, Draw::ShaderStage stage, std::string *errorMessage) {
@ -83,7 +178,7 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade
EShLanguage shaderStage = GetLanguage(stage);
glslang::TShader shader(shaderStage);
std::string preprocessed = Preprocess(src, srcLang);
std::string preprocessed = Preprocess(src, srcLang, stage);
shaderStrings[0] = src.c_str();
shader.setStrings(shaderStrings, 1);
@ -146,7 +241,7 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade
options.shader_model = 50;
hlsl.set_options(options);
std::string raw = hlsl.compile();
*dest = Postprocess(raw, destLang);
*dest = Postprocess(raw, destLang, stage);
return true;
}
#endif