Commit 92852964 authored by D-AIRY's avatar D-AIRY

New material system (continue); some bugfixes

parent 4a0261e2
......@@ -38,6 +38,16 @@ cbuffer CDataMaterial: register(b0)
#ifdef XMATERIAL_HAS_CONSTANTS
cbuffer XMaterialConstants: register(b6)
{
struct
{
XMAT_MS_CONST_STRUCT();
} g_xMaterialConstants;
};
#endif
......
XMaterial MainGBuffer(PSI_XMaterial IN)
{
XMaterial OUT = XMATERIAL_LOAD_DEFAULTS();
float4 fColor = g_txBase.Sample(g_sScene, IN.vTexUV);
#ifdef HAS_ALPHATEST
clip(fColor.a - g_xMaterialConstants.pbr_alphatest_threshold);
#endif
OUT.vBaseColor = fColor.xyz;
#ifdef HAS_PARAMMAP
float4 vParams = g_txParameters.Sample(g_sScene, IN.vTexUV);
OUT.fRoughness = vParams.x;
OUT.fMetallic = vParams.y;
OUT.fThickness = vParams.z;
OUT.fAO = vParams.w;
#else
OUT.fRoughness = g_xMaterialConstants.pbr_roughness;
OUT.fMetallic = g_xMaterialConstants.pbr_metallic;
OUT.fThickness = g_xMaterialConstants.pbr_thickness;
OUT.fAO = g_xMaterialConstants.pbr_ao;
#endif
#ifdef HAS_NORMALMAP
OUT.vNormal = MixNormalMicro(IN.vNormal,
Color2Normal(g_txNormals.Sample(g_sScene, IN.vTexUV).xyz) * g_xMaterialConstants.nm_weight
);
#else
OUT.vNormal = IN.vNormal;
#endif
#ifdef HAS_F0MAP
OUT.f0 = g_txF0.Sample(g_sScene, IN.vTexUV).x;
#else
OUT.f0 = g_xMaterialConstants.pbr_f0;
#endif
return(OUT);
}
XMaterial MainIllimination(PSI_XMaterial IN)
{
XMaterial OUT = XMATERIAL_LOAD_DEFAULTS();
return(OUT);
}
XMaterial MainShadow(PSI_XMaterial IN)
{
XMaterial OUT = XMATERIAL_LOAD_DEFAULTS();
return(OUT);
}
XMaterial MainPostprocess(PSI_XMaterial IN)
{
XMaterial OUT = XMATERIAL_LOAD_DEFAULTS();
return(OUT);
}
XMaterial MainTransparency(PSI_XMaterial IN)
{
XMaterial OUT = XMATERIAL_LOAD_DEFAULTS();
return(OUT);
}
XMaterial MainIllimination(PSI_XMaterial IN)
{
XMaterial OUT = XMATERIAL_LOAD_DEFAULTS();
return(OUT);
}
XMaterial MainShadow(PSI_XMaterial IN)
{
XMaterial OUT = XMATERIAL_LOAD_DEFAULTS();
return(OUT);
}
......@@ -10,27 +10,43 @@ gbuffer.ps
//##########################################################################
SamplerState g_sScene: register(s0);
Texture2D g_txColor: register(t0); // basetexture
Texture2D g_txParameters: register(t10); // basetexture
// SamplerState g_sScene: register(s0);
// Texture2D g_txColor: register(t0); // basetexture
// Texture2D g_txParameters: register(t10);
XMAT_MS_TEXTURES();
XMAT_MS_SAMPLERS();
struct XMaterial
{
XMATERIAL_OUTPUT_STRUCT();
};
XMATERIAL_DEFAULT_LOADER();
struct PSI_XMaterial
{
XMAT_PS_STRUCT();
};
//##########################################################################
#include MATERIAL_SHADER
#include XMATERIAL_SHADER
//##########################################################################
PSO_Gbuffer main(VSO_SceneCommon IN)
PSO_Gbuffer main(PSI_XMaterial IN)
{
// ClipFar(IN.vPos.z, g_vNearFarLayers.y);
IN.vNormal = normalize(IN.vNormal);
XMaterial mtrl = ProcessMaterial(MATERIAL_PARAMETERS);
XMaterial mtrl = XMATERIAL_MAIN(IN);
return(CreateGbuffer(
mtrl.albedo,
mtrl.normal,
mtrl.parameters,
float4(mtrl.vBaseColor, 0.0),
mtrl.vNormal,
float4(mtrl.fRoughness,
mtrl.fMetallic,
mtrl.fThickness,
mtrl.fAO),
IN.vPos,
g_vNearFarLayers
));
......
Low priority
\ No newline at end of file
Hello, world.
\ No newline at end of file
......@@ -485,6 +485,7 @@ String CShaderPreprocessor::process(const char *src, const char *file)
if(bCondState)
{
String path;
dArgs = makeExpansion(dArgs).trim();
bool isLocal = dArgs[0] == '"';
String inc = getInclude(dArgs.substr(1, dArgs.length() - 2), file, &path, isLocal);
inc = process(inc.c_str(), path.c_str());
......@@ -783,12 +784,20 @@ bool CShaderPreprocessor::isTrue(const String &_expr)
String CShaderPreprocessor::makeExpansion(const String &expr)
{
if(!expr.length())
{
return("");
}
ReplList rlist;
return(makeExpansion(expr, rlist));
}
String CShaderPreprocessor::makeExpansion(const String &_expr, ReplList &rlist)
{
if(!_expr.length())
{
return("");
}
String tok;
String expr = _expr;
if(!isspace(0xFF & _expr[_expr.length() - 1]))
......@@ -915,6 +924,10 @@ String CShaderPreprocessor::makeExpansion(const String &_expr, ReplList &rlist)
String CShaderPreprocessor::replArgs(const String &_expr, const _define *pDef, const Array<String> &szArgs)
{
if(!_expr.length())
{
return("");
}
String tok, tok_prev;
String expr = _expr;
if(!isspace(0xFF & _expr[_expr.length() - 1]))
......
......@@ -8,7 +8,7 @@ See the license in LICENSE
#include "ShaderPreprocessor.h"
#define SX_SHADER_CACHE_MAGIC MAKEFOURCC('X', 'C', 'S', 'F') /*!< X Compiled Shader File*/
#define SX_SHADER_CACHE_VERSION 3
#define SX_SHADER_CACHE_VERSION 4
//##########################################################################
......@@ -125,10 +125,10 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
{
for(UINT i = 0; i < uMacroCountFile; ++i)
{
uint8_t u8Len = 0;
pCacheFile->readBin(&u8Len, sizeof(u8Len));
char *szName = (char*)alloca(u8Len);
pCacheFile->readBin(szName, u8Len);
uint16_t u16Len = 0;
pCacheFile->readBin(&u16Len, sizeof(u16Len));
char *szName = (char*)alloca(u16Len);
pCacheFile->readBin(szName, u16Len);
if(strcmp(aMacro[i].szName, szName))
{
......@@ -136,10 +136,10 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
break;
}
u8Len = 0;
pCacheFile->readBin(&u8Len, sizeof(u8Len));
char *szDefinition = (char*)alloca(u8Len);
pCacheFile->readBin(szDefinition, u8Len);
u16Len = 0;
pCacheFile->readBin(&u16Len, sizeof(u16Len));
char *szDefinition = (char*)alloca(u16Len);
pCacheFile->readBin(szDefinition, u16Len);
if(strcmp(aMacro[i].szDefinition, szDefinition))
{
......@@ -156,10 +156,10 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
bool isValid = true;
for(UINT i = 0; i < uIncludeCount; ++i)
{
uint8_t u8Len = 0;
pCacheFile->readBin(&u8Len, sizeof(u8Len));
char *szName = (char*)alloca(u8Len);
pCacheFile->readBin(szName, u8Len);
uint16_t u16Len = 0;
pCacheFile->readBin(&u16Len, sizeof(u16Len));
char *szName = (char*)alloca(u16Len);
pCacheFile->readBin(szName, u16Len);
time_t tMod = 0;
pCacheFile->readBin(&tMod, sizeof(tMod));
......@@ -347,13 +347,13 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
for(UINT i = 0; i < uMacroCount; ++i)
{
uint8_t u8Len = (uint8_t)strlen(aMacro[i].szName) + 1;
pCacheFile->writeBin(&u8Len, sizeof(u8Len));
pCacheFile->writeBin(aMacro[i].szName, u8Len);
uint16_t u16Len = (uint16_t)strlen(aMacro[i].szName) + 1;
pCacheFile->writeBin(&u16Len, sizeof(u16Len));
pCacheFile->writeBin(aMacro[i].szName, u16Len);
u8Len = (uint8_t)strlen(aMacro[i].szDefinition) + 1;
pCacheFile->writeBin(&u8Len, sizeof(u8Len));
pCacheFile->writeBin(aMacro[i].szDefinition, u8Len);
u16Len = (uint16_t)strlen(aMacro[i].szDefinition) + 1;
pCacheFile->writeBin(&u16Len, sizeof(u16Len));
pCacheFile->writeBin(aMacro[i].szDefinition, u16Len);
}
uint32_t uIncludeCount = pPreprocessor->getIncludesCount();
......@@ -363,7 +363,7 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
++uIncludeCount;
pCacheFile->writeBin(&uIncludeCount, sizeof(uIncludeCount));
uint8_t uLen = (uint8_t)strlen(szFullPath) + 1;
uint16_t uLen = (uint16_t)strlen(szFullPath) + 1;
pCacheFile->writeBin(&uLen, sizeof(uLen));
pCacheFile->writeBin(szFullPath, uLen);
......@@ -372,7 +372,7 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
for(UINT i = 0; i < uIncludeCount - 1; ++i)
{
uLen = (uint8_t)strlen(pszIncludes[i]) + 1;
uLen = (uint16_t)strlen(pszIncludes[i]) + 1;
pCacheFile->writeBin(&uLen, sizeof(uLen));
pCacheFile->writeBin(pszIncludes[i], uLen);
......@@ -413,6 +413,21 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
}
pPreprocessor->reset();
if(!pGXShader)
{
LibReport(REPORT_MSG_LEVEL_WARNING, " ===== Compiled with: =====\n");
if(aMacro)
{
GXMacro *pMacro = aMacro;
while(pMacro->szName)
{
LibReport(REPORT_MSG_LEVEL_WARNING, " '" COLOR_CYAN "%s" COLOR_YELLOW "' = '" COLOR_LGREEN "%s" COLOR_YELLOW "'\n", pMacro->szName, pMacro->szDefinition);
++pMacro;
}
}
LibReport(REPORT_MSG_LEVEL_WARNING, " ==========================\n\n");
}
mem_release(pFile);
}
}
......@@ -433,8 +448,8 @@ static int LoadShader(CShaderPreprocessor *pPreprocessor, IFileSystem *pFileSyst
CShaderManager::CShaderManager()
{
m_pPreprocessor = new CShaderPreprocessor(Core_GetIXCore()->getFileSystem());
m_pPreprocessor->addIncPath("shaders/");
}
CShaderManager::~CShaderManager()
......@@ -685,11 +700,13 @@ ID CShaderManager::preLoad(SHADER_TYPE type, const char *szPath, GXMacro *aMacro
iCountMacros = i;
break;
}
assert(i < SXGC_SHADER_COUNT_MACRO - 1);
}
for(int i = 0; i < iCountMacros; i++)
{
pShader->m_aMacros[i] = aMacros[i];
pShader->m_aMacros[i].szDefinition = strdup(aMacros[i].szDefinition);
pShader->m_aMacros[i].szName = strdup(aMacros[i].szName);
}
pShader->m_aMacros[iCountMacros].szName = 0;
......
......@@ -174,7 +174,7 @@ enum DS_RT
#define SXGC_SHADER_VAR_MAX_COUNT 64
//! количество макросов в массиве макросов
#define SXGC_SHADER_COUNT_MACRO 12
#define SXGC_SHADER_COUNT_MACRO 32
//!@}
......
......@@ -92,18 +92,18 @@ bool XMETHODCALLTYPE CMaterialSystem::loadTexture(const char *szName, IXTexture
switch(pRes->getType())
{
case GXTEXTURE_TYPE_2D:
{
IXResourceTexture2D *pRes2D = pRes->as2D();
uWidth = pRes2D->getWidth();
uHeight = pRes2D->getHeight();
}
break;
{
IXResourceTexture2D *pRes2D = pRes->as2D();
uWidth = pRes2D->getWidth();
uHeight = pRes2D->getHeight();
}
break;
case GXTEXTURE_TYPE_CUBE:
{
IXResourceTextureCube *pResCube = pRes->asCube();
uWidth = uHeight = pResCube->getSize();
}
break;
{
IXResourceTextureCube *pResCube = pRes->asCube();
uWidth = uHeight = pResCube->getSize();
}
break;
default:
assert(!"Unknown format!");
}
......@@ -373,6 +373,9 @@ XRenderPassHandler* XMETHODCALLTYPE CMaterialSystem::registerRenderPass(const ch
++pSamplers;
}
String sOutStruct;
String sDefaultInitializer;
bool isFirst = true;
while(pOutput && pOutput->szName)
{
XRenderPassOutputElement tmp = *pOutput;
......@@ -380,9 +383,22 @@ XRenderPassHandler* XMETHODCALLTYPE CMaterialSystem::registerRenderPass(const ch
tmp.szName = strdup(tmp.szName);
tmp.szDefault = strdup(tmp.szDefault);
if(!isFirst)
{
sOutStruct += "; ";
sDefaultInitializer += "; ";
}
sOutStruct += String(getHLSLType(tmp.type)) + " " + tmp.szKey;
sDefaultInitializer += String("OUT.") + tmp.szKey + " = " + String(tmp.szDefault);
pass.aOutput.push_back(tmp);
++pOutput;
isFirst = false;
}
pass.aDefines.push_back({"XMATERIAL_OUTPUT_STRUCT()", strdup(sOutStruct.c_str())});
pass.aDefines.push_back({"XMATERIAL_DEFAULT_LOADER()", strdup((String("XMaterial XMATERIAL_LOAD_DEFAULTS(){XMaterial OUT = (XMaterial)0; ") + sDefaultInitializer + "; return(OUT);}").c_str())});
// pass.aDefines.push_back({"XMATERIAL_LOAD_DEFAULTS()", strdup("")});
// aDefines
updateReferences();
......@@ -499,6 +515,15 @@ XMaterialShaderHandler* XMETHODCALLTYPE CMaterialSystem::registerMaterialShader(
}
}
for(UINT i = 0, l = pPass->pRenderPass->aDefines.size(); i < l; ++i)
{
GXMacro *pTmp = &pPass->pRenderPass->aDefines[i];
GXMacro tmp;
tmp.szName = strdup(pTmp->szName);
tmp.szDefinition = strdup(pTmp->szDefinition);
pPass->aDefines.push_back(tmp);
}
{
IGXDevice *pDevice = SGCore_GetDXDevice();
......@@ -577,7 +602,12 @@ static void ParseTexturesConstants(Array<CMaterialSystem::MaterialProperty> &aPr
{
if(EvalCondition(pProp->pCondition, aStaticList))
{
aTextures.push_back(pProp->prop.szKey);
if(aTextures.indexOf(pProp->prop.szKey, [](const char *a, const char *b){
return(!fstrcmp(a, b));
}) < 0)
{
aTextures.push_back(pProp->prop.szKey);
}
}
}
else if(pProp->prop.varType != GXDECLTYPE_UNUSED)
......@@ -659,14 +689,28 @@ void CMaterialSystem::updateReferences()
{
MaterialShader *pShader = i.second;
String sVSOstruct;
for(UINT k = 0, kl = pShader->pVertexFormat->aDecl.size(); k < kl; ++k)
{
XVertexOutputElement *el = &pShader->pVertexFormat->aDecl[k];
if(k != 0)
{
sVSOstruct += "; ";
}
sVSOstruct += String(getHLSLType(el->type)) + " " + el->szName + ": " + getHLSLSemantic(el->usage);
}
for(UINT uPass = 0, uPassl = pShader->aPasses.size(); uPass < uPassl; ++uPass)
{
MaterialShaderPassData *pPass = &pShader->aPasses[uPass];
if(pPass->isDirty)
{
pPass->isDirty = false;
RenderPass *pMetaPass = pPass->pRenderPass;
Array<GXMacro> aGenericDefines = pPass->aDefines;
aGenericDefines.push_back({"XMAT_PS_STRUCT()", sVSOstruct.c_str()});
Array<MaterialShaderSamplerData> aSamplers({NULL, NULL}, GX_MAX_SAMPLERS);
for(UINT i = 0, l = pMetaPass->aSamplers.size(); i < l; ++i)
......@@ -682,9 +726,25 @@ void CMaterialSystem::updateReferences()
if(!aSamplers[j].szKey)
{
aSamplers[j] = pPass->aSamplers[i];
break;
}
}
}
String sSamplers;
bool isFirst = true;
for(UINT i = 0, l = aSamplers.size(); i < l; ++i)
{
if(aSamplers[i].szKey)
{
if(!isFirst)
{
sSamplers += "; ";
}
isFirst = false;
sSamplers += String("SamplerState g_") + aSamplers[i].szKey + ": register(s" + (int)i + ")";
}
}
aGenericDefines.push_back({"XMAT_MS_SAMPLERS()", sSamplers.c_str()});
pPass->aTotalSamplers.swap(aSamplers);
Array<MaterialDefine> aAllDefines;
......@@ -749,6 +809,7 @@ void CMaterialSystem::updateReferences()
if(aVariableList.size())
{
// bad variant, skipping
pPass->aVariants[i].isReady = false;
}
else
{
......@@ -768,6 +829,8 @@ void CMaterialSystem::updateReferences()
return(this->getTypeSize(a.type) > this->getTypeSize(b.type));
});
// Constants ---
for(UINT j = 0, jl = aConstants.size(); j < jl; ++j)
{
aConstants[j].uGroup = UINT_MAX;
......@@ -799,11 +862,72 @@ void CMaterialSystem::updateReferences()
break;
}
}
String sConstants;
bool isFirst = true;
for(UINT uG = 0; uG <= uGroup; ++uG)
{
for(UINT j = 0, jl = aConstants.size(); j < jl; ++j)
{
if(aConstants[j].uGroup == uG)
{
if(!isFirst)
{
sConstants += "; ";
}
isFirst = false;
sConstants += String(getHLSLType(aConstants[j].type)) + " " + aConstants[j].szKey;
}
}
}
aVariantDefines.push_back({"XMAT_MS_CONST_STRUCT()", strdupa(sConstants.c_str())});
if(aConstants.size())
{
aVariantDefines.push_back({"XMATERIAL_HAS_CONSTANTS", "1"});
}
// ---
// Textures ---
Array<const char*> aTextureMap(NULL, GX_MAX_TEXTURES);
for(UINT i = 0, l = pMetaPass->aTextures.size(); i < l; ++i)
{
aTextureMap[pMetaPass->aTextures[i].uSlot] = pMetaPass->aTextures[i].szKey;
}
// pMetaPass->szShaderFile;
// pPass->szShaderFile;
// pPass->szEntryPoint;
int a = 0;
UINT j = 0;
for(UINT k = 0, kl = aTextures.size(); k < kl; ++k)
{
for(; j < GX_MAX_TEXTURES; ++j)
{
if(!aTextureMap[j])
{
aTextureMap[j] = aTextures[k];
break;
}
}
}
String sTextures;
for(UINT j = 0; j < aTextureMap.size(); ++j)
{
if(aTextureMap[j])
{
sTextures += String("Texture2D g_") + aTextureMap[j] + ":register(t" + (int)j + ");";
}
}
aVariantDefines.push_back({"XMAT_MS_TEXTURES()", strdupa(sTextures.c_str())});
// ---
char *szTemp = (char*)alloca(strlen(pPass->szShaderFile) + 3);
sprintf(szTemp, "<%s>", pPass->szShaderFile);
aVariantDefines.push_back({"XMATERIAL_SHADER", szTemp});
aVariantDefines.push_back({"XMATERIAL_MAIN", pPass->szEntryPoint});
aVariantDefines.push_back({NULL, NULL});
// prepare for compile
ID idShader = SGCore_ShaderLoad(SHADER_TYPE_PIXEL, pMetaPass->szShaderFile, NULL, &aVariantDefines[0]);
MaterialVariant *pVariant = &pPass->aVariants[i];
pVariant->idShader = idShader;
pVariant->isReady = true;
}
}
}
......@@ -871,6 +995,12 @@ void CMaterialSystem::cleanData()
free((void*)pPass->aTextures[j].szKey);
}
for(UINT j = 0, jl = pPass->aDefines.size(); j < jl; ++j)
{
// free((void*)pPass->aDefines[j].szName);
free((void*)pPass->aDefines[j].szDefinition);
}
for(UINT j = 0, jl = pPass->aSamplers.size(); j < jl; ++j)
{
free((void*)pPass->aSamplers[j].szName);
......
......@@ -166,6 +166,7 @@ protected:
Array<XRenderPassTexturesElement> aTextures;
Array<XRenderPassSamplersElement> aSamplers;
Array<XRenderPassOutputElement> aOutput;
Array<GXMacro> aDefines;
};
struct MaterialShaderSamplerData
......@@ -186,6 +187,12 @@ protected:
CLogicExpression *pCondition;
};
struct MaterialVariant
{
bool isReady;
ID idShader;
};
struct MaterialShaderPassData
{
RenderPass *pRenderPass;
......@@ -197,6 +204,8 @@ protected:
bool isDirty;
Array<MaterialShaderSamplerData> aTotalSamplers;
Array<MaterialVariant> aVariants;
};
struct MaterialShader: public XMaterialShaderHandler
......
......@@ -54,9 +54,10 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
XRenderPassHandler *pRenderPassPostprocess = NULL;
XRenderPassHandler *pRenderPassShadow = NULL;
#if 1
{
XRenderPassSamplersElement pSamplers[] = {
{"Scene default", "g_sScene", 0},
{"Scene default", "sScene", 0},
XRENDER_PASS_SAMPLERS_LIST_END()
};
......@@ -74,9 +75,11 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
XRENDER_PASS_OUTPUT_LIST_END()
};
pRenderPassGBuffer = m_pMaterialSystem->registerRenderPass("xGBuffer", "shaders/material/gbuffer.ps", NULL, pSamplers, pOutput);
pRenderPassGBuffer = m_pMaterialSystem->registerRenderPass("xGBuffer", "material/scene/gbuffer.ps", NULL, pSamplers, pOutput);
}
#endif
#if 1
{
XRenderPassTexturesElement pTextures[] = {
{"GBuffer color(rgb) light(a)", "g_txGBufferC3L1", 0},
......@@ -89,8 +92,8 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
};
XRenderPassSamplersElement pSamplers[] = {
{"Scene default", "g_sScene", 0},
{"Point clamp", "g_sPointClamp", 1},
{"Scene default", "sScene", 0},
{"Point clamp", "sPointClamp", 1},
XRENDER_PASS_SAMPLERS_LIST_END()
};
......@@ -107,9 +110,11 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
XRENDER_PASS_OUTPUT_LIST_END()
};
pRenderPassTransparency = m_pMaterialSystem->registerRenderPass("xTransparency", "shaders/material/transparent.ps", pTextures, pSamplers, pOutput);
pRenderPassTransparency = m_pMaterialSystem->registerRenderPass("xTransparency", "material/transparent.ps", pTextures, pSamplers, pOutput);
}
#endif
#if 1
{
XRenderPassTexturesElement pTextures[] = {
{"GBuffer color(rgb) light(a)", "g_txGBufferC3L1", 0},
......@@ -122,8 +127,8 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice):
};