This commit is contained in:
Henrik Rydgård 2022-10-24 17:36:54 +02:00
parent f1b515caaf
commit 2bea495981
4 changed files with 61 additions and 6 deletions

View file

@ -94,6 +94,7 @@ struct UniformDef {
struct SamplerDef {
int binding; // Might only be used by some backends.
const char *name;
bool array;
// TODO: Might need unsigned samplers, 3d samplers, or other types in the future.
};

View file

@ -114,6 +114,9 @@ void ShaderWriter::Preamble(Slice<const char *> extensions) {
switch (lang_.shaderLanguage) {
case GLSL_VULKAN:
C("#version 450\n");
if (flags_ & ShaderWriterFlags::FS_AUTO_STEREO) {
C("#extension GL_EXT_multiview : enable\n");
}
// IMPORTANT! Extensions must be the first thing after #version.
for (size_t i = 0; i < extensions.size(); i++) {
F("%s\n", extensions[i]);
@ -462,6 +465,15 @@ void ShaderWriter::DeclareSamplers(Slice<SamplerDef> samplers) {
samplerDefs_ = samplers;
}
const SamplerDef *ShaderWriter::GetSamplerDef(const char *name) const {
for (int i = 0; i < (int)samplers_.size(); i++) {
if (!strcmp(samplers_[i].name, name)) {
return &samplers_[i];
}
}
return nullptr;
}
void ShaderWriter::DeclareTexture2D(const SamplerDef &def) {
switch (lang_.shaderLanguage) {
case HLSL_D3D11:
@ -472,7 +484,11 @@ void ShaderWriter::DeclareTexture2D(const SamplerDef &def) {
break;
case GLSL_VULKAN:
// In the thin3d descriptor set layout, textures start at 1 in set 0. Hence the +1.
F("layout(set = 0, binding = %d) uniform sampler2D %s;\n", def.binding + texBindingBase_, def.name);
if ((flags_ & ShaderWriterFlags::FS_AUTO_STEREO) && def.array) {
F("layout(set = 0, binding = %d) uniform sampler2DArray %s;\n", def.binding + texBindingBase_, def.name);
} else {
F("layout(set = 0, binding = %d) uniform sampler2D %s;\n", def.binding + texBindingBase_, def.name);
}
break;
default:
F("uniform sampler2D %s;\n", def.name);
@ -492,6 +508,7 @@ void ShaderWriter::DeclareSampler2D(const SamplerDef &def) {
}
ShaderWriter &ShaderWriter::SampleTexture2D(const char *sampName, const char *uv) {
const SamplerDef *samp = GetSamplerDef(sampName);
switch (lang_.shaderLanguage) {
case HLSL_D3D11:
F("%s.Sample(%sSamp, %s)", sampName, sampName, uv);
@ -501,13 +518,20 @@ ShaderWriter &ShaderWriter::SampleTexture2D(const char *sampName, const char *uv
break;
default:
// Note: we ignore the sampler. make sure you bound samplers to the textures correctly.
F("%s(%s, %s)", lang_.texture, sampName, uv);
if (samp && samp->array) {
const char *index = (flags_ & ShaderWriterFlags::FS_AUTO_STEREO) ? "float(gl_ViewIndex)" : "0.0";
F("%s(%s, vec3(%s, %s))", lang_.texture, sampName, uv, index);
} else {
F("%s(%s, %s)", lang_.texture, sampName, uv);
}
break;
}
return *this;
}
ShaderWriter &ShaderWriter::SampleTexture2DOffset(const char *sampName, const char *uv, int offX, int offY) {
const SamplerDef *samp = GetSamplerDef(sampName);
switch (lang_.shaderLanguage) {
case HLSL_D3D11:
F("%s.Sample(%sSamp, %s, int2(%d, %d))", sampName, sampName, uv, offX, offY);
@ -518,13 +542,20 @@ ShaderWriter &ShaderWriter::SampleTexture2DOffset(const char *sampName, const ch
break;
default:
// Note: we ignore the sampler. make sure you bound samplers to the textures correctly.
F("%sOffset(%s, %s, ivec2(%d, %d))", lang_.texture, sampName, uv, offX, offY);
if (samp->array) {
const char *index = (flags_ & ShaderWriterFlags::FS_AUTO_STEREO) ? "float(gl_ViewIndex)" : "0.0";
F("%sOffset(%s, vec3(%s, %s), ivec3(%d, %d))", lang_.texture, sampName, uv, index, offX, offY);
} else {
F("%sOffset(%s, %s, ivec2(%d, %d))", lang_.texture, sampName, uv, offX, offY);
}
break;
}
return *this;
}
ShaderWriter &ShaderWriter::LoadTexture2D(const char *sampName, const char *uv, int level) {
const SamplerDef *samp = GetSamplerDef(sampName);
switch (lang_.shaderLanguage) {
case HLSL_D3D11:
F("%s.Load(ivec3(%s, %d))", sampName, uv, level);
@ -535,7 +566,11 @@ ShaderWriter &ShaderWriter::LoadTexture2D(const char *sampName, const char *uv,
break;
default:
// Note: we ignore the sampler. make sure you bound samplers to the textures correctly.
F("texelFetch(%s, %s, %d)", sampName, uv, level);
if ((flags_ & ShaderWriterFlags::FS_AUTO_STEREO) && samp->array) {
F("texelFetch(%s, %s, %d)", sampName, uv, level);
} else {
F("texelFetch(%s, %s, %d)", sampName, uv, level);
}
break;
}
return *this;

View file

@ -33,7 +33,7 @@ struct VaryingDef {
enum class ShaderWriterFlags {
NONE = 0,
FS_WRITE_DEPTH = 1,
FS_AUTO_STEREO = 2,
FS_AUTO_STEREO = 2, // Automatically makes sampler 0 an array sampler, and samples it by gl_ViewIndex. Useful for stereo rendering.
};
ENUM_CLASS_BITOPS(ShaderWriterFlags);
@ -119,9 +119,12 @@ private:
void Preamble(Slice<const char *> extensions);
const SamplerDef *GetSamplerDef(const char *name) const;
char *p_;
const ShaderLanguageDesc &lang_;
const ShaderStage stage_;
Slice<SamplerDef> samplers_;
ShaderWriterFlags flags_ = ShaderWriterFlags::NONE;
Slice<SamplerDef> samplerDefs_;
int texBindingBase_ = 1;

View file

@ -96,6 +96,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
bool doTextureAlpha = id.Bit(FS_BIT_TEXALPHA);
bool arrayTexture = id.Bit(FS_BIT_SAMPLE_ARRAY_TEXTURE);
if (texture3D && arrayTexture) {
*errorString = "Invalid combination of 3D texture and array texture, shouldn't happen";
return false;
}
bool flatBug = bugs.Has(Draw::Bugs::BROKEN_FLAT_IN_SHADER) && g_Config.bVendorBugChecksEnabled;
@ -156,6 +160,9 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
return false;
}
// Currently only used by Vulkan.
std::vector<SamplerDef> samplers;
if (compat.shaderLanguage == ShaderLanguage::GLSL_VULKAN) {
if (useDiscardStencilBugWorkaround && !gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) {
WRITE(p, "layout (depth_unchanged) out float gl_FragDepth;\n");
@ -163,7 +170,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
WRITE(p, "layout (std140, set = 0, binding = 3) uniform baseUBO {\n%s};\n", ub_baseStr);
if (doTexture) {
WRITE(p, "layout (binding = 0) uniform %s%s tex;\n", texture3D ? "sampler3D" : "sampler2D", arrayTexture ? "array" : "");
WRITE(p, "layout (binding = 0) uniform %s%s tex;\n", texture3D ? "sampler3D" : "sampler2D", arrayTexture ? "Array" : "");
}
if (readFramebufferTex) {
@ -639,6 +646,15 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
} else {
WRITE(p, " vec4 t = %s(tex, vec3(%s.xy, u_mipBias));\n", compat.texture3D, texcoord);
}
} else if (arrayTexture) {
// Used for stereo rendering.
if (doTextureProjection) {
if (doTextureProjection) {
WRITE(p, " vec4 t = %sProj(tex, %s);\n", compat.texture, texcoord);
} else {
WRITE(p, " vec4 t = %s(tex, %s.xy);\n", compat.texture, texcoord);
}
}
} else {
if (doTextureProjection) {
WRITE(p, " vec4 t = %sProj(tex, %s);\n", compat.texture, texcoord);