diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index 97597d35c..1d959ceb3 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -15,13 +15,13 @@ jobs: steps: - name: Clone Platform - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Update Submodules run: git submodule update --init --force - name: Install Vulkan SDK - uses: humbletim/install-vulkan-sdk@v1.1.1 + uses: humbletim/install-vulkan-sdk@v1.2 with: version: 1.3.296.0 cache: true diff --git a/Applications/Sfx/CMakeLists.txt b/Applications/Sfx/CMakeLists.txt index 6f61da34d..2da6411f7 100644 --- a/Applications/Sfx/CMakeLists.txt +++ b/Applications/Sfx/CMakeLists.txt @@ -55,7 +55,4 @@ if(PLATFORM_WINDOWS OR PLATFORM_LINUX) VS_DEBUGGER_COMMAND_ARGUMENTS "${SFX_TEST_FILE} -I\"${CMAKE_SOURCE_DIR}/..\" -I\"${SIMUL_PLATFORM_DIR}/CrossPlatform/Shaders\" -o\"${CMAKE_BINARY_DIR}/Platform/shaderbin/$PLATFORM_NAME\" ${TEST_CONFIGS} -l -v ${SFX_TEST_DEFINES}" ) endif() - if(PLATFORM_LINUX) - target_link_libraries(Sfx c++) - endif() endif() diff --git a/Applications/Sfx/Compiler.cpp b/Applications/Sfx/Compiler.cpp index 353cdfa35..13476c8f4 100644 --- a/Applications/Sfx/Compiler.cpp +++ b/Applications/Sfx/Compiler.cpp @@ -440,6 +440,8 @@ void ReplaceRegexes(string &src, const std::map &replace) } static std::map useCompilerPath; +static bool checkedCompilerPath=false; + extern void CalcCompilerPathToUse(const SfxConfig &sfxConfig,const SfxOptions &sfxOptions) { std::string usePath=""; @@ -657,7 +659,7 @@ bool RewriteOutput(const SfxConfig &sfxConfig (*log)<< str.c_str(); return has_errors; } - +#pragma optimize("",off) bool IsShaderUnchanged(std::string sourceFilename,std::string outputFilename,const std::string &src) { if(!std::filesystem::exists(outputFilename)) @@ -676,7 +678,6 @@ bool IsShaderUnchanged(std::string sourceFilename,std::string outputFilename,con return true; } - int Compile(std::shared_ptr shaderInstance ,const string &sourceFile ,string targetFile @@ -869,7 +870,7 @@ int Compile(std::shared_ptr shaderInstance string src = preamble; src += sharedSource; src+=shaderInstance->m_augmentedSource; - ReplaceRegexes(src, sfxConfig.replace); + const char *strSrc=src.c_str(); wstring targetDir=StringToWString(GetDirectoryFromFilename(targetFile)); @@ -893,8 +894,8 @@ int Compile(std::shared_ptr shaderInstance #else ofstream ofs(WStringToUtf8(generatedSourceFilename).c_str()); #endif - ofs.write(strSrc, strlen(strSrc)); - ofs.close(); + ofs.write(strSrc, strlen(strSrc)); + ofs.close(); } #ifdef _MSC_VER // Now delete the corresponding sdb's @@ -933,52 +934,52 @@ int Compile(std::shared_ptr shaderInstance if(!unchanged) { compile_command=BuildCompileCommand - ( - shaderInstance, - sfxConfig, - sfxOptions, - targetDir, - outputFile, + ( + shaderInstance, + sfxConfig, + sfxOptions, + targetDir, + outputFile, generatedSourceFilename, - t, - pixelOutputFormat - ); - // If no compiler provided, we can return now (perhaps we are only interested in - // the shader source) - if (compile_command.empty()) - { - if(sfxOptions.verbose) + t, + pixelOutputFormat + ); + // If no compiler provided, we can return now (perhaps we are only interested in + // the shader source) + if (compile_command.empty()) + { + if(sfxOptions.verbose) std::cout< shaderInstance { if (terminate_command) exit(2000); - Sleep(10); + sleep(10); } if(!if_c.good()) { diff --git a/Applications/Sfx/Compiler.h b/Applications/Sfx/Compiler.h index 663e86024..55e949df1 100644 --- a/Applications/Sfx/Compiler.h +++ b/Applications/Sfx/Compiler.h @@ -1,10 +1,12 @@ #pragma once #include #include +#include #include "SfxClasses.h" #include "SfxEffect.h" #include "ShaderInstance.h" +extern void ReplaceRegexes(std::string &src, const std::map &replace); extern int Compile(std::shared_ptr shader, const std::string &sourceFile, std::string targetFile , sfx::ShaderType t , sfx::PixelOutputFormat pixelOutputFormat diff --git a/Applications/Sfx/Environ.h b/Applications/Sfx/Environ.h index aad36083a..50609101c 100644 --- a/Applications/Sfx/Environ.h +++ b/Applications/Sfx/Environ.h @@ -42,9 +42,7 @@ static void SetEnv(const std::string &name_utf8, const std::string &value_utf8) errno_t err = _wputenv_s( wname.c_str(),wval.c_str()); #else - char txt[1000]; - sprintf(txt,"%s=%s",name_utf8.c_str(),value_utf8.c_str()); - putenv(txt); + setenv(name_utf8.c_str(),value_utf8.c_str(),1); #endif } @@ -53,7 +51,6 @@ static void SetEnv(const std::string &name_utf8, const std::string &value_utf8) static std::string ProcessEnvironmentVariables(const std::string &str) { std::string ret=str; -#if defined(WIN32)|| defined(WIN64) std::regex re("\\$([A-Z|a-z|0-9|_]+)"); std::sregex_iterator next(str.begin(), str.end(), re); std::sregex_iterator end; @@ -71,6 +68,5 @@ static std::string ProcessEnvironmentVariables(const std::string &str) // Syntax error in the regular expression } } -#endif return ret; } \ No newline at end of file diff --git a/Applications/Sfx/FileLoader.cpp b/Applications/Sfx/FileLoader.cpp index cf47fec40..1ce7bc52a 100644 --- a/Applications/Sfx/FileLoader.cpp +++ b/Applications/Sfx/FileLoader.cpp @@ -197,7 +197,7 @@ void FileLoader::AcquireFileContents(void*& pointer, unsigned int& bytes, const fclose(fp); } -uint64_t FileLoader::GetFileDate(const char *filename_utf8) +uint64_t FileLoader::GetFileDateUnixTimeMs(const char *filename_utf8) { std::wstring filenamew=StringToWString(filename_utf8); #ifdef _MSC_VER @@ -208,7 +208,7 @@ uint64_t FileLoader::GetFileDate(const char *filename_utf8) stat(filename_utf8, &buf); #endif buf.st_mtime; - time_t t = buf.st_mtime; + time_t t = buf.st_mtime*1000; return static_cast(t); } diff --git a/Applications/Sfx/FileLoader.h b/Applications/Sfx/FileLoader.h index e22de1208..accfadbbe 100644 --- a/Applications/Sfx/FileLoader.h +++ b/Applications/Sfx/FileLoader.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #ifndef _MAX_PATH #define _MAX_PATH 260 #endif @@ -16,7 +17,7 @@ class FileLoader bool FileExists(const char *filename_utf8) const; const char *FindFileInPathStack(const char *filename_utf8,const std::vector &path_stack_utf8) const; void AcquireFileContents(void*& pointer, unsigned int& bytes, const char* filename_utf8,bool open_as_text); - static uint64_t GetFileDate(const char* filename_utf8); + static uint64_t GetFileDateUnixTimeMs(const char* filename_utf8); void ReleaseFileContents(void* pointer); void Save(void* pointer, unsigned int bytes, const char* filename_utf8,bool save_as_text); }; diff --git a/Applications/Sfx/Main.cpp b/Applications/Sfx/Main.cpp index e2d394f28..9f2ed0fbd 100644 --- a/Applications/Sfx/Main.cpp +++ b/Applications/Sfx/Main.cpp @@ -1,7 +1,3 @@ - -/* Parts of this program are Copyright (c) 2011, Max Aizenshtein -*/ - #include #include #include // for setw @@ -50,6 +46,7 @@ const SfxOptions &GetSfxOptions() return sfxOptions; } extern bool terminate_command; +#ifdef _MSC_VER // A ctrl message handler to detect "close" events. BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { @@ -86,13 +83,14 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) return FALSE; } } +#endif std::string templateOutputFile; int main(int argc, char** argv) { + #ifdef _MSC_VER if (SetConsoleCtrlHandler(CtrlHandler, TRUE)) { } - #ifdef _MSC_VER SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX | SEM_NOALIGNMENTFAULTEXCEPT); _set_abort_behavior(0, _WRITE_ABORT_MSG); #endif @@ -127,6 +125,8 @@ int main(int argc, char** argv) int a=0; for(int i=1;i=2&&(argv[i][0]=='-')) { const char *arg=argv[i]+2; @@ -241,6 +241,7 @@ int main(int argc, char** argv) } std::cout << std::setw(4)<< "info: building "< #include #include +#include enum Test { IS_DEFINED,NOT_DEFINED,ZERO,NONZERO,EQUALS,NOTEQUAL,GREATER,LESS,GREATER_EQUAL,LESS_EQUAL diff --git a/Applications/Sfx/Sfx.cpp b/Applications/Sfx/Sfx.cpp index ddb44d153..6dc6c8e78 100644 --- a/Applications/Sfx/Sfx.cpp +++ b/Applications/Sfx/Sfx.cpp @@ -59,6 +59,7 @@ typedef int errno_t; #include "SfxClasses.h" #include "Sfx.h" #include "SfxEffect.h" +#include "Compiler.h" #ifdef _MSC_VER #define YY_NO_UNISTD_H @@ -106,7 +107,7 @@ FILE* OpenFile(const char *filename_utf8,std::string &fullPathNameUtf8,uint64_t if(last_slash>0) path=path.substr(0,last_slash); shaderPathsUtf8.push_back(path); - datetime=FileLoader::GetFileDate(fullPathNameUtf8.c_str()); + datetime=FileLoader::GetFileDateUnixTimeMs(fullPathNameUtf8.c_str()); return f; } @@ -513,6 +514,13 @@ std::string GetExecutableDirectory() } else str=L""; +#else + char pBuf[512]; + size_t len = sizeof(pBuf); + int bytes = std::min((int)readlink("/proc/self/exe", pBuf, len), (int)len - 1); + if(bytes >= 0) + pBuf[bytes] = '\0'; + return std::string(pBuf); #endif return WStringToUtf8(str); } @@ -602,13 +610,13 @@ bool sfxParseEffectFromFile(int effect, const char *file, const std::vectorplatformFilename.c_str()); + uint64_t exe_datetime=FileLoader::GetFileDateUnixTimeMs(exeNameUtf8); + uint64_t platformfile_datetime=FileLoader::GetFileDateUnixTimeMs(config->platformFilename.c_str()); latest_datetime= std::max(exe_datetime,platformfile_datetime); latest_file=file; if (!preprocess(file, config->define, sfxOptions->disableLineWrites)) return false; - uint64_t output_filedatetime = FileLoader::GetFileDate(sfxoFilename.c_str()); + uint64_t output_filedatetime = FileLoader::GetFileDateUnixTimeMs(sfxoFilename.c_str()); bool recompile=false; if(sfxOptions->force) { @@ -646,9 +654,6 @@ bool sfxParseEffectFromFile(int effect, const char *file, const std::vectorverbose) { char buffer[_MAX_PATH]; - string wd=""; - if(_getcwd(buffer,_MAX_PATH)) - wd=string(buffer)+"/"; mkpath(sfxOptions->intermediateDirectory); ppfile=((string(sfxOptions->intermediateDirectory)+"/")+GetFilenameOnly(file))+"_pp"; ofstream pps(ppfile); diff --git a/Applications/Sfx/Sfx.ypp b/Applications/Sfx/Sfx.ypp index 9f67c28ae..9bf7844d5 100644 --- a/Applications/Sfx/Sfx.ypp +++ b/Applications/Sfx/Sfx.ypp @@ -1094,7 +1094,7 @@ primary_exp : IDENTIFIER { buildFunction.declarations.insert(varName); buildFunction.declareResource(varName); - if (cb=gEffect->GetNamedConstantBufferForMember(varName)) + if (cb=gEffect->GetNamedConstantBufferForMember(varName);cb) buildFunction.declareConstantBuffer(cb); } else if ((cb = gEffect->GetConstantBufferForMember(varName)) != nullptr) diff --git a/Applications/Sfx/SfxEffect.cpp b/Applications/Sfx/SfxEffect.cpp index 5b8a8de14..be5d19b55 100644 --- a/Applications/Sfx/SfxEffect.cpp +++ b/Applications/Sfx/SfxEffect.cpp @@ -1,14 +1,13 @@ -#include -#include -#include -#include -#include #include +#include +#include +#include #include -#include -#include #include -#include +#include +#include +#include +#include #ifndef _MSC_VER typedef int errno_t; @@ -18,39 +17,38 @@ typedef int errno_t; #include "Sfx.h" #include "SfxClasses.h" -#include "Sfx.h" #include "SfxEffect.h" #ifdef _MSC_VER #define YY_NO_UNISTD_H #endif +#include "Compiler.h" #include "GeneratedFiles/SfxScanner.h" +#include "SfxErrorCheck.h" #include "SfxProgram.h" #include "StringFunctions.h" -#include "Compiler.h" -#include "SfxErrorCheck.h" using namespace std; extern bool IsRW(ShaderResourceType); -void process_member_decl(string &str,string &memberDeclaration) +void process_member_decl(string &str, string &memberDeclaration) { // in square brackets [] is the definition for ONE member. std::regex re_member("\\[(.*)\\]"); std::smatch match; - if(std::regex_search(str,match,re_member)) + if (std::regex_search(str, match, re_member)) { - memberDeclaration=match[1].str(); - str.replace(match[0].first,match[0].first+match[0].length(),"{members}"); + memberDeclaration = match[1].str(); + str.replace(match[0].first, match[0].first + match[0].length(), "{members}"); } } -bool ShaderInstanceHasSemantic(std::shared_ptr shaderInstance, const char* semantic) +bool ShaderInstanceHasSemantic(std::shared_ptr shaderInstance, const char *semantic) { bool found = false; - Function* function = gEffect->GetFunction(shaderInstance->m_functionName, 0); - const std::map& declarations = gEffect->GetDeclarations(); - for (const auto& parameter : function->parameters) + Function *function = gEffect->GetFunction(shaderInstance->m_functionName, 0); + const std::map &declarations = gEffect->GetDeclarations(); + for (const auto ¶meter : function->parameters) { if (!parameter.semantic.empty()) { @@ -58,17 +56,16 @@ bool ShaderInstanceHasSemantic(std::shared_ptr shaderInstance, c } else if (declarations.find(parameter.type) != declarations.end()) { - Declaration* declaration = declarations.at(parameter.type); + Declaration *declaration = declarations.at(parameter.type); if (declaration->declarationType == DeclarationType::STRUCT) { - Struct* structure = reinterpret_cast(declaration); - for (const auto& member : structure->m_structMembers) + Struct *structure = reinterpret_cast(declaration); + for (const auto &member : structure->m_structMembers) { found |= member.semantic.compare(semantic) == 0; } } } - } return found; } @@ -110,52 +107,47 @@ bool CheckVariantCondition(const StructMember &m, std::string value) } Effect::Effect() - : m_includes(0) - , m_active(true) - , last_filenumber(0) - , current_texture_number(0) - , current_rw_texture_number(0) - , m_max_sampler_register_number(0) + : m_includes(0), m_active(true), last_filenumber(0), current_texture_number(0), current_rw_texture_number(0), m_max_sampler_register_number(0) { } Effect::~Effect() { - for(map::iterator it=m_programs.begin(); it!=m_programs.end(); ++it) + for (map::iterator it = m_programs.begin(); it != m_programs.end(); ++it) delete it->second; - for(auto i:m_declaredFunctions) + for (auto i : m_declaredFunctions) { - for(auto j:i.second) + for (auto j : i.second) delete j; } } -Function* Effect::DeclareFunction(const std::string &functionName, Function &buildFunction) +Function *Effect::DeclareFunction(const std::string &functionName, Function &buildFunction) { - Function* f = new Function; - *f = buildFunction; + Function *f = new Function; + *f = buildFunction; if (sfxConfig.combineTexturesSamplers) { // Remove texture templates: - for (auto& p : f->parameters) + for (auto &p : f->parameters) { if (!p.templ.empty() && (p.shaderResourceType & ShaderResourceType::TEXTURE) == ShaderResourceType::TEXTURE) { - find_and_replace(f->declaration, p.type+ "<" + p.templ + ">", CombinedTypeString(p.type, p.templ)); + find_and_replace(f->declaration, p.type + "<" + p.templ + ">", CombinedTypeString(p.type, p.templ)); } } // Checks if (!sfxConfig.combineInShader) { // If its not global (it's a param) add array: - for (auto& p : f->parameters) + for (auto &p : f->parameters) { if ((p.shaderResourceType & ShaderResourceType::TEXTURE) == ShaderResourceType::TEXTURE) { bool found = false; - for (auto& g : f->globals) + for (auto &g : f->globals) { if (g.first == p.identifier) { @@ -169,27 +161,32 @@ Function* Effect::DeclareFunction(const std::string &functionName, Function &bui find_and_replace(f->declaration, p.identifier, p.identifier + "[24]"); } } - } - find_and_replace(f->declaration, "Texture2D ", "uint64_t "); - find_and_replace(f->declaration, "Texture2DArray ", "uint64_t "); - find_and_replace(f->declaration, "Texture3D ", "uint64_t "); - find_and_replace(f->declaration, "Texture3D ", "uint64_t "); - find_and_replace(f->declaration, "TextureCube ", "uint64_t "); - find_and_replace(f->declaration, "TextureCubeArray ", "uint64_t "); - find_and_replace(f->declaration, "Texture2DMS ", "uint64_t "); + } + find_and_replace(f->declaration, "Texture2D ", "uint64_t "); + find_and_replace(f->declaration, "Texture2DArray ", "uint64_t "); + find_and_replace(f->declaration, "Texture3D ", "uint64_t "); + find_and_replace(f->declaration, "Texture3D ", "uint64_t "); + find_and_replace(f->declaration, "TextureCube ", "uint64_t "); + find_and_replace(f->declaration, "TextureCubeArray ", "uint64_t "); + find_and_replace(f->declaration, "Texture2DMS ", "uint64_t "); } } - + ReplaceRegexes(f->declaration, sfxConfig.replace); + ReplaceRegexes(f->content, sfxConfig.replace); + for (int i = 0; i < f->parameters.size(); i++) + { + ReplaceRegexes(f->parameters[i].type, sfxConfig.replace); + } m_declaredFunctions[functionName].push_back(f); return f; } -int SetsClash(const std::set &a,const std::set &b) +int SetsClash(const std::set &a, const std::set &b) { - for(auto A:a) + for (auto A : a) { - for(auto B:b) + for (auto B : b) { - if(A==B) + if (A == B) return A; } } @@ -197,67 +194,66 @@ int SetsClash(const std::set &a,const std::set &b) } void Effect::DeclareResourceGroup(int num, const ResourceGroupDeclaration &g) { - int bad=0; - for(auto &rg:resourceGroups) + int bad = 0; + for (auto &rg : resourceGroups) { - if(rg.first==num) + if (rg.first == num) { - std::cerr << "Redeclaring resource group "<=0) + int t = SetsClash(rg.second.textures, g.textures); + if (t >= 0) { std::cerr << "Texture slot " << t << " declared in two resource groups.\n"; - bad=376; + bad = 376; } int c = SetsClash(rg.second.constantBuffers, g.constantBuffers); - if (c>= 0) + if (c >= 0) { std::cerr << "Constant Buffer slot " << c << " declared in two resource groups.\n"; - bad=377; + bad = 377; } int s = SetsClash(rg.second.structuredBuffers, g.structuredBuffers); if (s >= 0) { std::cerr << "Structured Buffer slot " << s << " declared in two resource groups.\n"; - bad=378; + bad = 378; } int m = SetsClash(rg.second.samplers, g.samplers); if (m >= 0) { std::cerr << "Sampler slot " << s << " declared in two resource groups.\n"; - bad=379; + bad = 379; } } - if(bad!=0) + if (bad != 0) exit(bad); - resourceGroups[num]=g; + resourceGroups[num] = g; } -bool ConditionApplies( const std::string &value) +bool ConditionApplies(const std::string &value) { - bool val=(value=="true"); + bool val = (value == "true"); return val; - } bool ConditionsMatch(const std::set &variant_conditions, const std::map &variantValues) { - for(auto c:variant_conditions) + for (auto c : variant_conditions) { - std::string condition_name=c; - bool reverse=false; - if(condition_name[0]=='!') + std::string condition_name = c; + bool reverse = false; + if (condition_name[0] == '!') { - condition_name = condition_name.substr(1,condition_name.length()-1); - reverse=true; + condition_name = condition_name.substr(1, condition_name.length() - 1); + reverse = true; } auto v = variantValues.find(condition_name); - if(v==variantValues.end()) + if (v == variantValues.end()) return false; - std::string value=v->second; - if(!(reverse^ConditionApplies(value))) + std::string value = v->second; + if (!(reverse ^ ConditionApplies(value))) return false; } return true; @@ -266,68 +262,67 @@ bool ConditionsMatch(const std::set &variant_conditions, const std: void Effect::AccumulateFunctionsUsed2(const Function *f, std::map &variantValues, std::set &s) const { s.insert(f); - for(auto u=f->functionsCalled.begin();u!=f->functionsCalled.end();u++) + for (auto u = f->functionsCalled.begin(); u != f->functionsCalled.end(); u++) { - if(ConditionsMatch(u->second.variant_conditions,variantValues)) - AccumulateFunctionsUsed2(u->first, variantValues,s); + if (ConditionsMatch(u->second.variant_conditions, variantValues)) + AccumulateFunctionsUsed2(u->first, variantValues, s); } } void Effect::AccumulateFunctionsUsed(const Function *f, std::map &variantValues, std::set &s) const { - AccumulateFunctionsUsed2(f, variantValues,s); + AccumulateFunctionsUsed2(f, variantValues, s); for (auto u = f->variant_parameters.begin(); u != f->variant_parameters.end(); u++) { - if(u->type=="function") + if (u->type == "function") { - auto v=variantValues.find(u->identifier); - if(v!=variantValues.end()) + auto v = variantValues.find(u->identifier); + if (v != variantValues.end()) { - const Function *vf=GetFunction(v->second,0); - if(vf) + const Function *vf = GetFunction(v->second, 0); + if (vf) { s.insert(vf); - AccumulateFunctionsUsed(vf, variantValues,s); + AccumulateFunctionsUsed(vf, variantValues, s); } } } } } - const std::set &sfx::Function::GetTypesUsed() const { - if(!initialized) + if (!initialized) { - initialized=true; + initialized = true; types_used.clear(); - if(returnType!="void") + if (returnType != "void") types_used.insert(returnType); for (auto &i : constantBuffers) { types_used.insert(i.first->structureType); } - for(auto i:parameters) + for (auto i : parameters) { types_used.insert(i.type); } - for(auto i:locals) + for (auto i : locals) { types_used.insert(i.type); } - for(auto i:globals) + for (auto i : globals) { - Declaration *d=gEffect->GetDeclaration(i.first); - if(!d) + Declaration *d = gEffect->GetDeclaration(i.first); + if (!d) continue; - switch(d->declarationType) + switch (d->declarationType) { case DeclarationType::TEXTURE: { - DeclaredTexture *dt=(DeclaredTexture*)d; + DeclaredTexture *dt = (DeclaredTexture *)d; // Is is something like RWStructuredBuffer..? // Then we "use" StructureType and will need its declaration. - if(dt->structureType.length()) + if (dt->structureType.length()) { types_used.insert(dt->structureType); } @@ -335,13 +330,13 @@ const std::set &sfx::Function::GetTypesUsed() const } case DeclarationType::NAMED_CONSTANT_BUFFER: { - NamedConstantBuffer*dt=static_cast(d); + NamedConstantBuffer *dt = static_cast(d); // Is is something like ConstantBuffer..? - if(dt->structureType.length()) + if (dt->structureType.length()) { types_used.insert(dt->structureType); } - Struct* st = static_cast(d); + Struct *st = static_cast(d); for (auto s : st->m_structMembers) { types_used.insert(s.type); @@ -350,8 +345,8 @@ const std::set &sfx::Function::GetTypesUsed() const } case DeclarationType::STRUCT: { - Struct *st=(Struct*)d; - for(auto s:st->m_structMembers) + Struct *st = (Struct *)d; + for (auto s : st->m_structMembers) { types_used.insert(s.type); } @@ -369,76 +364,76 @@ const std::set &sfx::Function::GetTypesUsed() const return types_used; } -void Effect::AccumulateStructDeclarations(map &variantValues,std::set &s, std::string i) const +void Effect::AccumulateStructDeclarations(map &variantValues, std::set &s, std::string i) const { // Is the type declared? - auto decl=declarations.find(i); - if(decl==declarations.end()) + auto decl = declarations.find(i); + if (decl == declarations.end()) return; - - const Declaration *d=decl->second; - if(d) - switch(d->declarationType) - { - case DeclarationType::CONSTANT_BUFFER: - { - const ConstantBuffer* st = (const ConstantBuffer*)d; - s.insert(d); - for (int j = 0; j < st->m_structMembers.size(); j++) + + const Declaration *d = decl->second; + if (d) + switch (d->declarationType) + { + case DeclarationType::CONSTANT_BUFFER: { - AccumulateStructDeclarations(variantValues,s, st->m_structMembers[j].type); + const ConstantBuffer *st = (const ConstantBuffer *)d; + s.insert(d); + for (int j = 0; j < st->m_structMembers.size(); j++) + { + AccumulateStructDeclarations(variantValues, s, st->m_structMembers[j].type); + } } - } - case DeclarationType::STRUCT: - { - const Struct *st=(const Struct*)d; - s.insert(d); - for(int j=0;jm_structMembers.size();j++) + case DeclarationType::STRUCT: { - AccumulateStructDeclarations(variantValues,s,st->m_structMembers[j].type); + const Struct *st = (const Struct *)d; + s.insert(d); + for (int j = 0; j < st->m_structMembers.size(); j++) + { + AccumulateStructDeclarations(variantValues, s, st->m_structMembers[j].type); + } + } + default: + break; } - } - default: - break; - } } bool VariantsMatchConditions(const std::vector &variantStates, const std::map &variantValues) { // No states specified means always valid. if (!variantStates.size()) - return true; + return true; // But if any state IS specified, we must match at least one. bool ok = true; for (int i = 0; i < variantStates.size(); i++) { - const VariantState &variantState = variantStates[i]; - bool this_matches = true; - for (auto state : variantState.states) - { - // does this state string match the corresponding value? - std::string varName = state; - bool negate = false; - if (state[0] == '!') - { - negate = true; - varName = state.substr(1, state.length() - 1); - } - auto val = variantValues.find(varName); - if (val == variantValues.end()) + const VariantState &variantState = variantStates[i]; + bool this_matches = true; + for (auto state : variantState.states) { - this_matches = false; - break; - } - bool value = val->second == "true"; - if (value != (!negate)) - { - this_matches = false; - break; + // does this state string match the corresponding value? + std::string varName = state; + bool negate = false; + if (state[0] == '!') + { + negate = true; + varName = state.substr(1, state.length() - 1); + } + auto val = variantValues.find(varName); + if (val == variantValues.end()) + { + this_matches = false; + break; + } + bool value = val->second == "true"; + if (value != (!negate)) + { + this_matches = false; + break; + } } - } - if (this_matches) - return true; + if (this_matches) + return true; } return false; } @@ -446,47 +441,47 @@ bool VariantsMatchConditions(const std::vector &variantStates, con void Effect::AccumulateDeclarationsUsed(const Function *f, map &variantValues, set &s, std::set &rwLoad) const { // Accumulate rw textures used in load operations: - for (const auto& l : f->rwTexturesLoaded) + for (const auto &l : f->rwTexturesLoaded) { rwLoad.insert(l); } for (auto u = f->globals.begin(); u != f->globals.end(); u++) { - auto v=declarations.find(u->first); + auto v = declarations.find(u->first); // Probably member of an anonymous constant buffer, so don't fail. Should find which buffer? - if(v==declarations.end()) + if (v == declarations.end()) continue; - if(!VariantsMatchConditions(u->second,variantValues)) + if (!VariantsMatchConditions(u->second, variantValues)) continue; v->second->name = v->first; - const Declaration *d=v->second; + const Declaration *d = v->second; s.insert(d); } - const auto types_used=f->GetTypesUsed(); - for(auto i:types_used) + const auto types_used = f->GetTypesUsed(); + for (auto i : types_used) { - AccumulateStructDeclarations(variantValues,s, i); + AccumulateStructDeclarations(variantValues, s, i); } for (auto u = f->variant_parameters.begin(); u != f->variant_parameters.end(); u++) { - if(u->type=="function") + if (u->type == "function") { - auto v=variantValues.find(u->identifier); - if(v!=variantValues.end()) + auto v = variantValues.find(u->identifier); + if (v != variantValues.end()) { - const Function *vf=GetFunction(v->second,0); + const Function *vf = GetFunction(v->second, 0); if (vf) { - AccumulateDeclarationsUsed(vf, variantValues, s,rwLoad); + AccumulateDeclarationsUsed(vf, variantValues, s, rwLoad); } } } } } -void Effect::AccumulateGlobalsAsStrings(const Function* f, std::set& s) const +void Effect::AccumulateGlobalsAsStrings(const Function *f, std::set &s) const { - if(!f) + if (!f) return; for (auto i : f->globals) { @@ -496,14 +491,14 @@ void Effect::AccumulateGlobalsAsStrings(const Function* f, std::set } } -void Effect::AccumulateGlobals(const Function *f,std::set &s) const +void Effect::AccumulateGlobals(const Function *f, std::set &s) const { for (auto i : f->declarations) { - auto d= declarations.find(i); - if(d!=declarations.end()&&d->second->declarationType==DeclarationType::VARIABLE) + auto d = declarations.find(i); + if (d != declarations.end() && d->second->declarationType == DeclarationType::VARIABLE) { - const Variable*D=(const Variable*)d->second; + const Variable *D = (const Variable *)d->second; s.insert(D); } } @@ -520,71 +515,84 @@ void Effect::AccumulateConstantBuffersUsed(const Function *f, ShaderInstance &sh } for (auto i : f->globals) { - if(!VariantsMatchConditions(i.second,sh.variantValues)) + if (!VariantsMatchConditions(i.second, sh.variantValues)) continue; - auto d=declarations.find(i.first); - if(d!=declarations.end()) + auto d = declarations.find(i.first); + if (d != declarations.end()) { - if(d->second->declarationType==DeclarationType::NAMED_CONSTANT_BUFFER) + if (d->second->declarationType == DeclarationType::NAMED_CONSTANT_BUFFER) { - ConstantBuffer *cb = static_cast(d->second); + ConstantBuffer *cb = static_cast(d->second); sh.constantBuffers.insert(cb); } } } } -void Effect::DeclareStruct(const string &name,const Struct &ts,const string &original) +void Effect::DeclareStruct(const string &name, const Struct &ts, const string &original) { - Struct *rs =new Struct; - *rs =ts; - rs->name=name; - rs->original=original; - m_structs[name] =rs; - declarations[name]=rs; + Struct *rs = new Struct; + *rs = ts; + rs->name = name; + rs->original = original; + ReplaceRegexes(rs->original, sfxConfig.replace); + for (int i = 0; i < rs->m_structMembers.size(); i++) + { + ReplaceRegexes(rs->m_structMembers[i].type, sfxConfig.replace); + } + m_structs[name] = rs; + declarations[name] = rs; } void Effect::DeclareConstantBuffer(const std::string &name, int slot, int group_num, const Struct &ts, const string &original) { ConstantBuffer *cb = new ConstantBuffer; m_constantBuffers[name] = cb; - *(static_cast(cb)) = ts; - cb->original=original; - cb->declarationType=DeclarationType::CONSTANT_BUFFER; + *(static_cast(cb)) = ts; + cb->original = original; + ReplaceRegexes(cb->original, sfxConfig.replace); + for (int i = 0; i < cb->m_structMembers.size(); i++) + { + ReplaceRegexes(cb->m_structMembers[i].type, sfxConfig.replace); + } + cb->declarationType = DeclarationType::CONSTANT_BUFFER; cb->slot = slot; cb->group_num = group_num; - if(group_num<0) - cb->group_num=3; - cb->name=name; + if (group_num < 0) + cb->group_num = 3; + cb->name = name; cb->structureType = name; - declarations[name]=cb; - CheckConstantBufferSlotForResourceGroup(slot,group_num); + declarations[name] = cb; + CheckConstantBufferSlotForResourceGroup(slot, group_num); } -void Effect::DeclareVariable(const Variable* v) +void Effect::DeclareVariable(const Variable *v) { - Variable *variable=new Variable; - *variable=*v; + Variable *variable = new Variable; + *variable = *v; + ReplaceRegexes(variable->structureType, sfxConfig.replace); + ReplaceRegexes(variable->type, sfxConfig.replace); + ReplaceRegexes(variable->original, sfxConfig.replace); declarations[variable->name] = variable; } Function *Effect::GetFunction(const std::string &functionName, std::map &variantValues) { - if(!variantValues.size()) - return GetFunction(functionName,0); - auto f=m_declaredFunctions.find(functionName); - if(f==m_declaredFunctions.end()) + if (!variantValues.size()) + return GetFunction(functionName, 0); + auto f = m_declaredFunctions.find(functionName); + if (f == m_declaredFunctions.end()) return nullptr; - if(!f->second.size()) + if (!f->second.size()) return nullptr; - for(auto i:f->second) + for (auto i : f->second) { - Function *F=i; - if(F->variantValues==variantValues) + Function *F = i; + if (F->variantValues == variantValues) return F; - // Now create the specialized version. + // Now create the specialized version. } - Function *specializedFunction=DeclareFunction(functionName,*(f->second.begin().operator*())); + Function *specializedFunction = DeclareFunction(functionName, *(f->second.begin().operator*())); specializedFunction->variantValues = variantValues; for (auto u = specializedFunction->variant_parameters.begin(); u != specializedFunction->variant_parameters.end(); u++) { @@ -605,12 +613,12 @@ Function *Effect::GetFunction(const std::string &functionName, std::map=f->second.size()) + if (i < 0 || i >= f->second.size()) return nullptr; return f->second[i]; } @@ -625,59 +633,59 @@ const Function *Effect::GetFunction(const std::string &functionName, int i) cons return f->second[i]; } -int Effect::GenerateSamplerSlot(int s,bool offset) +int Effect::GenerateSamplerSlot(int s, bool offset) { - const SfxConfig *config =GetConfig(); - if(offset&&!config->sharedSlots) - return s+300; + const SfxConfig *config = GetConfig(); + if (offset && !config->sharedSlots) + return s + 300; return s; } -int Effect::GenerateTextureSlot(int s,bool offset) +int Effect::GenerateTextureSlot(int s, bool offset) { - const SfxConfig *config =GetConfig(); - if(offset&&!config->sharedSlots) - return s+100; + const SfxConfig *config = GetConfig(); + if (offset && !config->sharedSlots) + return s + 100; return s; } -int Effect::GenerateTextureWriteSlot(int s,bool offset) +int Effect::GenerateTextureWriteSlot(int s, bool offset) { - const SfxConfig *config =GetConfig(); - if(offset&&!config->sharedSlots) - return s+200; + const SfxConfig *config = GetConfig(); + if (offset && !config->sharedSlots) + return s + 200; return s; } -int Effect::GenerateConstantBufferSlot(int s,bool offset) +int Effect::GenerateConstantBufferSlot(int s, bool offset) { - const SfxConfig *config =GetConfig(); - if(offset&&!config->sharedSlots) + const SfxConfig *config = GetConfig(); + if (offset && !config->sharedSlots) return s; return s; } int Effect::GetSlot(const std::string &variableName) const { - auto i=declarations.find(variableName); - if(i!=declarations.end()) + auto i = declarations.find(variableName); + if (i != declarations.end()) { - if(i->second->declarationType==DeclarationType::TEXTURE) + if (i->second->declarationType == DeclarationType::TEXTURE) { - DeclaredTexture *dt=static_cast(i->second); + DeclaredTexture *dt = static_cast(i->second); return dt->slot; } - else if(i->second->declarationType==DeclarationType::SAMPLER) + else if (i->second->declarationType == DeclarationType::SAMPLER) { - SamplerState *ss=static_cast(i->second); + SamplerState *ss = static_cast(i->second); return ss->register_number; } } return -1; } -std::string Effect::GetFilenameOrNumber(const std::string &fn) +std::string Effect::GetFilenameOrNumber(const std::string &fn) { if (sfxConfig.lineDirectiveFilenames) - return "\""+fn+"\""; - return stringFormat("%d",GetFilenumber(fn)); + return "\"" + fn + "\""; + return stringFormat("%d", GetFilenumber(fn)); } std::string Effect::GetFilenameOrNumber(int filenumber) @@ -685,67 +693,67 @@ std::string Effect::GetFilenameOrNumber(int filenumber) string fn; if (sfxConfig.lineDirectiveFilenames) { - fn=fileList[filenumber]; - return "\""+fn+"\""; + fn = fileList[filenumber]; + return "\"" + fn + "\""; } - return stringFormat("%d",filenumber); + return stringFormat("%d", filenumber); } std::string Effect::GetFilename(int filenumber) { - string fn=fileList[filenumber]; + string fn = fileList[filenumber]; return fn; } -int Effect::GetFilenumber(const std::string &fn) +int Effect::GetFilenumber(const std::string &fn) { - auto i=filenumbers.find(fn); - if(i!=filenumbers.end()) + auto i = filenumbers.find(fn); + if (i != filenumbers.end()) return i->second; last_filenumber++; - filenumbers[fn]=last_filenumber; - fileList[last_filenumber]=fn; + filenumbers[fn] = last_filenumber; + fileList[last_filenumber] = fn; return last_filenumber; } -bool& Effect::Active() +bool &Effect::Active() { return m_active; } void Effect::SetConfig(const SfxConfig *config) { - if(config) - sfxConfig=*config; + if (config) + sfxConfig = *config; else - sfxConfig=SfxConfig(); -}; + sfxConfig = SfxConfig(); +}; void Effect::SetOptions(const SfxOptions *opts) { - if(opts) - sfxOptions=*opts; + if (opts) + sfxOptions = *opts; else - sfxOptions=SfxOptions(); + sfxOptions = SfxOptions(); }; -string& Effect::Filename() +string &Effect::Filename() { return m_filename; } -string& Effect::Dir() +string &Effect::Dir() { return m_dir; } extern int mkpath(const std::string &filename_utf8); #include -unsigned Effect::CompileAllShaders(string sfxoFilename,const string &sharedCode,string& log, BinaryMap &binaryMap) +unsigned Effect::CompileAllShaders(string sfxoFilename, const string &sharedCode, string &log, BinaryMap &binaryMap) { ostringstream sLog; - int res=1; - PixelOutputFormat pixelOutputFormat=FMT_UNKNOWN; + int res = 1; + PixelOutputFormat pixelOutputFormat = FMT_UNKNOWN; std::ofstream combinedBinary; mkpath(std::filesystem::path(sfxoFilename).generic_string()); if (sfxOptions.wrapOutput) @@ -753,45 +761,45 @@ unsigned Effect::CompileAllShaders(string sfxoFilename,const string &sharedCode, std::string sfxbFilename = sfxoFilename; find_and_replace(sfxbFilename, ".sfxo", ".sfxb"); combinedBinary.open(sfxbFilename, std::ios_base::binary); - if(!combinedBinary.is_open()) + if (!combinedBinary.is_open()) { std::cerr << "Failed to open " << sfxbFilename << " for writing.\n"; exit(3); } } - for(ShaderInstanceMap::iterator i=m_shaderInstances.begin();i!=m_shaderInstances.end();i++) + for (ShaderInstanceMap::iterator i = m_shaderInstances.begin(); i != m_shaderInstances.end(); i++) { m_uniqueShaderInstances.insert(i->second); } - for(auto i=m_uniqueShaderInstances.begin();i!=m_uniqueShaderInstances.end();i++) + for (auto i = m_uniqueShaderInstances.begin(); i != m_uniqueShaderInstances.end(); i++) { - std::shared_ptr shaderInstance=(*i); - // Hold on, is this even supported? - std::string profile_text=shaderInstance->m_profile; + std::shared_ptr shaderInstance = (*i); + // Hold on, is this even supported? + std::string profile_text = shaderInstance->m_profile; find_and_replace(profile_text, "ps_", ""); find_and_replace(profile_text, "vs_", ""); find_and_replace(profile_text, "cs_", ""); find_and_replace(profile_text, "_", "."); - double profile_number=atof(profile_text.c_str()); - if(profile_number>sfxConfig.maxShaderModel) + double profile_number = atof(profile_text.c_str()); + if (profile_number > sfxConfig.maxShaderModel) { - std::cout<<"Skipping "<m_functionName.c_str()<<" as profile "<m_profile.c_str()<<" is not supported.\n"; + std::cout << "Skipping " << shaderInstance->m_functionName.c_str() << " as profile " << shaderInstance->m_profile.c_str() << " is not supported.\n"; continue; } ConstructSource(shaderInstance.get()); - if(shaderInstance->shaderType==FRAGMENT_SHADER) + if (shaderInstance->shaderType == FRAGMENT_SHADER) { - if(sfxConfig.multiplePixelOutputFormats) + if (sfxConfig.multiplePixelOutputFormats) { - // TO-DO: implement this better, we could just set before hand the rt state name + // TO-DO: implement this better, we could just set before hand the rt state name // to the pass - const Declaration* rtFormat = nullptr; + const Declaration *rtFormat = nullptr; for (map::const_iterator g = m_techniqueGroups.begin(); g != m_techniqueGroups.end(); ++g) { - for (map::const_iterator it = g->second.m_techniques.begin(); it != g->second.m_techniques.end(); ++it) + for (map::const_iterator it = g->second.m_techniques.begin(); it != g->second.m_techniques.end(); ++it) { const vector &passes = it->second->GetPasses(); - vector< Pass>::const_iterator j = passes.begin(); + vector::const_iterator j = passes.begin(); for (; j != passes.end(); j++) { const Pass *pass = &(*j); @@ -801,8 +809,8 @@ unsigned Effect::CompileAllShaders(string sfxoFilename,const string &sharedCode, } if (pass->HasShader(ShaderType::FRAGMENT_SHADER)) { - auto v=pass->GetShaderVariants(ShaderType::FRAGMENT_SHADER); - if(shaderInstance->names.find(v[0])!=shaderInstance->names.end()) + auto v = pass->GetShaderVariants(ShaderType::FRAGMENT_SHADER); + if (shaderInstance->names.find(v[0]) != shaderInstance->names.end()) { // We found a rt format state! rtFormat = declarations[pass->passState.renderTargetFormatState.objectName]; @@ -812,58 +820,64 @@ unsigned Effect::CompileAllShaders(string sfxoFilename,const string &sharedCode, } } } - if (rtFormat) { break; } + if (rtFormat) + { + break; + } + } + if (rtFormat) + { + break; } - if (rtFormat) { break; } } - + // Just output generic formats that we may use if (!rtFormat) { - res&=Compile(shaderInstance,Filename(),sfxoFilename,shaderInstance->shaderType,FMT_32_ABGR,sharedCode, sLog,sfxConfig,sfxOptions,fileList ,combinedBinary,binaryMap); - res&=Compile(shaderInstance,Filename(),sfxoFilename,shaderInstance->shaderType,FMT_FP16_ABGR,sharedCode, sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap); - res&=Compile(shaderInstance,Filename(),sfxoFilename,shaderInstance->shaderType,FMT_UNORM16_ABGR,sharedCode, sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap); - res&=Compile(shaderInstance,Filename(),sfxoFilename,shaderInstance->shaderType,FMT_SNORM16_ABGR,sharedCode, sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap); + res &= Compile(shaderInstance, Filename(), sfxoFilename, shaderInstance->shaderType, FMT_32_ABGR, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); + res &= Compile(shaderInstance, Filename(), sfxoFilename, shaderInstance->shaderType, FMT_FP16_ABGR, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); + res &= Compile(shaderInstance, Filename(), sfxoFilename, shaderInstance->shaderType, FMT_UNORM16_ABGR, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); + res &= Compile(shaderInstance, Filename(), sfxoFilename, shaderInstance->shaderType, FMT_SNORM16_ABGR, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); } // We know the output format else { - res&=Compile(shaderInstance,Filename(),sfxoFilename,shaderInstance->shaderType,FMT_UNKNOWN,sharedCode,sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap,rtFormat); + res &= Compile(shaderInstance, Filename(), sfxoFilename, shaderInstance->shaderType, FMT_UNKNOWN, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap, rtFormat); } } else { - res&=Compile(shaderInstance,Filename(),sfxoFilename,shaderInstance->shaderType,FMT_UNKNOWN,sharedCode, sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap); + res &= Compile(shaderInstance, Filename(), sfxoFilename, shaderInstance->shaderType, FMT_UNKNOWN, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); } - if(!res) + if (!res) return 0; } - else if(shaderInstance->shaderType==VERTEX_SHADER) + else if (shaderInstance->shaderType == VERTEX_SHADER) { - res&=Compile(shaderInstance,Filename(),sfxoFilename,VERTEX_SHADER,pixelOutputFormat,sharedCode, sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap); - if(!res) + res &= Compile(shaderInstance, Filename(), sfxoFilename, VERTEX_SHADER, pixelOutputFormat, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); + if (!res) return 0; - res&=Compile(shaderInstance,Filename(),sfxoFilename,EXPORT_SHADER,pixelOutputFormat,sharedCode, sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap); - if(!res) + res &= Compile(shaderInstance, Filename(), sfxoFilename, EXPORT_SHADER, pixelOutputFormat, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); + if (!res) return 0; } - else if(shaderInstance->shaderType==UNKNOWN_SHADER_TYPE) + else if (shaderInstance->shaderType == UNKNOWN_SHADER_TYPE) { // TODO: this could be a template shader for variants, and therefore ok not to use it, the variants may be used. - //std::cerr<<"Warning: shader is not used "<m_functionName<m_functionName<shaderType,pixelOutputFormat,sharedCode, sLog,sfxConfig,sfxOptions, fileList, combinedBinary, binaryMap); - if(!res) + res &= Compile(shaderInstance, Filename(), sfxoFilename, shaderInstance->shaderType, pixelOutputFormat, sharedCode, sLog, sfxConfig, sfxOptions, fileList, combinedBinary, binaryMap); + if (!res) return 0; } } - log=sLog.str(); + log = sLog.str(); return res; } -ostringstream& Effect::Log() +ostringstream &Effect::Log() { return m_log; } @@ -873,29 +887,28 @@ TechniqueGroup &Effect::GetTechniqueGroup(const std::string &name) return m_techniqueGroups[name]; } -const vector& Effect::GetProgramList() const +const vector &Effect::GetProgramList() const { return m_programNames; } -const vector& Effect::GetFilenameList() const +const vector &Effect::GetFilenameList() const { return m_filenames; } - void Effect::SetFilenameList(const char **filenamesUtf8) { m_filenames.clear(); - const char **f=filenamesUtf8; - while(*f!=NULL) + const char **f = filenamesUtf8; + while (*f != NULL) { - string str=*f; - int pos=(int)str.find("\\"); - while(pos>0) + string str = *f; + int pos = (int)str.find("\\"); + while (pos > 0) { - str.replace(str.begin()+pos,str.begin()+pos+1,"/"); - pos=(int)str.find("\\"); + str.replace(str.begin() + pos, str.begin() + pos + 1, "/"); + pos = (int)str.find("\\"); } m_filenames.push_back(str); f++; @@ -905,13 +918,13 @@ void Effect::SetFilenameList(const char **filenamesUtf8) void Effect::PopulateProgramList() { m_programNames.clear(); - for(map::const_iterator it=m_programs.begin(); it!=m_programs.end(); ++it) + for (map::const_iterator it = m_programs.begin(); it != m_programs.end(); ++it) m_programNames.push_back(it->first); } string stringOf(ShaderCommand t) { - switch(t) + switch (t) { case SetVertexShader: return "vertex"; @@ -946,26 +959,26 @@ string stringOf(ShaderCommand t) string stringOf(Topology t) { - switch(t) - { - case POINTLIST: - return "PointList"; - case LINELIST: - return "LineList"; - case LINESTRIP: - return "LineStrip"; - case TRIANGLELIST: - return "TriangleList"; - case TRIANGLESTRIP: - return "TriangleStrip"; - case LINELIST_ADJACENCY: - return "LineListAdjacency"; - case LINESTRIP_ADJACENCY: - return "LineStripAdjacency"; - case TRIANGLELIST_ADJACENCY: - return "TriangleListAdjacency"; - case TRIANGLESTRIP_ADJACENCY: - return "TriangleStripAdjacency"; + switch (t) + { + case POINTLIST: + return "PointList"; + case LINELIST: + return "LineList"; + case LINESTRIP: + return "LineStrip"; + case TRIANGLELIST: + return "TriangleList"; + case TRIANGLESTRIP: + return "TriangleStrip"; + case LINELIST_ADJACENCY: + return "LineListAdjacency"; + case LINESTRIP_ADJACENCY: + return "LineStripAdjacency"; + case TRIANGLELIST_ADJACENCY: + return "TriangleListAdjacency"; + case TRIANGLESTRIP_ADJACENCY: + return "TriangleStripAdjacency"; default: break; }; @@ -973,42 +986,42 @@ string stringOf(Topology t) } extern string ToString(PixelOutputFormat pixelOutputFormat); -void Effect::CalculateResourceSlots(ShaderInstance *shaderInstance,set &textureSlots,set &uavSlots,set &textureSlotsForSB,set &uavTextureSlotsForSB,set &constantBufferSlots,set &samplerSlots) +void Effect::CalculateResourceSlots(ShaderInstance *shaderInstance, set &textureSlots, set &uavSlots, set &textureSlotsForSB, set &uavTextureSlotsForSB, set &constantBufferSlots, set &samplerSlots) { // Note there may be some API-dependence in how we do this. - for(auto d:shaderInstance->declarations) + for (auto d : shaderInstance->declarations) { - if(d->declarationType==DeclarationType::TEXTURE) + if (d->declarationType == DeclarationType::TEXTURE) { - DeclaredTexture *td=(DeclaredTexture *)(d); - int slot=td->slot; - if(IsTexture(td->shaderResourceType)) + DeclaredTexture *td = (DeclaredTexture *)(d); + int slot = td->slot; + if (IsTexture(td->shaderResourceType)) { - if(IsRW(td->shaderResourceType)) + if (IsRW(td->shaderResourceType)) uavSlots.insert(slot); else textureSlots.insert(slot); } - else if(IsStructuredBuffer(td->shaderResourceType)) + else if (IsStructuredBuffer(td->shaderResourceType)) { - if(IsRWStructuredBuffer(td->shaderResourceType)) + if (IsRWStructuredBuffer(td->shaderResourceType)) uavTextureSlotsForSB.insert(slot); else textureSlotsForSB.insert(slot); } - else if(td->shaderResourceType==ShaderResourceType::RAYTRACE_ACCELERATION_STRUCT) + else if (td->shaderResourceType == ShaderResourceType::RAYTRACE_ACCELERATION_STRUCT) { - textureSlots.insert(slot); + textureSlots.insert(slot); } else - std::cerr<<"Warning: unknown resource type "<<(int)td->shaderResourceType<shaderResourceType << std::endl; } - else if(d->declarationType==DeclarationType::SAMPLER) + else if (d->declarationType == DeclarationType::SAMPLER) { - SamplerState *ss=(SamplerState *)(d); + SamplerState *ss = (SamplerState *)(d); samplerSlots.insert(ss->register_number); } - else if(d->declarationType==DeclarationType::CONSTANT_BUFFER) + else if (d->declarationType == DeclarationType::CONSTANT_BUFFER) { constantBufferSlots.insert(d->slot); } @@ -1016,12 +1029,6 @@ void Effect::CalculateResourceSlots(ShaderInstance *shaderInstance,set &tex { constantBufferSlots.insert(d->slot); } - else - { - #if SIMUL_INTERNAL_CHECKS - std::cerr<< GetFilenameOrNumber(d->file_number)<<"("<line_number<<")" <<": Unhandled resource "<name.c_str()<<" of type "<<(int)d->declarationType<<"."<constantBuffers) @@ -1030,28 +1037,28 @@ void Effect::CalculateResourceSlots(ShaderInstance *shaderInstance,set &tex } } -std::shared_ptr Effect::AddShaderInstance(const std::string &shaderInstanceName,const std::string &functionName,ShaderType type,const std::string &profileName,int lineno) +std::shared_ptr Effect::AddShaderInstance(const std::string &shaderInstanceName, const std::string &functionName, ShaderType type, const std::string &profileName, int lineno) { - auto i=m_shaderInstances.find(shaderInstanceName); - if(i!=m_shaderInstances.end()) + auto i = m_shaderInstances.find(shaderInstanceName); + if (i != m_shaderInstances.end()) return i->second; - Function *function=gEffect->GetFunction(functionName,0); - if(!function) + Function *function = gEffect->GetFunction(functionName, 0); + if (!function) return nullptr; - //std::set declarations; + // std::set declarations; - std::shared_ptr shaderInstance=std::make_shared(); + std::shared_ptr shaderInstance = std::make_shared(); m_uniqueShaderInstances.insert(shaderInstance); - m_shaderInstances[shaderInstanceName] =shaderInstance; - - if(GetConfig()->entryPointOption.length()>0) - shaderInstance->entryPoint =functionName; + m_shaderInstances[shaderInstanceName] = shaderInstance; + + if (GetConfig()->entryPointOption.length() > 0) + shaderInstance->entryPoint = functionName; else - shaderInstance->entryPoint ="main"; - shaderInstance->m_functionName =functionName; - shaderInstance->shaderType =type; - shaderInstance->m_profile =profileName; - shaderInstance->global_line_number =lineno; + shaderInstance->entryPoint = "main"; + shaderInstance->m_functionName = functionName; + shaderInstance->shaderType = type; + shaderInstance->m_profile = profileName; + shaderInstance->global_line_number = lineno; /*for(auto d:declarations) { @@ -1062,66 +1069,66 @@ std::shared_ptr Effect::AddShaderInstance(const std::string &sha std::string ToNumericString(std::string input) { -// decimal? return as-is. - if(input.find('.') Effect::GenerateShaderInstanceVariants(const std::string &baseName,const VariantSpec &variantSpec) +std::vector Effect::GenerateShaderInstanceVariants(const std::string &baseName, const VariantSpec &variantSpec) { std::vector variantInstanceNames; auto b = m_shaderInstances.find(baseName); - if(b==m_shaderInstances.end()) + if (b == m_shaderInstances.end()) { std::cerr << "No base shader instance " << baseName << "\n"; return variantInstanceNames; } - std::shared_ptr baseInstance=b->second; - if(!baseInstance) + std::shared_ptr baseInstance = b->second; + if (!baseInstance) { - std::cerr<<"No base shader instance "< mul(variantSpec.variableSpecs.size()); - int last_mul=1; - for(int k=0;k mul(variantSpec.variableSpecs.size()); + int last_mul = 1; + for (int k = 0; k < variantSpec.variableSpecs.size(); k++) { - mul[k]=last_mul; - last_mul*=(int)variantSpec.variableSpecs[k].variableOptions.size(); + mul[k] = last_mul; + last_mul *= (int)variantSpec.variableSpecs[k].variableOptions.size(); } // each variant has N indices representing which value to use for each variable. - for(int i=0;i variantInstance=std::make_shared(*baseInstance); - //each variant corresponds to a set of indices: + std::shared_ptr variantInstance = std::make_shared(*baseInstance); + // each variant corresponds to a set of indices: variantInstance->variantVariableIndex.resize(variantSpec.variableSpecs.size()); - for(int j=0;j=0;k--) + auto &variableSpec = variantSpec.variableSpecs[j]; + int v = i; + int n = v; + for (int k = (int)variantSpec.variableSpecs.size() - 1; k >= 0; k--) { - variantInstance->variantVariableIndex[k]=n/mul[k]; - n-=variantInstance->variantVariableIndex[k]*mul[k]; + variantInstance->variantVariableIndex[k] = n / mul[k]; + n -= variantInstance->variantVariableIndex[k] * mul[k]; } } std::string variant_spec; - std::string variantInstanceName=baseName; + std::string variantInstanceName = baseName; std::map variantValues; Function *baseFunction = gEffect->GetFunction(baseInstance->m_functionName, 0); for (int k = 0; k < variantSpec.variableSpecs.size(); k++) @@ -1136,22 +1143,22 @@ std::vector Effect::GenerateShaderInstanceVariants(const std::strin std::cerr << "No function found: " << baseInstance->m_functionName << "\n"; continue; } - for(int k=0;kvariant_parameters[k]; const std::string &this_value = variantSpec.variableSpecs[k].variableOptions[variantInstance->variantVariableIndex[k]]; if (!k) variantInstanceName += "("; else - variantInstanceName+="_"; - variantInstanceName+=this_value; + variantInstanceName += "_"; + variantInstanceName += this_value; // glSlangValidator evalues true as false. Therefore we have to convert "true" and "false" to integers! - std::string def = "#define sfx_variant_var_"s + vp.identifier + " ("s + ToNumericString(this_value)+ ")\n"s; - variantInstance->variantDefinitions+=def; + std::string def = "#define sfx_variant_var_"s + vp.identifier + " ("s + ToNumericString(this_value) + ")\n"s; + variantInstance->variantDefinitions += def; - if(vp.type!="function") + if (vp.type != "function") { - std::string decl = vp.type + " "s + vp.identifier + "="s+vp.type+"(sfx_variant_var_"s + vp.identifier + ");\n"s; + std::string decl = vp.type + " "s + vp.identifier + "="s + vp.type + "(sfx_variant_var_"s + vp.identifier + ");\n"s; variantInstance->variantDeclarations += decl; } else @@ -1160,53 +1167,53 @@ std::vector Effect::GenerateShaderInstanceVariants(const std::strin variantInstance->variantDeclarations += decl; } - variantInstance->variantValues[vp.identifier]=this_value; + variantInstance->variantValues[vp.identifier] = this_value; } - if(variantSpec.variableSpecs.size()) + if (variantSpec.variableSpecs.size()) { variantInstanceName += ")"; } - variantInstance->variantName=variantInstanceName; + variantInstance->variantName = variantInstanceName; m_uniqueShaderInstances.insert(variantInstance); - m_shaderInstances[variantInstanceName] =variantInstance; + m_shaderInstances[variantInstanceName] = variantInstance; variantInstanceNames.push_back(variantInstanceName); } return variantInstanceNames; } - + std::size_t hash(const char *s) { size_t len = strlen(s); - //s[0] * (31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1] + // s[0] * (31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1] std::size_t h1 = std::hash{}(s); return h1; } -std::shared_ptr Effect::GetShaderInstance(const std::string &instanceName,ShaderType type) +std::shared_ptr Effect::GetShaderInstance(const std::string &instanceName, ShaderType type) { - auto s=m_shaderInstances.find(instanceName); - if(s!=m_shaderInstances.end()) + auto s = m_shaderInstances.find(instanceName); + if (s != m_shaderInstances.end()) { - if(s->second->shaderType==UNKNOWN_SHADER_TYPE||type==UNKNOWN_SHADER_TYPE||type==s->second->shaderType) - { - if(s->second->shaderType==UNKNOWN_SHADER_TYPE&&type!=UNKNOWN_SHADER_TYPE) - s->second->shaderType=type; + if (s->second->shaderType == UNKNOWN_SHADER_TYPE || type == UNKNOWN_SHADER_TYPE || type == s->second->shaderType) + { + if (s->second->shaderType == UNKNOWN_SHADER_TYPE && type != UNKNOWN_SHADER_TYPE) + s->second->shaderType = type; return s->second; } else { - std::string instanceName1=instanceName+stringOf((ShaderCommand)type); - return AddShaderInstance(instanceName1,s->second->m_functionName,type,s->second->m_profile,s->second->global_line_number); + std::string instanceName1 = instanceName + stringOf((ShaderCommand)type); + return AddShaderInstance(instanceName1, s->second->m_functionName, type, s->second->m_profile, s->second->global_line_number); } } - std::string functionName=instanceName; - Function *function=gEffect->GetFunction(functionName,0); - if(!function) + std::string functionName = instanceName; + Function *function = gEffect->GetFunction(functionName, 0); + if (!function) return nullptr; - return AddShaderInstance(instanceName,functionName,type,"",function->main_linenumber); + return AddShaderInstance(instanceName, functionName, type, "", function->main_linenumber); } -bool Effect::Save(string sfxFilename,string sfxoFilename) +bool Effect::Save(string sfxFilename, string sfxoFilename) { PopulateProgramList(); string log; @@ -1216,12 +1223,12 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) std::set usedConstantBufferSlots; // Write used declarations: - for(auto t:declarations) + for (auto t : declarations) { // t.second->ref_count; - if(t.second->declarationType==DeclarationType::TEXTURE) + if (t.second->declarationType == DeclarationType::TEXTURE) { - DeclaredTexture *dt=(DeclaredTexture*)t.second; + DeclaredTexture *dt = (DeclaredTexture *)t.second; if (IsRW(dt->shaderResourceType)) { rwTextureSlots.insert(dt->slot); @@ -1231,39 +1238,38 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) usedTextureSlots.insert(dt->slot); } } - else if(t.second->declarationType==DeclarationType::SAMPLER) + else if (t.second->declarationType == DeclarationType::SAMPLER) { - SamplerState *ss=(SamplerState*)t.second; + SamplerState *ss = (SamplerState *)t.second; usedSamplerSlots.insert(ss->register_number); } - } - string sharedCode=m_sharedCode.str(); - for(auto t:declarations) + string sharedCode = m_sharedCode.str(); + for (auto t : declarations) { - if(t.second->declarationType==DeclarationType::TEXTURE) + if (t.second->declarationType == DeclarationType::TEXTURE) { - DeclaredTexture *dt=(DeclaredTexture*)t.second; - bool writeable=IsRW(dt->shaderResourceType); - string type=string(writeable?"u":"t"); - if(t.second->ref_count>0) + DeclaredTexture *dt = (DeclaredTexture *)t.second; + bool writeable = IsRW(dt->shaderResourceType); + string type = string(writeable ? "u" : "t"); + if (t.second->ref_count > 0) { - if(dt->slot<0) + if (dt->slot < 0) { - dt->slot=0; - while(dt->slot<32) + dt->slot = 0; + while (dt->slot < 32) { - if(writeable) + if (writeable) { - if(rwTextureSlots.find(dt->slot)==rwTextureSlots.end()) + if (rwTextureSlots.find(dt->slot) == rwTextureSlots.end()) { rwTextureSlots.insert(dt->slot); break; } } else - { - if(usedTextureSlots.find(dt->slot)==usedTextureSlots.end()) + { + if (usedTextureSlots.find(dt->slot) == usedTextureSlots.end()) { usedTextureSlots.insert(dt->slot); break; @@ -1272,24 +1278,24 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) dt->slot++; } } - find_and_replace(sharedCode,type+string("####")+t.first+"####",type+std::to_string(dt->slot)); + find_and_replace(sharedCode, type + string("####") + t.first + "####", type + std::to_string(dt->slot)); } else { - find_and_replace(sharedCode,string(": register(")+type+string("####")+t.first+"####)",""); + find_and_replace(sharedCode, string(": register(") + type + string("####") + t.first + "####)", ""); } } - else if(t.second->declarationType==DeclarationType::SAMPLER) + else if (t.second->declarationType == DeclarationType::SAMPLER) { - if(!t.second->ref_count) + if (!t.second->ref_count) continue; - SamplerState *ss=(SamplerState*)t.second; - if(ss->register_number<0) + SamplerState *ss = (SamplerState *)t.second; + if (ss->register_number < 0) { - ss->register_number=0; - while(ss->register_number<32) + ss->register_number = 0; + while (ss->register_number < 32) { - if(usedSamplerSlots.find(ss->register_number)==usedSamplerSlots.end()) + if (usedSamplerSlots.find(ss->register_number) == usedSamplerSlots.end()) { usedSamplerSlots.insert(ss->register_number); break; @@ -1297,21 +1303,22 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) ss->register_number++; } } - string type="s"; - find_and_replace(sharedCode,type+string("####")+t.first+"####",type+std::to_string(ss->register_number)); + string type = "s"; + find_and_replace(sharedCode, type + string("####") + t.first + "####", type + std::to_string(ss->register_number)); } } + ReplaceRegexes(sharedCode, sfxConfig.replace); BinaryMap binaryMap; - int res =CompileAllShaders(sfxoFilename,sharedCode,log, binaryMap); - if(!res) + int res = CompileAllShaders(sfxoFilename, sharedCode, log, binaryMap); + if (!res) return 0; // Now we will write a sfxo definition file that enumerates all the techniques and their shader filenames. ofstream outstr(sfxoFilename); - auto Tab=[this](int tabcount) + auto Tab = [this](int tabcount) { return std::string(tabcount, '\t'); }; - outstr<<"SFX:"<slot); } - vector m_techniqueNames; + vector m_techniqueNames; // Add textures to the effect file for (auto t = declarations.begin(); t != declarations.end(); ++t) { @@ -1327,7 +1334,7 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) continue; if (t->second->declarationType == DeclarationType::TEXTURE) { - DeclaredTexture *dt = (DeclaredTexture*)t->second; + DeclaredTexture *dt = (DeclaredTexture *)t->second; bool writeable = IsRW(dt->shaderResourceType); bool is_array = IsArrayTexture(dt->shaderResourceType); bool is_cubemap = IsCubemap(dt->shaderResourceType); @@ -1335,23 +1342,23 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) int dimensions = GetTextureDimension(dt->shaderResourceType, true); string rw = writeable ? "read_write" : "read_only"; string ar = is_array ? "array" : "single"; - if(dt->shaderResourceType==ShaderResourceType::RAYTRACE_ACCELERATION_STRUCT) + if (dt->shaderResourceType == ShaderResourceType::RAYTRACE_ACCELERATION_STRUCT) { - outstr<< "accelerationstructure "; + outstr << "accelerationstructure "; } else { - outstr<< "texture "; + outstr << "texture "; } outstr << t->first << " "; - + if (is_cubemap) outstr << "cubemap"; else outstr << dimensions << "d"; if (is_msaa) outstr << "ms"; - + outstr << " " << rw << " " << (writeable ? GenerateTextureWriteSlot(dt->slot, false) : GenerateTextureSlot(dt->slot, false)) << " g" << t->second->group_num << " " << ar << std::endl; if (dt->slot >= 32) { @@ -1368,7 +1375,7 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) continue; if (!t->second->ref_count) continue; - NamedConstantBuffer *dt = static_cast(t->second); + NamedConstantBuffer *dt = static_cast(t->second); outstr << "namedconstantbuffer " << t->first << " "; outstr << " " << dt->slot << " g" << t->second->group_num << std::endl; } @@ -1381,16 +1388,16 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) continue; SamplerState *ss = (SamplerState *)t->second; outstr << "SamplerState " << t->first << " " - << GenerateSamplerSlot(ss->register_number,false) - << " g" << t->second->group_num - << "," << ToString(ss->Filter) - << "," << ToString(ss->AddressU) - << "," << ToString(ss->AddressV) - << "," << ToString(ss->AddressW) - << "," << ToString(ss->depthComparison) - << "," << "\n"; - } - + << GenerateSamplerSlot(ss->register_number, false) + << " g" << t->second->group_num + << "," << ToString(ss->Filter) + << "," << ToString(ss->AddressU) + << "," << ToString(ss->AddressV) + << "," << ToString(ss->AddressW) + << "," << ToString(ss->depthComparison) + << "," << "\n"; + } + // Add the render target format states to the effect file for (auto t = declarations.begin(); t != declarations.end(); ++t) { @@ -1398,7 +1405,7 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) continue; if (t->second->declarationType != DeclarationType::RENDERTARGETFORMAT_STATE) continue; - RenderTargetFormatState* s = (RenderTargetFormatState *)t->second; + RenderTargetFormatState *s = (RenderTargetFormatState *)t->second; outstr << "RenderTargetFormatState " << t->first << " ("; for (int i = 0; i < 8; i++) { @@ -1411,71 +1418,70 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) outstr << std::dec << ")" << "\n"; } // Add rasterizer states to the effect file - for(auto t=declarations.begin();t!=declarations.end();++t) + for (auto t = declarations.begin(); t != declarations.end(); ++t) { - if(!t->second->ref_count) + if (!t->second->ref_count) continue; - if(t->second->declarationType!=DeclarationType::RASTERIZERSTATE) + if (t->second->declarationType != DeclarationType::RASTERIZERSTATE) continue; - RasterizerState *b=(RasterizerState *)t->second; - outstr<<"RasterizerState "<first<<" (" - <AntialiasedLineEnable) - <<","<cullMode) - <<","<DepthBias) - <<","<DepthBiasClamp) - <<","<DepthClipEnable) - <<","<fillMode) - <<","<FrontCounterClockwise) - <<","<MultisampleEnable) - <<","<ScissorEnable) - <<","<SlopeScaledDepthBias) - ; - outstr<second; + outstr << "RasterizerState " << t->first << " (" + << ToString(b->AntialiasedLineEnable) + << "," << ToString(b->cullMode) + << "," << ToString(b->DepthBias) + << "," << ToString(b->DepthBiasClamp) + << "," << ToString(b->DepthClipEnable) + << "," << ToString(b->fillMode) + << "," << ToString(b->FrontCounterClockwise) + << "," << ToString(b->MultisampleEnable) + << "," << ToString(b->ScissorEnable) + << "," << ToString(b->SlopeScaledDepthBias); + outstr << std::dec << ")" << "\n"; } // Add blend states to the effect file - for(auto t=declarations.begin();t!=declarations.end();++t) + for (auto t = declarations.begin(); t != declarations.end(); ++t) { - if(!t->second->ref_count) + if (!t->second->ref_count) continue; - if(t->second->declarationType!=DeclarationType::BLENDSTATE) + if (t->second->declarationType != DeclarationType::BLENDSTATE) continue; - BlendState *b=(BlendState *)t->second; - outstr<<"BlendState "<first<<" " - <AlphaToCoverageEnable) - <<",("; - for(auto u=b->BlendEnable.begin();u!=b->BlendEnable.end();u++) - { - if(u!=b->BlendEnable.begin()) - outstr<<","; - outstr<second); - } - outstr<<"),"<BlendOp) - <<","<BlendOpAlpha) - <<","<SrcBlend) - <<","<DestBlend) - <<","<SrcBlendAlpha) - <<","<DestBlendAlpha)<<",("<RenderTargetWriteMask.begin();v!=b->RenderTargetWriteMask.end();v++) - { - if(v!=b->RenderTargetWriteMask.begin()) - outstr<<","; - outstr<second); - } - outstr<second; + outstr << "BlendState " << t->first << " " + << ToString(b->AlphaToCoverageEnable) + << ",("; + for (auto u = b->BlendEnable.begin(); u != b->BlendEnable.end(); u++) + { + if (u != b->BlendEnable.begin()) + outstr << ","; + outstr << ToString(u->second); + } + outstr << ")," << ToString(b->BlendOp) + << "," << ToString(b->BlendOpAlpha) + << "," << ToString(b->SrcBlend) + << "," << ToString(b->DestBlend) + << "," << ToString(b->SrcBlendAlpha) + << "," << ToString(b->DestBlendAlpha) << ",(" << std::hex; + for (auto v = b->RenderTargetWriteMask.begin(); v != b->RenderTargetWriteMask.end(); v++) + { + if (v != b->RenderTargetWriteMask.begin()) + outstr << ","; + outstr << ToString(v->second); + } + outstr << std::dec << ")" << "\n"; } // Add depth states to the effect file - for(auto t=declarations.begin();t!=declarations.end();++t) + for (auto t = declarations.begin(); t != declarations.end(); ++t) { - if(!t->second->ref_count) + if (!t->second->ref_count) continue; - if(t->second->declarationType!=DeclarationType::DEPTHSTATE) + if (t->second->declarationType != DeclarationType::DEPTHSTATE) continue; - DepthStencilState *d=(DepthStencilState *)t->second; - outstr<<"DepthStencilState "<first<<" " - <DepthTestEnable) - <<","<DepthWriteMask) - <<","<DepthFunc); - outstr<<"\n"; + DepthStencilState *d = (DepthStencilState *)t->second; + outstr << "DepthStencilState " << t->first << " " + << ToString(d->DepthTestEnable) + << "," << ToString(d->DepthWriteMask) + << "," << ToString((int)d->DepthFunc); + outstr << "\n"; } std::vector binBuffer; @@ -1484,192 +1490,191 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) // Add the group/technique/pass combinations to the effect file for (map::const_iterator g = m_techniqueGroups.begin(); g != m_techniqueGroups.end(); ++g) { - const TechniqueGroup &group=g->second; - outstr<<"group "<first<<"\n{\n"; - for (map::const_iterator it =group.m_techniques.begin(); it !=group.m_techniques.end(); ++it) - { - std::string techName=it->first; - const Technique *tech=it->second; - outstr<<"\ttechnique "< &passes=tech->GetPasses(); - vector::const_iterator j=passes.begin(); - for(;j!=passes.end();j++) - { - const Pass *pass=&(*j); - string passName=pass->name; - if(pass->GetNumVariants()>1) - outstr<second; + outstr << "group " << g->first << "\n{\n"; + for (map::const_iterator it = group.m_techniques.begin(); it != group.m_techniques.end(); ++it) + { + std::string techName = it->first; + const Technique *tech = it->second; + outstr << "\ttechnique " << techName << "\n\t{\n"; + const std::vector &passes = tech->GetPasses(); + vector::const_iterator j = passes.begin(); + for (; j != passes.end(); j++) + { + const Pass *pass = &(*j); + string passName = pass->name; + if (pass->GetNumVariants() > 1) + outstr << Tab(2) << "variant_pass " << passName << "\n"; else - outstr<GetNumVariants();var++) + outstr << Tab(2) << "pass " << passName << "\n"; + outstr << Tab(2) << "{\n"; + for (int var = 0; var < pass->GetNumVariants(); var++) { string variantName = pass->GetVariantName(var); - int t=3; - if(pass->GetNumVariants()>1) + int t = 3; + if (pass->GetNumVariants() > 1) { - outstr<passState.rasterizerState.objectName.length()>0) + if (pass->passState.rasterizerState.objectName.length() > 0) { - outstr<passState.rasterizerState.objectName<<"\n"; + outstr << Tab(t) << "rasterizer: " << pass->passState.rasterizerState.objectName << "\n"; } if (pass->passState.renderTargetFormatState.objectName.length() > 0) { - outstr << Tab(t)<<"targetformat: " << pass->passState.renderTargetFormatState.objectName << "\n"; + outstr << Tab(t) << "targetformat: " << pass->passState.renderTargetFormatState.objectName << "\n"; } - if(pass->passState.depthStencilState.objectName.length()>0) + if (pass->passState.depthStencilState.objectName.length() > 0) { - outstr<passState.depthStencilState.objectName<<" "<passState.depthStencilState.stencilRef<<"\n"; + outstr << Tab(t) << "depthstencil: " << pass->passState.depthStencilState.objectName << " " << pass->passState.depthStencilState.stencilRef << "\n"; } - if(pass->passState.blendState.objectName.length()>0) + if (pass->passState.blendState.objectName.length() > 0) { - outstr<passState.blendState.objectName<<" ("; - outstr<passState.blendState.blendFactor[0]<<","; - outstr<passState.blendState.blendFactor[1]<<","; - outstr<passState.blendState.blendFactor[2]<<","; - outstr<passState.blendState.blendFactor[3]<<") "; - outstr<passState.blendState.sampleMask<<"\n"; + outstr << Tab(t) << "blend: " << pass->passState.blendState.objectName << " ("; + outstr << pass->passState.blendState.blendFactor[0] << ","; + outstr << pass->passState.blendState.blendFactor[1] << ","; + outstr << pass->passState.blendState.blendFactor[2] << ","; + outstr << pass->passState.blendState.blendFactor[3] << ") "; + outstr << pass->passState.blendState.sampleMask << "\n"; } if (pass->HasShader(sfx::ShaderType::COMPUTE_SHADER)) { - const string &shaderInstanceName=pass->GetShader(sfx::ShaderType::COMPUTE_SHADER,var); - auto shaderInstance=GetShaderInstance(shaderInstanceName, sfx::ShaderType::COMPUTE_SHADER); - Function* function = gEffect->GetFunction(shaderInstance->m_functionName, 0); - outstr << Tab(t)<<"numthreads: " << function->numThreads[0] << " " << function->numThreads[1] <<" "<< function->numThreads[2] << "\n"; + const string &shaderInstanceName = pass->GetShader(sfx::ShaderType::COMPUTE_SHADER, var); + auto shaderInstance = GetShaderInstance(shaderInstanceName, sfx::ShaderType::COMPUTE_SHADER); + Function *function = gEffect->GetFunction(shaderInstance->m_functionName, 0); + outstr << Tab(t) << "numthreads: " << function->numThreads[0] << " " << function->numThreads[1] << " " << function->numThreads[2] << "\n"; } - if(pass->passState.topologyState.apply) + if (pass->passState.topologyState.apply) { - outstr<passState.topologyState.topology)<<"\n"; + outstr << Tab(t) << "topology: " << stringOf(pass->passState.topologyState.topology) << "\n"; } - - auto writeSb=[&] (ofstream &outstr,ShaderInstance *shaderInstance,const std::string &sbFilename,std::string pfm="") + + auto writeSb = [&](ofstream &outstr, ShaderInstance *shaderInstance, const std::string &sbFilename, std::string pfm = "") + { + if (!sbFilename.size()) + return; + outstr << Tab(t) << ""; + std::set textureSlots, uavSlots, cbufferSlots, samplerSlots, textureSlotsForSB, uavTextureSlotsForSB; + CalculateResourceSlots(shaderInstance, textureSlots, uavSlots, textureSlotsForSB, uavTextureSlotsForSB, cbufferSlots, samplerSlots); + outstr << stringOf((ShaderCommand)shaderInstance->shaderType); + if (!shaderInstance->rtFormatStateName.empty()) { - if(!sbFilename.size()) - return; - outstr< textureSlots,uavSlots,cbufferSlots,samplerSlots,textureSlotsForSB,uavTextureSlotsForSB; - CalculateResourceSlots(shaderInstance,textureSlots,uavSlots,textureSlotsForSB,uavTextureSlotsForSB,cbufferSlots,samplerSlots); - outstr<shaderType); - if (!shaderInstance->rtFormatStateName.empty()) - { - outstr << "(" << shaderInstance->rtFormatStateName << ")"; - } - else if(shaderInstance->shaderType==FRAGMENT_SHADER&&pfm.length()) - outstr<<"("<entryPoint.c_str()<<")"; - if (sfxOptions.wrapOutput) + outstr << "(" << shaderInstance->rtFormatStateName << ")"; + } + else if (shaderInstance->shaderType == FRAGMENT_SHADER && pfm.length()) + outstr << "(" << pfm << ")"; + outstr << ": " << sbFilename; + outstr << "(" << shaderInstance->entryPoint.c_str() << ")"; + if (sfxOptions.wrapOutput) + { + if (binaryMap.find(sbFilename) != binaryMap.end()) { - if(binaryMap.find(sbFilename)!=binaryMap.end()) - { // Write the offset and size. - std::streampos pos; - size_t sz; - std::tie(pos, sz) = binaryMap[sbFilename]; - if((int)pos<0) - { - SFX_CERR << sbFilename.c_str()<< " has bad entry in binary map."<< std::endl; - exit(153); - } - outstr << " inline:(0x" << std::hex << pos <<",0x"<< sz <variantValues.size()) - { - outstr << " variant:("; - bool first = true; - for (auto v : shaderInstance->variantValues) - { - if (!first) - outstr << ", "; - first = false; - outstr << v.first << "=" << v.second; - } - outstr << ")"; - } - // Print texture slots - outstr<<", t:("; - for(auto w:textureSlots) - { - if(w!=*(textureSlots.begin())) - outstr<<","; - outstr<variantValues.size()) + { + outstr << " variant:("; + bool first = true; + for (auto v : shaderInstance->variantValues) { - if(w!=*(samplerSlots.begin())) - outstr<<","; - outstr<HasShader(shaderType)) + ShaderType shaderType = (ShaderType)s; + if (!pass->HasShader(shaderType)) continue; - if(shaderType==ShaderType::EXPORT_SHADER) // either/or. + if (shaderType == ShaderType::EXPORT_SHADER) // either/or. continue; - if(shaderType==ShaderType::VERTEX_SHADER&&pass->HasShader(GEOMETRY_SHADER)) - shaderType=EXPORT_SHADER; - const std::vector shaderVariantNames=pass->GetShaderVariants(shaderType); - + if (shaderType == ShaderType::VERTEX_SHADER && pass->HasShader(GEOMETRY_SHADER)) + shaderType = EXPORT_SHADER; + const std::vector shaderVariantNames = pass->GetShaderVariants(shaderType); + { - auto shaderInstance=GetShaderInstance(pass->GetShader(shaderType,var),shaderType); - if(!shaderInstance) + auto shaderInstance = GetShaderInstance(pass->GetShader(shaderType, var), shaderType); + if (!shaderInstance) { - std::cerr << pass->name.c_str() << ": " << variantName<<": No shaderInstance found.\n "; + std::cerr << pass->name.c_str() << ": " << variantName << ": No shaderInstance found.\n "; return false; } - int vertex_or_export=0; - if(shaderType==EXPORT_SHADER) - vertex_or_export=1; + int vertex_or_export = 0; + if (shaderType == EXPORT_SHADER) + vertex_or_export = 1; Function *function = gEffect->GetFunction(shaderInstance->m_functionName, 0); @@ -1678,150 +1683,150 @@ bool Effect::Save(string sfxFilename,string sfxoFilename) multiview |= ShaderInstanceHasSemantic(shaderInstance, "SV_ViewId"); if (multiview && !multiviewDeclared) { - outstr << Tab(t)<<"multiview: 1\n"; + outstr << Tab(t) << "multiview: 1\n"; multiviewDeclared = true; } - if(shaderType==VERTEX_SHADER&&function->parameters.size()) + if (shaderType == VERTEX_SHADER && function->parameters.size()) { - outstr<parameters) + outstr << Tab(t) << "layout:\n"; + outstr << Tab(t) << "{\n"; + for (auto p : function->parameters) { auto D = declarations.find(p.type); - Declaration *d=nullptr; + Declaration *d = nullptr; if (D != declarations.end()) - d=D->second; + d = D->second; // It is a struct and we are in a vertex shader - if (d && d->declarationType == DeclarationType::STRUCT) + if (d && d->declarationType == DeclarationType::STRUCT) { - Struct *s=(Struct *)d; - if(s) + Struct *s = (Struct *)d; + if (s) { - for(auto m:s->m_structMembers) + for (auto m : s->m_structMembers) { // ignore automatic semantics. - size_t sem_pos=m.semantic.find("SV_"); - if(sem_pos0) + if (m.variantCondition.length() > 0) { string value = shaderInstance->variantValues[m.variantVariable]; - - if(!CheckVariantCondition(m,value)) + + if (!CheckVariantCondition(m, value)) continue; } - outstr<sbFilenames.begin();v!=shaderInstance->sbFilenames.end();v++) + for (auto v = shaderInstance->sbFilenames.begin(); v != shaderInstance->sbFilenames.end(); v++) { - string sbFilename=v->second; - PixelOutputFormat pixelOutputFormat=(PixelOutputFormat)v->first; - string pfm=ToString(pixelOutputFormat); - if(shaderType==FRAGMENT_SHADER||(int)pixelOutputFormat==vertex_or_export) - writeSb(outstr,shaderInstance.get(),sbFilename,pfm); + string sbFilename = v->second; + PixelOutputFormat pixelOutputFormat = (PixelOutputFormat)v->first; + string pfm = ToString(pixelOutputFormat); + if (shaderType == FRAGMENT_SHADER || (int)pixelOutputFormat == vertex_or_export) + writeSb(outstr, shaderInstance.get(), sbFilename, pfm); } } } - + // If it's raytrace, go through the hitgroups. - for(auto h:pass->passState.raytraceHitGroups) + for (auto h : pass->passState.raytraceHitGroups) { - outstr<sbFilenames[0]); + auto shaderInstance = GetShaderInstance(h.second.closestHit, CLOSEST_HIT_SHADER); + outstr << Tab(t) << "\t"; + writeSb(outstr, shaderInstance.get(), shaderInstance->sbFilenames[0]); } - if(h.second.anyHit.length()) + if (h.second.anyHit.length()) { - auto shaderInstance=GetShaderInstance(h.second.anyHit,ANY_HIT_SHADER); - outstr<sbFilenames[0]); + auto shaderInstance = GetShaderInstance(h.second.anyHit, ANY_HIT_SHADER); + outstr << Tab(t) << "\t"; + writeSb(outstr, shaderInstance.get(), shaderInstance->sbFilenames[0]); } - if(h.second.intersection.length()) + if (h.second.intersection.length()) { - auto shaderInstance=GetShaderInstance(h.second.intersection,INTERSECTION_SHADER); - outstr<sbFilenames[0]); + auto shaderInstance = GetShaderInstance(h.second.intersection, INTERSECTION_SHADER); + outstr << Tab(t) << "\t"; + writeSb(outstr, shaderInstance.get(), shaderInstance->sbFilenames[0]); } - outstr<passState.missShaders.empty()) { - outstr << Tab(t)<<"MissShaders:" << "\n\t\t\t{\n"; + outstr << Tab(t) << "MissShaders:" << "\n\t\t\t{\n"; for (auto m : pass->passState.missShaders) { if (m.length()) { auto shaderInstance = GetShaderInstance(m, MISS_SHADER); - outstr << Tab(t)<<"\t"; + outstr << Tab(t) << "\t"; writeSb(outstr, shaderInstance.get(), shaderInstance->sbFilenames[0]); } } - outstr << Tab(t)<<"}\n"; + outstr << Tab(t) << "}\n"; } - //If it's raytrace, go through the callable shaders. + // If it's raytrace, go through the callable shaders. if (!pass->passState.callableShaders.empty()) { - outstr << Tab(t)<<"CallableShaders:" << "\n\t\t\t{\n"; + outstr << Tab(t) << "CallableShaders:" << "\n\t\t\t{\n"; for (auto c : pass->passState.callableShaders) { if (c.length()) { auto shaderInstance = GetShaderInstance(c, CALLABLE_SHADER); - outstr << Tab(t)<<"\t"; + outstr << Tab(t) << "\t"; writeSb(outstr, shaderInstance.get(), shaderInstance->sbFilenames[0]); } } - outstr << Tab(t)<<"}\n"; + outstr << Tab(t) << "}\n"; } - //If it's raytrace, define the Shader and Pipeline configs + // If it's raytrace, define the Shader and Pipeline configs if (!pass->passState.raytraceHitGroups.empty()) { //---RayTracingShaderConfig--- - outstr << Tab(t)<<"RayTracingShaderConfig:" << "\n\t\t\t{\n"; - - //Default is sizeof(float) * 8. - int maxPayloadSize = pass->passState.maxPayloadSize != 0 ? pass->passState.maxPayloadSize : 32; - outstr << Tab(t)<<"\t" << "MaxPayloadSize: " << std::to_string(maxPayloadSize) << "\n"; - - //Default is sizeof(BuiltInTriangleIntersectionAttributes). - int maxAttributeSize = pass->passState.maxAttributeSize != 0 ? pass->passState.maxAttributeSize : 8; - outstr << Tab(t)<<"\t" << "MaxAttributeSize: " << std::to_string(maxAttributeSize) << "\n"; - - outstr << Tab(t)<<"}\n"; - + outstr << Tab(t) << "RayTracingShaderConfig:" << "\n\t\t\t{\n"; + + // Default is sizeof(float) * 8. + int maxPayloadSize = pass->passState.maxPayloadSize != 0 ? pass->passState.maxPayloadSize : 32; + outstr << Tab(t) << "\t" << "MaxPayloadSize: " << std::to_string(maxPayloadSize) << "\n"; + + // Default is sizeof(BuiltInTriangleIntersectionAttributes). + int maxAttributeSize = pass->passState.maxAttributeSize != 0 ? pass->passState.maxAttributeSize : 8; + outstr << Tab(t) << "\t" << "MaxAttributeSize: " << std::to_string(maxAttributeSize) << "\n"; + + outstr << Tab(t) << "}\n"; + //---RayTracingPipelineConfig--- - outstr << Tab(t)<<"RayTracingPipelineConfig:" << "\n\t\t\t{\n"; + outstr << Tab(t) << "RayTracingPipelineConfig:" << "\n\t\t\t{\n"; - //Default is 2 for inital hit and shadow. - int maxTraceRecursionDepth = pass->passState.maxTraceRecursionDepth != 0 ? pass->passState.maxTraceRecursionDepth : 2; - outstr << Tab(t)<<"\t" << "MaxTraceRecursionDepth: " << std::to_string(maxTraceRecursionDepth) << "\n"; + // Default is 2 for inital hit and shadow. + int maxTraceRecursionDepth = pass->passState.maxTraceRecursionDepth != 0 ? pass->passState.maxTraceRecursionDepth : 2; + outstr << Tab(t) << "\t" << "MaxTraceRecursionDepth: " << std::to_string(maxTraceRecursionDepth) << "\n"; - outstr << Tab(t)<<"}\n"; + outstr << Tab(t) << "}\n"; } - if(pass->GetNumVariants()>1) + if (pass->GetNumVariants() > 1) { t--; - outstr<(d); + const Struct *structure = static_cast(d); int offset = 0; - for (const StructMember& member : structure->m_structMembers) + for (const StructMember &member : structure->m_structMembers) { std::regex digits("\\d"); std::smatch match; @@ -1860,16 +1865,14 @@ bool Effect::IsConstantBufferMemberAlignmentValid(const Declaration* d) { size *= atoi(match[0].str().c_str()); } - if (member.type.find(match[0].str() + "x" + match[0].str()) != std::string::npos - || member.type.find("mat") != std::string::npos) + if (member.type.find(match[0].str() + "x" + match[0].str()) != std::string::npos || member.type.find("mat") != std::string::npos) { size *= atoi(match[0].str().c_str()); } - //std::cout << offset << ": " << structure->name << "::" << member.name << "\n"; + // std::cout << offset << ": " << structure->name << "::" << member.name << "\n"; - if (((offset % 16) && (size > 8)) - || ((offset % 8) && (size == 8))) + if (((offset % 16) && (size > 8)) || ((offset % 8) && (size == 8))) { std::cerr << fileList[d->file_number] << "(" << d->line_number << ") : error : Constant Buffer has misaligned members. "; std::cerr << d->name << "::" << member.name << " can not be at an offset of " << offset << " with a size of " << size << "." << std::endl; @@ -1882,7 +1885,7 @@ bool Effect::IsConstantBufferMemberAlignmentValid(const Declaration* d) return true; } -string Effect::GetTypeOfParameter(std::vector& parameters, string keyName) +string Effect::GetTypeOfParameter(std::vector ¶meters, string keyName) { for (auto p : parameters) { @@ -1899,34 +1902,34 @@ string Effect::GetDeclaredType(const string &name) const auto i = declarations.find(name); if (i != declarations.end()) { - if(i->second->declarationType==DeclarationType::TEXTURE) - return ((DeclaredTexture*)(i->second))->type; - if(i->second->declarationType==DeclarationType::SAMPLER) + if (i->second->declarationType == DeclarationType::TEXTURE) + return ((DeclaredTexture *)(i->second))->type; + if (i->second->declarationType == DeclarationType::SAMPLER) return "SamplerState"; - if(i->second->declarationType==DeclarationType::BLENDSTATE) + if (i->second->declarationType == DeclarationType::BLENDSTATE) return "BlendState"; - if(i->second->declarationType==DeclarationType::RASTERIZERSTATE) + if (i->second->declarationType == DeclarationType::RASTERIZERSTATE) return "RasterizerState"; - if(i->second->declarationType==DeclarationType::DEPTHSTATE) + if (i->second->declarationType == DeclarationType::DEPTHSTATE) return "DepthState"; - if(i->second->declarationType==DeclarationType::STRUCT) + if (i->second->declarationType == DeclarationType::STRUCT) return "struct"; } return "unknown"; } -NamedConstantBuffer* Effect::DeclareNamedConstantBuffer(const string &name,int slot,int group,int space,const string &structureType, const Struct& ts,const string &original) +NamedConstantBuffer *Effect::DeclareNamedConstantBuffer(const string &name, int slot, int group, int space, const string &structureType, const Struct &ts, const string &original) { - NamedConstantBuffer* t = new NamedConstantBuffer(); - *(static_cast(t)) = ts; - t->declarationType =DeclarationType::NAMED_CONSTANT_BUFFER; - t->structureType =structureType; - t->original =original; - t->name =name; - t->slot =slot; - t->group_num =group; - t->space =space; - t->instance_name =name; + NamedConstantBuffer *t = new NamedConstantBuffer(); + *(static_cast(t)) = ts; + t->declarationType = DeclarationType::NAMED_CONSTANT_BUFFER; + t->structureType = structureType; + t->original = original; + t->name = name; + t->slot = slot; + t->group_num = group; + t->space = space; + t->instance_name = name; declarations[name] = (t); declarations[structureType] = (t); if (!IsConstantBufferMemberAlignmentValid(declarations[name])) @@ -1939,11 +1942,11 @@ NamedConstantBuffer* Effect::DeclareNamedConstantBuffer(const string &name,int s void Effect::CheckTextureSlotForResourceGroup(int slot, int group) { auto g = resourceGroups.find(group); - if(g!=resourceGroups.end()) + if (g != resourceGroups.end()) { - if(g->second.textures.find(slot)==g->second.textures.end()) + if (g->second.textures.find(slot) == g->second.textures.end()) { - std::cerr << this->Filename().c_str() << ": error: texture slot "<Filename().c_str() << ": error: texture slot " << slot << " is not in the declared resource group " << group << std::endl; exit(984); } } @@ -1973,33 +1976,33 @@ void Effect::CheckStructuredBufferSlotForResourceGroup(int slot, int group) } } -DeclaredTexture* Effect::DeclareTexture(const string &name,ShaderResourceType shaderResourceType,int slot,int group,int space,const string &structureType,const string &original) +DeclaredTexture *Effect::DeclareTexture(const string &name, ShaderResourceType shaderResourceType, int slot, int group, int space, const string &structureType, const string &original) { - DeclaredTexture* t = new DeclaredTexture(); - t->structureType =structureType; - t->original =original; - t->name =name; - t->shaderResourceType =shaderResourceType; - t->group_num =group; + DeclaredTexture *t = new DeclaredTexture(); + t->structureType = structureType; + t->original = original; + t->name = name; + t->shaderResourceType = shaderResourceType; + t->group_num = group; bool write = IsRW(shaderResourceType); bool rw = IsRW(shaderResourceType); int num = 0; - CheckTextureSlotForResourceGroup(slot,group); + CheckTextureSlotForResourceGroup(slot, group); // We only generate slots for the default resource group. Other groups must stick to their assigned slots. if (sfxConfig.generateSlots && group == sfxConfig.defaultResourceGroupIndex) { - num = -1; + num = -1; // scene - if(shaderResourceType==ShaderResourceType::RAYTRACE_ACCELERATION_STRUCT) + if (shaderResourceType == ShaderResourceType::RAYTRACE_ACCELERATION_STRUCT) { - //keep declared slot?... - num=slot; + // keep declared slot?... + num = slot; } // RW texture - else if (shaderResourceType==ShaderResourceType::NAMED_CONSTANT_BUFFER) + else if (shaderResourceType == ShaderResourceType::NAMED_CONSTANT_BUFFER) { - //find a good buffer slot later... + // find a good buffer slot later... } else if (rw) { @@ -2032,7 +2035,7 @@ DeclaredTexture* Effect::DeclareTexture(const string &name,ShaderResourceType sh } else // TRY using the slot that's specified, if one IS specified... { - std::cerr << this->Filename().c_str()<< ": error: ran out of texture slots."<< std::endl; + std::cerr << this->Filename().c_str() << ": error: ran out of texture slots." << std::endl; exit(1424); num = GetTextureNumber(name.c_str(), slot); textureNumberMap[name] = num; @@ -2092,68 +2095,69 @@ DeclaredTexture* Effect::DeclareTexture(const string &name,ShaderResourceType sh } SamplerState *Effect::DeclareSamplerState(const string &name, int register_number, int group_number, const SamplerState &templateSS) { - SamplerState *s=new SamplerState(); - *s= templateSS; - if(register_number<0) + SamplerState *s = new SamplerState(); + *s = templateSS; + if (register_number < 0) { - register_number=m_max_sampler_register_number+1; + register_number = m_max_sampler_register_number + 1; } s->register_number = register_number; s->group_num = group_number; - declarations[name]=s; - m_max_sampler_register_number=std::max(register_number,m_max_sampler_register_number); + declarations[name] = s; + m_max_sampler_register_number = std::max(register_number, m_max_sampler_register_number); return s; } RasterizerState *Effect::DeclareRasterizerState(const string &name) { - RasterizerState *s=new RasterizerState(); - declarations[name]=s; + RasterizerState *s = new RasterizerState(); + declarations[name] = s; return s; } RenderTargetFormatState *Effect::DeclareRenderTargetFormatState(const std::string &name) { - RenderTargetFormatState *s = new RenderTargetFormatState(); - declarations[name] = s; + RenderTargetFormatState *s = new RenderTargetFormatState(); + declarations[name] = s; return s; } BlendState *Effect::DeclareBlendState(const string &name) { - BlendState *s=new BlendState(); - declarations[name]=s; + BlendState *s = new BlendState(); + declarations[name] = s; return s; } DepthStencilState *Effect::DeclareDepthStencilState(const string &name) { - DepthStencilState *s=new DepthStencilState(); - declarations[name]=s; + DepthStencilState *s = new DepthStencilState(); + declarations[name] = s; return s; } int Effect::GetRWTextureNumber(string n, int specified_slot) { int texture_number = current_rw_texture_number; - if(rwTextureNumberMap.find(n) != rwTextureNumberMap.end()) + if (rwTextureNumberMap.find(n) != rwTextureNumberMap.end()) texture_number = rwTextureNumberMap[n]; else { - if(specified_slot>=0) + if (specified_slot >= 0) texture_number = specified_slot; else { if (specified_slot >= 0) texture_number = specified_slot; - else return -1; - + else + return -1; + rwTextureNumberMap[n] = texture_number; } } return texture_number; } -int Effect::GetTextureNumber(string n,int specified_slot) +int Effect::GetTextureNumber(string n, int specified_slot) { int texture_number = current_texture_number; if (textureNumberMap.find(n) != textureNumberMap.end()) @@ -2162,227 +2166,227 @@ int Effect::GetTextureNumber(string n,int specified_slot) { if (specified_slot >= 0) texture_number = specified_slot; - else return -1; + else + return -1; textureNumberMap[n] = texture_number; } return texture_number; } - void errSem(const string& str, int lex_linenumber); +void errSem(const string &str, int lex_linenumber); - - std::string Effect::CombinedTypeString(const std::string& type, const std::string& memberType) - { - if (memberType.length() == 0) - return type; - std::string key = type + "<"; - key += memberType; - key += ">"; - auto i= sfxConfig.templateTypes.find(key); +std::string Effect::CombinedTypeString(const std::string &type, const std::string &memberType) +{ + if (memberType.length() == 0) + return type; + std::string key = type + "<"; + key += memberType; + key += ">"; + auto i = sfxConfig.templateTypes.find(key); if (i != sfxConfig.templateTypes.end()) { return i->second; } return type; - } - bool Effect::CheckDeclaredGlobal(const Function* func, const std::string toCheck) - { - for (const auto &g : func->globals) - { - if (g.first == toCheck) - { - return true; - } - } - for (const auto cf : func->functionsCalled) - { - if (CheckDeclaredGlobal(cf.first, toCheck)) - { - return true; - } - } - return false; - } - - void Effect::Declare( ShaderInstance *shaderInstance, ostream &os, const Declaration *d, ConstantBuffer &texCB, ConstantBuffer &sampCB, const std::set &rwLoad, std::set &declaredSS, const Function *mainFunction) - { - ShaderType shaderType=shaderInstance->shaderType; - switch(d->declarationType) - { - case DeclarationType::TEXTURE: - { - std::string dec = ""; - DeclaredTexture* td = (DeclaredTexture*)d; - if ((td->shaderResourceType & ShaderResourceType::MS)== ShaderResourceType::MS) - { - dec = ""; - } - // It is a (RW)StructuredBuffer - if (( td->type == "RWStructuredBuffer" || td->type == "StructuredBuffer") - - &&!sfxConfig.structuredBufferDeclaration.empty()) - { - dec = sfxConfig.structuredBufferDeclaration; - static int ssbouid = 0; - find_and_replace(dec, "{name}", td->name + "_ssbo"); - int temp_slot=td->slot; - if(IsRW(td->shaderResourceType)) - temp_slot=GenerateTextureWriteSlot(td->slot); - else - temp_slot=GenerateTextureSlot(td->slot); - find_and_replace(dec, "{slot}", ToString(temp_slot)); - find_and_replace(dec, "{group}", ToString(td->group_num)); - find_and_replace(dec, "{content}", td->structureType + " " + td->name + "[];"); - ssbouid++; - - } - // Its an Image or Texture +} +bool Effect::CheckDeclaredGlobal(const Function *func, const std::string toCheck) +{ + for (const auto &g : func->globals) + { + if (g.first == toCheck) + { + return true; + } + } + for (const auto cf : func->functionsCalled) + { + if (CheckDeclaredGlobal(cf.first, toCheck)) + { + return true; + } + } + return false; +} + +void Effect::Declare(ShaderInstance *shaderInstance, ostream &os, const Declaration *d, ConstantBuffer &texCB, ConstantBuffer &sampCB, const std::set &rwLoad, std::set &declaredSS, const Function *mainFunction) +{ + ShaderType shaderType = shaderInstance->shaderType; + switch (d->declarationType) + { + case DeclarationType::TEXTURE: + { + std::string dec = ""; + DeclaredTexture *td = (DeclaredTexture *)d; + if ((td->shaderResourceType & ShaderResourceType::MS) == ShaderResourceType::MS) + { + dec = ""; + } + // It is a (RW)StructuredBuffer + if ((td->type == "RWStructuredBuffer" || td->type == "StructuredBuffer") + + && !sfxConfig.structuredBufferDeclaration.empty()) + { + dec = sfxConfig.structuredBufferDeclaration; + static int ssbouid = 0; + find_and_replace(dec, "{name}", td->name + "_ssbo"); + int temp_slot = td->slot; + if (IsRW(td->shaderResourceType)) + temp_slot = GenerateTextureWriteSlot(td->slot); else + temp_slot = GenerateTextureSlot(td->slot); + find_and_replace(dec, "{slot}", ToString(temp_slot)); + find_and_replace(dec, "{group}", ToString(td->group_num)); + find_and_replace(dec, "{content}", td->structureType + " " + td->name + "[];"); + ssbouid++; + } + // Its an Image or Texture + else + { + if ((td->type == "RWStructuredBuffer" || td->type == "StructuredBuffer")) + { + std::cout << ""; + } + // Check the type of this texture (we want to know if will be used to load/store operations) + bool isImage = false; + bool isImageArray = false; + ShaderResourceType type = td->shaderResourceType & sfx::ShaderResourceType::RW; + if (type == sfx::ShaderResourceType::RW) { - if ( (td->type == "RWStructuredBuffer" || td->type == "StructuredBuffer")) + isImage = true; + type = td->shaderResourceType & sfx::ShaderResourceType::ARRAY; + if (type == sfx::ShaderResourceType::ARRAY) { - std::cout<<""; + isImageArray = true; } - // Check the type of this texture (we want to know if will be used to load/store operations) - bool isImage = false; - bool isImageArray = false; - ShaderResourceType type = td->shaderResourceType & sfx::ShaderResourceType::RW; - if (type == sfx::ShaderResourceType::RW) + } + // Image + if (isImage) + { + string str = sfxConfig.imageDeclaration; + // Not used in load operations + if (rwLoad.find(td->name) == rwLoad.end()) { - isImage = true; - type = td->shaderResourceType & sfx::ShaderResourceType::ARRAY; - if (type == sfx::ShaderResourceType::ARRAY) - { - isImageArray = true; - } + str = sfxConfig.imageDeclarationWriteOnly; } - // Image - if (isImage) + if (str.length() == 0) { - string str = sfxConfig.imageDeclaration; - // Not used in load operations - if (rwLoad.find(td->name) == rwLoad.end()) - { - str = sfxConfig.imageDeclarationWriteOnly; - } - if (str.length() == 0) + str = "{pass_through}"; + } + // Find the correct image type image,uimage,iimage etc + string ntype = td->structureType; + if (!sfxConfig.toImageType.empty()) + { + auto ele = sfxConfig.toImageType.find(td->structureType); + if (ele == sfxConfig.toImageType.end()) { - str = "{pass_through}"; + // error; + std::cerr << "Could not find the combination of this image type! \n"; + ntype = "null"; } - // Find the correct image type image,uimage,iimage etc - string ntype = td->structureType; - if (!sfxConfig.toImageType.empty()) + else { - auto ele = sfxConfig.toImageType.find(td->structureType); - if (ele == sfxConfig.toImageType.end()) + ntype = ele->second; + if ((td->shaderResourceType & ShaderResourceType::TEXTURE_1D) == ShaderResourceType::TEXTURE_1D) { - // error; - std::cerr << "Could not find the combination of this image type! \n"; - ntype = "null"; + ntype += "1D"; } - else + else if ((td->shaderResourceType & ShaderResourceType::TEXTURE_2D) == ShaderResourceType::TEXTURE_2D) { - ntype = ele->second; - if ((td->shaderResourceType & ShaderResourceType::TEXTURE_1D) == ShaderResourceType::TEXTURE_1D) - { - ntype += "1D"; - } - else if ((td->shaderResourceType & ShaderResourceType::TEXTURE_2D) == ShaderResourceType::TEXTURE_2D) - { - ntype += "2D"; - } - else if ((td->shaderResourceType & ShaderResourceType::TEXTURE_3D) == ShaderResourceType::TEXTURE_3D) - { - ntype += "3D"; - } - else if ((td->shaderResourceType & ShaderResourceType::TEXTURE_CUBE) == ShaderResourceType::TEXTURE_CUBE) - { - ntype += "Cube"; - } - if ((td->shaderResourceType & ShaderResourceType::ARRAY) == ShaderResourceType::ARRAY) - { - ntype += "Array"; - } + ntype += "2D"; } - } - - find_and_replace(str, "{pass_through}", td->original); - find_and_replace(str, "{type}", ntype); - find_and_replace(str, "{name}", td->name); - int slot=td->slot; - if(shaderType==FRAGMENT_SHADER) - slot++; - slot=GenerateTextureWriteSlot(slot); - find_and_replace(str, "{slot}", ToString(slot)); - find_and_replace(str, "{group}", ToString(td->group_num)); - - if (!sfxConfig.toImageFormat.empty()) - { - auto fmt = sfxConfig.toImageFormat.find(td->structureType); - string iFmt = ""; - if (!sfxConfig.toImageType.empty() && fmt == sfxConfig.toImageFormat.end()) + else if ((td->shaderResourceType & ShaderResourceType::TEXTURE_3D) == ShaderResourceType::TEXTURE_3D) { - std::cerr << "Couldn't find the image format:" << td->structureType << "\n"; - iFmt = "null"; + ntype += "3D"; } - else + else if ((td->shaderResourceType & ShaderResourceType::TEXTURE_CUBE) == ShaderResourceType::TEXTURE_CUBE) + { + ntype += "Cube"; + } + if ((td->shaderResourceType & ShaderResourceType::ARRAY) == ShaderResourceType::ARRAY) { - iFmt = fmt->second; + ntype += "Array"; } - find_and_replace(str, "{fqualifier}", iFmt); } - - dec = str; } - // Texture - else + + find_and_replace(str, "{pass_through}", td->original); + find_and_replace(str, "{type}", ntype); + find_and_replace(str, "{name}", td->name); + int slot = td->slot; + if (shaderType == FRAGMENT_SHADER) + slot++; + slot = GenerateTextureWriteSlot(slot); + find_and_replace(str, "{slot}", ToString(slot)); + find_and_replace(str, "{group}", ToString(td->group_num)); + + if (!sfxConfig.toImageFormat.empty()) { - string str = sfxConfig.textureDeclaration; - if (str.length() == 0) - { - str = "{pass_through}"; - } - // Add it to the texture constant buffer - if (sfxConfig.combineTexturesSamplers&&!sfxConfig.combineInShader) + auto fmt = sfxConfig.toImageFormat.find(td->structureType); + string iFmt = ""; + if (!sfxConfig.toImageType.empty() && fmt == sfxConfig.toImageFormat.end()) { - StructMember texMember = { "uint64_t",td->name + "[24]", "" }; - texCB.m_structMembers.push_back(texMember); + std::cerr << "Couldn't find the image format:" << td->structureType << "\n"; + iFmt = "null"; } else { - find_and_replace(str, "{pass_through}", td->original); - find_and_replace(str, "{type}", CombinedTypeString(td->type,td->structureType)); - find_and_replace(str, "{name}", td->name); - find_and_replace(str, "{slot}", ToString(GenerateTextureSlot(td->slot))); - find_and_replace(str, "{group}", ToString(td->group_num)); - dec = str; + iFmt = fmt->second; } + find_and_replace(str, "{fqualifier}", iFmt); } + + dec = str; } - os << dec.c_str() << endl; - } - break; - case DeclarationType:: SAMPLER: - { - SamplerState* ss = (SamplerState*)d; - if (sfxConfig.combineTexturesSamplers && sfxConfig.combineInShader) + // Texture + else { - bool found = false; - // We dont want to add duplicates - for (auto& memb : sampCB.m_structMembers) + string str = sfxConfig.textureDeclaration; + if (str.length() == 0) { - if (memb.name == ss->name) - { - found = true; - break; - } + str = "{pass_through}"; + } + // Add it to the texture constant buffer + if (sfxConfig.combineTexturesSamplers && !sfxConfig.combineInShader) + { + StructMember texMember = {"uint64_t", td->name + "[24]", ""}; + texCB.m_structMembers.push_back(texMember); } - if (!found) + else + { + find_and_replace(str, "{pass_through}", td->original); + find_and_replace(str, "{type}", CombinedTypeString(td->type, td->structureType)); + find_and_replace(str, "{name}", td->name); + find_and_replace(str, "{slot}", ToString(GenerateTextureSlot(td->slot))); + find_and_replace(str, "{group}", ToString(td->group_num)); + dec = str; + } + } + } + ReplaceRegexes(dec, sfxConfig.replace); + os << dec.c_str() << endl; + } + break; + case DeclarationType::SAMPLER: + { + SamplerState *ss = (SamplerState *)d; + if (sfxConfig.combineTexturesSamplers && sfxConfig.combineInShader) + { + bool found = false; + // We dont want to add duplicates + for (auto &memb : sampCB.m_structMembers) + { + if (memb.name == ss->name) { - StructMember sMember = { "uint64_t",ss->name, "" }; - sampCB.m_structMembers.push_back(sMember); + found = true; + break; } } + if (!found) + { + StructMember sMember = {"uint64_t", ss->name, ""}; + sampCB.m_structMembers.push_back(sMember); + } + } /* else if(!sfxConfig.passThroughSamplers && !sfxConfig.maintainSamplerDeclaration) { string str = sfxConfig.samplerDeclaration; @@ -2390,232 +2394,235 @@ int Effect::GetTextureNumber(string n,int specified_slot) find_and_replace(str, "{slot}", ToString(ss->register_number)); os< - //GLSL 420 has the struct declared with layout(std140, binding = X) uniform - //PSSL Doesn't support templatized ConstantBuffer, we need to convert it back to a global constant buffer. - if (sfxConfig.constantBufferDeclaration.length() || sfxConfig.sourceExtension.compare("pssl") == 0) - { - bool structIsUsedInTemplatizedConstantBuffer = false; - for (auto& decl : declarations) + case DeclarationType::RASTERIZERSTATE: + break; + case DeclarationType::DEPTHSTATE: + break; + case DeclarationType::BUFFER: + break; + case DeclarationType::STRUCT: + { + Struct *s = (Struct *)d; + string str = sfxConfig.structDeclaration; + if (str.length() == 0) + str = "struct {name}\n{\n[\t{type} {name};]};"; + + // Check if struct is used in templatized ConstantBuffer + // HLSL SM5.1 has the struct declared before ConstantBuffer<> + // GLSL 420 has the struct declared with layout(std140, binding = X) uniform + // PSSL Doesn't support templatized ConstantBuffer, we need to convert it back to a global constant buffer. + if (sfxConfig.constantBufferDeclaration.length() || sfxConfig.sourceExtension.compare("pssl") == 0) + { + bool structIsUsedInTemplatizedConstantBuffer = false; + for (auto &decl : declarations) + { + if (decl.second->declarationType == DeclarationType::CONSTANT_BUFFER && decl.second->structureType.length()) { - if (decl.second->declarationType == DeclarationType::CONSTANT_BUFFER && decl.second->structureType.length()) + if (decl.second->structureType.compare(d->name) == 0) { - if (decl.second->structureType.compare(d->name) == 0) - { - structIsUsedInTemplatizedConstantBuffer = true; - } + structIsUsedInTemplatizedConstantBuffer = true; } } - if (structIsUsedInTemplatizedConstantBuffer) - break; //Struct should now be declared with the templatized ConstantBuffer. } + if (structIsUsedInTemplatizedConstantBuffer) + break; // Struct should now be declared with the templatized ConstantBuffer. + } - if (sfxConfig.pixelOutputDeclaration.empty() || sfxConfig.pixelOutputDeclarationDSB.empty()) + if (sfxConfig.pixelOutputDeclaration.empty() || sfxConfig.pixelOutputDeclarationDSB.empty()) + { + for (auto &member : s->m_structMembers) { - for (auto& member : s->m_structMembers) + if (member.semantic.size() == std::string("SV_TARGET688366XX").size()) // SV_TARGET6883660##n for Dual Source Blending { - if (member.semantic.size() == std::string("SV_TARGET688366XX").size()) //SV_TARGET6883660##n for Dual Source Blending - { - char checkDSB[3]; - checkDSB[0] = (char)(10 * atoi(member.semantic.substr(9, 1).c_str())) + atoi(member.semantic.substr(10, 1).c_str()); - checkDSB[1] = (char)(10 * atoi(member.semantic.substr(11, 1).c_str())) + atoi(member.semantic.substr(12, 1).c_str()); - checkDSB[2] = (char)(10 * atoi(member.semantic.substr(13, 1).c_str())) + atoi(member.semantic.substr(14, 1).c_str()); - - if (checkDSB[0] != 'D' || checkDSB[1] != 'S' || checkDSB[2] != 'B') - std::cerr << "SV_TARGET index is not a valid for dual source blending: " << member.semantic << std::endl; - - int slotidx = atoi(member.semantic.substr(16, 1).c_str()); - int dsbIndex = atoi(member.semantic.substr(15, 1).c_str()); - int finalSV_TargetIdx = slotidx + dsbIndex; - if(finalSV_TargetIdx < 0 || finalSV_TargetIdx > 7) - std::cerr << "Resolved SV_TARGET index (for dual source blending) is not a valid: " << member.semantic << std::endl; - - std::string replacementSemantic = "SV_TARGET" + std::to_string(finalSV_TargetIdx); - size_t pos = s->original.find(member.semantic); - if(pos != std::string::npos) - s->original.replace(pos, member.semantic.size(), replacementSemantic); - } + char checkDSB[3]; + checkDSB[0] = (char)(10 * atoi(member.semantic.substr(9, 1).c_str())) + atoi(member.semantic.substr(10, 1).c_str()); + checkDSB[1] = (char)(10 * atoi(member.semantic.substr(11, 1).c_str())) + atoi(member.semantic.substr(12, 1).c_str()); + checkDSB[2] = (char)(10 * atoi(member.semantic.substr(13, 1).c_str())) + atoi(member.semantic.substr(14, 1).c_str()); + + if (checkDSB[0] != 'D' || checkDSB[1] != 'S' || checkDSB[2] != 'B') + std::cerr << "SV_TARGET index is not a valid for dual source blending: " << member.semantic << std::endl; + + int slotidx = atoi(member.semantic.substr(16, 1).c_str()); + int dsbIndex = atoi(member.semantic.substr(15, 1).c_str()); + int finalSV_TargetIdx = slotidx + dsbIndex; + if (finalSV_TargetIdx < 0 || finalSV_TargetIdx > 7) + std::cerr << "Resolved SV_TARGET index (for dual source blending) is not a valid: " << member.semantic << std::endl; + + std::string replacementSemantic = "SV_TARGET" + std::to_string(finalSV_TargetIdx); + size_t pos = s->original.find(member.semantic); + if (pos != std::string::npos) + s->original.replace(pos, member.semantic.size(), replacementSemantic); + } + } + } + + if (!s->hasVariants && sfxConfig.structDeclaration.length() == 0) + { + str = "{pass_through}"; + os << s->original.c_str() << endl; + return; + } + find_and_replace(str, "{pass_through}", s->original); + string members; + // in square brackets [] is the definition for ONE member. + string structMemberDeclaration; + process_member_decl(str, structMemberDeclaration); + int texcoord_auto_index = 0; + for (int i = 0; i < s->m_structMembers.size(); i++) + { + auto &member = s->m_structMembers[i]; + if (member.variantCondition.length() > 0) + { + string value = shaderInstance->variantValues[member.variantVariable]; + if (!CheckVariantCondition(member, value)) + continue; + } + string m = structMemberDeclaration; + // This should only be done for structs used for vertex output declaration + // GLSL requires the flat + if (member.type.length() && (member.type == "uint" || member.type == "int")) + { + find_and_replace(m, "{flat}", "flat"); + } + else + { + find_and_replace(m, "{flat}", ""); + } + find_and_replace(m, "{type}", member.type); + find_and_replace(m, "{name}", member.name); + if (member.semantic.size()) + { + string sem = ":"s + member.semantic; + if (member.semantic == "TEXCOORD_AUTO") + { + string number_str; + WriteInt(number_str, texcoord_auto_index++); + sem = ":TEXCOORD"s + number_str; } + find_and_replace(m, "{semantic}", sem); } + else + find_and_replace(m, "{semantic}", ""); + members += m + "\n"; + } + find_and_replace(str, "{members}", members); + find_and_replace(str, "{name}", s->name); + ReplaceRegexes(str, sfxConfig.replace); + os << str.c_str() << endl; + } + break; + case DeclarationType::CONSTANT_BUFFER: + { + // Anonymous. + ConstantBuffer *s = (ConstantBuffer *)d; + string str = sfxConfig.constantBufferDeclaration; + if (str.length() == 0) + { + str = "{pass_through}"; + os << s->original.c_str() << endl; + return; + } - if (!s->hasVariants && sfxConfig.structDeclaration.length() == 0) + find_and_replace(str, "{pass_through}", s->original); + string members; + // in square brackets [] is the definition for ONE member. + std::regex re_member("\\[(.*)\\]"); + std::smatch match; + string structMemberDeclaration; + if (std::regex_search(str, match, re_member)) + { + structMemberDeclaration = match[1].str(); + str.replace(match[0].first, match[0].first + match[0].length(), "{members}"); + } + for (int i = 0; i < s->m_structMembers.size(); i++) + { + auto &member = s->m_structMembers[i]; + if (member.variantCondition.length() > 0) { - str = "{pass_through}"; - os << s->original.c_str() << endl; - return; + string value = shaderInstance->variantValues[member.variantVariable]; + if (!CheckVariantCondition(member, value)) + continue; } - find_and_replace(str, "{pass_through}", s->original); + string m = structMemberDeclaration; + string type = member.type; + find_and_replace(m, "{type}", type); + find_and_replace(m, "{name}", s->m_structMembers[i].name); + find_and_replace(m, "{semantic}", s->m_structMembers[i].semantic); + members += m + "\n"; + } + find_and_replace(str, "{members}", members); + find_and_replace(str, "{name}", s->name); + if (s->slot == -1) + { + // Let the compiler decide + find_and_replace(str, "binding = {slot}", ""); + } + else + { + find_and_replace(str, "{slot}", ToString(GenerateConstantBufferSlot(s->slot))); + } + find_and_replace(str, "{group}", ToString(s->group_num)); + ReplaceRegexes(str, sfxConfig.replace); + os << str.c_str() << endl; + } + break; + case DeclarationType::NAMED_CONSTANT_BUFFER: + { + if (!d->structureType.length()) + { + std::cerr << "Could not find structureType:" << d->name << std::endl; + } + else if (!sfxConfig.namedConstantBufferDeclaration.length()) + { + std::cerr << "No namedConstantBufferDeclaration in json file:" << d->name << std::endl; + } + else + { + // named. + const NamedConstantBuffer *c = static_cast(d); + string str = sfxConfig.namedConstantBufferDeclaration; + Struct *s = (Struct *)declarations[d->structureType]; string members; // in square brackets [] is the definition for ONE member. + std::regex re_member("\\[(.*)\\]"); + std::smatch match; string structMemberDeclaration; - process_member_decl(str, structMemberDeclaration); - int texcoord_auto_index=0; + if (std::regex_search(str, match, re_member)) + { + structMemberDeclaration = match[1].str(); + str.replace(match[0].first, match[0].first + match[0].length(), "{members}"); + } for (int i = 0; i < s->m_structMembers.size(); i++) { + string m = structMemberDeclaration; auto &member = s->m_structMembers[i]; if (member.variantCondition.length() > 0) { string value = shaderInstance->variantValues[member.variantVariable]; + if (!CheckVariantCondition(member, value)) continue; } - string m = structMemberDeclaration; - // This should only be done for structs used for vertex output declaration - // GLSL requires the flat - if (member.type.length() && (member.type == "uint" || member.type == "int")) - { - find_and_replace(m, "{flat}", "flat"); - } - else - { - find_and_replace(m, "{flat}", ""); - } find_and_replace(m, "{type}", member.type); find_and_replace(m, "{name}", member.name); - if(member.semantic.size()) - { - string sem = ":"s+member.semantic; - if(member.semantic=="TEXCOORD_AUTO") - { - string number_str; - WriteInt(number_str,texcoord_auto_index++); - sem=":TEXCOORD"s+number_str; - } - find_and_replace(m, "{semantic}", sem); - } - else - find_and_replace(m, "{semantic}", ""); + find_and_replace(m, "{semantic}", member.semantic); members += m + "\n"; } find_and_replace(str, "{members}", members); - find_and_replace(str, "{name}", s->name); + find_and_replace(str, "{name}", s->structureType); + find_and_replace(str, "{slot}", ToString(c->slot)); + find_and_replace(str, "{group}", ToString(c->group_num)); + find_and_replace(str, "{instance_name}", c->instance_name); + ReplaceRegexes(str, sfxConfig.replace); os << str.c_str() << endl; } - break; - case DeclarationType::CONSTANT_BUFFER: - { - // Anonymous. - ConstantBuffer* s = (ConstantBuffer*)d; - string str = sfxConfig.constantBufferDeclaration; - if (str.length() == 0) - { - str = "{pass_through}"; - os << s->original.c_str() << endl; - return; - } - - find_and_replace(str, "{pass_through}", s->original); - string members; - // in square brackets [] is the definition for ONE member. - std::regex re_member("\\[(.*)\\]"); - std::smatch match; - string structMemberDeclaration; - if (std::regex_search(str, match, re_member)) - { - structMemberDeclaration = match[1].str(); - str.replace(match[0].first, match[0].first + match[0].length(), "{members}"); - } - for (int i = 0; i < s->m_structMembers.size(); i++) - { - auto &member = s->m_structMembers[i]; - if(member.variantCondition.length()>0) - { - string value = shaderInstance->variantValues[member.variantVariable]; - if (!CheckVariantCondition(member, value)) - continue; - } - string m = structMemberDeclaration; - string type = member.type; - find_and_replace(m, "{type}", type); - find_and_replace(m, "{name}", s->m_structMembers[i].name); - find_and_replace(m, "{semantic}", s->m_structMembers[i].semantic); - members += m + "\n"; - } - find_and_replace(str, "{members}", members); - find_and_replace(str, "{name}", s->name); - if (s->slot == -1) - { - // Let the compiler decide - find_and_replace(str, "binding = {slot}", ""); - } - else - { - find_and_replace(str, "{slot}", ToString(GenerateConstantBufferSlot(s->slot))); - } - find_and_replace(str, "{group}", ToString(s->group_num)); - os << str.c_str() << endl; - } - break; - case DeclarationType::NAMED_CONSTANT_BUFFER: - { - if (!d->structureType.length()) - { - std::cerr << "Could not find structureType:" << d->name << std::endl; - } - else if (!sfxConfig.namedConstantBufferDeclaration.length()) - { - std::cerr << "No namedConstantBufferDeclaration in json file:" << d->name << std::endl; - } - else - { - // named. - const NamedConstantBuffer *c = static_cast(d); - string str = sfxConfig.namedConstantBufferDeclaration; - Struct* s = (Struct*)declarations[d->structureType]; - string members; - // in square brackets [] is the definition for ONE member. - std::regex re_member("\\[(.*)\\]"); - std::smatch match; - string structMemberDeclaration; - if (std::regex_search(str, match, re_member)) - { - structMemberDeclaration = match[1].str(); - str.replace(match[0].first, match[0].first + match[0].length(), "{members}"); - } - for (int i = 0; i < s->m_structMembers.size(); i++) - { - string m = structMemberDeclaration; - auto &member = s->m_structMembers[i]; - if(member.variantCondition.length()>0) - { - string value = shaderInstance->variantValues[member.variantVariable]; - - if (!CheckVariantCondition(member, value)) - continue; - } - find_and_replace(m, "{type}", member.type); - find_and_replace(m, "{name}", member.name); - find_and_replace(m, "{semantic}", member.semantic); - members += m + "\n"; - } - find_and_replace(str, "{members}", members); - find_and_replace(str, "{name}", s->structureType); - find_and_replace(str, "{slot}", ToString(c->slot)); - find_and_replace(str, "{group}", ToString(c->group_num)); - find_and_replace(str, "{instance_name}", c->instance_name); - os << str.c_str() << endl; - } - } - break; - default: + } + break; + default: break; }; } @@ -2637,18 +2644,18 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } std::set decs; - std::set samplerStates; + std::set samplerStates; std::set rwTexturesUsedForLoad; std::set fns; AccumulateFunctionsUsed(function, shaderInstance->variantValues, fns); - for(auto f:fns) - AccumulateDeclarationsUsed(f, shaderInstance->variantValues,decs, rwTexturesUsedForLoad); + for (auto f : fns) + AccumulateDeclarationsUsed(f, shaderInstance->variantValues, decs, rwTexturesUsedForLoad); // Keep a set of the sampler states used: for (const auto d : decs) { - if(d->declarationType == DeclarationType::SAMPLER) + if (d->declarationType == DeclarationType::SAMPLER) { - SamplerState* ss = (SamplerState*)d; + SamplerState *ss = (SamplerState *)d; if (ss) { samplerStates.insert(ss); @@ -2657,85 +2664,85 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } std::set globals; for (auto f : fns) - AccumulateGlobalsAsStrings(f,globals); + AccumulateGlobalsAsStrings(f, globals); // find out what slots the function uses by interrogating its global variables. // At this point we're not interested in params, just globals. - for(auto i:globals) + for (auto i : globals) { - string type=gEffect->GetDeclaredType(i); - auto d=gEffect->GetDeclarations().find(i); - if (d==gEffect->GetDeclarations().end()) + string type = gEffect->GetDeclaredType(i); + auto d = gEffect->GetDeclarations().find(i); + if (d == gEffect->GetDeclarations().end()) continue; - Declaration *dec=d->second; + Declaration *dec = d->second; decs.insert(dec); } for (auto f : fns) - AccumulateConstantBuffersUsed(f,*shaderInstance); + AccumulateConstantBuffersUsed(f, *shaderInstance); // for now, add in ALL the constant buffers - except the named ones, we should be able to // distinguish which of those are needed... - for(auto i:shaderInstance->constantBuffers) + for (auto i : shaderInstance->constantBuffers) { - if(i->declarationType!=DeclarationType::NAMED_CONSTANT_BUFFER) + if (i->declarationType != DeclarationType::NAMED_CONSTANT_BUFFER) decs.insert(i); } - std::map ordered_decs; + std::map ordered_decs; for (auto u = decs.begin(); u != decs.end(); u++) { (*u)->ref_count++; // Check if this declaration is dependent on a variant condition: shaderInstance->declarations.insert(*u); - int main_linenumber=(*u)->global_line_number; + int main_linenumber = (*u)->global_line_number; while (ordered_decs.find(main_linenumber) != ordered_decs.end()) { main_linenumber++; } - ordered_decs[main_linenumber]=*u; + ordered_decs[main_linenumber] = *u; } // Used for platforms that dont support separate sampler and textures: ConstantBuffer textureCB; ConstantBuffer samplerCB; // declare the samplers if we didn't pass them through already: - if(!sfxConfig.passThroughSamplers) + if (!sfxConfig.passThroughSamplers) { for (const auto s : samplerStates) { - if(sfxConfig.samplerDeclaration.size() > 0) + if (sfxConfig.samplerDeclaration.size() > 0) { - string thisDeclaration=sfxConfig.samplerDeclaration; - find_and_replace(thisDeclaration,"{name}",s->name); + string thisDeclaration = sfxConfig.samplerDeclaration; + find_and_replace(thisDeclaration, "{name}", s->name); find_and_replace(thisDeclaration, "{slot}", ToString(gEffect->GenerateSamplerSlot(s->register_number))); find_and_replace(thisDeclaration, "{group}", ToString(s->group_num)); - find_and_replace(thisDeclaration,"{type}","sampler"); - theShader<original<<"\n"; + theShader << s->original << "\n"; } } } - char kTexHandleUbo [] = "_TextureHandles_X"; - char ext[]={'v','h','d','g','p','c'}; - bool combo=sfxConfig.combineTexturesSamplers&&!sfxConfig.combineInShader; + char kTexHandleUbo[] = "_TextureHandles_X"; + char ext[] = {'v', 'h', 'd', 'g', 'p', 'c'}; + bool combo = sfxConfig.combineTexturesSamplers && !sfxConfig.combineInShader; if (combo) { - textureCB.declarationType = DeclarationType::CONSTANT_BUFFER; - kTexHandleUbo[16]=ext[shaderInstance->shaderType]; - textureCB.name = kTexHandleUbo; - textureCB.ref_count = 1; - textureCB.slot = kTexHandleUbo[16] == 'p' ? 1 : 0; + textureCB.declarationType = DeclarationType::CONSTANT_BUFFER; + kTexHandleUbo[16] = ext[shaderInstance->shaderType]; + textureCB.name = kTexHandleUbo; + textureCB.ref_count = 1; + textureCB.slot = kTexHandleUbo[16] == 'p' ? 1 : 0; - samplerCB.declarationType = DeclarationType::CONSTANT_BUFFER; - samplerCB.name = "_SamplerHandles_"; - samplerCB.ref_count = 1; - samplerCB.slot = -1; + samplerCB.declarationType = DeclarationType::CONSTANT_BUFFER; + samplerCB.name = "_SamplerHandles_"; + samplerCB.ref_count = 1; + samplerCB.slot = -1; } theShader << shaderInstance->variantDefinitions; - + // Declare them! - for(auto u=ordered_decs.begin();u!=ordered_decs.end();u++) + for (auto u = ordered_decs.begin(); u != ordered_decs.end(); u++) { - const Declaration *d=(u->second); + const Declaration *d = (u->second); if (d->line_number > 0 && d->file_number > 0) { // Dont add the line number for textures and samplers as we will acum it @@ -2754,22 +2761,22 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) { if (!textureCB.m_structMembers.empty()) { - Declare(shaderInstance,theShader, (Declaration*)&textureCB, textureCB, samplerCB, rwTexturesUsedForLoad, samplerStates,function); + Declare(shaderInstance, theShader, (Declaration *)&textureCB, textureCB, samplerCB, rwTexturesUsedForLoad, samplerStates, function); } if (sfxConfig.combineInShader && !samplerCB.m_structMembers.empty()) { - Declare(shaderInstance,theShader, (Declaration*)&samplerCB, textureCB, samplerCB, rwTexturesUsedForLoad, samplerStates, function); + Declare(shaderInstance, theShader, (Declaration *)&samplerCB, textureCB, samplerCB, rwTexturesUsedForLoad, samplerStates, function); } } std::map ordered_fns; std::set vars; - for(auto u=fns.begin();u!=fns.end();u++) + for (auto u = fns.begin(); u != fns.end(); u++) { AccumulateGlobals(*u, vars); // Add only the called functions, not the main one. That goes at the end. if (*u != function) { - ordered_fns[(*u)->main_linenumber]=*u; + ordered_fns[(*u)->main_linenumber] = *u; } else { @@ -2782,10 +2789,10 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } } - //Convert constant buffer accesses from templatized to global style in main function: + // Convert constant buffer accesses from templatized to global style in main function: if (sfxConfig.sourceExtension.compare("pssl") == 0) { - for (auto& decl : declarations) + for (auto &decl : declarations) { if (decl.second->declarationType == DeclarationType::CONSTANT_BUFFER && decl.second->structureType.length()) { @@ -2797,22 +2804,22 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } for (auto v = vars.begin(); v != vars.end(); v++) { - theShader<original<original << std::endl; } - for(auto u=ordered_fns.begin();u!=ordered_fns.end();u++) + for (auto u = ordered_fns.begin(); u != ordered_fns.end(); u++) { - const Function* f = (u->second); + const Function *f = (u->second); if (GetOptions()->disableLineWrites) - theShader <<"//"; + theShader << "//"; theShader << "#line " << f->local_linenumber << " " << gEffect->GetFilenameOrNumber(f->filename) << endl; - std::string newDec = f->declaration; + std::string newDec = f->declaration; std::string newCont = f->content; - + // Remove semantics on non-main functions: if (combo) { - find_and_replace(newDec, ":",""); - for (auto & p : f->parameters) + find_and_replace(newDec, ":", ""); + for (auto &p : f->parameters) { find_and_replace(newDec, p.semantic, ""); } @@ -2825,10 +2832,10 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) find_and_replace(newCont, s->name, "1 + " + std::to_string(s->register_number)); } } - //Convert constant buffer accesses from templatized to global style in non-main functions: + // Convert constant buffer accesses from templatized to global style in non-main functions: if (sfxConfig.sourceExtension.compare("pssl") == 0) { - for (auto& decl : declarations) + for (auto &decl : declarations) { if (decl.second->declarationType == DeclarationType::CONSTANT_BUFFER && decl.second->structureType.length()) { @@ -2838,81 +2845,82 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } theShader << newDec; - theShader << "\n{\n" << newCont << "\n}\n"; + theShader << "\n{\n" + << newCont << "\n}\n"; } - string entryPoint = "main"; - const SfxConfig *config = gEffect->GetConfig(); - string dec = function->declaration; + string entryPoint = "main"; + const SfxConfig *config = gEffect->GetConfig(); + string dec = function->declaration; if (config->entryPointOption.length() > 0) { - entryPoint = shaderName; + entryPoint = shaderName; } else { - find_and_replace(dec,shaderName,"main"); + find_and_replace(dec, shaderName, "main"); } - + // in square brackets [] is the definition for ONE member. string memberDeclaration; - //find_and_replace(memberDeclaration,"{blockname}",blockname); - // extract and replace the member declaration. - // If this shader language can't accept input parameters in main shader functions - // we will have an inputDeclaration specifying how to rewrite the input. - bool split_structs = false; - int num=0; + // find_and_replace(memberDeclaration,"{blockname}",blockname); + // extract and replace the member declaration. + // If this shader language can't accept input parameters in main shader functions + // we will have an inputDeclaration specifying how to rewrite the input. + bool split_structs = false; + int num = 0; string inputDeclaration = sfxConfig.pixelInputDeclaration; - if(shaderInstance->shaderType==sfx::ShaderType::VERTEX_SHADER) + if (shaderInstance->shaderType == sfx::ShaderType::VERTEX_SHADER) { if (sfxConfig.vertexInputDeclaration.length() > 0) { - inputDeclaration=sfxConfig.vertexInputDeclaration; + inputDeclaration = sfxConfig.vertexInputDeclaration; split_structs = true; } } - if(shaderInstance->shaderType==sfx::ShaderType::FRAGMENT_SHADER) + if (shaderInstance->shaderType == sfx::ShaderType::FRAGMENT_SHADER) { - if(sfxConfig.pixelInputDeclaration.find("{member_type}")content; - string str=inputDeclaration; - process_member_decl(str,memberDeclaration); + string content = function->content; + string str = inputDeclaration; + process_member_decl(str, memberDeclaration); string blockname = "ioblock"; - if(inputDeclaration.length()>0) + if (inputDeclaration.length() > 0) { string members; string setup_code; - for(auto i:function->parameters) + for (auto i : function->parameters) { auto D = declarations.find(i.type); - Declaration *d=nullptr; + Declaration *d = nullptr; if (D != declarations.end()) - d=D->second; - // It is a struct + d = D->second; + // It is a struct if (d && split_structs && d->declarationType == DeclarationType::STRUCT) { - Struct *s=(Struct *)d; - if(s) + Struct *s = (Struct *)d; + if (s) { - setup_code+=(i.type+" ")+i.identifier+";\n"; + setup_code += (i.type + " ") + i.identifier + ";\n"; string structPrefix; - if(shaderInstance->shaderType==sfx::ShaderType::FRAGMENT_SHADER) + if (shaderInstance->shaderType == sfx::ShaderType::FRAGMENT_SHADER) { - structPrefix=i.type+"BlocKData"; + structPrefix = i.type + "BlocKData"; } - for(auto j:s->m_structMembers) + for (auto j : s->m_structMembers) { - string m=memberDeclaration; - if(j.variantCondition.length()>0) + string m = memberDeclaration; + if (j.variantCondition.length() > 0) { - string value=shaderInstance->variantValues[j.variantVariable]; - if(!CheckVariantCondition(j,value)) + string value = shaderInstance->variantValues[j.variantVariable]; + if (!CheckVariantCondition(j, value)) continue; } /*if(j.variantCondition.length()>0) @@ -2920,23 +2928,23 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) setup_code+="#if "; setup_code+=j.variantCondition+"\n"; }*/ - find_and_replace(m,"{struct_type}",i.type); - find_and_replace(m,"{struct_name}","BlocKData"); - find_and_replace(m,"{member_type}",j.type); - find_and_replace(m,"{member_name}",j.name); - find_and_replace(m,"{type}",j.type); - find_and_replace(m,"{name}",j.name); - find_and_replace(m,"{semantic}",j.semantic); + find_and_replace(m, "{struct_type}", i.type); + find_and_replace(m, "{struct_name}", "BlocKData"); + find_and_replace(m, "{member_type}", j.type); + find_and_replace(m, "{member_name}", j.name); + find_and_replace(m, "{type}", j.type); + find_and_replace(m, "{name}", j.name); + find_and_replace(m, "{semantic}", j.semantic); find_and_replace(m, "{slot}", ToString(num++)); - auto s=sfxConfig.vertexSemantics.find(j.semantic); - if(shaderInstance->shaderType==sfx::ShaderType::VERTEX_SHADER&&s!=sfxConfig.vertexSemantics.end()) + auto s = sfxConfig.vertexSemantics.find(j.semantic); + if (shaderInstance->shaderType == sfx::ShaderType::VERTEX_SHADER && s != sfxConfig.vertexSemantics.end()) { - setup_code+=((i.identifier+".")+j.name+"=")+s->second+";\n"; + setup_code += ((i.identifier + ".") + j.name + "=") + s->second + ";\n"; } else { - members+=m+"\n"; - setup_code+=((i.identifier+".")+j.name+"=")+structPrefix+j.name+";\n"; + members += m + "\n"; + setup_code += ((i.identifier + ".") + j.name + "=") + structPrefix + j.name + ";\n"; } /*if (j.variantCondition.length() > 0) { @@ -2956,20 +2964,20 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } } // Fragment shader (could be or not a struct) - else if(shaderInstance->shaderType == sfx::ShaderType::FRAGMENT_SHADER) + else if (shaderInstance->shaderType == sfx::ShaderType::FRAGMENT_SHADER) { string customId = i.identifier; - auto s=sfxConfig.pixelSemantics.find(i.semantic); - if(i.semantic.length()>0&&s!=sfxConfig.pixelSemantics.end()) + auto s = sfxConfig.pixelSemantics.find(i.semantic); + if (i.semantic.length() > 0 && s != sfxConfig.pixelSemantics.end()) { - setup_code+=((i.type+" ")+i.identifier+"=")+s->second+";\n"; + setup_code += ((i.type + " ") + i.identifier + "=") + s->second + ";\n"; } else { if (sfxConfig.identicalIOBlocks) { // In GLSL io blocks should match, i.e. the names of - // the members should be the same. + // the members should be the same. customId = "BlockData0"; find_and_replace(content, i.identifier, customId); } @@ -2979,11 +2987,11 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) find_and_replace_identifier(content, i.identifier, customId); } string m = memberDeclaration; - string acceptable_type=i.type; + string acceptable_type = i.type; // ioblocks can't have bool's. - if(i.type=="bool") + if (i.type == "bool") { - acceptable_type="char"; + acceptable_type = "char"; } find_and_replace(m, "{type}", acceptable_type); find_and_replace(m, "{name}", customId); @@ -2996,11 +3004,11 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) // Compute shader (could be or not a struct) else if (shaderInstance->shaderType == sfx::ShaderType::COMPUTE_SHADER) { - for (auto s: sfxConfig.computeSemantics) + for (auto s : sfxConfig.computeSemantics) { if (strcasecmp(s.first.c_str(), i.semantic.c_str()) == 0) { - setup_code += i.type + " " + i.identifier + " = " + s.second + ";\n"; + setup_code += i.type + " " + i.identifier + " = " + s.second + ";\n"; break; } } @@ -3013,41 +3021,41 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) // Write members if (!members.empty()) { - find_and_replace(str,"{members}",members); + find_and_replace(str, "{members}", members); find_and_replace(str, "{slot}", ToString(0)); - theShader<returnType!="void") + if (function->returnType != "void") { - if(shaderInstance->shaderType==sfx::ShaderType::FRAGMENT_SHADER) + if (shaderInstance->shaderType == sfx::ShaderType::FRAGMENT_SHADER) { - if(sfxConfig.pixelOutputDeclaration.length()>0) + if (sfxConfig.pixelOutputDeclaration.length() > 0) { // replace each return statement with a block that writes - string str=sfxConfig.pixelOutputDeclaration; - find_and_replace(str,"{slot}","0"); // TODO: What if this is not 0! + string str = sfxConfig.pixelOutputDeclaration; + find_and_replace(str, "{slot}", "0"); // TODO: What if this is not 0! string m; // extract and replace the member declaration. - process_member_decl(str,m); + process_member_decl(str, m); // Simple case: one return. - if(function->returnType=="vec4"|| function->returnType == "float4") + if (function->returnType == "vec4" || function->returnType == "float4") { // Declare the output - string returnName="returnObject_"+function->returnType; - find_and_replace(m,"{type}",function->returnType); - find_and_replace(m,"{name}",returnName); - find_and_replace(m,"{slot}","0"); // What if this is not 0! Could be SV_TARGET4! - find_and_replace(str,"{members}",m+"\n"); - theShader<returnType; + find_and_replace(m, "{type}", function->returnType); + find_and_replace(m, "{name}", returnName); + find_and_replace(m, "{slot}", "0"); // What if this is not 0! Could be SV_TARGET4! + find_and_replace(str, "{members}", m + "\n"); + theShader << str.c_str() << endl; // now replace every instance of return ...; with returnName=...;return; regex re("return\\s+(.*);"); - string ret="{"; + string ret = "{"; // CHECK ret += returnName + "=$1;return;}"; - //ret+=returnName+"=$1;return;}"; + // ret+=returnName+"=$1;return;}"; content = std::regex_replace(content, re, ret); } // We are returning a struct? @@ -3056,12 +3064,12 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) auto outStructDec = declarations.find(function->returnType); if (outStructDec != declarations.end()) { - auto s = (Struct*)outStructDec->second; + auto s = (Struct *)outStructDec->second; content += "\n"; for (auto member : s->m_structMembers) { string str; - if (member.semantic.size() == std::string("SV_TARGET688366XX").size() && sfxConfig.pixelOutputDeclarationDSB.length() > 0 ) + if (member.semantic.size() == std::string("SV_TARGET688366XX").size() && sfxConfig.pixelOutputDeclarationDSB.length() > 0) str = sfxConfig.pixelOutputDeclarationDSB; else str = sfxConfig.pixelOutputDeclaration; @@ -3083,12 +3091,11 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) // TO-DO: replace with gl_Depth = value; slotidx = "1"; content += "gl_FragDepth = tmp." + member.name + ";\n"; - } - else if (member.semantic.size() == std::string("SV_TARGET688366XX").size()) //SV_TARGET6883660##n for Dual Source Blending + else if (member.semantic.size() == std::string("SV_TARGET688366XX").size()) // SV_TARGET6883660##n for Dual Source Blending { char checkDSB[3]; - checkDSB[0] = (char)(10 * atoi(member.semantic.substr(9 , 1).c_str())) + atoi(member.semantic.substr(10, 1).c_str()); + checkDSB[0] = (char)(10 * atoi(member.semantic.substr(9, 1).c_str())) + atoi(member.semantic.substr(10, 1).c_str()); checkDSB[1] = (char)(10 * atoi(member.semantic.substr(11, 1).c_str())) + atoi(member.semantic.substr(12, 1).c_str()); checkDSB[2] = (char)(10 * atoi(member.semantic.substr(13, 1).c_str())) + atoi(member.semantic.substr(14, 1).c_str()); @@ -3108,7 +3115,7 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } // TO-DO: find a way of implementing this find_and_replace(m, "{slot}", slotidx); - //find_and_replace(m, "{slot}", std::to_string(cnt)); + // find_and_replace(m, "{slot}", std::to_string(cnt)); find_and_replace(str, "{members}", m + "\n"); theShader << str.c_str() << endl; content += member.name + " = tmp." + member.name + ";\n"; @@ -3125,70 +3132,70 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) } } } - else if(sfxConfig.vertexOutputDeclaration.length()>0) + else if (sfxConfig.vertexOutputDeclaration.length() > 0) { - Declaration* retDec = nullptr; + Declaration *retDec = nullptr; auto retEntry = declarations.find(function->returnType); // replace each return statement with a block that writes - string vertexOutputDeclaration=sfxConfig.vertexOutputDeclaration; - find_and_replace(vertexOutputDeclaration,"{blockname}",blockname); + string vertexOutputDeclaration = sfxConfig.vertexOutputDeclaration; + find_and_replace(vertexOutputDeclaration, "{blockname}", blockname); string m; // extract and replace the member declaration. - process_member_decl(vertexOutputDeclaration,m); + process_member_decl(vertexOutputDeclaration, m); string members; // if the member declaration contains member_name, we will declar the struct members individually, instead of passing a whole structure. // This alternative approach is to get around Qualcomm's broken SPIR-V drivers for Adreno 600-series devices, e.g. Oculus Quest etc. // NOTE(NACHO): we want to match io block member names... - bool as_blocks=true; - if(m.find("{member_name}")second; - int slot=1; + int slot = 1; if (retDec && retDec->declarationType == DeclarationType::STRUCT) { - Struct* retStruct = (Struct *)retDec; + Struct *retStruct = (Struct *)retDec; for (auto j : retStruct->m_structMembers) { - if(j.variantCondition.length()>0) + if (j.variantCondition.length() > 0) { - string value=shaderInstance->variantValues[j.variantVariable]; - if(!CheckVariantCondition(j,value)) + string value = shaderInstance->variantValues[j.variantVariable]; + if (!CheckVariantCondition(j, value)) continue; } - string this_member_decl=m; - find_and_replace(this_member_decl,"{member_type}",j.type); - find_and_replace(this_member_decl,"{member_name}",j.name); - find_and_replace(this_member_decl,"{slot}",std::to_string(slot++)); // TODO: What if this is not 0! - members+=this_member_decl+"\n"; + string this_member_decl = m; + find_and_replace(this_member_decl, "{member_type}", j.type); + find_and_replace(this_member_decl, "{member_name}", j.name); + find_and_replace(this_member_decl, "{slot}", std::to_string(slot++)); // TODO: What if this is not 0! + members += this_member_decl + "\n"; } } - m=members; + m = members; } else { - members=m; + members = m; } string returnName = "BlockData0"; - find_and_replace(members,"{type}",function->returnType); - find_and_replace(members,"{name}",returnName); - find_and_replace(vertexOutputDeclaration,"{members}",members+"\n"); - - find_and_replace(vertexOutputDeclaration,"{slot}","0"); // TODO: What if this is not 0! + find_and_replace(members, "{type}", function->returnType); + find_and_replace(members, "{name}", returnName); + find_and_replace(vertexOutputDeclaration, "{members}", members + "\n"); + + find_and_replace(vertexOutputDeclaration, "{slot}", "0"); // TODO: What if this is not 0! // Now construct the replacement for the return command. string ret = "{\n"; regex re("return\\s+(.*);"); // if we're returning by block - // + // // Now replace every instance of return ...; with returnName=...;return; - if(as_blocks) + if (as_blocks) { ret += (blockname + ".") + returnName + "=$1;"; } else { - // If we're filling individual elements: + // If we're filling individual elements: } // If required, write to global outputs @@ -3197,13 +3204,13 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) retDec = retEntry->second; if (retDec && retDec->declarationType == DeclarationType::STRUCT) { - Struct* retStruct = (Struct *)retDec; + Struct *retStruct = (Struct *)retDec; for (auto j : retStruct->m_structMembers) { - std::string returnobject = (blockname + ".") + returnName; - if(!as_blocks) + std::string returnobject = (blockname + ".") + returnName; + if (!as_blocks) { - string this_member_fill= function->returnType+returnName+j.name + "=" + "$1" + "." + j.name + ";\n"; + string this_member_fill = function->returnType + returnName + j.name + "=" + "$1" + "." + j.name + ";\n"; ret += this_member_fill; returnobject = returnName; } @@ -3213,9 +3220,9 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) if (sem != sfxConfig.vertexOutputAssignment.end()) { std::string code; - if(sfxConfig.reverseVertexOutputY&&is_equal(j.semantic,"SV_POSITION")) + if (sfxConfig.reverseVertexOutputY && is_equal(j.semantic, "SV_POSITION")) { - code += "\n"s + sem->second + "="s + "vec4("s+returnobject+"." + j.name + ".x,-"s+returnobject+"." + j.name + ".y,"s+returnobject+"."+j.name+".z,"s+returnobject+"."+j.name+".w);\n "; + code += "\n"s + sem->second + "="s + "vec4("s + returnobject + "." + j.name + ".x,-"s + returnobject + "." + j.name + ".y,"s + returnobject + "." + j.name + ".z,"s + returnobject + "." + j.name + ".w);\n "; } else { @@ -3230,7 +3237,7 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) ret += "\n}"; content = std::regex_replace(content, re, ret); - theShader< 0) { std::string cur; - std::vector < std::string> items; + std::vector items; bool isReading = false; // First we get all the values for (auto c : csLayout) @@ -3268,31 +3275,31 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) find_and_replace(csLayout, "$3", items[2]); } - theShader<< csLayout <<"\n"; + theShader << csLayout << "\n"; } if (shaderInstance->shaderType == RAY_GENERATION_SHADER) { - theShader<<"[shader(\"raygeneration\")]\n"; + theShader << "[shader(\"raygeneration\")]\n"; } if (shaderInstance->shaderType == CLOSEST_HIT_SHADER) { - theShader<<"[shader(\"closesthit\")]\n"; + theShader << "[shader(\"closesthit\")]\n"; } if (shaderInstance->shaderType == ANY_HIT_SHADER) { - theShader<<"[shader(\"anyhit\")]\n";//sfxConfig + theShader << "[shader(\"anyhit\")]\n"; // sfxConfig } if (shaderInstance->shaderType == MISS_SHADER) { - theShader<<"[shader(\"miss\")]\n";//sfxConfig + theShader << "[shader(\"miss\")]\n"; // sfxConfig } if (shaderInstance->shaderType == INTERSECTION_SHADER) { - theShader << "[shader(\"intersection\")]\n";//sfxConfig + theShader << "[shader(\"intersection\")]\n"; // sfxConfig } if (shaderInstance->shaderType == CALLABLE_SHADER) { - theShader<<"[shader(\"callable\")]\n";//sfxConfig + theShader << "[shader(\"callable\")]\n"; // sfxConfig } // Only if COMPILED as a GS, not VS streamout. if (shaderInstance->shaderType == GEOMETRY_SHADER) @@ -3310,8 +3317,8 @@ void Effect::ConstructSource(ShaderInstance *shaderInstance) // Add main function content: theShader << "{\n"; theShader << shaderInstance->variantDeclarations; - theShader<m_augmentedSource = theShader.str(); } diff --git a/Applications/Sfx/SfxEffect.h b/Applications/Sfx/SfxEffect.h index b3004d2b0..725946ac7 100644 --- a/Applications/Sfx/SfxEffect.h +++ b/Applications/Sfx/SfxEffect.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "Sfx.h" #include "SfxParser.h" #include "Function.h" diff --git a/Applications/Sfx/StringFunctions.cpp b/Applications/Sfx/StringFunctions.cpp index 6b1bbf3dc..9b607a4cd 100644 --- a/Applications/Sfx/StringFunctions.cpp +++ b/Applications/Sfx/StringFunctions.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace std; #ifndef _MSC_VER diff --git a/CMake/Include.cmake b/CMake/Include.cmake index 6f015dbb1..8114b4a2f 100644 --- a/CMake/Include.cmake +++ b/CMake/Include.cmake @@ -1,6 +1,6 @@ include_guard() -set( PLATFORM_CPP_VERSION 20 CACHE STRING "Set the C++ version to compile." ) +set( PLATFORM_CPP_VERSION 17 CACHE STRING "Set the C++ version to compile." ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_CXX_EXTENSIONS ON ) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -297,8 +297,8 @@ function(LibraryDefaults targname) target_compile_definitions(${targname} PRIVATE PLATFORM_NO_OPTIMIZATION ) elseif(PLATFORM_LINUX) target_compile_definitions(${targname} PRIVATE "PLATFORM_NO_OPTIMIZATION=__attribute__((optnone))" ) - target_compile_options(${targname} PRIVATE -Wall -Wextra -pedantic -Wno-keyword-macro -Wno-ignored-qualifiers -Wno-unused-function -Wno-sign-compare -Wno-gnu-anonymous-struct -Wno-gnu-redeclared-enum -Wno-nested-anon-types -Wno-gnu-zero-variadic-macro-arguments -Wno-unused-parameter -Wno-unused-variable -Wno-unused-value -Wno-missing-braces -Wno-keyword-macro -Wno-language-extension-token -Wno-missing-field-initializers) - target_compile_options(${targname} PUBLIC -Wall -Wextra -pedantic -Wno-keyword-macro -Wno-ignored-qualifiers -Wno-unused-function -Wno-sign-compare -Wno-gnu-anonymous-struct -Wno-gnu-redeclared-enum -Wno-nested-anon-types -Wno-gnu-zero-variadic-macro-arguments -Wno-unused-parameter -Wno-unused-variable -Wno-unused-value -Wno-missing-braces -Wno-inconsistent-missing-override -Wno-deprecated-declarations) + target_compile_options(${targname} PRIVATE -pedantic -Wno-nullability-completeness -Wno-keyword-macro -Wno-ignored-qualifiers -Wno-unused-function -Wno-sign-compare -Wno-gnu-anonymous-struct -Wno-gnu-redeclared-enum -Wno-nested-anon-types -Wno-gnu-zero-variadic-macro-arguments -Wno-unused-parameter -Wno-unused-variable -Wno-unused-value -Wno-missing-braces -Wno-keyword-macro -Wno-language-extension-token -Wno-missing-field-initializers) + target_compile_options(${targname} PUBLIC -pedantic -Wno-nullability-completeness -Wno-keyword-macro -Wno-ignored-qualifiers -Wno-unused-function -Wno-sign-compare -Wno-gnu-anonymous-struct -Wno-gnu-redeclared-enum -Wno-nested-anon-types -Wno-gnu-zero-variadic-macro-arguments -Wno-unused-parameter -Wno-unused-variable -Wno-unused-value -Wno-missing-braces -Wno-inconsistent-missing-override -Wno-deprecated-declarations) elseif(PLATFORM_EMSCRIPTEN) target_compile_definitions(${targname} PRIVATE "PLATFORM_NO_OPTIMIZATION=__attribute__((optnone))" ) set_target_properties(${targname} PROPERTIES LINK_FLAGS "-s USE_WEBGPU -s WASM=1 -s ASSERTIONS=1 -s SAFE_HEAP=1 -s DEMANGLE_SUPPORT=1 -s EXPORTED_RUNTIME_METHODS=['ccall'] ") @@ -352,9 +352,9 @@ function(add_static_library libname) set(LINK_SUFFIX "_MD" ) endif() endif() - - set(target "${libname}${LINK_SUFFIX}") - set(target "${target}" PARENT_SCOPE) + + set(target "${libname}${LINK_SUFFIX}" ) + set(target "${libname}${LINK_SUFFIX}" PARENT_SCOPE) add_library(${target} STATIC ${IMP_LIB} ) add_library(Platform::${target} ALIAS ${target}) if(SIMUL_SOURCE_BUILD) @@ -416,22 +416,16 @@ function(add_static_library libname) else() ImportedLibraryDefaults(${target}) endif() - message("add_static_library target is " ${target}) - return(PROPAGATE target) endfunction() function(add_dynamic_library libname) if( SIMUL_DYNAMIC_LIBS ) add_dll( ${libname} ${ARGN} ) - set(target "${target}" PARENT_SCOPE) - return(PROPAGATE target) endif() - return("") endfunction() function(add_dll libname) set(target "${libname}${DYNAMIC_LINK_SUFFIX}") - set(target "${target}" PARENT_SCOPE) cmake_parse_arguments(dll "" "RUNTIME;FOLDER" "SOURCES;DEFINITIONS;LINK;LINK_DIRS;PROPERTIES;INCLUDES;PUBLICINCLUDES" ${ARGN} ) if("${dll_FOLDER}" STREQUAL "") set(dll_FOLDER Dynamic) @@ -501,7 +495,6 @@ function(add_dll libname) else() ImportedLibraryDefaults(${target}) endif() - return(PROPAGATE target) endfunction() function(ExecutableDefaults target) @@ -543,7 +536,6 @@ function(add_static_executable target) set_target_runtime(${target} ${PLATFORM_WINDOWS_RUNTIME}) LibraryDefaults(${target}) ExecutableDefaults(${target}) - return(PROPAGATE target) endfunction() function(add_dynamic_executable target) @@ -580,5 +572,4 @@ function(add_dynamic_executable target) if(NOT "${exe_LINK}" STREQUAL "") target_link_libraries( ${target} ${exe_LINK} ) endif() - return(PROPAGATE target) endfunction() \ No newline at end of file diff --git a/CMake/Shader.cmake b/CMake/Shader.cmake index 3d86a2bae..28d3e38ca 100644 --- a/CMake/Shader.cmake +++ b/CMake/Shader.cmake @@ -147,6 +147,7 @@ function ( add_multiplatform_sfx_shader_project targetName ) else() set(intermediate_folder ${sfx_INTERMEDIATE}) endif() + set (this_exe "${PLATFORM_SFX_EXECUTABLE}") foreach(in_f ${sfx_SOURCES}) list(APPEND srcs ${in_f}) string(FIND ${in_f} ".sl" slpos REVERSE) @@ -160,13 +161,15 @@ function ( add_multiplatform_sfx_shader_project targetName ) string(REPLACE ".sfx" ".sfxo" out_f ${name}) set(out_f "${out_folder}/${out_f}") string(REPLACE ".sfxo" ".sfx_summary" main_output_file ${out_f}) - #message("add_custom_command \"${PLATFORM_SFX_EXECUTABLE}\" ${in_f} ${INCLUDE_OPTS} -O\"${sfx_OUTPUT}\" ${SET_CONFIGS} ${EXTRA_OPTS_S}") + #message("add_custom_command sfx_OUTPUT ${sfx_OUTPUT}") add_custom_command(OUTPUT ${main_output_file} - COMMAND "${PLATFORM_SFX_EXECUTABLE}" ${in_f} ${INCLUDE_OPTS} -O"${sfx_OUTPUT}" ${SET_CONFIGS} ${EXTRA_OPTS_S} + COMMAND "${this_exe}" ${in_f} ${INCLUDE_OPTS} -O"${sfx_OUTPUT}" ${SET_CONFIGS} ${EXTRA_OPTS_S} MAIN_DEPENDENCY ${in_f} WORKING_DIRECTORY ${out_folder} DEPENDS ${PLATFORM_SFX_EXECUTABLE} - COMMENT "info: Sfx compiling ${in_f}" + COMMENT "\"${this_exe}\" ${in_f} ${INCLUDE_OPTS} -O\"${sfx_OUTPUT}\" ${SET_CONFIGS} ${EXTRA_OPTS_S}" + #VERBATIM + COMMAND_EXPAND_LISTS ) list(APPEND outputs${targetName} ${out_f}) else() diff --git a/CMake/Variables.cmake b/CMake/Variables.cmake index 26acf1a7d..08b667116 100644 --- a/CMake/Variables.cmake +++ b/CMake/Variables.cmake @@ -42,9 +42,9 @@ set( PLATFORM_EMSCRIPTEN_DIR "$ENV{EMSCRIPTEN}" CACHE STRING "Set the location o set( PLATFORM_DEBUG_DISABLE 0 CACHE STRING "Set disable-level for debugging. Zero for full functionality." ) if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(PLATFORM_LINUX ON) + option(PLATFORM_LINUX "" ON ) else() - set(PLATFORM_LINUX OFF) + option(PLATFORM_LINUX "" OFF ) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") @@ -62,18 +62,18 @@ option(PLATFORM_USE_FMT "Include the fmt formatting library?" ON ) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set( WINDOWS ON ) - set(PLATFORM_WINDOWS ON) + option(PLATFORM_WINDOWS "" ON) option(PLATFORM_SUPPORT_WIN7 "" ON ) option(PLATFORM_SUPPORT_OPENGL "" ON) option(PLATFORM_SUPPORT_D3D11 "" ON ) - set(PLATFORM_D3D11_SFX ON ) + option(PLATFORM_D3D11_SFX "" ON ) option(PLATFORM_SUPPORT_D3D12 "" ON ) - option(PLATFORM_USE_ASSIMP "" ON ) - option(PLATFORM_BUILD_ASSIMP "" ON ) + option(PLATFORM_USE_ASSIMP "" OFF ) + option(PLATFORM_BUILD_ASSIMP "" OFF ) option(PLATFORM_BUILD_MD_LIBS "Build dynamically-linked dlls?" OFF) set( ON) - else() - set(PLATFORM_WINDOWS OFF) +else() + option(PLATFORM_WINDOWS "" OFF) option(PLATFORM_USE_ASSIMP "" OFF ) option(PLATFORM_BUILD_ASSIMP "" OFF ) option(PLATFORM_SUPPORT_OPENGL "" OFF ) @@ -90,7 +90,7 @@ endif() if(PLATFORM_WINDOWS OR PLATFORM_LINUX) if("${Vulkan_INCLUDE_DIR}" STREQUAL "") - set(PLATFORM_SUPPORT_VULKAN OFF ) + option(PLATFORM_SUPPORT_VULKAN "" OFF ) else() option(PLATFORM_SUPPORT_VULKAN "" ON) endif() @@ -114,7 +114,8 @@ endif() if(PLATFORM_WINDOWS) set(PLATFORM_SFX_EXECUTABLE "${CMAKE_BINARY_DIR}/bin/Release/Sfx.exe" CACHE STRING "") else() -find_program(PLATFORM_SFX_EXECUTABLE sfx PATHS "${CMAKE_BINARY_DIR}/bin/Release" "${CMAKE_BINARY_DIR}/bin/Debug" "${CMAKE_BINARY_DIR}/bin/Sfx") +set(PLATFORM_SFX_EXECUTABLE "${CMAKE_BINARY_DIR}/bin/Sfx" CACHE STRING "") +#find_program(PLATFORM_SFX_EXECUTABLE sfx PATHS "${CMAKE_BINARY_DIR}/bin" PATH_SUFFIXES "" "Release" "Debug") endif() mark_as_advanced(SIMUL_INTERNAL_CHECKS SIMUL_DEBUG_SHADERS PLATFORM_INTERNAL_PROFILING) diff --git a/Core/BaseMouseHandler.h b/Core/BaseMouseHandler.h index 41b21ab15..2ee6b4fb9 100644 --- a/Core/BaseMouseHandler.h +++ b/Core/BaseMouseHandler.h @@ -2,6 +2,7 @@ #define PLATFORM_CORE_MOUSEHANDLER_H #include +#include #include "Platform/Core/Export.h" #include "Platform/Core/EnumClassBitwiseOperators.h" @@ -21,6 +22,10 @@ namespace platform Button4 = 8, Button5 = 16, }; + MouseButtons operator|(MouseButtons a,MouseButtons b) + { + return (MouseButtons)((int)a|(int)b); + } enum class KeyboardModifiers : uint16_t { NoModifier = 0, diff --git a/Core/DefaultFileLoader.cpp b/Core/DefaultFileLoader.cpp index 823230edc..072370638 100644 --- a/Core/DefaultFileLoader.cpp +++ b/Core/DefaultFileLoader.cpp @@ -14,8 +14,7 @@ #include #endif #include // for fopen, seek, fclose -#include // for malloc, free -// TODO: replace stdlib.h with cstdlib +#include // for malloc, free #include typedef struct stat Stat; using namespace platform; @@ -153,7 +152,7 @@ void DefaultFileLoader::AcquireFileContents(void *&pointer, unsigned int &bytes, filesLoaded.insert(filename_utf8); } -uint64_t DefaultFileLoader::GetFileDate(const char *filename_utf8) const +uint64_t DefaultFileLoader::GetFileDateUnixTimeMs(const char *filename_utf8) const { if (!FileExists(filename_utf8)) return 0; @@ -183,7 +182,7 @@ uint64_t DefaultFileLoader::GetFileDate(const char *filename_utf8) const std::chrono::system_clock::time_point systemTime = std::chrono::time_point_cast(fileTime - fs::file_time_type::clock::now() + std::chrono::system_clock::now()); const time_t time = std::chrono::system_clock::to_time_t(systemTime); #endif - return time; + return time*1000; #endif #if defined(_MSC_VER) && defined(_WIN32) @@ -196,7 +195,7 @@ uint64_t DefaultFileLoader::GetFileDate(const char *filename_utf8) const struct stat buf; stat(filename_utf8, &buf); time_t t = buf.st_mtime; - return t; + return t*1000; #endif return 0; } diff --git a/Core/DefaultFileLoader.h b/Core/DefaultFileLoader.h index 837192f75..2f095110e 100644 --- a/Core/DefaultFileLoader.h +++ b/Core/DefaultFileLoader.h @@ -1,4 +1,5 @@ #pragma once +#include #include "Platform/Core/FileLoader.h" #include "Platform/Core/Export.h" #if defined(__ANDROID__) @@ -16,7 +17,7 @@ namespace platform ~DefaultFileLoader() = default; bool FileExists(const char *filename_utf8) const override; void AcquireFileContents(void*& pointer, unsigned int& bytes, const char* filename_utf8,bool open_as_text) override; - uint64_t GetFileDate(const char* filename_utf8) const override; + uint64_t GetFileDateUnixTimeMs(const char* filename_utf8) const override; void ReleaseFileContents(void* pointer) override; bool Save(const void* pointer, unsigned int bytes, const char* filename_utf8,bool save_as_text) override; }; diff --git a/Core/FileLoader.cpp b/Core/FileLoader.cpp index b8235de19..8f9ba4aef 100644 --- a/Core/FileLoader.cpp +++ b/Core/FileLoader.cpp @@ -258,7 +258,7 @@ int FileLoader::FindIndexInPathStack(const char* filename_utf8, const char* cons f += filename_utf8; if (FileExists(f.c_str())) { - uint64_t filedate = GetFileDate(f.c_str()); + uint64_t filedate = GetFileDateUnixTimeMs(f.c_str()); if (filedate >= newest_date) { fn = f; diff --git a/Core/FileLoader.h b/Core/FileLoader.h index 94ea6c9ce..d5372109c 100644 --- a/Core/FileLoader.h +++ b/Core/FileLoader.h @@ -1,6 +1,7 @@ #ifndef SIMUL_BASE_FILEINTERFACE_H #define SIMUL_BASE_FILEINTERFACE_H #include +#include #include #include #include "Platform/Core/Export.h" @@ -41,8 +42,8 @@ namespace platform //! The memory should later be freed by a call to ReleaseFileContents. //! The filename should be unicode UTF8-encoded. virtual void AcquireFileContents(void*& pointer, unsigned int& bytes, const char* filename_utf8,bool open_as_text)=0; - //! Get the unix timestamp. Return zero if the file doesn't exist. - virtual uint64_t GetFileDate(const char* filename_utf8) const=0; + //! Get the unix timestamp in milliseconds. Return zero if the file doesn't exist. + virtual uint64_t GetFileDateUnixTimeMs(const char* filename_utf8) const=0; //! Free the memory allocated by AcquireFileContents. virtual void ReleaseFileContents(void* pointer)=0; //! Save the chunk of memory to storage. diff --git a/Core/MemoryInterface.cpp b/Core/MemoryInterface.cpp index b97ee9985..83a072c91 100644 --- a/Core/MemoryInterface.cpp +++ b/Core/MemoryInterface.cpp @@ -1,7 +1,7 @@ #include "MemoryInterface.h" #ifdef _MSC_VER #include -#elif __APPLE__ +#else #include #endif #include @@ -28,7 +28,7 @@ namespace platform return _aligned_malloc(nbytes,align); #else #ifndef UNIX - return memalign(align,nbytes); + return aligned_alloc(align,nbytes); #else if(align==1) { diff --git a/Core/ProfilingInterface.cpp b/Core/ProfilingInterface.cpp index 6df39fd78..50ab65e11 100644 --- a/Core/ProfilingInterface.cpp +++ b/Core/ProfilingInterface.cpp @@ -11,27 +11,17 @@ #include "Platform/Core/StringFunctions.h" #include -#ifndef _MSC_VER - #ifndef UNIX - #ifdef NN_NINTENDO_SDK - #include - #define _isnanf (nn::util::FloatFormat16::IsNan) - #else - #define _isnanf isnan - #endif - #else - #include - #define _isnanf ( std::isnan ) - #endif +#ifdef _MSC_VER + #include + #define _isnanf _isnan #else -#include -#define _isnanf _isnan + #include + #define _isnanf ( std::isnan ) #endif using namespace platform; using namespace core; using std::string; - namespace platform { namespace core diff --git a/Core/RelativeFilePath.cpp b/Core/RelativeFilePath.cpp index 9f52c8b2f..70420407a 100644 --- a/Core/RelativeFilePath.cpp +++ b/Core/RelativeFilePath.cpp @@ -22,7 +22,7 @@ typedef stack StackPtrChar; } #define path_separator "\\" #define path_sep_char '\\' -#elif defined(__ORBIS__)||defined(UNIX)||defined(__COMMODORE__) || defined(__SWITCH__) +#else #define path_separator "/" #define path_sep_char '/' @@ -30,8 +30,6 @@ char *strtok_s(char * str, size_t * , const char * delim, char ** ) { return strtok(str,delim); } -#else - #error define your compiler #endif // Macro off the string buffer manipulation functions. diff --git a/Core/RuntimeError.h b/Core/RuntimeError.h index c8218a44e..c3c4f7c54 100644 --- a/Core/RuntimeError.h +++ b/Core/RuntimeError.h @@ -65,6 +65,29 @@ namespace platform extern PLATFORM_CORE_EXPORT bool DebugBreaksEnabled(); extern PLATFORM_CORE_EXPORT void EnableDebugBreaks(bool b); extern PLATFORM_CORE_EXPORT bool SimulInternalChecks; +#if __cplusplus>=202002L + template + void Error(const std::format_string txt,const char *file, int line, Args&&... args) + { + std::string str1 = std::format("{} ({}): warning: ", file, line); + std::string str2 = std::vformat(txt.get(), std::make_format_args(args...) ); + std::cerr << str1< + void Warn(const std::format_string txt, const char *file, unsigned int line, const T &...args) + { + std::string str1 = std::format("{} ({}): warning: ", file, line); + std::string str2 = std::vformat(txt.get(), std::make_format_args(args...) ); + std::cerr << str1 << str2 << "\n"; + } + template + void Info(const std::format_string txt, const char *file, unsigned int line, const T &...args) + { + std::string str1 = std::format("{} ({}): info: ", file, line); + std::string str2 = std::vformat(txt.get(), std::make_format_args(args...) ); + std::cerr << str1 << str2 << "\n"; + } +#else template void Error(const char *txt, const char* file, unsigned int line, const T &...args) { @@ -83,6 +106,7 @@ namespace platform std::string str = fmt::format(txt, args...); std::cout << fmt::format("{0} ({1}): info: {2}", file, line, str) << "\n"; } +#endif //! This is a throwable error class derived from std::runtime_error. //! It is used in builds that have C++ exceptions enabled. As it always outputs to std::cerr, //! it is easier to see the nature of the error than with runtime_error alone. diff --git a/Core/Settings.cpp b/Core/Settings.cpp index 23071ed9c..6992ae994 100644 --- a/Core/Settings.cpp +++ b/Core/Settings.cpp @@ -51,7 +51,7 @@ bool Settings::LoadFileInternal() SI_Error siError = m_Ini.LoadData(str); if (siError < 0) { - PLATFORM_ERROR("CSimpleIniA failed to load data from {} with error code {}.", m_Filename, siError); + PLATFORM_ERROR("CSimpleIniA failed to load data from {} with error code {}.", m_Filename, (int)siError); return false; } @@ -68,7 +68,7 @@ bool Settings::SaveFileInternal() SI_Error siError = m_Ini.Save(str); if (siError < 0) { - PLATFORM_ERROR("CSimpleIniA failed to save data to {} with error code {}.", m_Filename, siError); + PLATFORM_ERROR("CSimpleIniA failed to save data to {} with error code {}.", m_Filename, (int)siError); return false; } diff --git a/Core/StringFunctions.cpp b/Core/StringFunctions.cpp index 59c252187..5b08d10dc 100644 --- a/Core/StringFunctions.cpp +++ b/Core/StringFunctions.cpp @@ -3,9 +3,7 @@ #include #include #include -#ifdef UNIX #include // for strlen -#endif #ifndef _MSC_VER #define sprintf_s(buffer, buffer_size, stringbuffer, ...) (snprintf(buffer, buffer_size, stringbuffer, ##__VA_ARGS__)) #endif diff --git a/CrossPlatform/Camera.cpp b/CrossPlatform/Camera.cpp index ed1942e5d..cf3996b4a 100644 --- a/CrossPlatform/Camera.cpp +++ b/CrossPlatform/Camera.cpp @@ -482,6 +482,103 @@ void platform::crossplatform::GetCubeInvViewProjMatrix(float *mat4x4,int face,bo } memcpy(mat4x4,ivp_matrices[combo][face],sizeof(float)*16); } + +void MakeCubeInvViewProjMatricesForAxesStandard(platform::math::Matrix4x4 mat[], bool ReverseDepth, bool ReverseDirection, AxesStandard axesStandard) +{ + static math::Matrix4x4 view, proj; + proj = crossplatform::Camera::MakeDepthReversedProjectionMatrix(SIMUL_PI_F/2.f, SIMUL_PI_F/2.f, 1.0f, 0.0f); + + // Define face mappings for different coordinate systems + int faceMapping[6]; + + switch (axesStandard) + { + case AxesStandard::OpenGL: // Y vertical, right-handed + // OpenGL: +X=right, +Y=up, +Z=towards viewer + // Engineering: +X=right, +Y=forward, +Z=up + // Face mapping: swap Y and Z axes + faceMapping[0] = 0; // +X stays +X + faceMapping[1] = 1; // -X stays -X + faceMapping[2] = 4; // +Y -> +Z + faceMapping[3] = 5; // -Y -> -Z + faceMapping[4] = 3; // +Z -> -Y + faceMapping[5] = 2; // -Z -> +Y + break; + + case AxesStandard::Unreal: // Z vertical, left-handed + // Unreal: +X=forward, +Y=right, +Z=up + // Engineering: +X=right, +Y=forward, +Z=up + // Face mapping: swap X and Y axes, flip handedness + faceMapping[0] = 4; // +X -> +Z (forward) + faceMapping[1] = 5; // -X -> -Z (back) + faceMapping[2] = 2; // +Y stays +Y (up) + faceMapping[3] = 3; // -Y stays -Y (down) + faceMapping[4] = 1; // +Z -> -X (left, flipped) + faceMapping[5] = 0; // -Z -> +X (right, flipped) + break; + + case AxesStandard::Unity: // Y vertical, left-handed + // Unity: +X=right, +Y=up, +Z=forward + // Engineering: +X=right, +Y=forward, +Z=up + // Face mapping: swap Y and Z, flip Z + faceMapping[0] = 0; // +X stays +X + faceMapping[1] = 1; // -X stays -X + faceMapping[2] = 5; // +Y -> -Z (forward, flipped) + faceMapping[3] = 4; // -Y -> +Z (back, flipped) + faceMapping[4] = 2; // +Z -> +Y (up) + faceMapping[5] = 3; // -Z -> -Y (down) + break; + + default: // Engineering or unknown + for (int j = 0; j < 6; j++) faceMapping[j] = j; + break; + } + + for (int i = 0; i < 6; i++) + { + // Get the Engineering view matrix for the mapped face + int mappedFace = faceMapping[i]; + GetCubeMatrix((float*)&view, mappedFace, ReverseDepth, ReverseDirection); + + // Calculate inverse view-projection matrix + MakeInvViewProjMatrix((float*)&mat[i], view, proj); + } +} + +void platform::crossplatform::GetCubeInvViewProjMatrix(float *mat4x4,int face,bool ReverseDepth,bool ReverseDirection,AxesStandard axesStandard) +{ + // For Engineering standard, use the original function + if (axesStandard == AxesStandard::Engineering) + { + GetCubeInvViewProjMatrix(mat4x4, face, ReverseDepth, ReverseDirection); + return; + } + + // Static cache for different axes standards and combinations + static bool init[4][4] = {{false,false,false,false},{false,false,false,false},{false,false,false,false},{false,false,false,false}}; + int combo = (ReverseDepth?2:0) + (ReverseDirection?1:0); + int axesIndex = 0; + + // Map axes standard to index + switch (axesStandard) + { + case AxesStandard::OpenGL: axesIndex = 1; break; + case AxesStandard::Unreal: axesIndex = 2; break; + case AxesStandard::Unity: axesIndex = 3; break; + default: axesIndex = 0; break; // Engineering + } + + static math::Matrix4x4 ivp_matrices[4][4][6]; // [axesStandard][combo][face] + + if (!init[axesIndex][combo]) + { + // Generate matrices for this axes standard + MakeCubeInvViewProjMatricesForAxesStandard(ivp_matrices[axesIndex][combo], ReverseDepth, ReverseDirection, axesStandard); + init[axesIndex][combo] = true; + } + + memcpy(mat4x4, ivp_matrices[axesIndex][combo][face], sizeof(float)*16); +} math::Matrix4x4 platform::crossplatform::MakeOrthoProjectionMatrix(float left, float right, float bottom, @@ -895,7 +992,7 @@ void platform::crossplatform::UpdateMouseCamera( Camera *cam if(pos.z>max_height) pos.z=max_height; - cam->SetPosition(pos); + cam->SetPosition(pos.Values); int dx=input.MouseX-input.LastMouseX; int dy=input.MouseY-input.LastMouseY; @@ -922,16 +1019,16 @@ void platform::crossplatform::UpdateMouseCamera( Camera *cam platform::math::Vector3 del =vertical*x_rotate; platform::math::Vector3 dir =del; dir.Normalize(); - cam->Rotate(del.Magnitude(),dir); + cam->Rotate(del.Magnitude(),dir.Values); del =cam->Orientation.Tx()*y_rotate*(-1.f); dir =del; dir.Normalize(); - cam->Rotate(del.Magnitude(),dir); + cam->Rotate(del.Magnitude(),dir.Values); float tilt =0; tilt =asin(cam->Orientation.Tx().z); dir =cam->Orientation.Tz(); dir.Normalize(); - cam->Rotate(-0.5f*tilt,dir); -} \ No newline at end of file + cam->Rotate(-0.5f*tilt,dir.Values); +} diff --git a/CrossPlatform/Camera.h b/CrossPlatform/Camera.h index 787e1cb9a..05b62b502 100644 --- a/CrossPlatform/Camera.h +++ b/CrossPlatform/Camera.h @@ -7,6 +7,7 @@ #include "Platform/CrossPlatform/Export.h" #include "Platform/CrossPlatform/Shaders/CppSl.sl" #include "Platform/CrossPlatform/Frustum.h" +#include "AxesStandard.h" #ifdef _MSC_VER #pragma warning(push) @@ -147,6 +148,7 @@ namespace platform void SIMUL_CROSSPLATFORM_EXPORT GetCubeMatrixAtPosition(float *mat4x4,int i,vec3 cam_pos,bool ReverseDepth,bool ReverseDirection); void SIMUL_CROSSPLATFORM_EXPORT GetCubeInvViewProjMatrix(float *mat4x4,int i,bool ReverseDepth,bool ReverseDirection); + void SIMUL_CROSSPLATFORM_EXPORT GetCubeInvViewProjMatrix(float *mat4x4,int i,bool ReverseDepth,bool ReverseDirection,AxesStandard axesStandard); extern SIMUL_CROSSPLATFORM_EXPORT math::Matrix4x4 MakeOrthoProjectionMatrix(float left, float right, diff --git a/CrossPlatform/Effect.cpp b/CrossPlatform/Effect.cpp index cf0a7436f..054d1f1f1 100644 --- a/CrossPlatform/Effect.cpp +++ b/CrossPlatform/Effect.cpp @@ -1044,7 +1044,8 @@ bool Effect::Load(crossplatform::RenderPlatform *r, const char *filename_utf8) platform::core::find_and_replace(sfxbFilenameUtf8, ".sfxo", ".sfxb"); #if 0 - uint64_t timestamp = platform::core::FileLoader::GetFileLoader()->GetFileDate(sfxbFilenameUtf8.c_str()); + uint64_t timestamp = platform::core::FileLoader::GetFileLoader()->GetFileDateUnixTimeMs(sfxbFilenameUtf8.c_str()); + uint64_t timestamp_s=timestamp/1000; struct tm timeDate; gmtime_s(&timeDate, (time_t *)×tamp); std::cout << sfxbFilenameUtf8 << " write time " << @@ -1088,8 +1089,13 @@ bool Effect::Load(crossplatform::RenderPlatform *r, const char *filename_utf8) string group_name,tech_name,pass_name; int shaderCount=0; bool platformChecked = false; - const std::regex re_resources("(\\b[a-z]):\\(([^\\)]*)\\)"); - const std::regex element_re("([a-zA-Z]+[0-9]?)[\\s]+([a-zA-Z][a-zA-Z0-9_]*);"); + static const std::regex re_resources("(\\b[a-z]):\\(([^\\)]*)\\)"); + static const std::regex element_re("([a-zA-Z]+[0-9]?)[\\s]+([a-zA-Z][a-zA-Z0-9_]*);"); + static const std::string var_name_regex = "[a-z0-9A-Z_]+"; + static const std::string var_val_regex = "[a-z0-9A-Z]+"; + static const std::string var_combo_regex = "("s + var_name_regex + ")\\s*=\\s*(" + var_name_regex + ")"; + static const std::string variant_regex = "(?:\\s*variant:\\(" + var_combo_regex + "(?:\\s*,\\s*" + var_combo_regex + ")*\\))?"s; //" + var_combo_regex+"(?:,"+var_combo_regex+")* + static const std::regex re_file_entry("([a-z0-9A-Z_\\((\\))]+\\.[a-z0-9A-Z_]+)(?:\\(([a-z0-9A-Z_]+)\\))?(?:\\s*inline:\\(0x([a-f0-9A-F]+),0x([a-f0-9A-F]+)\\))?"s + variant_regex); while(next>=0) { #ifdef UNIX @@ -1481,11 +1487,6 @@ bool Effect::Load(crossplatform::RenderPlatform *r, const char *filename_utf8) uses=line.substr(cm+1,line.length()-cm-1); platform::core::ClipWhitespace(uses); platform::core::ClipWhitespace(type); - const std::string var_name_regex = "[a-z0-9A-Z_]+"; - const std::string var_val_regex = "[a-z0-9A-Z]+"; - const std::string var_combo_regex = "("s + var_name_regex + ")\\s*=\\s*(" + var_name_regex + ")"; - const std::string variant_regex = "(?:\\s*variant:\\(" + var_combo_regex + "(?:\\s*,\\s*" + var_combo_regex + ")*\\))?"s; //" + var_combo_regex+"(?:,"+var_combo_regex+")* - const std::regex re_file_entry("([a-z0-9A-Z_\\((\\))]+\\.[a-z0-9A-Z_]+)(?:\\(([a-z0-9A-Z_]+)\\))?(?:\\s*inline:\\(0x([a-f0-9A-F]+),0x([a-f0-9A-F]+)\\))?"s + variant_regex); std::smatch fe_smatch; std::smatch sm; @@ -1597,8 +1598,8 @@ bool Effect::Load(crossplatform::RenderPlatform *r, const char *filename_utf8) } else if(_stricmp(type.c_str(),"topology")==0) { - Topology t=toTopology(name); - p->SetTopology(t); + Topology top=toTopology(name); + p->SetTopology(top); } else if (_stricmp(type.c_str(), "multiview") == 0) { @@ -1703,6 +1704,41 @@ bool Effect::Load(crossplatform::RenderPlatform *r, const char *filename_utf8) SIMUL_BREAK("Unknown shader type or command: {}\n",type); continue; } + if(t!=crossplatform::ShaderType::SHADERTYPE_COUNT&&std::regex_search(line, sm, re_file_entry)) + { + filenamestr= sm.str(1); + if(sm.length()>2) + entry_point= sm.str(2); + entry_point = sm.str(2); + if (entry_point.length()>0&&sm.length() > 4) + { + if (sm.length(3) && sm.length(4)) + { + string inline_offset_str = sm.str(3); + string inline_length_str = sm.str(4); + inline_offset = std::stoul(inline_offset_str, nullptr, 16); + inline_length = std::stoul(inline_length_str, nullptr, 16); + if (!bin_ptr) + { + platform::core::FileLoader::GetFileLoader()->AcquireFileContents(bin_ptr, bin_num_bytes, sfxbFilenameUtf8.c_str(), true); + if (!bin_ptr) + { + SIMUL_BREAK("Failed to load combined shader binary: {}", sfxbFilenameUtf8); + } + } + } + { + int pos=5; + while(sm.length(pos+1)>0) + { + string var_name = sm.str(pos); + string var_value = sm.str(pos+1); + variantValues[var_name] = var_value; + pos+=2; + } + } + } + } Shader *s = nullptr; if(filenamestr.length()>0) { diff --git a/CrossPlatform/LensFlare.cpp b/CrossPlatform/LensFlare.cpp index 8443ab77e..7efd1771a 100644 --- a/CrossPlatform/LensFlare.cpp +++ b/CrossPlatform/LensFlare.cpp @@ -49,7 +49,7 @@ int LensFlare::GetNumArtifacts() const const float *LensFlare::GetArtifactPosition(int i) const { - return artifacts[i].pos; + return artifacts[i].pos.Values; } float LensFlare::GetArtifactSize(int i) const diff --git a/CrossPlatform/MouseHandler.cpp b/CrossPlatform/MouseHandler.cpp index 791eba74a..30c5cabde 100644 --- a/CrossPlatform/MouseHandler.cpp +++ b/CrossPlatform/MouseHandler.cpp @@ -227,7 +227,7 @@ void MouseHandler::Update(float time_step) (y_vertical ? pos.y : pos.z) += up_down_spd * time_step; (y_vertical ? pos.y : pos.z) = std::clamp((y_vertical ? pos.y : pos.z), minAlt, maxAlt); - camera->SetPosition(pos); + camera->SetPosition(pos.Values); static float x_rotate=0.f; static float y_rotate=0.f; @@ -277,22 +277,22 @@ void MouseHandler::Update(float time_step) step_rotate_x=0; math::Vector3 dir=del; dir.Normalize(); - camera->Rotate(del.Magnitude(),dir); + camera->Rotate(del.Magnitude(),dir.Values); del=camera->Orientation.Tx()*(y_rotate+sr*step_rotate_y)*(-1.f); step_rotate_y=0; dir=del; dir.Normalize(); - camera->Rotate(del.Magnitude(),dir); + camera->Rotate(del.Magnitude(),dir.Values); del=math::Vector3(0.f,0.f,z_rotate); - camera->LocalRotate(del); + camera->LocalRotate(del.Values); static float correct_tilt=0.005f; dir=camera->Orientation.Tz(); dir.Normalize(); if(!alt_down) - camera->Rotate(-correct_tilt * tilt, view_dir); + camera->Rotate(-correct_tilt * tilt, view_dir.Values); } else if (cameraSpatial == SPHERICAL) @@ -384,7 +384,7 @@ void MouseHandler::Update(float time_step) y_vertical ? pos.z : pos.y = (float)position.y; y_vertical ? pos.y : pos.z = (float)position.z; } - camera->SetPosition(pos); + camera->SetPosition(pos.Values); static float x_rotate = 0.f; static float y_rotate = 0.f; @@ -434,22 +434,22 @@ void MouseHandler::Update(float time_step) step_rotate_x = 0; math::Vector3 dir = del; dir.Normalize(); - camera->Rotate(del.Magnitude(), dir); + camera->Rotate(del.Magnitude(), dir.Values); del = camera->Orientation.Tx() * (y_rotate + sr * step_rotate_y) * (-1.f); step_rotate_y = 0; dir = del; dir.Normalize(); - camera->Rotate(del.Magnitude(), dir); + camera->Rotate(del.Magnitude(), dir.Values); del = math::Vector3(0.f, 0.f, z_rotate); - camera->LocalRotate(del); + camera->LocalRotate(del.Values); static float correct_tilt = 0.005f; dir = camera->Orientation.Tz(); dir.Normalize(); if (!alt_down) - camera->Rotate(-correct_tilt * tilt, view_dir); + camera->Rotate(-correct_tilt * tilt, view_dir.Values); } if(cameraMode==CENTRED) { @@ -458,9 +458,9 @@ void MouseHandler::Update(float time_step) camera->Orientation.LocalToGlobalDirection(dir,offset_camspace); pos=centre; pos+=dir; - camera->SetPosition(pos); + camera->SetPosition(pos.Values); dir.Normalize(); - camera->LookInDirection(-dir); + camera->LookInDirection((-dir).Values); } lastTimeStep = time_step; } diff --git a/CrossPlatform/RenderPlatform.cpp b/CrossPlatform/RenderPlatform.cpp index e38bd9ab1..6a4ce24af 100644 --- a/CrossPlatform/RenderPlatform.cpp +++ b/CrossPlatform/RenderPlatform.cpp @@ -700,6 +700,7 @@ void RenderPlatform::ContextFrameBegin(GraphicsDeviceContext &deviceContext) { if (!frame_started) BeginFrame(); + //Defrag(deviceContext); if(gpuProfiler && !gpuProfileFrameStarted) { gpuProfiler->StartFrame(deviceContext); @@ -779,7 +780,7 @@ void RenderPlatform::BeginFrame(long long f) void RenderPlatform::Clear(GraphicsDeviceContext &deviceContext,vec4 colour_rgba) { - if (deviceContext.targetStack.empty() && deviceContext.defaultTargetsAndViewport.m_rt) + if (deviceContext.targetStack.empty() ) { crossplatform::EffectTechnique *clearTechnique = debugEffect->GetTechniqueByName("clear"); if (deviceContext.AsMultiviewGraphicsDeviceContext()) @@ -1039,8 +1040,102 @@ bool RenderPlatform::SaveTextureDataToDisk(const char* filename, int width, int uint64_t texelSize = elementCount * elementSize; uint64_t size = texelCount * texelSize; - std::vector imageData; - imageData.reserve(texelCount * elementCount); + // Check if we should save as HDR format + std::string filenameStr(filename); + bool saveAsHDR = (filenameStr.find(".hdr") != std::string::npos); + + if (saveAsHDR) + { + // For HDR format, we need to preserve floating point data + std::vector hdrData; + hdrData.reserve(texelCount * 3); // RGB only for HDR + + if (data) + { + for (uint64_t i = 0; i < size; i += elementSize) + { + float floatValue = 0.0f; + void* _ptr = (void*)((uint64_t)data + i); + + switch (type) + { + using namespace crossplatform; + case PixelFormatType::DOUBLE: + { + floatValue = static_cast(*(double*)_ptr); + break; + } + case PixelFormatType::FLOAT: + { + floatValue = *(float*)_ptr; + break; + } + case PixelFormatType::HALF: + { + floatValue = math::ToFloat32(*(uint16_t*)_ptr); + break; + } + case PixelFormatType::UINT: + { + uint32_t value = *(uint32_t*)_ptr; + floatValue = static_cast(value) / static_cast(UINT32_MAX); + break; + } + case PixelFormatType::USHORT: + { + uint16_t value = *(uint16_t*)_ptr; + floatValue = static_cast(value) / static_cast(UINT16_MAX); + break; + } + case PixelFormatType::UCHAR: + { + uint8_t value = *(uint8_t*)_ptr; + floatValue = static_cast(value) / 255.0f; + break; + } + case PixelFormatType::INT: + { + int32_t value = std::max(0, *(int32_t*)_ptr); + floatValue = static_cast(value) / static_cast(INT32_MAX); + break; + } + case PixelFormatType::SHORT: + { + int16_t value = std::max(0, *(int16_t*)_ptr); + floatValue = static_cast(value) / static_cast(INT16_MAX); + break; + } + case PixelFormatType::CHAR: + { + int8_t value = std::max(0, *(int8_t*)_ptr); + floatValue = static_cast(value) / static_cast(INT8_MAX); + break; + } + } + + // For HDR, we only store RGB (skip alpha if present) + uint64_t componentIndex = (i / elementSize) % elementCount; + if (componentIndex < 3) // R, G, B only + { + hdrData.push_back(floatValue); + } + } + } + + // Write HDR file using stb_image_write + int res = stbi_write_hdr(filename, width, height, 3, hdrData.data()); + if (res != 1) + { + SIMUL_BREAK_ONCE("Failed to save HDR data to disk."); + return false; + } + return true; + } + else + { + // Original PNG saving code + std::vector imageData; + imageData.reserve(texelCount * elementCount); if (data) { @@ -1109,13 +1204,14 @@ bool RenderPlatform::SaveTextureDataToDisk(const char* filename, int width, int } } - int res = stbi_write_png(filename, width, height, (int)elementCount, imageData.data(), (int)(elementCount * width)); - if (res != 1) - { - SIMUL_BREAK_ONCE("Failed to save screenshot data to disk."); - return false; - } - return true; + int res = stbi_write_png(filename, width, height, (int)elementCount, imageData.data(), (int)(elementCount * width)); + if (res != 1) + { + SIMUL_BREAK_ONCE("Failed to save screenshot data to disk."); + return false; + } + return true; + } // End of else block } void RenderPlatform::DrawLine(GraphicsDeviceContext &deviceContext,vec3 startp, vec3 endp, vec4 colour,float width) @@ -1226,15 +1322,15 @@ void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext,const float { vec3 direction(dir); direction = normalize(direction); - vec3 z(0, 0, 1.f); - vec3 y(0, 1.f, 0); - vec3 x = cross(z, direction); - if (length(x) > .1f) - x = normalize(x); + vec3 z(0,0,1.f); + vec3 y(0,1.f,0); + vec3 x=cross(z,direction); + if(length(x)>.1f) + x=normalize(x); else - x = cross(direction, y); - x *= radius; - y = cross(direction, x); + x=cross(direction,y); + x*=radius; + y = cross(direction , x); mat4 wvp; if (view_centred) @@ -1325,13 +1421,13 @@ crossplatform::Texture* RenderPlatform::GetOrCreateTexture(const char* filename, if (i != textures.end()) return i->second; - crossplatform::Texture* t = CreateTexture(filename, gen_mips); + crossplatform::Texture* t=CreateTexture(filename, gen_mips); textures[filename] = t; // special textures: if (std::string(filename) == "white") { - t->ensureTexture2DSizeAndFormat(this, 1, 1, 1, PixelFormat::RGBA_8_UNORM, false, false, false, 1, 0, true, vec4(1.f, 1.f, 1.f, 1.f)); + t->ensureTexture2DSizeAndFormat(this,1,1, 1,PixelFormat::RGBA_8_UNORM,false,false,false,1,0,true,vec4(1.f,1.f,1.f,1.f)); uint8_t dataWhite[4] = {0xFF, 0xFF, 0xFF, 0xFF}; t->setTexels(GetImmediateContext(), &dataWhite, 0, 1); } @@ -1386,9 +1482,9 @@ ShaderBindingTable* RenderPlatform::CreateShaderBindingTable() Mesh *RenderPlatform::CreateMesh() { return new Mesh(this); -} +} -Texture* RenderPlatform::CreateTexture(const char *fileNameUtf8, bool gen_mips) +Texture* RenderPlatform::CreateTexture(const char* fileNameUtf8, bool gen_mips) { crossplatform::Texture* tex = createTexture(); if (fileNameUtf8 && strlen(fileNameUtf8) > 0) @@ -1410,7 +1506,7 @@ Texture* RenderPlatform::CreateTexture(const char *fileNameUtf8, bool gen_mips) return tex; } -void RenderPlatform::InvalidatingTexture(Texture* t) +void RenderPlatform::InvalidatingTexture(Texture *t) { for(auto i:unfinishedTextures) { @@ -1418,7 +1514,7 @@ void RenderPlatform::InvalidatingTexture(Texture* t) { unfinishedTextures.erase(i.first); break; - } +} } } @@ -2385,4 +2481,4 @@ void platform::crossplatform::DrawGrid(GraphicsDeviceContext &deviceContext,vec3 void RenderPlatform::SetStandardRenderState (DeviceContext &deviceContext,StandardRenderState s) { SetRenderState(deviceContext,standardRenderStates[s]); -} \ No newline at end of file +} diff --git a/CrossPlatform/RenderPlatform.h b/CrossPlatform/RenderPlatform.h index fdeb6a6ed..8fa01d9bb 100644 --- a/CrossPlatform/RenderPlatform.h +++ b/CrossPlatform/RenderPlatform.h @@ -528,6 +528,7 @@ namespace platform void ScheduleRecompileEffects(const std::vector& effect_names,std::function f); protected: + virtual void Defrag(GraphicsDeviceContext &deviceContext){} struct EffectRecompile { std::string effect_name; diff --git a/CrossPlatform/Resource.h b/CrossPlatform/Resource.h index 2c09a1679..9f629ac9e 100644 --- a/CrossPlatform/Resource.h +++ b/CrossPlatform/Resource.h @@ -5,6 +5,13 @@ namespace platform { namespace crossplatform { + struct GraphicsDeviceContext; + class Resource + { + public: + virtual void Reallocate(GraphicsDeviceContext &dev,const void *src,const void *dest){}; + }; + static const int PER_PASS_RESOURCE_GROUP=3; //! The grouping for shader resources. Using this grouping we can ensure that //! resource layouts are not uploaded more often than necessary. See ConstantBuffer<>. diff --git a/CrossPlatform/Shaders/CppSl.sl b/CrossPlatform/Shaders/CppSl.sl index 31370cb47..60041c8a5 100644 --- a/CrossPlatform/Shaders/CppSl.sl +++ b/CrossPlatform/Shaders/CppSl.sl @@ -4,6 +4,7 @@ // Definitions shared across C++, HLSL, and GLSL! #ifdef __cplusplus + #include // required for sqrt #include // required for std::min and max diff --git a/CrossPlatform/Shaders/texture_compression.sfx b/CrossPlatform/Shaders/texture_compression.sfx index 7d985876b..d8e09b652 100644 --- a/CrossPlatform/Shaders/texture_compression.sfx +++ b/CrossPlatform/Shaders/texture_compression.sfx @@ -994,7 +994,7 @@ groupshared BufferShared shared_temp[THREAD_GROUP_SIZE]; uint4 quantize(uint4 color, uint uPrec) { - return (((color << 8) + color) * ((1 << uPrec) - 1) + 32768) >> 16; + return (((color << 8u) + color) * ((1u << uPrec) - 1u) + 32768u) >> 16u; } uint4 unquantize(uint4 color, uint uPrec) diff --git a/CrossPlatform/Shaders/vec2.sl b/CrossPlatform/Shaders/vec2.sl index 37b309134..f814489e2 100644 --- a/CrossPlatform/Shaders/vec2.sl +++ b/CrossPlatform/Shaders/vec2.sl @@ -235,4 +235,16 @@ typedef tvector2 vec2d; typedef tvector2 int2; typedef tvector2 uint2; +// POD-compatible packed version for use in packed structs +template +struct pvector2 +{ + T x, y; +}; + +typedef pvector2 vec2_packed; +typedef pvector2 vec2d_packed; +typedef pvector2 int2_packed; +typedef pvector2 uint2_packed; + #endif \ No newline at end of file diff --git a/CrossPlatform/Shaders/vec3.sl b/CrossPlatform/Shaders/vec3.sl index 242e0608b..2dab07bb8 100644 --- a/CrossPlatform/Shaders/vec3.sl +++ b/CrossPlatform/Shaders/vec3.sl @@ -1,6 +1,14 @@ #ifndef VEC3_SL #define VEC3_SL + +// POD-compatible packed version for use in packed structs +template +struct pvector3 +{ + T x, y, z; +}; + template struct tvector3 { @@ -52,6 +60,13 @@ struct tvector3 y = T(v.y); z = T(v.z); } + template + tvector3(const pvector3 &v) + { + x = T(v.x); + y = T(v.y); + z = T(v.z); + } // Equality operators bool operator==(const tvector3 &v) const @@ -268,4 +283,21 @@ typedef tvector3 vec3d; typedef tvector3 int3; typedef tvector3 uint3; +typedef pvector3 vec3_packed; +typedef pvector3 vec3d_packed; +typedef pvector3 int3_packed; +typedef pvector3 uint3_packed; + +template +pvector3 packed(const tvector3 &v) +{ + return pvector3{v.x, v.y, v.z}; +} + +template +tvector3 unpacked(const pvector3 &v) +{ + return tvector3{v.x, v.y, v.z}; +} + #endif \ No newline at end of file diff --git a/CrossPlatform/Shaders/vec4.sl b/CrossPlatform/Shaders/vec4.sl index d289c3eaa..866e865a7 100644 --- a/CrossPlatform/Shaders/vec4.sl +++ b/CrossPlatform/Shaders/vec4.sl @@ -1,6 +1,15 @@ #ifndef VEC4_SL #define VEC4_SL + +// POD-compatible packed version for use in packed structs +template +struct pvector4 +{ + T x, y, z, w; +}; + +//! Four-element vector template struct. template struct tvector4 { @@ -77,6 +86,14 @@ struct tvector4 z = T(v.z); w = T(v.w); } + template + tvector4(const pvector4 &v) + { + x = T(v.x); + y = T(v.y); + z = T(v.z); + w = T(v.w); + } // Equality operators bool operator==(const tvector4 &v) const @@ -305,4 +322,21 @@ typedef tvector4 vec4d; typedef tvector4 int4; typedef tvector4 uint4; +typedef pvector4 vec4_packed; +typedef pvector4 vec4d_packed; +typedef pvector4 int4_packed; +typedef pvector4 uint4_packed; + +template +pvector4 packed(const tvector4 &v) +{ + return pvector4{v.x, v.y, v.z, v.w}; +} + +template +tvector3 unpacked(const pvector4 &v) +{ + return tvector4{v.x, v.y, v.z, v.w}; +} + #endif \ No newline at end of file diff --git a/CrossPlatform/Texture.h b/CrossPlatform/Texture.h index d7386b05e..e16e23938 100644 --- a/CrossPlatform/Texture.h +++ b/CrossPlatform/Texture.h @@ -1,6 +1,7 @@ #pragma once #include "Platform/Core/MemoryInterface.h" #include "Platform/CrossPlatform/Export.h" +#include "Platform/CrossPlatform/Resource.h" #include "Platform/CrossPlatform/PixelFormat.h" #include "Platform/CrossPlatform/Shaders/CppSl.sl" #include @@ -323,7 +324,7 @@ namespace platform }; /// A Texture base class. - class SIMUL_CROSSPLATFORM_EXPORT Texture + class SIMUL_CROSSPLATFORM_EXPORT Texture : public crossplatform::Resource { public: Texture(const char *name=NULL); diff --git a/DirectX11/CompileShaderDX1x.cpp b/DirectX11/CompileShaderDX1x.cpp index eab81da66..05aa6a02c 100644 --- a/DirectX11/CompileShaderDX1x.cpp +++ b/DirectX11/CompileShaderDX1x.cpp @@ -116,7 +116,7 @@ ERRNO_CHECK } void *buf=NULL; unsigned fileSize=0; - uint64_t timestamp= platform::core::FileLoader::GetFileLoader()->GetFileDate(finalPathUtf8.c_str()); + uint64_t timestamp= platform::core::FileLoader::GetFileLoader()->GetFileDateUnixTimeMs(finalPathUtf8.c_str()); if(timestamp>newest) newest=timestamp; if(timestamp>lastCompileTime) diff --git a/DirectX11/DeviceManager.cpp b/DirectX11/DeviceManager.cpp index 288f5b119..1d59ece17 100644 --- a/DirectX11/DeviceManager.cpp +++ b/DirectX11/DeviceManager.cpp @@ -648,7 +648,7 @@ void DeviceManager::Shutdown() d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); } #endif - PLATFORM_WARN("There are {0} reported unfreed references remain in DirectX 11.", references); + PLATFORM_WARN("There are {} reported unfreed references remain in DirectX 11.", (int)references); } #ifndef _XBOX_ONE SAFE_RELEASE(d3dDebug); diff --git a/External/freetype b/External/freetype deleted file mode 160000 index 978fdb292..000000000 --- a/External/freetype +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 978fdb292a2fda55157cb39525ccddc98c3e1d44 diff --git a/ImGui/imgui_impl_platform.cpp b/ImGui/imgui_impl_platform.cpp index 74546747b..5b8689827 100644 --- a/ImGui/imgui_impl_platform.cpp +++ b/ImGui/imgui_impl_platform.cpp @@ -8,7 +8,7 @@ #include "Platform/CrossPlatform/Effect.h" #include "Platform/CrossPlatform/Macros.h" #include "Platform/CrossPlatform/GraphicsDeviceInterface.h" - +#pragma optimize("",off) #include "Platform/External/glfw/include/GLFW/glfw3.h" using namespace platform; @@ -79,8 +79,10 @@ struct ImGui_ImplPlatform_Data { bool hosted =false; RenderPlatform* renderPlatform = nullptr; - Buffer* pVB = nullptr; - Buffer* pIB = nullptr; + std::vector> vertexBuffers; + std::vector> indexBuffers; + //Buffer* pVB = nullptr; + //Buffer* pIB = nullptr; bool reload_shaders=false; std::shared_ptr effect = nullptr; EffectPass* effectPass_testDepth=nullptr; @@ -182,8 +184,6 @@ static void ImGui_ImplPlatform_SetupRenderState(ImDrawData* draw_data, GraphicsD unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; deviceContext.contextState.applyVertexBuffers.clear(); - bd->renderPlatform->SetVertexBuffers(deviceContext, 0, 1, &bd->pVB, bd->pInputLayout); - bd->renderPlatform->SetIndexBuffer(deviceContext, bd->pIB); bd->renderPlatform->SetTopology(deviceContext, crossplatform::Topology::TRIANGLELIST); TextureCreate tc; tc.make_rt=true; @@ -232,54 +232,56 @@ void ImGui_ImplPlatform_RenderDrawData(GraphicsDeviceContext &deviceContext,ImDr bd->framebufferTexture=renderPlatform->CreateTexture("imgui_framebuffer"); } int4 old_scissor=renderPlatform->GetScissor(deviceContext); - // Create and grow vertex/index buffers if needed - if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) + bd->vertexBuffers.resize(draw_data->CmdListsCount); + bd->indexBuffers.resize(draw_data->CmdListsCount); + for (int n = 0; n < draw_data->CmdListsCount; n++) { - if (bd->pVB) - { - delete bd->pVB; - bd->pVB = NULL; + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + std::shared_ptr &vb=bd->vertexBuffers[n]; + // Create and grow vertex/index buffers if needed + if (!vb || vb->count < cmd_list->VtxBuffer.size()) + { + if (!vb) + { + vb.reset(renderPlatform->CreateBuffer()); + } + bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; + vb->EnsureVertexBuffer(renderPlatform, bd->VertexBufferSize, bd->pInputLayout, nullptr,true); } - bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; - bd->pVB=renderPlatform->CreateBuffer(); - bd->pVB->EnsureVertexBuffer(renderPlatform, bd->VertexBufferSize, bd->pInputLayout, nullptr,true); - } - if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) - { - if (bd->pIB) + // Upload vertex/index data into a single contiguous GPU buffer + ImDrawVert* vtx_dst= (ImDrawVert*)vb->Map(deviceContext); + if (!vtx_dst) { - SAFE_DELETE(bd->pIB); + // Force recreate to find error. + vb.reset(); + return; } - bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; - bd->pIB=renderPlatform->CreateBuffer(); - bd->pIB->EnsureIndexBuffer(renderPlatform, bd->IndexBufferSize, sizeof(ImDrawIdx),nullptr,true); - } - - // Upload vertex/index data into a single contiguous GPU buffer - ImDrawVert* vtx_dst= (ImDrawVert*)bd->pVB->Map(deviceContext); - if (!vtx_dst) - { - // Force recreate to find error. - SAFE_DELETE(bd->pVB); - return; - } - ImDrawIdx* idx_dst= (ImDrawIdx*)bd->pIB->Map(deviceContext); - if (!idx_dst) - { - bd->pVB->Unmap(deviceContext); - SAFE_DELETE(bd->pIB); - return; - } - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); - memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); vtx_dst += cmd_list->VtxBuffer.Size; + vb->Unmap(deviceContext); + + std::shared_ptr &ib=bd->indexBuffers[n]; + if (!ib || bd->IndexBufferSize < cmd_list->IdxBuffer.size()) + { + if (!ib) + { + ib.reset(renderPlatform->CreateBuffer()); + } + bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; + ib->EnsureIndexBuffer(renderPlatform, bd->IndexBufferSize, sizeof(ImDrawIdx),nullptr,true); + } + + ImDrawIdx* idx_dst= (ImDrawIdx*)ib->Map(deviceContext); + if (!idx_dst) + { + ib.reset(); + return; + } + + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); idx_dst += cmd_list->IdxBuffer.Size; + ib->Unmap(deviceContext); } - bd->pVB->Unmap(deviceContext); - bd->pIB->Unmap(deviceContext); // Setup orthographic projection matrix into our constant buffer // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. @@ -345,21 +347,6 @@ void ImGui_ImplPlatform_RenderDrawData(GraphicsDeviceContext &deviceContext,ImDr bd->imgui_to_world = mul(bd->local_to_world,bd->imgui_to_local); bd->canvas_to_world=mul(bd->local_to_world,canvas_to_local); bd->world_to_local=mat4::unscaled_inverse_transform(bd->local_to_world); - #if 0 - mat4 check_inverse; - ((platform::math::Matrix4x4 *)&bd->local_to_world)->SimpleInverseOfTransposeTransform(*((platform::math::Matrix4x4 *)&check_inverse)); - - vec3 check_centre=(bd->local_to_world*vec4(0,0,0,1.0f)).xyz; - vec3 check_zero=(bd->world_to_local*vec4(bd->centre,1.0f)).xyz; - - mat4 i_test = mul(bd->local_to_world,check_inverse); - ((platform::math::Matrix4x4 *)&bd->local_to_world)->Inverse(*((platform::math::Matrix4x4 *)&check_inverse)); - - i_test = mul(bd->local_to_world,check_inverse); - platform::math::Matrix4x4 *g=(platform::math::Matrix4x4 *)&bd->local_to_world; - //g->SimpleInverse(*((platform::math::Matrix4x4 *)&bd->world_to_local)); - i_test = mul(bd->local_to_world,bd->world_to_local); - #endif // store the inverse for mouse clicks: platform::math::Matrix4x4 *m=(platform::math::Matrix4x4 *)&bd->imgui_to_world; @@ -407,8 +394,13 @@ void ImGui_ImplPlatform_RenderDrawData(GraphicsDeviceContext &deviceContext,ImDr ImVec2 clip_off = draw_data->DisplayPos; for (int n = 0; n < draw_data->CmdListsCount; n++) { + std::shared_ptr &vb=bd->vertexBuffers[n]; + std::shared_ptr &ib=bd->indexBuffers[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n]; renderPlatform->BeginEvent(deviceContext, cmd_list->_OwnerName); + Buffer * v[]={vb.get()}; + bd->renderPlatform->SetVertexBuffers(deviceContext, 0, 1, v, bd->pInputLayout); + bd->renderPlatform->SetIndexBuffer(deviceContext, ib.get()); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { @@ -467,8 +459,8 @@ void ImGui_ImplPlatform_RenderDrawData(GraphicsDeviceContext &deviceContext,ImDr } } - global_idx_offset += cmd_list->IdxBuffer.Size; - global_vtx_offset += cmd_list->VtxBuffer.Size; + //global_idx_offset += cmd_list->IdxBuffer.Size; + // global_vtx_offset += cmd_list->VtxBuffer.Size; renderPlatform->EndEvent(deviceContext); } @@ -576,8 +568,8 @@ void ImGui_ImplPlatform_InvalidateDeviceObjects() ImGui::GetIO().Fonts->SetTexID(NULL); // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. } - SAFE_DELETE(bd->pIB); - SAFE_DELETE(bd->pVB); + bd->indexBuffers.clear(); + bd->vertexBuffers.clear(); SAFE_DELETE(bd->pBlendState); bd->constantBuffer.InvalidateDeviceObjects(); diff --git a/Linux/ThisPlatform/Threads.h b/Linux/ThisPlatform/Threads.h index ba2985926..676ab1f57 100644 --- a/Linux/ThisPlatform/Threads.h +++ b/Linux/ThisPlatform/Threads.h @@ -16,33 +16,39 @@ inline void SetThisThreadName(const char *name) prctl(PR_SET_NAME, (long)name, 0, 0, 0); } -inline void SetThreadPriority(std::thread &thread,int p) +inline int MapPriorityToSchedPriority(int p) { - sched_param sch_params; switch(p) { case -2: - sch_params.sched_priority = 1; - break; + return 1; case -1: - sch_params.sched_priority = 25; - break; + return 25; case 0: - sch_params.sched_priority = 50; - break; + return 50; case 1: - sch_params.sched_priority = 75; - break; + return 75; case 2: - sch_params.sched_priority = 99; - break; + return 99; default: - sch_params.sched_priority = 50; - break; + return 50; } +} + +inline void SetThreadPriority(std::thread &thread,int p) +{ + sched_param sch_params; + sch_params.sched_priority = MapPriorityToSchedPriority(p); pthread_setschedparam(thread.native_handle(), SCHED_RR, &sch_params); } +inline void SetThisThreadPriority(int p) +{ + sched_param sch_params; + sch_params.sched_priority = MapPriorityToSchedPriority(p); + pthread_setschedparam(pthread_self(), SCHED_RR, &sch_params); +} + inline int fopen_s(FILE** pFile, const char *filename, const char *mode) { *pFile = fopen(filename, mode); diff --git a/Math/Noise3D.cpp b/Math/Noise3D.cpp index b4587b0b3..88a6397fe 100644 --- a/Math/Noise3D.cpp +++ b/Math/Noise3D.cpp @@ -8,10 +8,6 @@ using namespace platform::math; -static float lerp(float t, float a, float b) -{ - return ( a + t * (b - a) ); -} NoiseInterface::NoiseInterface(){} NoiseInterface::~NoiseInterface(){} diff --git a/Math/SimVector.cpp b/Math/SimVector.cpp index 38a0b0fa0..8831f5659 100644 --- a/Math/SimVector.cpp +++ b/Math/SimVector.cpp @@ -2783,7 +2783,7 @@ void Vector::InsertAdd(const Vector3 &v,unsigned pos) unsigned i; for(i=0;i<3;++i) { - Values[pos+i]+=v[i]; + Values[pos+i]+=v.Values[i]; } } //------------------------------------------------------------------------------ diff --git a/Math/Vector3.cpp b/Math/Vector3.cpp index e7009eae0..b5f0fc27a 100644 --- a/Math/Vector3.cpp +++ b/Math/Vector3.cpp @@ -85,14 +85,6 @@ Vector3::Vector3(const Vector3 &v) operator=(v); } -Vector3::operator const float*() const -{ - return Values; -} -Vector3::operator float*() -{ - return Values; -} void Vector3::Define(float x,float y,float z) { Values[0]=x; @@ -1175,7 +1167,7 @@ void CrossProduct(Vector3 &result,const Vector3 &v1,const Vector3 &v2) #ifndef PLAYSTATION2 float total=0.0f; for(unsigned i=0;i<3;i++) - total+=v1[i]*v2[i]; + total+=v1.Values[i]*v2.Values[i]; return total; #else float d; diff --git a/Math/Vector3.h b/Math/Vector3.h index 48799bcc3..155684fb0 100644 --- a/Math/Vector3.h +++ b/Math/Vector3.h @@ -36,8 +36,6 @@ namespace platform Vector3(float a,float b,float c); ///< Constructor, values are set to (a,b,c). Vector3(const float *x); ///< Constructor, values are set to (x[0],x[1],x[2]). - operator const float*() const; - operator float*(); void Define(float x,float y,float z); ///< Set the values to (x,y,z). void DefineValues(const float *x); ///< Set the values to (x[0],x[1],x[2]). void Zero(); ///< Set all values to zero. @@ -65,9 +63,9 @@ namespace platform /// Is this vector equal to v? bool operator==(const Vector3 &v) const { - return(Values[0]==v[0]&& - Values[1]==v[1]&& - Values[2]==v[2]); + return(Values[0]==v.Values[0]&& + Values[1]==v.Values[1]&& + Values[2]==v.Values[2]); } void operator-=(const Vector3 &v); ///< Subtract v from this. void operator+=(const Vector3 &v); ///< Add v to this. diff --git a/Vulkan/Allocation.h b/Vulkan/Allocation.h index 8d87256c7..7e9197b37 100644 --- a/Vulkan/Allocation.h +++ b/Vulkan/Allocation.h @@ -1,4 +1,5 @@ #pragma once +#include "Platform/CrossPlatform/Resource.h" #include "vk_mem_alloc.h" namespace platform::vulkan diff --git a/Vulkan/Buffer.cpp b/Vulkan/Buffer.cpp index 4e464499b..5abaab9eb 100644 --- a/Vulkan/Buffer.cpp +++ b/Vulkan/Buffer.cpp @@ -51,7 +51,7 @@ void Buffer::EnsureVertexBuffer(crossplatform::RenderPlatform* r size = num_vertices * stride; count = num_vertices; - vulkanRenderPlatform->CreateVulkanBuffer( + vulkanRenderPlatform->CreateVulkanBuffer(nullptr, size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, mStagingBuffer, mStagingAllocation, "VertexBuffer Upload"); @@ -67,7 +67,7 @@ void Buffer::EnsureVertexBuffer(crossplatform::RenderPlatform* r } } - vulkanRenderPlatform->CreateVulkanBuffer( + vulkanRenderPlatform->CreateVulkanBuffer(nullptr, size, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eDeviceLocal, mBuffer, mAllocation, "VertexBuffer"); @@ -83,8 +83,7 @@ void Buffer::EnsureIndexBuffer(crossplatform::RenderPlatform* r,int num_indices, stride = index_size_bytes; size = num_indices * index_size_bytes; count = num_indices; - - vulkanRenderPlatform->CreateVulkanBuffer( + vulkanRenderPlatform->CreateVulkanBuffer(nullptr, size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, mStagingBuffer, mStagingAllocation, "IndexBuffer Upload"); @@ -99,8 +98,8 @@ void Buffer::EnsureIndexBuffer(crossplatform::RenderPlatform* r,int num_indices, vmaUnmapMemory(mStagingAllocation.allocator, mStagingAllocation.allocation); } } - - vulkanRenderPlatform->CreateVulkanBuffer( + + vulkanRenderPlatform->CreateVulkanBuffer(nullptr, size, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eDeviceLocal, mBuffer, mAllocation, "IndexBuffer"); diff --git a/Vulkan/CMakeLists.txt b/Vulkan/CMakeLists.txt index f6c7060b5..0562f0668 100644 --- a/Vulkan/CMakeLists.txt +++ b/Vulkan/CMakeLists.txt @@ -38,6 +38,7 @@ set(HEADERS ${HEADERS} "${SIMUL_PLATFORM_DIR}/External/VulkanMemoryAllocator/inc add_static_library( SimulVulkan SOURCES ${SOURCES} ${HEADERS} ${SHADERS} ${SHADER_INCLUDES} ${SHADER_DEFS} DEFINITIONS ${VK_DEFS} FOLDER ${SIMUL_PLATFORM_FOLDER_PREFIX}) if(SIMUL_SOURCE_BUILD) + add_dependencies(SimulVulkan${STATIC_LINK_SUFFIX} SimulCrossPlatform${STATIC_LINK_SUFFIX}) add_dependencies(SimulVulkan${STATIC_LINK_SUFFIX} SimulCrossPlatform${STATIC_LINK_SUFFIX}) if(PLATFORM_WINDOWS) target_compile_definitions(SimulVulkan${STATIC_LINK_SUFFIX} PRIVATE VK_USE_PLATFORM_WIN32_KHR ) @@ -47,6 +48,7 @@ if(SIMUL_SOURCE_BUILD) target_compile_definitions(SimulVulkan${STATIC_LINK_SUFFIX} PRIVATE VK_USE_PLATFORM_XCB_KHR ) endif() + message("target_include_directories(SimulVulkan${STATIC_LINK_SUFFIX} PUBLIC \"${Vulkan_INCLUDE_DIR}\"") target_include_directories(SimulVulkan${STATIC_LINK_SUFFIX} PUBLIC "${Vulkan_INCLUDE_DIR}") target_include_directories(SimulVulkan${STATIC_LINK_SUFFIX} PRIVATE "${SIMUL_PLATFORM_DIR}/External/stb") # For parallel_hashmap diff --git a/Vulkan/DeviceManager.cpp b/Vulkan/DeviceManager.cpp index de3556912..d0b30d7b8 100644 --- a/Vulkan/DeviceManager.cpp +++ b/Vulkan/DeviceManager.cpp @@ -139,13 +139,13 @@ DeviceManager::~DeviceManager() { if (debugReportCallback) { - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)deviceManagerInternal->instance.getProcAddr("vkDestroyDebugReportCallbackEXT"); deviceManagerInternal->instance.destroyDebugReportCallbackEXT(debugReportCallback, nullptr, d); } if (debugUtilsMessenger) { - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)deviceManagerInternal->instance.getProcAddr("vkDestroyDebugUtilsMessengerEXT"); deviceManagerInternal->instance.destroyDebugUtilsMessengerEXT(debugUtilsMessenger, nullptr, d); } @@ -578,7 +578,7 @@ void DeviceManager::Initialize(bool use_debug, bool instrument, bool default_dri } else if (IsInVector(instance_extension_names, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)deviceManagerInternal->instance.getProcAddr("vkGetPhysicalDeviceFeatures2"); d.vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)deviceManagerInternal->instance.getProcAddr("vkGetPhysicalDeviceProperties2"); deviceManagerInternal->gpu.getFeatures2(&deviceManagerInternal->gpu_features2, d); @@ -768,7 +768,7 @@ void DeviceManager::SetupDebugCallback(bool debugUtils, bool debugReport, bool d .setPfnUserCallback(DebugUtilsCallback) .setPUserData(this); - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)deviceManagerInternal->instance.getProcAddr("vkCreateDebugUtilsMessengerEXT"); debugUtilsMessenger = deviceManagerInternal->instance.createDebugUtilsMessengerEXT(debugUtilsMessengerCI, nullptr, d); debugUtilsSupported = true; @@ -783,7 +783,7 @@ void DeviceManager::SetupDebugCallback(bool debugUtils, bool debugReport, bool d .setPfnCallback(DebugReportCallback) .setPUserData(this); - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)deviceManagerInternal->instance.getProcAddr("vkCreateDebugReportCallbackEXT"); debugReportCallback = deviceManagerInternal->instance.createDebugReportCallbackEXT(debugReportCallbackCI, nullptr, d); debugMarkerSupported = debugMarker; diff --git a/Vulkan/DisplaySurface.cpp b/Vulkan/DisplaySurface.cpp index e05a4a441..619348b2f 100644 --- a/Vulkan/DisplaySurface.cpp +++ b/Vulkan/DisplaySurface.cpp @@ -172,6 +172,7 @@ void DisplaySurface::InvalidateDeviceObjects() vulkanDevice->destroySemaphore(draw_complete_semaphores[i], nullptr); vulkanDevice->destroySemaphore(image_ownership_semaphores[i], nullptr); vulkanDevice->destroyFence(fences[i], nullptr); + fences[i]=nullptr; } vulkanDevice->destroyRenderPass(render_pass, nullptr); } diff --git a/Vulkan/EffectPass.cpp b/Vulkan/EffectPass.cpp index 343d6a5b9..54232f226 100644 --- a/Vulkan/EffectPass.cpp +++ b/Vulkan/EffectPass.cpp @@ -86,6 +86,11 @@ void EffectPass::Apply(crossplatform::DeviceContext& deviceContext, bool asCompu void EffectPass::ApplyContextState(crossplatform::DeviceContext& deviceContext, vk::DescriptorSet& descriptorSet) { + if(!descriptorSet) + { + SIMUL_CERR << "Descriptor set is null.\n"; + return; + } crossplatform::ContextState* cs = &deviceContext.contextState; vulkan::Shader *c = (vulkan::Shader *)shaders[crossplatform::SHADERTYPE_COMPUTE]; vulkan::RenderPlatform *rp = (vulkan::RenderPlatform *)renderPlatform; diff --git a/Vulkan/PlatformConstantBuffer.cpp b/Vulkan/PlatformConstantBuffer.cpp index fdd1cc7a5..04dc0e559 100644 --- a/Vulkan/PlatformConstantBuffer.cpp +++ b/Vulkan/PlatformConstantBuffer.cpp @@ -48,7 +48,7 @@ void PlatformConstantBuffer::RestoreDeviceObjects(crossplatform::RenderPlatform* vrp->PushToReleaseManager(mBuffers[i], &(mAllocationInfo[i])); std::string name = "ConstantBuffer " + std::to_string(i); - vrp->CreateVulkanBuffer(mBufferSize, vk::BufferUsageFlagBits::eUniformBuffer, + vrp->CreateVulkanBuffer(nullptr,mBufferSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, mBuffers[i], mAllocationInfo[i], name.c_str()); if(addr) @@ -132,7 +132,6 @@ void PlatformConstantBuffer::ActualApply(crossplatform::DeviceContext &deviceCon last_offset = (kBufferAlign * mSlots) * mCurApplyCount; lastBuffer = &mBuffers[currentFrameIndex]; const AllocationInfo &_allocationInfo = mAllocationInfo[currentFrameIndex]; - uint8_t *pData = nullptr; vmaMapMemory(_allocationInfo.allocator, _allocationInfo.allocation, (void **)&pData); if(pData) diff --git a/Vulkan/PlatformStructuredBuffer.cpp b/Vulkan/PlatformStructuredBuffer.cpp index 6e375bfe3..e65aa166e 100644 --- a/Vulkan/PlatformStructuredBuffer.cpp +++ b/Vulkan/PlatformStructuredBuffer.cpp @@ -56,7 +56,7 @@ void PlatformStructuredBuffer::RestoreDeviceObjects(crossplatform::RenderPlatfor vk::BufferUsageFlags usageFlags=vk::BufferUsageFlagBits::eStorageBuffer|vk::BufferUsageFlagBits::eTransferDst; for (unsigned int i = 0; i < kNumBuffers; i++) { - vulkanRenderPlatform->CreateVulkanBuffer(buffer_aligned_size, usageFlags + vulkanRenderPlatform->CreateVulkanBuffer(nullptr,buffer_aligned_size, usageFlags , vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent , mReadBuffers[i], mReadBufferAllocationInfo[i],(name+"psb read").c_str()); } @@ -75,7 +75,7 @@ void PlatformStructuredBuffer::AddPerFrameBuffer(const void *init_data) vk::Device *vulkanDevice = ((vulkan::RenderPlatform *)renderPlatform)->AsVulkanDevice(); perFrameBuffers.push_back(PerFrameBuffer()); PerFrameBuffer &perFrameBuffer=perFrameBuffers.back(); - vulkanRenderPlatform->CreateVulkanBuffer(alloc_size + vulkanRenderPlatform->CreateVulkanBuffer(nullptr,alloc_size , usageFlags , vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent , perFrameBuffer.mBuffer, perFrameBuffer.mAllocationInfo,"psb"); diff --git a/Vulkan/RenderPlatform.cpp b/Vulkan/RenderPlatform.cpp index bcc95cc23..a1605f282 100644 --- a/Vulkan/RenderPlatform.cpp +++ b/Vulkan/RenderPlatform.cpp @@ -30,6 +30,27 @@ bool platform::vulkan::debugUtilsSupported=false; bool platform::vulkan::debugMarkerSupported=false; +size_t platform::vulkan::MemoryInterface::GetCurrentVideoBytesAllocated() const +{ + VmaTotalStatistics stat; + vmaCalculateStatistics(mGPUAllocator, &stat); + return stat.total.statistics.allocationBytes; +} + +size_t platform::vulkan::MemoryInterface:: GetTotalVideoBytesAllocated() const +{ + VmaTotalStatistics stat; + vmaCalculateStatistics(mGPUAllocator, &stat); + return stat.total.statistics.allocationBytes; +} + +size_t platform::vulkan::MemoryInterface::GetTotalVideoBytesFreed() const +{ + VmaTotalStatistics stat; + vmaCalculateStatistics(mGPUAllocator, &stat); + return 0; +} + namespace platform::vulkan { static PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr; @@ -42,12 +63,21 @@ using namespace platform; using namespace vulkan; RenderPlatform::RenderPlatform(): - mDummy2D(nullptr) + vulkanMemoryInterface(mGPUAllocator) + ,mDummy2D(nullptr) ,mDummy3D(nullptr) { - mirrorY = false; - mirrorY2 = false; - mirrorYText = false; + memoryInterface =&vulkanMemoryInterface; + mirrorY = false; + mirrorY2 = false; + mirrorYText = false; + for(int i=0;i<4;i++) + { + for (int j = 0; j < 4; j++) + { + lastDescriptorSet[i][j] = nullptr; + } + } } RenderPlatform::~RenderPlatform() @@ -214,6 +244,63 @@ void RenderPlatform::RestoreDeviceObjects(void *vkDevice_vkInstance_gpu) m_DescriptorSets_It[g][i] = m_DescriptorSets[g][i].begin(); } +void RenderPlatform::Defrag(crossplatform::GraphicsDeviceContext &deviceContext) +{ + uint8_t t=0; + t--; + if(t) + return; + VmaDefragmentationInfo defragInfo = {}; + defragInfo.pool = VK_NULL_HANDLE; + defragInfo.flags = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT; + + VmaDefragmentationContext defragCtx; + VkResult res = vmaBeginDefragmentation(mGPUAllocator, &defragInfo, &defragCtx); + // Check res... + + for (;;) + { + VmaDefragmentationPassMoveInfo pass; + res = vmaBeginDefragmentationPass(mGPUAllocator, defragCtx, &pass); + if (res == VK_SUCCESS) + break; + else if (res != VK_INCOMPLETE) + { + break; + } + + for (uint32_t i = 0; i < pass.moveCount; ++i) + { + // Inspect pass.pMoves[i].srcAllocation, identify what buffer/image it represents. + VmaAllocationInfo allocInfo; + vmaGetAllocationInfo(mGPUAllocator, pass.pMoves[i].srcAllocation, &allocInfo); + crossplatform::Resource *resData = (crossplatform::Resource *)allocInfo.pUserData; + resData->Reallocate(deviceContext,allocInfo.deviceMemory,pass.pMoves[i].dstTmpAllocation); + } + + // Make sure the copy commands finished executing. + // vkWaitForFences(...); + + // Destroy old buffers/images bound with pass.pMoves[i].srcAllocation. + //for (uint32_t i = 0; i < pass.moveCount; ++i) + //{ + // ... + // vkDestroyImage(device, resData->img, nullptr); + //} + + // Update appropriate descriptors to point to the new places... + + res = vmaEndDefragmentationPass(mGPUAllocator, defragCtx, &pass); + if (res == VK_SUCCESS) + break; + else if (res != VK_INCOMPLETE) + { + } + } + + vmaEndDefragmentation(mGPUAllocator, defragCtx, nullptr); +} + void RenderPlatform::CreateDescriptorPool(int g, int countPerFrame) { const crossplatform::ResourceGroupLayout &resourceGroupLayout = resourceGroupLayouts[g]; @@ -565,7 +652,7 @@ void RenderPlatform::BeginEvent(crossplatform::DeviceContext& deviceContext, con labelInfo.pLabelName = name; labelInfo.color[0] = labelInfo.color[1] = labelInfo.color[2] = labelInfo.color[3] = 1.0f; - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkCmdBeginDebugUtilsLabelEXT = vkCmdBeginDebugUtilsLabelEXT; commandBuffer->beginDebugUtilsLabelEXT(&labelInfo, d); } @@ -577,7 +664,7 @@ void RenderPlatform::BeginEvent(crossplatform::DeviceContext& deviceContext, con markerInfo.pMarkerName = name; markerInfo.color[0] = markerInfo.color[1] = markerInfo.color[2] = markerInfo.color[3] = 1.0f; - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkCmdDebugMarkerBeginEXT = vkCmdDebugMarkerBeginEXT; commandBuffer->debugMarkerBeginEXT(markerInfo, d); } @@ -588,14 +675,14 @@ void RenderPlatform::EndEvent(crossplatform::DeviceContext& deviceContext) if (debugUtilsSupported) { vk::CommandBuffer *commandBuffer = (vk::CommandBuffer *)deviceContext.platform_context; - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkCmdEndDebugUtilsLabelEXT = vkCmdEndDebugUtilsLabelEXT; commandBuffer->endDebugUtilsLabelEXT(d); } if (debugMarkerSupported) { vk::CommandBuffer *commandBuffer = (vk::CommandBuffer *)deviceContext.platform_context; - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkCmdDebugMarkerEndEXT = vkCmdDebugMarkerEndEXT; commandBuffer->debugMarkerEndEXT(d); } @@ -971,7 +1058,7 @@ uint32_t RenderPlatform::FindMemoryType(uint32_t typeFilter,vk::MemoryPropertyFl return 0; } -void RenderPlatform::CreateVulkanBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer& buffer, AllocationInfo& allocationInfo, const char *name) +void RenderPlatform::CreateVulkanBuffer(crossplatform::Resource *res,vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer& buffer, AllocationInfo& allocationInfo, const char *name) { vk::BufferCreateInfo bufferInfo = {}; bufferInfo.size = size; @@ -988,7 +1075,7 @@ void RenderPlatform::CreateVulkanBuffer(vk::DeviceSize size, vk::BufferUsageFlag allocationCI.preferredFlags = 0; allocationCI.memoryTypeBits = 0; allocationCI.pool = VK_NULL_HANDLE; - allocationCI.pUserData = nullptr; + allocationCI.pUserData = res; bool gpuMemory = (properties & vk::MemoryPropertyFlagBits::eDeviceLocal) == vk::MemoryPropertyFlagBits::eDeviceLocal; allocationInfo.allocator = gpuMemory ? mGPUAllocator : mCPUAllocator; @@ -1003,7 +1090,7 @@ void RenderPlatform::CreateVulkanBuffer(vk::DeviceSize size, vk::BufferUsageFlag } } -void RenderPlatform::CreateVulkanImage(vk::ImageCreateInfo &imageCreateInfo, vk::MemoryPropertyFlags properties, vk::Image &image, AllocationInfo &allocationInfo, const char *name) +void RenderPlatform::CreateVulkanImage(crossplatform::Resource *res,vk::ImageCreateInfo &imageCreateInfo, vk::MemoryPropertyFlags properties, vk::Image &image, AllocationInfo &allocationInfo, const char *name) { VkImage _image = VK_NULL_HANDLE; const VkImageCreateInfo &_imageCreateInfo = imageCreateInfo.operator const VkImageCreateInfo &(); @@ -1015,7 +1102,7 @@ void RenderPlatform::CreateVulkanImage(vk::ImageCreateInfo &imageCreateInfo, vk: allocationCI.preferredFlags = 0; allocationCI.memoryTypeBits = 0; allocationCI.pool = VK_NULL_HANDLE; - allocationCI.pUserData = nullptr; + allocationCI.pUserData = res; bool gpuMemory = (properties & vk::MemoryPropertyFlagBits::eDeviceLocal) == vk::MemoryPropertyFlagBits::eDeviceLocal; allocationInfo.allocator = gpuMemory ? mGPUAllocator : mCPUAllocator; @@ -1023,11 +1110,23 @@ void RenderPlatform::CreateVulkanImage(vk::ImageCreateInfo &imageCreateInfo, vk: SIMUL_VK_CHECK((vk::Result)vmaCreateImage(allocationInfo.allocator, &_imageCreateInfo, &allocationCI, &_image, &allocationInfo.allocation, &allocationInfo.allocationInfo)); image = _image; - if (name) + if (name&&image) { SetVulkanName(this, image, name); vmaSetAllocationName(allocationInfo.allocator, allocationInfo.allocation, name); } + else + { + PLATFORM_WARN("Failed to create texture {}",name); + } +} + +void RenderPlatform::ReallocVulkanImage(vk::ImageCreateInfo& imageCreateInfo, VmaAllocation &dstAllocation, vk::Image &newImg) +{ + vk::Result res = vulkanDevice->createImage(&imageCreateInfo, nullptr, &newImg); + SIMUL_VK_CHECK(res); + res=(vk::Result)vmaBindImageMemory(mGPUAllocator, dstAllocation, newImg); + SIMUL_VK_CHECK(res); } void RenderPlatform::InsertFences(crossplatform::DeviceContext& deviceContext) @@ -1416,7 +1515,7 @@ vk::Format RenderPlatform::ToVulkanFormat(crossplatform::PixelFormat p,crossplat case crossplatform::CompressionFormat::BC6H: return vk::Format::eBc6HUfloatBlock; default: - return vk::Format::eR16G16B16A16Sfloat; + return vk::Format::eR16G16B16A16Sfloat; }; case RGBA_32_FLOAT: return vk::Format::eR32G32B32A32Sfloat; diff --git a/Vulkan/RenderPlatform.h b/Vulkan/RenderPlatform.h index 0968fc218..9525c24a2 100644 --- a/Vulkan/RenderPlatform.h +++ b/Vulkan/RenderPlatform.h @@ -38,11 +38,23 @@ namespace platform extern bool debugMarkerSupported; class Material; class Texture; - + + class SIMUL_VULKAN_EXPORT MemoryInterface: public core::MemoryInterface + { + VmaAllocator &mGPUAllocator; + public: + MemoryInterface(VmaAllocator &alloc):mGPUAllocator(alloc){} + size_t GetCurrentVideoBytesAllocated() const override; + size_t GetTotalVideoBytesAllocated() const override; + size_t GetTotalVideoBytesFreed() const override; + void Deallocate(void* ) override{}; + }; //! Vulkan renderplatform implementation class SIMUL_VULKAN_EXPORT RenderPlatform:public crossplatform::RenderPlatform { + // No external memory interface, and this is read-only. + MemoryInterface vulkanMemoryInterface; public: RenderPlatform(); virtual ~RenderPlatform() override; @@ -51,6 +63,7 @@ namespace platform vk::Instance *AsVulkanInstance() override; vk::PhysicalDevice *GetVulkanGPU(); + uint32_t GetInstanceAPIVersion(); uint32_t GetPhysicalDeviceAPIVersion(); bool CheckInstanceExtension(const std::string& instanceExtensionName); @@ -69,7 +82,7 @@ namespace platform } else if (CheckDeviceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)vulkanInstance->getProcAddr("vkGetPhysicalDeviceFeatures2"); vulkanGpu->getFeatures2(&features2, d); } @@ -88,7 +101,7 @@ namespace platform } else if (CheckDeviceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)vulkanInstance->getProcAddr("vkGetPhysicalDeviceProperties2"); vulkanGpu->getProperties2(&properties2, d); } @@ -166,7 +179,6 @@ namespace platform void InsertFences(crossplatform::DeviceContext& deviceContext); - crossplatform::Material* CreateMaterial(); crossplatform::Framebuffer* CreateFramebuffer(const char *name=nullptr) override; crossplatform::SamplerState* CreateSamplerState(crossplatform::SamplerStateDesc *) override; crossplatform::Effect* CreateEffect() override; @@ -237,8 +249,9 @@ namespace platform static vk::Extent2D GetTargetAndViewportExtext2D(const crossplatform::TargetsAndViewport* targetsAndViewport); uint32_t FindMemoryType(uint32_t typeFilter,vk::MemoryPropertyFlags properties); - void CreateVulkanBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer &buffer, AllocationInfo &allocationInfo, const char *name); - void CreateVulkanImage(vk::ImageCreateInfo& imageCreateInfo, vk::MemoryPropertyFlags properties, vk::Image &image, AllocationInfo &allocationInfo, const char *name); + void CreateVulkanBuffer(crossplatform::Resource *res,vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer &buffer, AllocationInfo &allocationInfo, const char *name); + void CreateVulkanImage(crossplatform::Resource *res,vk::ImageCreateInfo& imageCreateInfo, vk::MemoryPropertyFlags properties, vk::Image &image, AllocationInfo &allocationInfo, const char *name); + void ReallocVulkanImage(vk::ImageCreateInfo& imageCreateInfo, VmaAllocation &dstAllocation, vk::Image &image); void CreateVulkanRenderpass(crossplatform::DeviceContext& deviceContext, vk::RenderPass &renderPass ,int num_colour,const crossplatform::PixelFormat *pixelFormats ,crossplatform::PixelFormat depthFormat=crossplatform::PixelFormat::UNKNOWN @@ -280,6 +293,7 @@ namespace platform } protected: + void Defrag(crossplatform::GraphicsDeviceContext &deviceContext) override; void CreateDescriptorPool(int g, int countPerFrame); vk::DescriptorPool mDescriptorPools[3]; vk::DescriptorSetLayout descriptorSetLayouts[3]; @@ -301,7 +315,7 @@ namespace platform vk::SamplerYcbcrConversionInfo samplerYcbcrConversionInfo; - crossplatform::Texture* createTexture() override; + crossplatform::Texture* createTexture() override; vk::Instance* vulkanInstance=nullptr; vk::PhysicalDevice* vulkanGpu=nullptr; vk::Device* vulkanDevice=nullptr; @@ -323,8 +337,8 @@ namespace platform vk::DeviceSize mCPUPreferredBlockSize = 0; vk::DeviceSize mGPUPreferredBlockSize = 0; - VmaAllocator mCPUAllocator; - VmaAllocator mGPUAllocator; + VmaAllocator mCPUAllocator = 0; + VmaAllocator mGPUAllocator = 0; //! Vulkan-specific apply resource group, called from ApplyContextState(). vk::DescriptorSet *GetDescriptorSetForResourceGroup(crossplatform::DeviceContext &deviceContext, uint8_t g); @@ -338,7 +352,7 @@ namespace platform if (debugUtilsSupported) { - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)instance->getProcAddr("vkSetDebugUtilsObjectNameEXT"); if (d.vkSetDebugUtilsObjectNameEXT) { @@ -356,7 +370,7 @@ namespace platform // TODO: this won't compile if the Vulkan version is too early if(debugMarkerSupported) { - vk::DispatchLoaderDynamic d; + vk::detail::DispatchLoaderDynamic d; d.vkDebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)instance->getProcAddr("vkDebugMarkerSetObjectNameEXT"); if (d.vkDebugMarkerSetObjectNameEXT) { diff --git a/Vulkan/Texture.cpp b/Vulkan/Texture.cpp index 55b1b040a..237e71a04 100644 --- a/Vulkan/Texture.cpp +++ b/Vulkan/Texture.cpp @@ -51,10 +51,10 @@ void SamplerState::Init(crossplatform::RenderPlatform*r,crossplatform::SamplerSt SetVulkanName(renderPlatform,mSampler,"Sampler"); } - vk::Sampler *SamplerState::AsVulkanSampler() - { - return &mSampler; - } +vk::Sampler *SamplerState::AsVulkanSampler() +{ + return &mSampler; +} void SamplerState::InvalidateDeviceObjects() { @@ -314,6 +314,8 @@ void Texture::FinishLoading(crossplatform::DeviceContext &deviceContext) textureUploadComplete = true; } +#pragma optimize("",off) + vk::ImageView *Texture::AsVulkanImageView(crossplatform::TextureView textureView) { #if PLATFORM_INTERNAL_CHECKS @@ -347,8 +349,11 @@ vk::ImageView *Texture::AsVulkanImageView(crossplatform::TextureView textureView mImageViews[hash] = imageView; return imageView; } + vk::ImageView *Texture::CreateVulkanImageView(crossplatform::TextureView textureView) { + if(!mImage) + return nullptr; // TODO: Should we override aspect if the texture is a depth stencil? - AJR vk::ImageAspectFlagBits aspect = depthStencil ? vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits(textureView.elements.subresourceRange.aspectMask); const uint8_t &startMip = textureView.elements.subresourceRange.baseMipLevel; @@ -520,7 +525,7 @@ bool Texture::ensureTexture2DSizeAndFormat(crossplatform::RenderPlatform* r, int vk::FormatProperties props = gpu->getFormatProperties(tex_format); vk::ImageFormatProperties image_props = gpu->getImageFormatProperties(tex_format, vk::ImageType::e2D, vk::ImageTiling::eOptimal, usageFlags, imageCreateFlags); - vk::ImageCreateInfo imageCreateInfo = vk::ImageCreateInfo() + imageCreateInfo = vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setFormat(tex_format) .setExtent({ (uint32_t)w, (uint32_t)l, (int32_t)1 }) @@ -536,7 +541,7 @@ bool Texture::ensureTexture2DSizeAndFormat(crossplatform::RenderPlatform* r, int .setInitialLayout(vk::ImageLayout::ePreinitialized); std::string _name = name + " texture mImage"; - vulkanRenderPlatform->CreateVulkanImage(imageCreateInfo, vk::MemoryPropertyFlagBits::eDeviceLocal, mImage, mAllocationInfo, _name.c_str()); + vulkanRenderPlatform->CreateVulkanImage(this,imageCreateInfo, vk::MemoryPropertyFlagBits::eDeviceLocal, mImage, mAllocationInfo, _name.c_str()); InitViewTable(1, m); AssumeLayout(vk::ImageLayout::ePreinitialized); @@ -565,7 +570,7 @@ bool Texture::ensureTexture2DSizeAndFormat(crossplatform::RenderPlatform* r, int { uint32_t n = CalculateSubresourceIndex(i, 0, 0, mips, 1); LoadedTexture& loadedTexture=mLoadedTextures[i][0]; - SetTextureData(loadedTexture, (*data)[i].data(), mip_width, mip_length, 1, 0, pixelFormat, compressionFormat); + SetTextureData(loadedTexture, (*data)[i].data(), mip_width, mip_length, 1, 0, pixelFormat, compressionFormat); mip_width=(mip_width+1)/2; mip_length=(mip_length+1)/2; } @@ -618,7 +623,7 @@ bool Texture::ensureTextureArraySizeAndFormat(crossplatform::RenderPlatform* r, vk::FormatProperties props = gpu->getFormatProperties(tex_format); vk::ImageFormatProperties image_props = gpu->getImageFormatProperties(tex_format, vk::ImageType::e2D, vk::ImageTiling::eOptimal, usageFlags, imageCreateFlags); - vk::ImageCreateInfo imageCreateInfo = vk::ImageCreateInfo() + imageCreateInfo = vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setFormat(tex_format) .setExtent({ (uint32_t)w, (uint32_t)l, (uint32_t)1 }) @@ -634,7 +639,7 @@ bool Texture::ensureTextureArraySizeAndFormat(crossplatform::RenderPlatform* r, .setInitialLayout(vk::ImageLayout::ePreinitialized); std::string _name = name + " texture mImage"; - vulkanRenderPlatform->CreateVulkanImage(imageCreateInfo, vk::MemoryPropertyFlagBits::eDeviceLocal, mImage, mAllocationInfo, _name.c_str()); + vulkanRenderPlatform->CreateVulkanImage(this,imageCreateInfo, vk::MemoryPropertyFlagBits::eDeviceLocal, mImage, mAllocationInfo, _name.c_str()); pixelFormat=f; width=w; @@ -697,7 +702,7 @@ bool Texture::ensureTexture3DSizeAndFormat(crossplatform::RenderPlatform* r, int if(computable) usageFlags|=vk::ImageUsageFlagBits::eStorage; - vk::ImageCreateInfo imageCreateInfo = vk::ImageCreateInfo() + imageCreateInfo = vk::ImageCreateInfo() .setImageType(vk::ImageType::e3D) .setFormat(tex_format) .setExtent({ (uint32_t)w, (uint32_t)l, (uint32_t)d }) @@ -712,7 +717,7 @@ bool Texture::ensureTexture3DSizeAndFormat(crossplatform::RenderPlatform* r, int .setInitialLayout(vk::ImageLayout::ePreinitialized); std::string _name = name + " texture mImage"; - vulkanRenderPlatform->CreateVulkanImage(imageCreateInfo, vk::MemoryPropertyFlagBits::eDeviceLocal, mImage, mAllocationInfo, _name.c_str()); + vulkanRenderPlatform->CreateVulkanImage(this,imageCreateInfo, vk::MemoryPropertyFlagBits::eDeviceLocal, mImage, mAllocationInfo, _name.c_str()); InitViewTable(1, m); AssumeLayout(vk::ImageLayout::ePreinitialized); @@ -921,28 +926,28 @@ void Texture::SetTextureData(LoadedTexture <,const void *data,int x,int y,int break; }; if(cf!=crossplatform::CompressionFormat::UNCOMPRESSED) - { + { // The memory pitch of a line for uncompressed formats, becomes the memory pitch // of a row of blocks in the case of the compressed. - size_t block_width =std::max(1,(x+3)/4); - size_t block_height =std::max(1,(y+3)/4); - SysMemPitch = block_size_bytes*block_width; - // buffer must be at least one block in size. - bufferSize = std::max(block_size_bytes,SysMemPitch*block_height); - numRowsToCopy =block_height; - } + size_t block_width =std::max(1,(x+3)/4); + size_t block_height =std::max(1,(y+3)/4); + SysMemPitch = block_size_bytes*block_width; + // buffer must be at least one block in size. + bufferSize = std::max(block_size_bytes,SysMemPitch*block_height); + numRowsToCopy =block_height; + } //int texelBytes=vulkan::RenderPlatform::FormatTexelBytes(f); vk::Device *vulkanDevice = ((vulkan::RenderPlatform *)renderPlatform)->AsVulkanDevice(); vulkan::RenderPlatform *vkRenderPlatform=(vulkan::RenderPlatform *)renderPlatform; std::string _name = name + " texture upload buffer"; - vkRenderPlatform->CreateVulkanBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc, + vkRenderPlatform->CreateVulkanBuffer(nullptr,bufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, lt.buffer, lt.allocationInfo, _name.c_str()); vk::SubresourceLayout layout; memset(&layout, 0, sizeof(layout)); - layout.rowPitch = SysMemPitch;//lt.x * texelBytes; + layout.rowPitch = SysMemPitch; void *mapped_data = nullptr; vmaMapMemory(lt.allocationInfo.allocator, lt.allocationInfo.allocation, &mapped_data); SIMUL_ASSERT(mapped_data !=nullptr); @@ -1223,6 +1228,71 @@ vk::ImageLayout Texture::GetLayout(crossplatform::DeviceContext& deviceContext, return mSubResourcesLayouts[startLayer][startMip]; } +void Texture::Reallocate(crossplatform::GraphicsDeviceContext& deviceContext, const void *src_ptr, const void *dest_alloc) +{ + if(mImage!=src_ptr) + return; + vk::CommandBuffer* cmdBuffer = (vk::CommandBuffer*)deviceContext.platform_context; + if (!cmdBuffer) + return; + // Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset. + vk::Image newImg; + auto r=((vulkan::RenderPlatform*)renderPlatform); + r->ReallocVulkanImage(imageCreateInfo, *((VmaAllocation*)dest_alloc), newImg); + + // Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place. + vk::ImageLayout srcLayout = mCurrentImageLayout; + + int w=width,h=length; + for (uint32_t mip = 0; mip < mips; mip++) + { + for (uint32_t layer = 0; layer < arraySize; layer++) + { + if (mip >= mLoadedTextures.size()) + continue; + if (layer >= mLoadedTextures[mip].size()) + continue; + + LoadedTexture < = mLoadedTextures[mip][layer]; + auto const subresource = vk::ImageSubresourceLayers() + .setAspectMask(vk::ImageAspectFlagBits::eColor) + .setMipLevel(mip) + .setBaseArrayLayer(layer) + .setLayerCount(1); + + int row_texels = w; + int rows = h; + if(compressionFormat!=crossplatform::CompressionFormat::UNCOMPRESSED) + { + // must be at least a block size; + if(row_texels<4) + row_texels=4; + if(rows<4) + rows=4; + } + + vk::Offset3D offset = { 0, 0, 0 }; + vk::Extent3D extent = vk::Extent3D() + .setWidth(w) + .setHeight(h) + .setDepth(1); + + auto const copy_region = + vk::ImageCopy() + .setSrcSubresource(subresource) + .setDstSubresource(subresource) + .setExtent(extent); + + cmdBuffer->copyImage(mImage, vk::ImageLayout::eTransferSrcOptimal, newImg, vk::ImageLayout::eTransferDstOptimal, 1, ©_region); + + } + w/=2; + h/=2; + } + r->PushToReleaseManager(mImage, &mAllocationInfo); + mImage = newImg; +} + void Texture::SetImageLayout(vk::CommandBuffer* commandBuffer, vk::Image image, vk::ImageAspectFlags aspectMask, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::AccessFlags srcAccessMask, vk::PipelineStageFlags src_stages, vk::PipelineStageFlags dest_stages, crossplatform::SubresourceRange subresourceRange) { diff --git a/Vulkan/Texture.h b/Vulkan/Texture.h index 62bad880d..b2a186aee 100644 --- a/Vulkan/Texture.h +++ b/Vulkan/Texture.h @@ -105,6 +105,8 @@ namespace platform void AssumeLayout(vk::ImageLayout imageLayout); /// Get the tracked current layout. vk::ImageLayout GetLayout(crossplatform::DeviceContext& deviceContext, const crossplatform::SubresourceRange& subresourceRange); + + void Reallocate(crossplatform::GraphicsDeviceContext& deviceContext,const void *src,const void *dest) override; private: void SetImageLayout(vk::CommandBuffer* commandBuffer, vk::Image image, vk::ImageAspectFlags aspectMask @@ -134,7 +136,7 @@ namespace platform std::vector> mLoadedTextures; //By mip, then by layer. int mNumSamples = 1; vk::ImageLayout mExternalLayout; - + vk::ImageCreateInfo imageCreateInfo; //!< Stored for defragmentation purposes. }; }