CDirect3D9Texture::CDirect3D9Texture(IDirect3DDevice9Ex* device, const PTexture& texture) : m_device(device) { // Automatically generates mipmaps. HRESULT hr; D3DFORMAT fmt = PixelFormats[static_cast<uint>(texture.pixelFormat)]; IDirect3DTexture9* pTexture; hr = device->CreateTexture(texture.width, texture.height, 0, 0, fmt, D3DPOOL_DEFAULT, &pTexture, NULL); if (FAILED(hr)) throw graphics_device_exception("Failed to create texture: " + string(DXGetErrorStringA(hr))); m_texture = make_directx_unique<IDirect3DTexture9>(pTexture); // Load bits into surface. auto surface = make_directx_unique<IDirect3DSurface9>(LoadTexture(m_device, texture)); // Copy surface into texture. IDirect3DSurface9* pTexSurface; hr = m_texture->GetSurfaceLevel(0, &pTexSurface); if (FAILED(hr)) throw graphics_device_exception("Failed to get texture surface level 0: " + string(DXGetErrorDescriptionA(hr))); auto texSurface = make_directx_unique<IDirect3DSurface9>(pTexSurface); hr = device->UpdateSurface(surface.get(), NULL, pTexSurface, NULL); if (FAILED(hr)) throw graphics_device_exception("Failed to update surface: " + string(DXGetErrorDescriptionA(hr))); }
void D3D9_Resize(HWND window) { // This should only be called from the emu thread. int xres, yres; GetRes(xres, yres); bool w_changed = pp.BackBufferWidth != xres; bool h_changed = pp.BackBufferHeight != yres; if (device && (w_changed || h_changed)) { DX9::fbo_shutdown(); pp.BackBufferWidth = xres; pp.BackBufferHeight = yres; HRESULT hr = device->Reset(&pp); if (FAILED(hr)) { ERROR_LOG_REPORT(G3D, "Unable to reset device: %s", DXGetErrorStringA(hr)); PanicAlert("Unable to reset D3D9 device: %s", DXGetErrorStringA(hr)); } DX9::fbo_init(d3d); } }
void cgl::CGLManager::Notify( UINT notificationType, CGLObject* pObject /*= NULL*/, HRESULT result /*= S_OK */, void* pData ) { bool debugOutput = true; if (m_notificationCallback) { debugOutput = m_notificationCallback(notificationType, pObject, result, DXGetErrorStringA(result), DXGetErrorDescriptionA(result)); } if (debugOutput) { CGLLogger::LogObjectState(notificationType, pObject, result, pData); } }
bool validate_d3d_result( HRESULT hr, bool show_error_message=true ) { if( FAILED(hr) ) { if( show_error_message ) { const char* err_str = DXGetErrorStringA(hr); Log::error("D3D Error: %s", err_str); } return false; } else { return true; } }
void failed(trace::Call &call, HRESULT hr) { std::ostream &os = warning(call); os << "failed with 0x" << std::hex << hr << std::dec; LPCSTR lpszErrorString = DXGetErrorStringA(hr); assert(lpszErrorString); os << " (" << lpszErrorString << "): "; char szErrorDesc[512]; DXGetErrorDescriptionA(hr, szErrorDesc, sizeof szErrorDesc); os << szErrorDesc; os << "\n"; }
CDirect3D9CubeTexture::CDirect3D9CubeTexture(IDirect3DDevice9Ex* device, const PCubeMap& cubeMap) : m_device(device) { HRESULT hr; D3DFORMAT fmt; const int NumFaces = 6; const D3DCUBEMAP_FACES faces[NumFaces] = { D3DCUBEMAP_FACE_POSITIVE_X, D3DCUBEMAP_FACE_NEGATIVE_X, D3DCUBEMAP_FACE_POSITIVE_Z, D3DCUBEMAP_FACE_NEGATIVE_Z, D3DCUBEMAP_FACE_POSITIVE_Y, D3DCUBEMAP_FACE_NEGATIVE_Y }; vector<shared_ptr<PTexture>> cubeTexs(NumFaces); cubeTexs[0] = GPob->GetTypedPob<PTexture>(cubeMap.positiveX); cubeTexs[1] = GPob->GetTypedPob<PTexture>(cubeMap.negativeX); cubeTexs[2] = GPob->GetTypedPob<PTexture>(cubeMap.positiveZ); cubeTexs[3] = GPob->GetTypedPob<PTexture>(cubeMap.negativeZ); cubeTexs[4] = GPob->GetTypedPob<PTexture>(cubeMap.positiveY); // Optional bottom face. cubeTexs[5] = GPob->GetTypedPob<PTexture>(cubeMap.negativeY); if (!cubeTexs[0] || !cubeTexs[1] || !cubeTexs[2] || !cubeTexs[3] || !cubeTexs[4]) THROW_EXCEPT(graphics_device_exception, "Failed to get cubemap textures"); // Create the cube texture, using parameters from +X. fmt = PixelFormats[static_cast<uint>(cubeTexs[0]->pixelFormat)]; uint edgeLength = cubeTexs[0]->width; IDirect3DCubeTexture9* pCubeMap; hr = m_device->CreateCubeTexture(edgeLength, 0, 0, fmt, D3DPOOL_DEFAULT, &pCubeMap, NULL); if (FAILED(hr)) throw graphics_device_exception("Failed to create cube texture: " + string(DXGetErrorStringA(hr))); m_cubeMap = make_directx_unique<IDirect3DCubeTexture9>(pCubeMap); // Load bits into surface. for (int i=0; i < NumFaces; ++i) { shared_ptr<PTexture> texture(cubeTexs[i] ? cubeTexs[i] : cubeTexs[0]); auto surface = make_directx_unique<IDirect3DSurface9>(LoadTexture(m_device, *texture)); UpdateCubeMapSurface(faces[i], surface.get()); } }
void cgl::CGLLogger::LogObjectState( UINT logType, cgl::CGLObject* pObject, HRESULT result, void* pData ) { switch (logType) { case CGL_NOTIFICATION_INVALID_PTR: { Print("ERROR: invalid ptr"); } break; case CGL_NOTIFICATION_INSTANTIATION: { Print("INFO: instantiated [%i]->%s ", pObject->getLuid(), pObject->getTypeName().c_str()); } break; case CGL_NOTIFICATION_CYCLIC_DEPENDENCY: { Print("ERROR: cyclic dependency detected [%i]->%s", pObject->getLuid(), pObject->getTypeName().c_str()); } break; case CGL_NOTIFICATION_RESET: { Print("INFO: reset [%i]->%s", pObject->getLuid(), pObject->getTypeName().c_str()); } break; case CGL_NOTIFICATION_DESCTRUCTION: { Print("INFO: destroyed [%i]->%s", pObject->getLuid(), pObject->getTypeName().c_str()); } break; case CGL_NOTIFICATION_STILL_ALIVE: { Print("WARNING: still alive [%i]->%s", pObject->getLuid(), pObject->getTypeName().c_str()); } break; case CGL_NOTIFICATION_COM_INTERFACE_STILL_ALIVE: { Print("ERROR: [%i]->%s::OnReset() COM interface not fully released (%i refs)", pObject->getLuid(), pObject->getTypeName().c_str(), *((int*)pData) ); } break; case CGL_NOTIFICATION_NO_DEVICE: { if (pObject) { Print("ERROR: registration failed [%i]->%s\n Error: no device registered!\n", pObject->getLuid(), pObject->getTypeName().c_str()); } else { Print("ERROR: no device registered!"); } } break; case CGL_NOTIFICATION_CREATION: { if (SUCCEEDED(result)) { Print("INFO: created [%i]->%s ", pObject->getLuid(), pObject->getTypeName().c_str()); } else { Print("ERROR: creation failed [%i]->%s\n Error: %s" "\n Description: %s\n", pObject->getLuid(), pObject->getTypeName().c_str(), DXGetErrorStringA(result), DXGetErrorDescriptionA(result)); } } break; case CGL_NOTIFICATION_RESTORATION: { if (SUCCEEDED(result)) { Print("INFO: restored [%i]->%s", pObject->getLuid(), pObject->getTypeName().c_str()); } else { Print("ERROR: failed [%i]->%s::OnRestore()\n Error: %s" "\n Description: %s\n", pObject->getLuid(), pObject->getTypeName().c_str(), DXGetErrorStringA(result), DXGetErrorDescriptionA(result)); } } break; case CGL_NOTIFICATION_REGISTRATION: { if (SUCCEEDED(result)) { Print("INFO: registered [%i]->%s", pObject->getLuid(), pObject->getTypeName().c_str()); } else { Print("ERROR: not registered [%i]->%s", pObject->getLuid(), pObject->getTypeName().c_str()); } } break; } }
const char8 * DXHelperGetErrorDescription( HRESULT hr) { return Format("(DX) %s - %s", DXGetErrorStringA(hr), DXGetErrorDescriptionA(hr)); }
CDirect3D9MeshPack::CDirect3D9MeshPack(IDirect3DDevice9Ex* device, const PMeshPack& meshPack) : m_meshes(CopyMeshes(meshPack)), m_vb(nullptr), m_ib(nullptr), m_device(device) { assert(m_device); assert(meshPack.bits); const uint NumVertexBytes = meshPack.firstIndexOffset; const uint NumIndexBytes = meshPack.bitsSize - NumVertexBytes; HRESULT hr; IDirect3DVertexBuffer9* pVb; hr = m_device->CreateVertexBuffer(NumVertexBytes, D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &pVb, NULL); if (FAILED(hr)) THROW_EXCEPT(graphics_device_exception, "Failed to create vertex buffer of size: " + string(DXGetErrorStringA(hr))); m_vb = make_directx_unique<IDirect3DVertexBuffer9>(pVb); // Copy vertex bits into buffer. VOID* bufferPtr; hr = m_vb->Lock(0, 0, reinterpret_cast<VOID**>(&bufferPtr), 0); if (FAILED(hr)) THROW_EXCEPT(graphics_device_exception, "Failed to lock vertex buffer: " + string(DXGetErrorStringA(hr))); memcpy(bufferPtr, meshPack.bits, NumVertexBytes); m_vb->Unlock(); IDirect3DIndexBuffer9* pIb; hr = m_device->CreateIndexBuffer(NumIndexBytes, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIb, NULL); if (FAILED(hr)) THROW_EXCEPT(graphics_device_exception, "Failed to create vertex buffer of size: " + string(DXGetErrorStringA(hr))); m_ib = make_directx_unique<IDirect3DIndexBuffer9>(pIb); // Copy index bits into buffer. hr = m_ib->Lock(0, 0, reinterpret_cast<VOID**>(&bufferPtr), 0); if (FAILED(hr)) THROW_EXCEPT(graphics_device_exception, "Failed to lock index buffer: " + string(DXGetErrorStringA(hr))); memcpy(bufferPtr, meshPack.bits + NumVertexBytes, NumIndexBytes); m_ib->Unlock(); // Create vertex declaration. m_vdecls.reserve(meshPack.meshesSize); for (uint i=0; i<meshPack.meshesSize; ++i) { auto vertexDecl = MakeVertexDecl(GetPobStruct(&meshPack, meshes, i)); IDirect3DVertexDeclaration9* pVdecl; hr = m_device->CreateVertexDeclaration(&vertexDecl[0], &pVdecl); if (FAILED(hr)) THROW_EXCEPT(graphics_device_exception, "Failed to create vertex declaration: " + string(DXGetErrorStringA(hr))); m_vdecls.emplace_back(shared_ptr<IDirect3DVertexDeclaration9>(pVdecl, directx_deleter<IDirect3DVertexDeclaration9>())); } }
CDirect3D9DynamicTexture::CDirect3D9DynamicTexture(IDirect3DDevice9Ex* device, const point_t& size, PTexture::PixelFormatEnum pixelFmt) : m_device(device) { assert(m_device); HRESULT hr; D3DFORMAT fmt = PixelFormats[static_cast<uint>(pixelFmt)]; IDirect3DTexture9* pTexture; hr = m_device->CreateTexture(size.x, size.y, 0, D3DUSAGE_DYNAMIC, fmt, D3DPOOL_DEFAULT, &pTexture, NULL); if (FAILED(hr)) throw graphics_device_exception("Failed to create dynamic texture: " + string(DXGetErrorStringA(hr))); m_texture = make_directx_unique<IDirect3DTexture9>(pTexture); }
bool GFXD3D9Shader::_compileShader( const Torque::Path &filePath, const String& target, const D3DXMACRO *defines, GenericConstBufferLayout* bufferLayoutF, GenericConstBufferLayout* bufferLayoutI, Vector<GFXShaderConstDesc> &samplerDescriptions ) { PROFILE_SCOPE( GFXD3D9Shader_CompileShader ); HRESULT res = D3DERR_INVALIDCALL; LPD3DXBUFFER code = NULL; LPD3DXBUFFER errorBuff = NULL; #ifdef TORQUE_DEBUG U32 flags = D3DXSHADER_DEBUG; #else U32 flags = 0; #endif #ifdef TORQUE_OS_XENON flags |= D3DXSHADER_PREFER_FLOW_CONTROL; #endif #ifdef D3DXSHADER_USE_LEGACY_D3DX9_31_DLL if( D3DX_SDK_VERSION >= 32 ) { // will need to use old compiler for 1_1 shaders - check for pixel // or vertex shader with appropriate version. if ((target.compare("vs1", 3) == 0) || (target.compare("vs_1", 4) == 0)) flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL; if ((target.compare("ps1", 3) == 0) || (target.compare("ps_1", 4) == 0)) flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL; } #endif #if !defined(TORQUE_OS_XENON) && (D3DX_SDK_VERSION <= 40) #error This version of the DirectX SDK is too old. Please install a newer version of the DirectX SDK: http://msdn.microsoft.com/en-us/directx/default.aspx #endif ID3DXConstantTable* table = NULL; static String sHLSLStr( "hlsl" ); static String sOBJStr( "obj" ); // Is it an HLSL shader? if ( filePath.getExtension().equal(sHLSLStr, String::NoCase) ) { FrameAllocatorMarker fam; char *buffer = NULL; // Set this so that the D3DXInclude::Open will have this // information for relative paths. smD3DXInclude->setPath( filePath.getRootAndPath() ); FileStream s; if ( !s.open( filePath, Torque::FS::File::Read ) ) { AssertISV(false, avar("GFXD3D9Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str())); if ( smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Failed to open shader file '%s'.", filePath.getFullPath().c_str() ); return false; } // Convert the path which might have virtualized // mount paths to a real file system path. Torque::Path realPath; if ( !FS::GetFSPath( filePath, realPath ) ) realPath = filePath; // Add a #line pragma so that error and warning messages // returned by the HLSL compiler report the right file. String linePragma = String::ToString( "#line 1 \"%s\"\r\n", realPath.getFullPath().c_str() ); U32 linePragmaLen = linePragma.length(); U32 bufSize = s.getStreamSize(); buffer = (char *)fam.alloc( bufSize + linePragmaLen + 1 ); dStrncpy( buffer, linePragma.c_str(), linePragmaLen ); s.read( bufSize, buffer + linePragmaLen ); buffer[bufSize+linePragmaLen] = 0; res = GFXD3DX.D3DXCompileShader( buffer, bufSize + linePragmaLen, defines, smD3DXInclude, "main", target, flags, &code, &errorBuff, &table ); } // Is it a precompiled obj shader? else if ( filePath.getExtension().equal( sOBJStr, String::NoCase ) ) { FileStream s; if(!s.open(filePath, Torque::FS::File::Read)) { AssertISV(false, avar("GFXD3D9Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str())); if ( smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Failed to open shader file '%s'.", filePath.getFullPath().c_str() ); return false; } res = GFXD3DX.D3DXCreateBuffer(s.getStreamSize(), &code); AssertISV(res == D3D_OK, "Unable to create buffer!"); s.read(s.getStreamSize(), code->GetBufferPointer()); if (res == D3D_OK) { DWORD* data = (DWORD*) code->GetBufferPointer(); res = GFXD3DX.D3DXGetShaderConstantTable(data, &table); } } else { if ( smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Unsupported shader file type '%s'.", filePath.getFullPath().c_str() ); return false; } if ( res != D3D_OK && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Error compiling shader: %s: %s (%x)", DXGetErrorStringA(res), DXGetErrorDescriptionA(res), res ); if ( errorBuff ) { // remove \n at end of buffer U8 *buffPtr = (U8*) errorBuff->GetBufferPointer(); U32 len = dStrlen( (const char*) buffPtr ); buffPtr[len-1] = '\0'; if( res != D3D_OK ) { if ( smLogErrors ) Con::errorf( " %s", (const char*) errorBuff->GetBufferPointer() ); } else { if ( smLogWarnings ) Con::warnf( "%s", (const char*) errorBuff->GetBufferPointer() ); } } else if ( code == NULL && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - no compiled code produced; possibly missing file '%s'.", filePath.getFullPath().c_str() ); // Create the proper shader if we have code if( code != NULL ) { #ifndef TORQUE_SHIPPING LPD3DXBUFFER disassem = NULL; D3DXDisassembleShader( (DWORD*)code->GetBufferPointer(), false, NULL, &disassem ); mDissasembly = (const char*)disassem->GetBufferPointer(); SAFE_RELEASE( disassem ); if ( gDisassembleAllShaders ) { String filename = filePath.getFullPath(); filename.replace( ".hlsl", "_dis.txt" ); FileStream *fstream = FileStream::createAndOpen( filename, Torque::FS::File::Write ); if ( fstream ) { fstream->write( mDissasembly ); fstream->close(); delete fstream; } } #endif if (target.compare("ps_", 3) == 0) res = mD3D9Device->CreatePixelShader( (DWORD*)code->GetBufferPointer(), &mPixShader ); else res = mD3D9Device->CreateVertexShader( (DWORD*)code->GetBufferPointer(), &mVertShader ); if (res == S_OK) _getShaderConstants(table, bufferLayoutF, bufferLayoutI, samplerDescriptions); #ifdef TORQUE_ENABLE_CSF_GENERATION // Ok, we've got a valid shader and constants, let's write them all out. if ( !_saveCompiledOutput(filePath, code, bufferLayoutF, bufferLayoutI) && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Unable to save shader compile output for: %s", filePath.getFullPath().c_str() ); #endif SAFE_RELEASE(table); if ( res != S_OK && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Unable to create shader for '%s'.", filePath.getFullPath().c_str() ); } bool result = code != NULL && res == S_OK; SAFE_RELEASE( code ); SAFE_RELEASE( errorBuff ); return result; }