bool RendererD3D::Init(void* window, int width, int height, bool fullScreen) { IDirect3D9* d3d = Direct3DCreate9(D3D_SDK_VERSION); D3DPRESENT_PARAMETERS presentParams; memset(&presentParams, 0, sizeof(presentParams)); presentParams.Windowed = fullScreen ? FALSE : TRUE; presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; presentParams.hDeviceWindow = (HWND)window; presentParams.BackBufferFormat = D3DFMT_X8R8G8B8; presentParams.BackBufferWidth = width; presentParams.BackBufferHeight = height; presentParams.EnableAutoDepthStencil = TRUE; presentParams.AutoDepthStencilFormat = D3DFMT_D24S8; d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &mDeviceCaps); HRESULT res = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, (HWND)window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presentParams, &mDevice); if( res != D3D_OK ) return false; mCurrentVertexBuffers = (VertexBuffer**)malloc(sizeof(VertexBuffer*) * mDeviceCaps.MaxStreams); memset(mCurrentVertexBuffers, 0, sizeof(VertexBuffer*) * mDeviceCaps.MaxStreams); mVertexShaderProfile = D3DXGetVertexShaderProfile(mDevice); mPixelShaderProfile = D3DXGetPixelShaderProfile(mDevice); mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); //mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); CreateSpriteProfile(); return true; }
ErrorCode Shader::compile(std::string vert, std::string pixel) { LPD3DXBUFFER code; LPD3DXBUFFER err; HRESULT result; result = D3DXCompileShader(vert.c_str(), vert.length(), NULL, NULL, "main", D3DXGetVertexShaderProfile(mamain->d3ddev), 0, &code, &err, &VConstants.constants); if (FAILED(result)) { ErrorHandleCritical(mamain->err, mamain->errCrit, ErrorCompileVertexShader, result, (char*) err->GetBufferPointer()); err->Release(); return ErrorCompileVertexShader; } result = mamain->d3ddev->CreateVertexShader((DWORD*) code->GetBufferPointer(), &VShader); code->Release(); if (FAILED(result)) return ErrorHandleCritical(mamain->err, mamain->errCrit, ErrorCreateVertexShader, result); result = D3DXCompileShader(pixel.c_str(), pixel.length(), NULL, NULL, "main", D3DXGetPixelShaderProfile(mamain->d3ddev), 0, &code, &err, &PConstants.constants); if (FAILED(result)) { ErrorHandleCritical(mamain->err, mamain->errCrit, ErrorCompilePixelShader, result, (char*) err->GetBufferPointer()); err->Release(); VShader->Release(); VShader = 0; return ErrorCompilePixelShader; } result = mamain->d3ddev->CreatePixelShader((DWORD*) code->GetBufferPointer(), &PShader); code->Release(); if (FAILED(result)) { ErrorHandleCritical(mamain->err, mamain->errCrit, ErrorCreatePixelShader, result); VShader->Release(); VShader = 0; return ErrorCreatePixelShader; } return ErrorOk; }
//--------------------------------------------------------------------------------- // init // this function load and compile a vertex/fragment program on the specified context // if the source file is not found, it assigns a default GREEN color shader // if the compile failed, it assigns a default RED color shader //--------------------------------------------------------------------------------- bool FFxProgram::init(CGcontext aContext) { CGenum fileType; // remove existing program (in case a program is already loaded) if (mProgram) { cgDestroyProgram(mProgram); mProgram = 0; } fileType = CG_SOURCE; #ifdef WIN32 HRESULT hr; if (GDD->GetClassID() == ClassIDZDisplayDeviceDX9) { const char** profileOpts; profileOpts = cgD3D9GetOptimalOptions(mProfile); const char *nOpts[16]; nOpts[0] = COMPILE_ARGS[0]; int idx =1; while ( (idx<15) && profileOpts[idx-1]) { nOpts[idx] = profileOpts[idx-1]; idx++; } nOpts[idx] = 0; const char *szDXprofile = NULL; if (mProfile == CG_PROFILE_VS_2_0) { szDXprofile = D3DXGetVertexShaderProfile(GDD->GetD3D9Device()); } else { szDXprofile = D3DXGetPixelShaderProfile(GDD->GetD3D9Device()); } /* //LPD3DXBUFFER mDXShader; D3DXCompileShader( mSourceBuffer, strlen(mSourceBuffer), NULL, NULL, mEntry.c_str(), szDXprofile, 0, &mDXShader, NULL, NULL ); */ mProgram = cgCreateProgram(aContext, fileType, mSourceBuffer, mProfile, mEntry.c_str(), nOpts); hr = cgD3D9LoadProgram(mProgram, true, 0); } else #endif { // opengl //mProgram = cgCreateProgram(aContext, fileType, mSourceBuffer, mProfile, mEntry.c_str(), COMPILE_ARGS); mProfile = (mProfileDomain == CG_VERTEX_DOMAIN) ?cgGLGetLatestProfile(CG_GL_VERTEX):cgGLGetLatestProfile(CG_GL_FRAGMENT ); assert(cgGLIsProfileSupported(mProfile)); mProgram = cgCreateProgramFromFile(aContext, fileType, mFileName, mProfile, mEntry.c_str(), COMPILE_ARGS); if (mProgram == NULL) { CGerror error; const char* errTxt = cgGetLastErrorString(&error); LOG ("ERROR %x: can't compile %s : %s\n", error, mFileName.c_str(), errTxt); useDefaultProgram(aContext); assert(false); return false; } cgGLLoadProgram(mProgram); checkForCgError("loadprog"); } if (mProgram == 0) { CGerror error = cgGetError(); LOG ("ERROR %x: can't load or compile %s : %s\n", error, mFileName.c_str(), cgGetLastErrorString(&error)); useDefaultProgram(aContext); assert(false); return false; } return true; }
/* extern "C" { LPCSTR WINAPI D3DXGetPixelShaderProfile (LPDIRECT3DDEVICE9 pDevice); LPCSTR WINAPI D3DXGetVertexShaderProfile (LPDIRECT3DDEVICE9 pDevice); }; */ HRESULT CRender::shader_compile ( LPCSTR name, LPCSTR pSrcData, UINT SrcDataLen, void* _pDefines, void* _pInclude, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void* _ppShader, void* _ppErrorMsgs, void* _ppConstantTable) { D3DXMACRO defines [128]; int def_it = 0; CONST D3DXMACRO* pDefines = (CONST D3DXMACRO*) _pDefines; char c_smapsize [32]; char c_gloss [32]; // Msg("%s.%s", name, pTarget); if (pDefines) { // transfer existing defines for (;; def_it++) { if (0==pDefines[def_it].Name) break; defines[def_it] = pDefines[def_it]; } } // options { sprintf (c_smapsize,"%d",u32(o.smapsize)); defines[def_it].Name = "SMAP_size"; defines[def_it].Definition = c_smapsize; def_it ++ ; } if (o.fp16_filter) { defines[def_it].Name = "FP16_FILTER"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.fp16_blend) { defines[def_it].Name = "FP16_BLEND"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.HW_smap) { defines[def_it].Name = "USE_HWSMAP"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.HW_smap_PCF) { defines[def_it].Name = "USE_HWSMAP_PCF"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.HW_smap_FETCH4) { defines[def_it].Name = "USE_FETCH4"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.sjitter) { defines[def_it].Name = "USE_SJITTER"; defines[def_it].Definition = "1"; def_it ++ ; } if (HW.Caps.raster_major >= 3) { defines[def_it].Name = "USE_BRANCHING"; defines[def_it].Definition = "1"; def_it ++ ; } if (HW.Caps.geometry.bVTF) { defines[def_it].Name = "USE_VTF"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.Tshadows) { defines[def_it].Name = "USE_TSHADOWS"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.mblur) { defines[def_it].Name = "USE_MBLUR"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.sunfilter) { defines[def_it].Name = "USE_SUNFILTER"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.sunstatic) { defines[def_it].Name = "USE_R2_STATIC_SUN"; defines[def_it].Definition = "1"; def_it ++ ; } if (o.forcegloss) { sprintf (c_gloss,"%f",o.forcegloss_v); defines[def_it].Name = "FORCE_GLOSS"; defines[def_it].Definition = c_gloss; def_it ++ ; } if (o.forceskinw) { defines[def_it].Name = "SKIN_COLOR"; defines[def_it].Definition = "1"; def_it ++; } // skinning if (m_skinning<0) { defines[def_it].Name = "SKIN_NONE"; defines[def_it].Definition = "1"; def_it ++ ; } if (0==m_skinning) { defines[def_it].Name = "SKIN_0"; defines[def_it].Definition = "1"; def_it ++; } if (1==m_skinning) { defines[def_it].Name = "SKIN_1"; defines[def_it].Definition = "1"; def_it ++; } if (2==m_skinning) { defines[def_it].Name = "SKIN_2"; defines[def_it].Definition = "1"; def_it ++; } // finish defines[def_it].Name = 0; defines[def_it].Definition = 0; def_it ++; // if (0==xr_strcmp(pFunctionName,"main")) { if ('v'==pTarget[0]) pTarget = D3DXGetVertexShaderProfile (HW.pDevice); // vertex "vs_2_a"; // else pTarget = D3DXGetPixelShaderProfile (HW.pDevice); // pixel "ps_2_a"; // } LPD3DXINCLUDE pInclude = (LPD3DXINCLUDE) _pInclude; LPD3DXBUFFER* ppShader = (LPD3DXBUFFER*) _ppShader; LPD3DXBUFFER* ppErrorMsgs = (LPD3DXBUFFER*) _ppErrorMsgs; LPD3DXCONSTANTTABLE* ppConstantTable = (LPD3DXCONSTANTTABLE*)_ppConstantTable; #ifdef D3DXSHADER_USE_LEGACY_D3DX9_31_DLL // December 2006 and later HRESULT _result = D3DXCompileShader(pSrcData,SrcDataLen,defines,pInclude,pFunctionName,pTarget,Flags|D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,ppShader,ppErrorMsgs,ppConstantTable); #else HRESULT _result = D3DXCompileShader(pSrcData,SrcDataLen,defines,pInclude,pFunctionName,pTarget,Flags,ppShader,ppErrorMsgs,ppConstantTable); #endif if (SUCCEEDED(_result) && o.disasm) { ID3DXBuffer* code = *((LPD3DXBUFFER*)_ppShader); ID3DXBuffer* disasm = 0; D3DXDisassembleShader (LPDWORD(code->GetBufferPointer()), FALSE, 0, &disasm ); string_path dname; strconcat (dname,"disasm\\",name,('v'==pTarget[0])?".vs":".ps" ); IWriter* W = FS.w_open("$logs$",dname); W->w (disasm->GetBufferPointer(),disasm->GetBufferSize()); FS.w_close (W); _RELEASE (disasm); } return _result; }
bool U2D3DXEffectShader::LoadResource() { U2ASSERT(0 == m_pD3DEffect); HRESULT hr; IDirect3DDevice9* pD3DDev = m_pRenderer->GetD3DDevice(); U2ASSERT(pD3DDev); U2FilePath fPath; TCHAR fullPath[MAX_PATH]; // StackString Memory Leak... U2DynString includePath(FX_SHADER_PATH); includePath += _T("\\2.0"); fPath.ConvertToAbs(fullPath, MAX_PATH * sizeof(TCHAR) , m_szFilename.Str(), includePath); U2File* pFile = U2File::GetFile(fullPath, U2File::READ_ONLY); if(!pFile) { U2_DELETE pFile; return false; } uint32 uBuffLen = pFile->GetfileSize(); if(uBuffLen == 0) { U2_DELETE pFile; return false; } unsigned char* pBuffer = U2_ALLOC(unsigned char, uBuffLen); pFile->Read(pBuffer, uBuffLen); U2_DELETE pFile; ID3DXBuffer* pErrorBuffer = NULL; #ifdef DEBUG_SHADER DWORD compileFlags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION | D3DXSHADER_USE_LEGACY_D3DX9_31_DLL | D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT | D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT ; #else DWORD compileFlags = D3DXSHADER_USE_LEGACY_D3DX9_31_DLL; #endif //U2DynString includePath(FX_SHADER_PATH); //includePath += _T("\\2.0"); U2D3DXEffectShaderInclude includeHandler(includePath); ID3DXEffectPool* pEffectPool = m_pRenderer->GetD3DEffectPool(); U2ASSERT(pEffectPool); // get the highest supported shader profiles // LPCSTR vsProfile, psProfile; //#ifdef UNICODE // vsProfile = ToUnicode( D3DXGetVertexShaderProfile(pD3DDev) ); // psProfile = ToUnicode( D3DXGetPixelShaderProfile(pD3DDev) ); //#else // vsProfile = D3DXGetVertexShaderProfile(pD3DDev); // psProfile = D3DXGetPixelShaderProfile(pD3DDev); //#endif LPCSTR vsProfile = D3DXGetVertexShaderProfile(pD3DDev); LPCSTR psProfile = D3DXGetPixelShaderProfile(pD3DDev); if (0 == vsProfile) { FDebug("Invalid Vertex Shader profile! Fallback to vs_2_0!\n"); vsProfile = "vs_2_0"; } if (0 == psProfile) { FDebug("Invalid Pixel Shader profile! Fallback to ps_2_0!\n"); psProfile = "ps_2_0"; } // create macro definitions for shader compiler D3DXMACRO defines[] = { { "VS_PROFILE", vsProfile }, { "PS_PROFILE", psProfile }, { 0, 0 }, }; // create effect if (compileFlags) { hr = D3DXCreateEffectFromFile( pD3DDev, // pDevice fullPath, // File name defines, // pDefines &includeHandler, // pInclude compileFlags, // Flags pEffectPool, // pPool &m_pD3DEffect, // ppEffect &pErrorBuffer); // ppCompilationErrors } else { hr = D3DXCreateEffect( pD3DDev, // pDevice pBuffer, // pFileData uBuffLen, // DataSize defines, // pDefines &includeHandler, // pInclude compileFlags, // Flags pEffectPool, // pPool &(m_pD3DEffect), // ppEffect &pErrorBuffer); // ppCompilationErrors } U2_FREE(pBuffer); pBuffer = NULL; if (FAILED(hr)) { FDebug("nD3D9Shader: failed to load fx file '%s' with:\n\n%s\n", fullPath, pErrorBuffer ? pErrorBuffer->GetBufferPointer() : "No D3DX error message."); if (pErrorBuffer) { pErrorBuffer->Release(); } return false; } U2ASSERT(m_pD3DEffect); m_bValidated = false; m_bNotValidate = false; this->ValidateEffect(); return true; }
bool CShaderHLSL::Create(P3D::sShaderDesc &desc) { const char *pData; ULONG fsize; IFileSystem* pFS = CRenderer::mEngine()->mFilesystem(); wchar path[P3DMAX_PATH]; wsprintf(path, P3DMAX_PATH-1, _W("shaders/%s.rshader"), desc.ShaderFile.Get()); FSFILE *fp = pFS->Load(path, (BYTE *&)pData, fsize, true); if (!fp) { CON(MSG_ERR, _W("Can't open %s.hlsl shader file from data/shaders directory!"), desc.ShaderFile.Get()); return false; } ID3DXBuffer *pShaderBlob = NULL; ID3DXBuffer *pErrors = NULL; DWORD flags = D3DXSHADER_DEBUG; //D3DXSHADER_OPTIMIZATION_LEVEL3 char profile[128]; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: strcpy(profile, D3DXGetVertexShaderProfile(g_pD3ddev)); break; case SHADERTYPE_PIXEL_SHADER: strcpy(profile, D3DXGetPixelShaderProfile(g_pD3ddev)); break; case SHADERTYPE_GEOMETRY_SHADER: CON(MSG_ERR, _W("DX9 does not support geometry shaders.")); return false; default: CON(MSG_ERR, _W("Chader creation failed. No apropriate ShaderType given.")); return false; } CIncludeHandler includeHandler; D3DXMACRO Shader_Macros[] = { { "DX9", NULL }, { "SM3", NULL }, NULL }; if(FAILED(D3DXCompileShader( pData, fsize, Shader_Macros, &includeHandler, _W2A(desc.EntryFunction.Get()), profile, flags, &pShaderBlob, &pErrors, &m_pConstTable ))) { if(pErrors) CON(MSG_ERR, _W("%s"), _A2W((char*)pErrors->GetBufferPointer())); else CON(MSG_ERR, _W("Error description not given")); CON(MSG_ERR, _W("Shader %s could not be compiled"), desc.ShaderFile.Get()); SAFE_RELEASE(pErrors); return false; } pFS->UnLoad(fp, (BYTE *)pData); //save to cache fp = pFS->Open(_W("cache/shaders/hlsl"), _W("wb")); const char* cs = (const char*)pShaderBlob->GetBufferPointer(); pFS->Write(cs, 1, pShaderBlob->GetBufferSize(), fp); pFS->Close(fp); bool shaderCreated = false; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: shaderCreated = SUCCEEDED(g_pD3ddev->CreateVertexShader((const DWORD*)pShaderBlob->GetBufferPointer(), &m_pVS)); break; case SHADERTYPE_PIXEL_SHADER: shaderCreated = SUCCEEDED(g_pD3ddev->CreatePixelShader((const DWORD*)pShaderBlob->GetBufferPointer(), &m_pPS)); break; } if(!shaderCreated) { CON(MSG_ERR, _W("Shader creation error")); return false; } //set constant to their default values m_pConstTable->SetDefaults(g_pD3ddev); //create vertex declaration if(desc.ShaderType == SHADERTYPE_VERTEX_SHADER) m_pVertDecl = new CVertexDeclaration(CRenderer::cGraphicsManager()->GetVertexDescByID(desc.VertexDescID), pShaderBlob); SAFE_RELEASE(pShaderBlob); m_desc = desc; CON(MSG_INFO, _W("Shader '%s' created"), desc.ShaderFile); return true; }
HRESULT InitD3D(HINSTANCE hInstance) { // 先创建DInput和DSound if(FAILED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_pDI, NULL))) return E_FAIL; if(FAILED(g_pDI->CreateDevice(GUID_SysKeyboard, &g_pDIKey, NULL))) return E_FAIL; if(FAILED(g_pDI->CreateDevice(GUID_SysMouse, &g_pDIMouse, NULL))) return E_FAIL; // 设置参数 if(FAILED(g_pDIKey->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))) return E_FAIL; if(FAILED(g_pDIKey->SetDataFormat(&c_dfDIKeyboard))) return E_FAIL; if(FAILED(g_pDIMouse->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))) return E_FAIL; if(FAILED(g_pDIMouse->SetDataFormat(&c_dfDIMouse))) return E_FAIL; // 缓冲输入,设置数据格式和属性 DIPROPDWORD dipdw; dipdw.diph.dwSize = sizeof(DIPROPDWORD); dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); dipdw.diph.dwObj = 0; dipdw.diph.dwHow = DIPH_DEVICE; dipdw.dwData = SAMPLE_BUFFER_SIZE; // Arbitary buffer size #ifdef USE_BUFFERED_KEYBOARD_INPUT if( FAILED( g_pDIKey->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) ) return E_FAIL; #endif #ifdef USE_BUFFERED_MOUSE_INPUT if( FAILED( g_pDIMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) ) return E_FAIL; #endif // 开始 g_pDIKey->Acquire(); g_pDIMouse->Acquire(); // 初始化D3D if(NULL==(d3d=Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL; //查询当前显卡模式,Desktop是目前桌面设置,d3ddm总是当前使用全屏模式的设置,即使是窗口模式,颜色数值也总和当前的一样 if(FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DesktopDisplayMode))) return E_FAIL; if(FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) return E_FAIL; //全屏的话默认是32位色 if(!WindowMode) d3ddm.Format = D3DFMT_X8R8G8B8; //查询设备能力,并设置顶点处理器模式 DWORD UserVertexShaderProcessing; d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps); if(FAILED(DetectDeviceCaps())) return E_FAIL; if(d3dcaps.VertexShaderVersion < D3DVS_VERSION(1, 0)) UserVertexShaderProcessing=D3DCREATE_HARDWARE_VERTEXPROCESSING; else UserVertexShaderProcessing=D3DCREATE_SOFTWARE_VERTEXPROCESSING; //创建D3D设备 ZeroMemory(&d3dpp,sizeof(d3dpp)); d3dpp.Windowed = WindowMode; d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; d3dpp.hDeviceWindow = hWnd; d3dpp.BackBufferCount = 1; d3dpp.BackBufferWidth = d3ddm.Width; d3dpp.BackBufferHeight = d3ddm.Height; d3dpp.EnableAutoDepthStencil = TRUE; if(WindowMode) { d3ddm.Format = DesktopDisplayMode.Format; d3dpp.BackBufferWidth = WindowWidth; d3dpp.BackBufferHeight = WindowHeight; } d3dpp.BackBufferFormat = d3ddm.Format; if(d3ddm.Format == D3DFMT_X8R8G8B8) { d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; TextureFormat = D3DFMT_A8R8G8B8; } else { d3dpp.AutoDepthStencilFormat = D3DFMT_D16; TextureFormat = D3DFMT_A4R4G4B4; } // 先强制以硬件顶点方式创建设备(为了不漏掉MX440这种不支持VS但支持T&L的显卡,XIXI) UserVertexShaderProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING; HRESULT hr = d3d->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd, UserVertexShaderProcessing, &d3dpp, &d3ddevice); // 这种错误表示顶点处理方式不被硬件支持,强制以软件方式创建设备(为了兼容不支持T&L的DX7显卡,比如某些集成显卡) if(hr == D3DERR_INVALIDCALL) { mymessage("警告:显卡不支持硬件顶点处理,强制以软件方式创建设备,性能会急剧下降!!!"); UserVertexShaderProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING; hr = d3d->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd, UserVertexShaderProcessing, &d3dpp, &d3ddevice); } // 全部失败?有问题吧? if(FAILED(hr)) { char szErrorInfo[512] = ""; sprintf(szErrorInfo, "创建D3D设备失败!请检查系统或硬件设置!比如显卡驱动程序或DirectX是否安装正确!错误号%x", hr); mymessage(szErrorInfo); return E_FAIL; } // Shader版本检测 char pVSVersion[7] = "", pPSVersion[7] = ""; char pNeedVSVersion[7] = USE_VSVERSION, pNeedPSVersion[7] = USE_PSVERSION; char szErrorInfo[100] = ""; #ifdef USE_PIXELSHADER // 判断PS版本 memcpy(pPSVersion, D3DXGetPixelShaderProfile(d3ddevice), 7); // 2.x中'b'虽然字母数值大于'a',但它从支持度上来看是小于a的,所以这里强制把它置为小于'a',以便后面比较 if(pPSVersion[3] == '2' && pPSVersion[5] == 'b') pPSVersion[5] = 'a'-1; if(pNeedPSVersion[3] == '2' && pNeedPSVersion[5] == 'b') pNeedPSVersion[5] = 'a'-1; if(pPSVersion[3]<pNeedPSVersion[3] || pPSVersion[3]==pNeedPSVersion[3]&&pPSVersion[5]<pNeedPSVersion[5]) { sprintf(szErrorInfo, "不支持Pixel Shader %c.%c!", pNeedPSVersion[3], pNeedPSVersion[5]); mymessage(szErrorInfo); return E_FAIL; } // 判断PS2.0x的条件是否符合程序的最小需求 if(!strcmp(USE_PSVERSION, "ps_2_a") || !strcmp(USE_PSVERSION, "ps_2_b") || !strcmp(USE_PSVERSION, "ps_2_x")) { BOOL bFlowControl = FALSE; #ifdef PS2x_USE_FLOWCONTROL bFlowControl = TRUE; #endif if(!CheckPS2xSupport(PS2x_USE_MAXNUM_TEMP, bFlowControl)) { sprintf(szErrorInfo, "不完整支持Pixel Shader 2.x,无法执行程序!"); mymessage(szErrorInfo); return E_FAIL; } } #endif USE_PIXELSHADER #ifdef USE_VERTEXSHADER BOOL bSoftwareVertexProcessing = FALSE; // 完全不支持的,要跳过版本检测,否则D3DXGetVertexShaderProfile会返回空指针造成非法操作 if((d3dcaps.VertexShaderVersion&0xffff) == 0) { bSoftwareVertexProcessing = TRUE; } else { // 判断VS版本 memcpy(pVSVersion, D3DXGetVertexShaderProfile(d3ddevice), 7); if(pVSVersion[3]<pNeedVSVersion[3] || pVSVersion[3]==pNeedVSVersion[3]&&pVSVersion[5]<pNeedVSVersion[5]) { bSoftwareVertexProcessing = TRUE; } // 判断VS2.0x的条件是否符合程序的最小需求 if(!strcmp(USE_VSVERSION, "vs_2_a") || !strcmp(USE_VSVERSION, "vs_2_b") || !strcmp(USE_VSVERSION, "vs_2_x")) { #ifdef VS2a_USE_MAXNUM_TEMP if(d3dcaps.VS20Caps.NumTemps < VS2x_USE_MAXNUM_TEMP) { bSoftwareVertexProcessing = TRUE; } #endif } } // 如果刚才是以硬件顶点创建设备的,而现在又需要强制软顶点以运行硬件不支持的VS,那么释放设备,重新创建 if(bSoftwareVertexProcessing && UserVertexShaderProcessing == D3DCREATE_HARDWARE_VERTEXPROCESSING) { // 如果不支持指定版本的Vertex Shader,就强制创建软顶点处理设备 sprintf(szErrorInfo, "警告:显卡不支持Vertex Shader %c.%c!强制以软件方式创建设备,性能会急剧下降!!!", pNeedVSVersion[3], pNeedVSVersion[5]); mymessage(szErrorInfo); SAFE_RELEASE(d3ddevice); hr = d3d->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddevice); if(FAILED(hr)) { char szErrorInfo[512] = ""; sprintf(szErrorInfo, "创建D3D设备失败!请检查系统或硬件设置!比如显卡驱动程序或DirectX是否安装正确!错误号%x", hr); mymessage(szErrorInfo); return E_FAIL; } } #endif //初始化摄像机,之所以放在这里,是为了设备丢失后不会又重置到初始位置 D3DXVECTOR3 PtLookAt = g_PtCameraInitPos + g_VecCameraInitDir; CameraChange.InitCamera(g_PtCameraInitPos.x, g_PtCameraInitPos.y, g_PtCameraInitPos.z, PtLookAt.x, PtLookAt.y, PtLookAt.z, 0.0f,1.0f,0.0f, 7,7,90); //得到硬件精确计时器的频率 QueryPerformanceFrequency(&PerformanceFrequency); return S_OK; }
void D3D9Device::init( const ion_uint32 width,const ion_uint32 height, const base::String& title,const bool fullscreen,void* displayhandle, const ion_uint32 adapter, const video::Pixelformat colorbufferformat, const video::Pixelformat depthstencilformat,const ion_uint32 Hz,const bool vsync) { if (!m_IsValid) { base::log("D3D9Device::init()",base::Warning) << "Initializing an invalid device\n"; } openWindow(width,height,title,fullscreen,displayhandle); bool windowed=!m_Fullscreen; D3DFORMAT adapterfmt; if (windowed) { D3DDISPLAYMODE d3ddm; m_pD3D9->GetAdapterDisplayMode(adapter,&d3ddm); adapterfmt=d3ddm.Format; } else adapterfmt=d3dpixelformat(colorbufferformat); if (adapterfmt==D3DFMT_UNKNOWN) { base::log("D3D9Device::init()",base::Error) << "Unknown/unsupported color buffer format\n"; m_IsValid=false; return; } RECT r; GetClientRect(m_hWindow,&r); m_D3DPP.Windowed=windowed; m_D3DPP.BackBufferWidth=r.right-r.left; m_D3DPP.BackBufferHeight=r.bottom-r.top; m_D3DPP.BackBufferCount=1; m_D3DPP.BackBufferFormat=adapterfmt; m_D3DPP.AutoDepthStencilFormat=d3dpixelformat(depthstencilformat); m_D3DPP.EnableAutoDepthStencil=TRUE; m_D3DPP.Flags=0; m_D3DPP.PresentationInterval=vsync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE; m_D3DPP.FullScreen_RefreshRateInHz=windowed ? 0 : Hz; m_D3DPP.hDeviceWindow=m_hWindow; m_D3DPP.MultiSampleQuality=0; m_D3DPP.MultiSampleType=D3DMULTISAMPLE_NONE; m_D3DPP.SwapEffect=D3DSWAPEFFECT_DISCARD; m_D3DPP.Windowed=windowed; // Getting caps base::log("D3D9Device::init()",base::Message) << "Getting caps\n"; HRESULT hr=m_pD3D9->GetDeviceCaps(adapter,D3DDEVTYPE_HAL,&m_D3DCaps); if (FAILED(hr)) { base::log("D3D9Device::init()",base::Error) << "GetDeviceCaps() failed\n"; m_IsValid=false; return; } // Caps structure is initialized here { base::log("D3D9Device::init()",base::Message) << "Analyzing caps\n"; m_Caps.m_NPOTTextures=!((m_D3DCaps.TextureCaps&D3DPTEXTURECAPS_POW2) || (m_D3DCaps.TextureCaps&D3DPTEXTURECAPS_NONPOW2CONDITIONAL)); m_Caps.m_RectangularTextures=(m_D3DCaps.TextureCaps&D3DPTEXTURECAPS_SQUAREONLY)==0; m_Caps.m_Cubemaps=(m_D3DCaps.TextureCaps&D3DPTEXTURECAPS_CUBEMAP)!=0; m_Caps.m_NPOTCubemaps=(m_D3DCaps.TextureCaps&D3DPTEXTURECAPS_CUBEMAP_POW2)==0; m_Caps.m_ProjectedTextures=(m_D3DCaps.TextureCaps&D3DPTEXTURECAPS_PROJECTED)!=0; m_Caps.m_DisplacementMaps=false; m_Caps.m_CompressedTextures=false; m_Caps.m_MaxTextureWidth=m_D3DCaps.MaxTextureWidth; m_Caps.m_MaxTextureHeight=m_D3DCaps.MaxTextureHeight; m_Caps.m_MaxTextureVolumeDepth=m_D3DCaps.MaxVolumeExtent; m_Caps.m_MaxAnisotropy=m_D3DCaps.MaxAnisotropy; m_Caps.m_MaxTextureBlendStages=m_D3DCaps.MaxTextureBlendStages; m_Caps.m_MaxActiveFFLights=m_D3DCaps.MaxActiveLights; m_Caps.m_MaxPointSize=m_D3DCaps.MaxPointSize; m_Caps.m_MaxPrimitiveCount=m_D3DCaps.MaxPrimitiveCount; m_Caps.m_MaxVertexIndex=m_D3DCaps.MaxVertexIndex; } // Probing formats { video::Caps::Texflags **pTexflags, *pTexflagarrays[]={m_Caps.m_Valid2DTextureFormats,m_Caps.m_Valid3DTextureFormats, m_Caps.m_ValidCubemapFormats,0}; const D3DRESOURCETYPE rtype[]={D3DRTYPE_TEXTURE,D3DRTYPE_VOLUMETEXTURE,D3DRTYPE_CUBETEXTURE}; pTexflags=pTexflagarrays; unsigned int ii=0; base::log("D3D9Device::init()",base::Message) << "Probing texture formats\n"; while (*pTexflags) { video::Caps::Texflags *pTexflagarray=*pTexflags; for (unsigned int i=0;i<video::Pixelformat_NumFormats;++i) { D3DFORMAT fmt=d3dpixelformat((video::Pixelformat)i); hr=0; hr=m_pD3D9->CheckDeviceFormat(adapter,D3DDEVTYPE_HAL,adapterfmt,0,rtype[ii],fmt); if (FAILED(hr)) { pTexflagarray[i].m_Supported=false; continue; } else pTexflagarray[i].m_Supported=true; if ((i==video::Pixelformat_RGB_DXT1) || (i==video::Pixelformat_RGBA_DXT1) || (i==video::Pixelformat_RGBA_DXT3) || (i==video::Pixelformat_RGBA_DXT5)) m_Caps.m_CompressedTextures=true; // Volume textures are not supported as render targets if (rtype[ii]!=D3DRTYPE_VOLUMETEXTURE) { hr=m_pD3D9->CheckDeviceFormat(adapter,D3DDEVTYPE_HAL,adapterfmt,D3DUSAGE_RENDERTARGET,rtype[ii],fmt); pTexflagarray[i].m_Rendertarget=(hr==D3D_OK); m_Caps.m_Rendertargets=true; } else pTexflagarray[i].m_Rendertarget=false; hr=m_pD3D9->CheckDeviceFormat(adapter,D3DDEVTYPE_HAL,adapterfmt,D3DUSAGE_DYNAMIC,rtype[ii],fmt); pTexflagarray[i].m_Dynamic=(hr==D3D_OK); // For depth buffers, only depth formats are supported // Volume textures are not supported if (isDepthformat((video::Pixelformat)i) && (rtype[ii]!=D3DRTYPE_VOLUMETEXTURE)) { hr=m_pD3D9->CheckDeviceFormat(adapter,D3DDEVTYPE_HAL,adapterfmt,D3DUSAGE_DEPTHSTENCIL,rtype[ii],fmt); pTexflagarray[i].m_Depth=(hr==D3D_OK); } else pTexflagarray[i].m_Depth=false; if ((m_D3DCaps.DevCaps2&D3DDEVCAPS2_DMAPNPATCH)!=0) { hr=m_pD3D9->CheckDeviceFormat(adapter,D3DDEVTYPE_HAL,adapterfmt,D3DUSAGE_DMAP,rtype[ii],fmt); pTexflagarray[i].m_DisplacementMap=(hr==D3D_OK); } else pTexflagarray[i].m_DisplacementMap=false; } ++pTexflags; ++ii; } } base::log("D3D9Device::init()",base::Message) << "Creating D3D device\n"; hr=m_pD3D9->CreateDevice(adapter,D3DDEVTYPE_HAL,m_hWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING,&m_D3DPP,&m_pD3DDev9); if (FAILED(hr)) { base::log("D3D9Device::init()",base::Error) << "CreateDevice() failed\n"; m_IsValid=false; return; } D3DVIEWPORT9 viewport; viewport.X=0; viewport.Y=0; viewport.Width=r.right-r.left; viewport.Height=r.bottom-r.top; viewport.MinZ=0; viewport.MaxZ=1; m_pD3DDev9->SetViewport(&viewport); #ifdef D3D9DRV_USE_CG base::log("D3D9Device::init()",base::Message) << "Initializing Cg\n"; { m_CgContext=cgCreateContext(); cgD3D9SetDevice(m_pD3DDev9); #ifdef D3D9DRV_CG_DEBUG_ERRORCALLBACK errctx=m_CgContext; cgSetErrorCallback(cgErrorCallback); #endif m_CgVertexProfile=cgD3D9GetLatestVertexProfile(); m_CgFragmentProfile=cgD3D9GetLatestPixelProfile(); m_CgOptimalVertexProfileOptions=cgD3D9GetOptimalOptions(m_CgVertexProfile); m_CgOptimalFragmentProfileOptions=cgD3D9GetOptimalOptions(m_CgFragmentProfile); } #endif base::log("D3D9Device::init()",base::Message) << "Probing queries\n"; { IDirect3DQuery9* pQuery=0; hr=m_pD3DDev9->CreateQuery(D3DQUERYTYPE_OCCLUSION,&pQuery); m_Caps.m_HWOcclusionQueries=(hr==D3D_OK); if (pQuery) pQuery->Release(); } { base::log("D3D9Device::init()",base::Message) << "Probing vertex program support\n"; // Supported vertex programs { unsigned int version=HIBYTE(LOWORD(m_D3DCaps.VertexShaderVersion)); unsigned int subversion=LOBYTE(LOWORD(m_D3DCaps.VertexShaderVersion)); if (version>=3) { m_Caps.m_SupportedProgramFormats.addString("d3d_vs11"); m_Caps.m_SupportedProgramFormats.addString("d3d_vs20"); m_Caps.m_SupportedProgramFormats.addString("d3d_vs30"); } else if (version>=2) { m_Caps.m_SupportedProgramFormats.addString("d3d_vs11"); if (subversion>=0) m_Caps.m_SupportedProgramFormats.addString("d3d_vs20"); } else if (version>=1) { if (subversion>=1) m_Caps.m_SupportedProgramFormats.addString("d3d_vs11"); } // HLSL support LPCSTR vsprofile=D3DXGetVertexShaderProfile(m_pD3DDev9); base::String hlslvsprofile; if (vsprofile) hlslvsprofile=vsprofile; if (hlslvsprofile.compare("vs_1_1",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs11"); } else if (hlslvsprofile.compare("vs_2_0",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs20"); } else if (hlslvsprofile.compare("vs_2_a",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs20"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs2a"); } else if (hlslvsprofile.compare("vs_3_0",true) || (version>=3)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs20"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs2a"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_vs30"); } #ifdef D3D9DRV_USE_CG m_Caps.m_SupportedProgramFormats.addString("cg_vprogram"); #endif } base::log("D3D9Device::init()",base::Message) << "Probing fragment program support\n"; // Supported fragment programs { unsigned int version=HIBYTE(LOWORD(m_D3DCaps.PixelShaderVersion)); unsigned int subversion=LOBYTE(LOWORD(m_D3DCaps.PixelShaderVersion)); if (version>=3) { m_Caps.m_SupportedProgramFormats.addString("d3d_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_ps12"); m_Caps.m_SupportedProgramFormats.addString("d3d_ps13"); m_Caps.m_SupportedProgramFormats.addString("d3d_ps14"); m_Caps.m_SupportedProgramFormats.addString("d3d_ps20"); if (subversion>=0) m_Caps.m_SupportedProgramFormats.addString("d3d_ps30"); } else if (version>=2) { m_Caps.m_SupportedProgramFormats.addString("d3d_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_ps12"); m_Caps.m_SupportedProgramFormats.addString("d3d_ps13"); m_Caps.m_SupportedProgramFormats.addString("d3d_ps14"); if (subversion>=0) m_Caps.m_SupportedProgramFormats.addString("d3d_ps20"); } else if (version>=1) { if (subversion>=1) m_Caps.m_SupportedProgramFormats.addString("d3d_ps11"); if (subversion>=2) m_Caps.m_SupportedProgramFormats.addString("d3d_ps12"); if (subversion>=3) m_Caps.m_SupportedProgramFormats.addString("d3d_ps13"); if (subversion>=4) m_Caps.m_SupportedProgramFormats.addString("d3d_ps14"); } // HLSL support LPCSTR vsprofile=D3DXGetPixelShaderProfile(m_pD3DDev9); base::String hlslpsprofile; if (vsprofile) hlslpsprofile=vsprofile; if (hlslpsprofile.compare("ps_1_1",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps11"); } else if (hlslpsprofile.compare("ps_1_2",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps12"); } else if (hlslpsprofile.compare("ps_1_3",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps12"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps13"); } else if (hlslpsprofile.compare("ps_1_4",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps12"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps13"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps14"); } else if (hlslpsprofile.compare("ps_2_0",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps12"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps13"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps14"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps20"); } else if (hlslpsprofile.compare("ps_2_a",true)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps12"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps13"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps14"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps20"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps2a"); } else if (hlslpsprofile.compare("ps_3_0",true) || (version>=3)) { m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps11"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps12"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps13"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps14"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps20"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps2a"); m_Caps.m_SupportedProgramFormats.addString("d3d_hlsl_ps30"); } #ifdef D3D9DRV_USE_CG m_Caps.m_SupportedProgramFormats.addString("cg_fprogram"); #endif } } // Caps end m_Displaywidth=viewport.Width; m_Displayheight=viewport.Height; m_ColorbufferFormat=colorbufferformat; m_DepthstencilbufferFormat=depthstencilformat; m_pD3DDev9->SetRenderState(D3DRS_FOGVERTEXMODE,D3DFOG_LINEAR); fixedLighting(false); base::log("D3D9Device::init()",base::Message) << "Init complete\n"; }