diff --git a/src/bgfx_shader.sh b/src/bgfx_shader.sh index 8328117f..6ab080be 100644 --- a/src/bgfx_shader.sh +++ b/src/bgfx_shader.sh @@ -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) ) diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 7603d30f..7c127a85 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -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) ); diff --git a/tools/bin/windows/shaderc.exe b/tools/bin/windows/shaderc.exe index 0de73560..4aec1f94 100644 Binary files a/tools/bin/windows/shaderc.exe and b/tools/bin/windows/shaderc.exe differ diff --git a/tools/shaderc/shaderc.cpp b/tools/shaderc/shaderc.cpp index f261c0da..489def74 100644 --- a/tools/shaderc/shaderc.cpp +++ b/tools/shaderc/shaderc.cpp @@ -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 @@ -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(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 {