shaderc: Added ARB_shader_texture_lod extension.

This commit is contained in:
Branimir Karadžić 2014-02-09 16:46:50 -08:00
parent cc77e7c743
commit ad335be715
4 changed files with 330 additions and 128 deletions

View file

@ -93,7 +93,7 @@ vec4 bgfxTextureCubeLod(BgfxSamplerCube _sampler, vec3 _coord, float _level)
# else
# define SAMPLER2D(_name, _reg) uniform sampler2D _name : register(s ## _reg)
# define texture2D(_sampler, _coord) tex2D(_sampler, _coord)
# define texture2DLod(_sampler, _coord, _level) tex2Dlod(_sampler, vec3( (_coord).xy, _level) )
# define texture2DLod(_sampler, _coord, _level) tex2Dlod(_sampler, vec4( (_coord).xy, _level, 0.0) )
# define SAMPLER3D(_name, _reg) uniform sampler3D _name : register(s ## _reg)
# define texture3D(_sampler, _coord) tex3D(_sampler, _coord)
# define texture3DLod(_sampler, _coord, _level) tex3Dlod(_sampler, vec4( (_coord).xyz, _level) )

View file

@ -228,6 +228,7 @@ namespace bgfx
ARB_multisample,
ARB_sampler_objects,
ARB_seamless_cube_map,
ARB_shader_texture_lod,
ARB_texture_compression_rgtc,
ARB_texture_float,
ARB_texture_multisample,
@ -248,6 +249,7 @@ namespace bgfx
EXT_framebuffer_blit,
EXT_framebuffer_sRGB,
EXT_occlusion_query_boolean,
EXT_shadow_samplers,
EXT_texture_array,
EXT_texture_compression_dxt1,
EXT_texture_compression_latc,
@ -314,6 +316,7 @@ namespace bgfx
{ "GL_ARB_multisample", false, true },
{ "GL_ARB_sampler_objects", BGFX_CONFIG_RENDERER_OPENGL >= 33, true },
{ "GL_ARB_seamless_cube_map", BGFX_CONFIG_RENDERER_OPENGL >= 32, true },
{ "GL_ARB_shader_texture_lod", BGFX_CONFIG_RENDERER_OPENGL >= 30, true },
{ "GL_ARB_texture_compression_rgtc", BGFX_CONFIG_RENDERER_OPENGL >= 30, true },
{ "GL_ARB_texture_float", BGFX_CONFIG_RENDERER_OPENGL >= 30, true },
{ "GL_ARB_texture_multisample", BGFX_CONFIG_RENDERER_OPENGL >= 32, true },
@ -334,6 +337,7 @@ namespace bgfx
{ "GL_EXT_framebuffer_blit", BGFX_CONFIG_RENDERER_OPENGL >= 30, true },
{ "GL_EXT_framebuffer_sRGB", BGFX_CONFIG_RENDERER_OPENGL >= 30, true },
{ "GL_EXT_occlusion_query_boolean", false, true },
{ "GL_EXT_shadow_samplers", false, true },
{ "GL_EXT_texture_array", BGFX_CONFIG_RENDERER_OPENGL >= 30, true },
{ "GL_EXT_texture_compression_dxt1", false, true },
{ "GL_EXT_texture_compression_latc", false, true },
@ -377,6 +381,46 @@ namespace bgfx
{ "GL_OES_vertex_type_10_10_10_2", false, true },
};
static const char* s_ARB_shader_texture_lod[] =
{
"texture2DLod",
"texture2DProjLod",
"texture3DLod",
"texture3DProjLod",
"textureCubeLod",
"shadow2DLod",
"shadow2DProjLod",
NULL
// "texture1DLod",
// "texture1DProjLod",
// "shadow1DLod",
// "shadow1DProjLod",
};
static const char* s_EXT_shadow_samplers[] =
{
"shadow2D",
"shadow2DProj",
NULL
};
static const char* s_OES_standard_derivatives[] =
{
"dFdx",
"dFdy",
"fwidth",
NULL
};
static const char* s_OES_texture_3D[] =
{
"texture3D",
"texture3DProj",
"texture3DLod",
"texture3DProjLod",
NULL
};
#if BGFX_CONFIG_RENDERER_OPENGLES3
# define s_vertexAttribDivisor glVertexAttribDivisor
# define s_drawArraysInstanced glDrawArraysInstanced
@ -1786,33 +1830,6 @@ namespace bgfx
bx::write(_writer, _str, (int32_t)strlen(_str) );
}
const char* findMatch(const char* _str, const char* _word)
{
size_t len = strlen(_word);
const char* ptr = strstr(_str, _word);
for (; NULL != ptr; ptr = strstr(ptr + len, _word) )
{
if (ptr != _str)
{
char ch = *(ptr - 1);
if (isalnum(ch) || '_' == ch)
{
continue;
}
}
char ch = ptr[len];
if (isalnum(ch) || '_' == ch)
{
continue;
}
return ptr;
}
return ptr;
}
void strins(char* _str, const char* _insert)
{
size_t len = strlen(_insert);
@ -1838,111 +1855,146 @@ namespace bgfx
if (0 != m_id)
{
#if BGFX_CONFIG_RENDERER_OPENGLES2
bool usesDerivatives = s_extension[Extension::OES_standard_derivatives].m_supported &&
( findMatch(code, "dFdx")
|| findMatch(code, "dFdy")
|| findMatch(code, "fwidth")
);
if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES2) )
{
bool usesDerivatives = s_extension[Extension::OES_standard_derivatives].m_supported
&& bx::findIdentifierMatch(code, s_OES_standard_derivatives)
;
bool usesFragDepth = !!findMatch(code, "gl_FragDepth");
bool usesFragDepth = !!bx::findIdentifierMatch(code, "gl_FragDepth");
bool usesTexture3D = s_extension[Extension::OES_texture_3D].m_supported &&
( findMatch(code, "texture3D")
|| findMatch(code, "texture3DProj")
|| findMatch(code, "texture3DLod")
|| findMatch(code, "texture3DProjLod")
);
bool usesShadowSamplers = s_extension[Extension::EXT_shadow_samplers].m_supported
&& bx::findIdentifierMatch(code, s_EXT_shadow_samplers)
;
if (usesDerivatives
|| usesFragDepth
|| usesTexture3D)
bool usesTexture3D = s_extension[Extension::OES_texture_3D].m_supported
&& bx::findIdentifierMatch(code, s_OES_texture_3D)
;
if (usesDerivatives
|| usesFragDepth
|| usesShadowSamplers
|| usesTexture3D)
{
int32_t codeLen = (int32_t)strlen(code);
int32_t tempLen = codeLen + 1024;
char* temp = (char*)alloca(tempLen);
bx::StaticMemoryBlockWriter writer(temp, tempLen);
if (usesDerivatives)
{
writeString(&writer, "#extension GL_OES_standard_derivatives : enable\n");
}
bool insertFragDepth = false;
if (usesFragDepth)
{
if (s_extension[Extension::EXT_frag_depth].m_supported)
{
writeString(&writer
, "#extension GL_EXT_frag_depth : enable\n"
"#define gl_FragDepth gl_FragDepthEXT\n"
);
char str[128];
bx::snprintf(str, BX_COUNTOF(str), "%s float gl_FragDepthEXT;\n"
, s_extension[Extension::OES_fragment_precision_high].m_supported ? "highp" : "mediump"
);
writeString(&writer, str);
}
else
{
insertFragDepth = true;
}
}
if (usesShadowSamplers)
{
writeString(&writer, "#extension GL_EXT_shadow_samplers : enable\n");
}
if (usesTexture3D)
{
writeString(&writer, "#extension GL_OES_texture_3D : enable\n");
}
bx::write(&writer, code, codeLen);
bx::write(&writer, '\0');
code = temp;
if (insertFragDepth)
{
char* entry = strstr(temp, "void main ()");
if (NULL != entry)
{
char* brace = strstr(entry, "{");
if (NULL != brace)
{
const char* end = bx::strmb(brace, '{', '}');
if (NULL != end)
{
strins(brace+1, "\n float gl_FragDepth = 0.0;\n");
}
}
}
}
}
}
else if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL == 21) )
{
bool usesTextureLod = s_extension[Extension::ARB_shader_texture_lod].m_supported
&& bx::findIdentifierMatch(code, s_ARB_shader_texture_lod)
;
if (usesTextureLod)
{
int32_t codeLen = (int32_t)strlen(code);
int32_t tempLen = codeLen + 1024;
char* temp = (char*)alloca(tempLen);
bx::StaticMemoryBlockWriter writer(temp, tempLen);
writeString(&writer, "#version 120\n");
if (_type == GL_FRAGMENT_SHADER)
{
writeString(&writer, "#extension GL_ARB_shader_texture_lod : enable\n");
}
bx::write(&writer, code, codeLen);
bx::write(&writer, '\0');
code = temp;
}
}
else if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL >= 31) )
{
int32_t codeLen = (int32_t)strlen(code);
int32_t tempLen = codeLen + 1024;
char* temp = (char*)alloca(tempLen);
bx::StaticMemoryBlockWriter writer(temp, tempLen);
if (usesDerivatives)
writeString(&writer, "#version 140\n");
if (_type == GL_FRAGMENT_SHADER)
{
writeString(&writer, "#extension GL_OES_standard_derivatives : enable\n");
writeString(&writer, "#define varying in\n");
writeString(&writer, "#define texture2D texture\n");
writeString(&writer, "#define texture2DLod textureLod\n");
writeString(&writer, "#define texture3D texture\n");
writeString(&writer, "#define texture3DLod textureLod\n");
writeString(&writer, "#define textureCube texture\n");
writeString(&writer, "#define textureCubeLod textureLod\n");
writeString(&writer, "out vec4 bgfx_FragColor;\n");
writeString(&writer, "#define gl_FragColor bgfx_FragColor\n");
}
bool insertFragDepth = false;
if (usesFragDepth)
else
{
if (s_extension[Extension::EXT_frag_depth].m_supported)
{
writeString(&writer
, "#extension GL_EXT_frag_depth : enable\n"
"#define gl_FragDepth gl_FragDepthEXT\n"
);
char str[128];
bx::snprintf(str, BX_COUNTOF(str), "%s float gl_FragDepthEXT;\n"
, s_extension[Extension::OES_fragment_precision_high].m_supported ? "highp" : "mediump"
);
writeString(&writer, str);
}
else
{
insertFragDepth = true;
}
}
if (usesTexture3D)
{
writeString(&writer, "#extension GL_OES_texture_3D : enable\n");
writeString(&writer, "#define attribute in\n");
writeString(&writer, "#define varying out\n");
}
bx::write(&writer, code, codeLen);
bx::write(&writer, '\0');
code = temp;
if (insertFragDepth)
{
char* entry = strstr(temp, "void main ()");
if (NULL != entry)
{
char* brace = strstr(entry, "{");
if (NULL != brace)
{
const char* end = bx::strmb(brace, '{', '}');
if (NULL != end)
{
strins(brace+1, "\n float gl_FragDepth = 0.0;\n");
}
}
}
}
}
#elif BGFX_CONFIG_RENDERER_OPENGL >= 31
int32_t codeLen = (int32_t)strlen(code);
int32_t tempLen = codeLen + 1024;
char* temp = (char*)alloca(tempLen);
bx::StaticMemoryBlockWriter writer(temp, tempLen);
writeString(&writer, "#version 140\n");
if (_type == GL_FRAGMENT_SHADER)
{
writeString(&writer, "#define varying in\n");
writeString(&writer, "#define texture2D texture\n");
writeString(&writer, "#define texture3D texture\n");
writeString(&writer, "#define textureCube texture\n");
writeString(&writer, "out vec4 bgfx_FragColor;\n");
writeString(&writer, "#define gl_FragColor bgfx_FragColor\n");
}
else
{
writeString(&writer, "#define attribute in\n");
writeString(&writer, "#define varying out\n");
}
bx::write(&writer, code, codeLen);
bx::write(&writer, '\0');
code = temp;
#endif // BGFX_CONFIG_RENDERER_OPENGLES2
GL_CHECK(glShaderSource(m_id, 1, (const GLchar**)&code, NULL) );
GL_CHECK(glCompileShader(m_id) );

Binary file not shown.

View file

@ -7,8 +7,32 @@
# define SHADERC_DEBUG 0
#endif // SHADERC_DEBUG
#define _BX_TRACE(_format, ...) \
do { \
fprintf(stderr, BX_FILE_LINE_LITERAL "" _format "\n", ##__VA_ARGS__); \
} while(0)
#define _BX_WARN(_condition, _format, ...) \
do { \
if (!(_condition) ) \
{ \
BX_TRACE("WARN " _format, ##__VA_ARGS__); \
} \
} while(0)
#define _BX_CHECK(_condition, _format, ...) \
do { \
if (!(_condition) ) \
{ \
BX_TRACE("CHECK " _format, ##__VA_ARGS__); \
bx::debugBreak(); \
} \
} while(0)
#if SHADERC_DEBUG
# define BX_TRACE(_format, ...) fprintf(stderr, "" _format "\n", ##__VA_ARGS__)
# define BX_TRACE _BX_TRACE
# define BX_WARN _BX_WARN
# define BX_CHECK _BX_CHECK
#endif // DEBUG
#include <bx/bx.h>
@ -83,6 +107,46 @@ struct Attrib
};
};
static const char* s_ARB_shader_texture_lod[] =
{
"texture2DLod",
"texture2DProjLod",
"texture3DLod",
"texture3DProjLod",
"textureCubeLod",
"shadow2DLod",
"shadow2DProjLod",
NULL
// "texture1DLod",
// "texture1DProjLod",
// "shadow1DLod",
// "shadow1DProjLod",
};
static const char* s_EXT_shadow_samplers[] =
{
"shadow2D",
"shadow2DProj",
NULL
};
static const char* s_OES_standard_derivatives[] =
{
"dFdx",
"dFdy",
"fwidth",
NULL
};
static const char* s_OES_texture_3D[] =
{
"texture3D",
"texture3DProj",
"texture3DLod",
"texture3DProjLod",
NULL
};
struct RemapInputSemantic
{
Attrib::Enum m_attr;
@ -445,9 +509,19 @@ void strins(char* _str, const char* _insert)
void strreplace(char* _str, const char* _find, const char* _replace)
{
const size_t len = strlen(_find);
char* replace = (char*)alloca(len+1);
bx::strlcpy(replace, _replace, len+1);
for (uint32_t ii = strlen(replace); ii < len; ++ii)
{
replace[ii] = ' ';
}
replace[len] = '\0';
BX_CHECK(len >= strlen(_replace), "");
for (char* ptr = strstr(_str, _find); NULL != ptr; ptr = strstr(ptr + len, _find) )
{
memcpy(ptr, _replace, len);
memcpy(ptr, replace, len);
}
}
@ -520,7 +594,7 @@ void writeFile(const char* _filePath, const void* _data, int32_t _size)
}
}
bool compileGLSLShader(bx::CommandLine& _cmdLine, const std::string& _code, bx::WriterI* _writer)
bool compileGLSLShader(bx::CommandLine& _cmdLine, uint32_t _gles, const std::string& _code, bx::WriterI* _writer)
{
const glslopt_shader_type type = tolower(_cmdLine.findOption('\0', "type")[0]) == 'f' ? kGlslOptShaderFragment : kGlslOptShaderVertex;
@ -529,7 +603,7 @@ bool compileGLSLShader(bx::CommandLine& _cmdLine, const std::string& _code, bx::
glslopt_ctx* ctx = glslopt_initialize(gles);
glslopt_shader* shader = glslopt_optimize(ctx, type, _code.c_str(), kGlslOptionSkipPreprocessor);
glslopt_shader* shader = glslopt_optimize(ctx, type, _code.c_str(), 0);
if (!glslopt_get_status(shader) )
{
@ -540,7 +614,8 @@ bool compileGLSLShader(bx::CommandLine& _cmdLine, const std::string& _code, bx::
int32_t start = 0;
int32_t end = INT32_MAX;
if (3 == sscanf(log, "%u:%u(%u):", &source, &line, &column) )
if (3 == sscanf(log, "%u:%u(%u):", &source, &line, &column)
&& 0 != line)
{
start = bx::uint32_imax(1, line-10);
end = start + 20;
@ -554,11 +629,26 @@ bool compileGLSLShader(bx::CommandLine& _cmdLine, const std::string& _code, bx::
const char* optimizedShader = glslopt_get_output(shader);
const char* version = strstr(optimizedShader, "#version");
if (NULL != version)
// Trim all directives.
while ('#' == *optimizedShader)
{
// trim version line...
optimizedShader = bx::strnl(version);
optimizedShader = bx::strnl(optimizedShader);
}
if (0 != _gles)
{
char* shader = const_cast<char*>(optimizedShader);
strreplace(shader, "gl_FragDepthEXT", "gl_FragDepth");
strreplace(shader, "texture2DLodEXT", "texture2DLod");
strreplace(shader, "texture2DProjLodEXT", "texture2DProjLod");
strreplace(shader, "textureCubeLodEXT", "textureCubeLod");
strreplace(shader, "texture2DGradEXT", "texture2DGrad");
strreplace(shader, "texture2DProjGradEXT", "texture2DProjGrad");
strreplace(shader, "textureCubeGradEXT", "textureCubeGrad");
strreplace(shader, "shadow2DEXT", "shadow2D");
strreplace(shader, "shadow2DProjEXT", "shadow2DProj");
}
bx::write(_writer, optimizedShader, (int32_t)strlen(optimizedShader) );
@ -658,7 +748,8 @@ bool compileHLSLShaderDx9(bx::CommandLine& _cmdLine, const std::string& _code, b
int32_t start = 0;
int32_t end = INT32_MAX;
if (3 == sscanf(log, "%[^(](%u,%u):", source, &line, &column) )
if (3 == sscanf(log, "%[^(](%u,%u):", source, &line, &column)
&& 0 != line)
{
start = bx::uint32_imax(1, line-10);
end = start + 20;
@ -678,7 +769,7 @@ bool compileHLSLShaderDx9(bx::CommandLine& _cmdLine, const std::string& _code, b
return false;
}
BX_TRACE("Creator: %s 0x%08x", desc.Creator, desc.Version);
BX_TRACE("Creator: %s 0x%08x", desc.Creator, (uint32_t /*mingw warning*/)desc.Version);
BX_TRACE("Num constants: %d", desc.Constants);
BX_TRACE("# cl ty RxC S By Name");
@ -868,7 +959,8 @@ bool compileHLSLShaderDx11(bx::CommandLine& _cmdLine, const std::string& _code,
int32_t start = 0;
int32_t end = INT32_MAX;
if (2 == sscanf(log, "(%u,%u):", &line, &column) )
if (2 == sscanf(log, "(%u,%u):", &line, &column)
&& 0 != line)
{
start = bx::uint32_imax(1, line-10);
end = start + 20;
@ -2016,12 +2108,70 @@ int main(int _argc, const char* _argv[])
if (glsl)
{
std::string code;
bool hasTextureLod = NULL != bx::findIdentifierMatch(data, s_ARB_shader_texture_lod /*EXT_shader_texture_lod*/);
if (0 == gles)
{
bx::stringPrintf(code, "#version %s\n", profile);
int32_t version = atoi(profile);
if (hasTextureLod
&& 130 > version)
{
bx::stringPrintf(code
, "#extension GL_ARB_shader_texture_lod : enable\n"
);
}
}
else
{
// Pretend that all extensions are available.
// This will be stripped later.
if (hasTextureLod)
{
bx::stringPrintf(code
, "#extension GL_EXT_shader_texture_lod : enable\n"
"#define texture2DLod texture2DLodEXT\n"
"#define texture2DProjLod texture2DProjLodEXT\n"
"#define textureCubeLod textureCubeLodEXT\n"
// "#define texture2DGrad texture2DGradEXT\n"
// "#define texture2DProjGrad texture2DProjGradEXT\n"
// "#define textureCubeGrad textureCubeGradEXT\n"
);
}
if (NULL != bx::findIdentifierMatch(data, s_OES_standard_derivatives) )
{
bx::stringPrintf(code, "#extension GL_OES_standard_derivatives : enable\n");
}
if (NULL != bx::findIdentifierMatch(data, s_OES_texture_3D) )
{
bx::stringPrintf(code, "#extension GL_OES_texture_3D : enable\n");
}
if (NULL != bx::findIdentifierMatch(data, s_EXT_shadow_samplers) )
{
bx::stringPrintf(code
, "#extension GL_EXT_shadow_samplers : enable\n"
"#define shadow2D shadow2DEXT\n"
"#define shadow2DProj shadow2DProjEXT\n"
);
}
if (NULL != bx::findIdentifierMatch(data, "gl_FragDepth") )
{
bx::stringPrintf(code
, "#extension GL_EXT_frag_depth : enable\n"
"#define gl_FragDepth gl_FragDepthEXT\n"
);
}
bx::stringPrintf(code, "precision highp float;\n");
}
code += preprocessor.m_preprocessed;
compiled = compileGLSLShader(cmdLine, code, writer);
compiled = compileGLSLShader(cmdLine, gles, code, writer);
}
else
{