/*************************************************************************/ /** ** ** **/ /*************************************************************************/ bool D3DShader::compileShader(GLenum type, IContainer *pContainer) { DebugBreak(); if(m_shaderCode.empty()) return false; GLenum shdtype = convertShaderType(type); GLhandleARB &shaderObj = m_shaderObjs[shdtype]; if(!shaderObj) { //shaderObj = glCreateShaderObjectARB(shdtype); // add common parts std::string strShd; D3DShader *pShd; std::vector<codeInfo> codeBlocks; int lineOffset = 0; for(int i=0; pShd = static_cast<D3DShader*>(pContainer->findShader(i)); i++) { if(*(pShd->getName()) == '\0') { strShd += pShd->getShaderCode(); std::vector<codeInfo>::iterator iCI; // calculate all the source code ranges for line # error tracking for(iCI = pShd->m_startLineNumbers.begin(); iCI != pShd->m_startLineNumbers.end(); iCI++) codeBlocks.push_back(codeInfo(iCI->lineInFX, iCI->lineinShader + lineOffset, pShd->m_totalLines, iCI->fname.c_str())); lineOffset += pShd->m_totalLines; } } // set source strShd += m_shaderCode.c_str(); std::vector<codeInfo>::iterator iCI; // calculate all the source code ranges for line # error tracking for(iCI = m_startLineNumbers.begin(); iCI != m_startLineNumbers.end(); iCI++) { codeBlocks.push_back(codeInfo(iCI->lineInFX, iCI->lineinShader + lineOffset, m_totalLines, iCI->fname.c_str())); } lineOffset += m_totalLines; GLint size = strShd.length(); const /*GLcharARB*/char* progString = strShd.c_str(); //glShaderSource(shaderObj, 1, &progString, &size); //glCompileShader(shaderObj); // // Get Log even if things went well... for warnings or other messages // char buf[1024]; int len = 0; //glGetInfoLogARB(shaderObj, 1024, &len, buf); if(len) { char *p = strstr(buf, "0("); nvFX::printf("Log for Shader %d:\n", shaderObj); if(p==NULL) p = strstr(buf, "0:"); // iOS error display if(p==NULL) nvFX::printf("%s\n", buf); while(p) { *p = '\0'; p+=2; char *pNum = p; while((*p != ')')&&(*p != ':')) p++; *p++ = '\0'; int num = atoi(pNum); num--; int offsetNum = num; std::vector<codeInfo>::iterator iCB; std::vector<codeInfo>::iterator iCBFound = codeBlocks.end(); for(iCB = codeBlocks.begin(); iCB != codeBlocks.end(); iCB++) if(num >= iCB->lineinShader) { if(num < (iCB->lineinShader + iCB->totalLinesInFX)) { iCBFound = iCB; offsetNum = num - iCB->lineinShader; break; } } if/*assert*/( iCBFound != codeBlocks.end() ) nvFX::printf("%s(%d)", iCBFound->fname.c_str(), iCBFound->lineInFX + offsetNum); else nvFX::printf("()"); pNum = strstr(p, "0("); if(pNum==NULL) pNum = strstr(p, "0:"); //if(pNum) && (!isalnum(pNum[2]))) // pNum = NULL; if(pNum) *pNum='\0'; nvFX::printf("%s", p); p = pNum; } //else nvFX::printf("Log for %d:\n%s\n", shaderObj, buf); } // // Check if we failed // GLint status = 0; //glGetShaderiv(shaderObj, GL_COMPILE_STATUS, &status); #ifndef SHADERCONCAT_USE if(status == 0) { #endif //nvFX::printf("Shader code: \n%s\n", strShd.c_str()); //glDeleteObjectARB(shaderObj); shaderObj = 0; #ifndef SHADERCONCAT_USE return false; } #else if(status == 0) return false; #endif } return true; }
/*************************************************************************/ /** ** ** TODO: in SHADERCONCAT_USE, add error log with proper line numbers to nvFX files ** **/ /*************************************************************************/ bool D3DShaderProgram::bind(IContainer* pContainer) { char buf[1024]; bool err = false; HRESULT hr; ID3D1XBlob *shaderErrors; //if(m_bound) To remove... can't do this // return true; //m_bound = true; ID3D1XDevice *pd3d1X = (ID3D1XDevice *)nvFX::getDevice(); #ifdef USE_D3D11 ID3D11DeviceContext *pd3dDC; pd3d1X->GetImmediateContext(&pd3dDC); #endif if(m_linkNeeded) { // // add common parts for line-number conversion :-( // std::vector<D3DShader::codeInfo> codeBlocks; int lineOffset = 0; ShaderMap::iterator iShd, iEnd; iShd = m_data.shaders.begin(); iEnd = m_data.shaders.end(); for(;iShd != iEnd; iShd++) { for(int n=0; n<(int)iShd->second->m_startLineNumbers.size(); n++) codeBlocks.push_back(iShd->second->m_startLineNumbers[n]); } m_data.code.clear(); // Add common header code D3DShader *pShd; for(int i=0; pShd = static_cast<D3DShader*>(pContainer->findShader(i)); i++) if(*(pShd->getName()) == '\0') { if(m_data.shaders.size()>0) m_data.code += pShd->getShaderCode(); } if(m_data.shaders.size()>0) { iShd = m_data.shaders.begin(); iEnd = m_data.shaders.end(); for(;iShd != iEnd; iShd++) m_data.code += iShd->second->getShaderCode(); } // // Compile the vertex shader // const char *profile; switch(m_shaderFlags) { #pragma MESSAGE(__FILE__"(298) : TODO TODO TODO TODO TODO : allow to chose the shader models!") case FX_VERTEX_SHADER_BIT: profile = "vs_4_0"; break; case FX_FRAGMENT_SHADER_BIT: profile = "ps_4_0"; break; case FX_GEOMETRY_SHADER_BIT: profile = "gs_4_0"; break; case FX_TESS_CONTROL_SHADER_BIT: profile = "hs_5_0"; break; case FX_TESS_EVALUATION_SHADER_BIT: profile = "ds_5_0"; break; default: profile = NULL; assert(1); break; } /*if*/assert(m_data.shaders.size()>0); { hr = D3DX1XCompileFromMemory( m_data.code.c_str(), m_data.code.size(), "Shader", NULL,//CONST D3D1X_SHADER_MACRO* NULL, //LPD3D1XINCLUDE pInclude "main", profile, 0,//Flags1 0,//Flags2 NULL,//ID3DX10ThreadPump *pPump &m_data.compiledShader, &shaderErrors, NULL); //OutputDebugStringA(m_data.code.c_str()); if(FAILED(hr)) { err = true; LPCSTR p = (LPCSTR)shaderErrors->GetBufferPointer(); replaceLineNumbers(buf, 1024, p, codeBlocks); nvFX::printf("Log for Vtx Shader: \n%s\n", buf); } else { switch(m_shaderFlags) { case FX_VERTEX_SHADER_BIT: hr = pd3d1X->CreateVertexShader(m_data.compiledShader->GetBufferPointer(), m_data.compiledShader->GetBufferSize(), #ifdef USE_D3D11 NULL, // This is ID3D11ClassLinkage pointer. TODO: see how to use it later. #endif &m_data.vtxShader); break; case FX_FRAGMENT_SHADER_BIT: hr = pd3d1X->CreatePixelShader(m_data.compiledShader->GetBufferPointer(), m_data.compiledShader->GetBufferSize(), #ifdef USE_D3D11 NULL, // This is ID3D11ClassLinkage pointer. TODO: see how to use it later. #endif &m_data.pixShader); break; case FX_GEOMETRY_SHADER_BIT: hr = pd3d1X->CreateGeometryShader(m_data.compiledShader->GetBufferPointer(), m_data.compiledShader->GetBufferSize(), #ifdef USE_D3D11 NULL, // This is ID3D11ClassLinkage pointer. TODO: see how to use it later. #endif &m_data.gsShader); break; case FX_TESS_CONTROL_SHADER_BIT: //#ifdef USE_D3D11 //hr = pd3d1X->CreateHullShader(m_data.compiledShader->GetBufferPointer(), m_data.compiledShader->GetBufferSize(), //NULL, // This is ID3D11ClassLinkage pointer. TODO: see how to use it later. //&m_data.hullShader); //#else assert(1); //#endif case FX_TESS_EVALUATION_SHADER_BIT: //#ifdef USE_D3D11 //hr = pd3d1X->CreateDomainShader(m_data.compiledShader->GetBufferPointer(), m_data.compiledShader->GetBufferSize(), //NULL, // This is ID3D11ClassLinkage pointer. TODO: see how to use it later. //&m_data.evalShader); //#else assert(1); //#endif } if(FAILED(hr)) { err = true; LPCSTR p = (LPCSTR)shaderErrors->GetBufferPointer(); replaceLineNumbers(buf, 1024, p, codeBlocks); nvFX::printf("Shader creation error : \n%s\n", p); } // IID_ID3D1XShaderReflection doesn't work... WTF ?!? hr = D3DReflect( m_data.compiledShader->GetBufferPointer(), m_data.compiledShader->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&m_data.reflector); if(FAILED(hr)) { err = true; nvFX::printf("Shader reflector failed\n"); } // // Let's check if the shader forgot some parameters in $Globals cbuffer // D3D11_SHADER_DESC sd; ID3D1XShaderReflectionConstantBuffer *pCst = NULL; m_data.reflector->GetDesc((D3D1X_SHADER_DESC*)&sd); D3D1X_SHADER_BUFFER_DESC bufDesc; bufDesc.Name = NULL; pCst = m_data.reflector->GetConstantBufferByName("$Globals"); pCst->GetDesc(&bufDesc); if(bufDesc.Name && (!strcmp(bufDesc.Name, "$Globals"))) { nvFX::printf("WARNING: some uniform parameters are outside of any cbuffer and won't be initialized properly : \n"); for(int i=0; i<(int)bufDesc.Variables; i++) { ID3D1XShaderReflectionVariable* pVar = pCst->GetVariableByIndex(i); D3D11_SHADER_VARIABLE_DESC vd; // because of a bug...?!? pVar->GetDesc((D3D1X_SHADER_VARIABLE_DESC*)&vd); nvFX::printf("%s\n", vd.Name); } } if(shaderErrors) shaderErrors->Release(); } } //if(m_data.shaders.size()>0) if(err) return false; else m_linkNeeded = false; } //if(m_linkNeeded) // // Activate the shaders // #ifdef USE_D3D11 // TODO: see how to take advantage of ID3D11ClassInstance * argument ! switch(m_shaderFlags) { case FX_VERTEX_SHADER_BIT: pd3dDC->VSSetShader(m_data.vtxShader, NULL, 0); break; case FX_FRAGMENT_SHADER_BIT: pd3dDC->PSSetShader(m_data.pixShader, NULL, 0); break; case FX_GEOMETRY_SHADER_BIT: pd3dDC->GSSetShader(m_data.gsShader, NULL, 0); break; case FX_TESS_CONTROL_SHADER_BIT: //pd3dDC->...SetShader(m_data.); //break; case FX_TESS_EVALUATION_SHADER_BIT: //pd3dDC->...SetShader(m_data.); //break; default: assert(1); } #else switch(m_shaderFlags) { case FX_VERTEX_SHADER_BIT: pd3d1X->VSSetShader(m_data.vtxShader); break; case FX_FRAGMENT_SHADER_BIT: pd3d1X->PSSetShader(m_data.pixShader); break; case FX_GEOMETRY_SHADER_BIT: pd3d1X->GSSetShader(m_data.gsShader); break; default: assert(1); } #endif return true; }