//========================================================================================================================= void TextureManager::WriteTGAToFile(LPCWSTR filename, ID3D11ShaderResourceView* textureSRV) { // https://directxtex.codeplex.com/wikipage?title=CaptureTexture ID3D11Texture2D *textureInterface = 0; ID3D11Resource *textureResource; textureSRV->GetResource(&textureResource); textureResource->QueryInterface<ID3D11Texture2D>(&textureInterface); HRESULT result; //ScratchImage image; ScratchImage image; result = CaptureTexture(mD3DSystem->GetDevice11(), mD3DSystem->GetDeviceContext(), textureInterface, image); if (SUCCEEDED(result)) { result = SaveToTGAFile(*image.GetImages(), filename); if (FAILED(result)) { ZShadeMessageCenter::MsgBoxError(NULL, "Failed to save TGA texture !!"); } } SAFE_RELEASE(textureInterface); SAFE_RELEASE(textureResource); }
//=============================================================================================================================== void TextureManager::WritePNGToFile(LPCWSTR filename, ID3D11ShaderResourceView* textureSRV) { ID3D11Texture2D *textureInterface = 0; ID3D11Resource *textureResource; textureSRV->GetResource(&textureResource); textureResource->QueryInterface<ID3D11Texture2D>(&textureInterface); HRESULT result; result = SaveWICTextureToFile(mD3DSystem->GetDeviceContext(), textureInterface, GUID_ContainerFormatPng, filename); if (FAILED(result)) { ScratchImage image; result = CaptureTexture(mD3DSystem->GetDevice11(), mD3DSystem->GetDeviceContext(), textureInterface, image); if (SUCCEEDED(result)) { result = SaveToWICFile(image.GetImages(), image.GetImageCount(), WIC_FLAGS_NONE, GUID_ContainerFormatPng, filename); if (FAILED(result)) { ZShadeMessageCenter::MsgBoxError(NULL, "Failed to save PNG texture !!"); } } } SAFE_RELEASE(textureInterface); SAFE_RELEASE(textureResource); }
//------------------------------------------------------------------------------------- // Compression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image ) { if ( IsCompressed(srcImage.format) || !IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; // Image size must be a multiple of 4 (degenerate cases for mipmaps are allowed) bool degenerate = false; size_t width = srcImage.width; if ( (width % 4) != 0 ) { if ( width != 1 && width != 2 ) return E_INVALIDARG; degenerate = true; } size_t height = srcImage.height; if ( (height % 4) != 0 ) { if ( height != 1 && height != 2 ) return E_INVALIDARG; degenerate = true; } // Create compressed image HRESULT hr = image.Initialize2D( format, width, height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *img = image.GetImage( 0, 0, 0 ); if ( !img ) { image.Release(); return E_POINTER; } // Compress single image if ( (compress & TEX_COMPRESS_PARALLEL) && !degenerate ) { #ifndef _OPENMP return E_NOTIMPL; #else hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), alphaRef ); #endif // _OPENMP } else { hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), alphaRef, degenerate ); } if ( FAILED(hr) ) image.Release(); return hr; }
//------------------------------------------------------------------------------------- // Resize image //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter, ScratchImage& image ) { if ( width == 0 || height == 0 ) return E_INVALIDARG; #ifdef _M_X64 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) ) return E_INVALIDARG; if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif if ( !srcImage.pixels ) return E_POINTER; if ( IsCompressed( srcImage.format ) ) { // We don't support resizing compressed images return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } HRESULT hr = image.Initialize2D( srcImage.format, width, height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *rimage = image.GetImage( 0, 0, 0 ); if ( !rimage ) return E_POINTER; if ( _UseWICFiltering( srcImage.format, filter ) ) { WICPixelFormatGUID pfGUID; if ( _DXGIToWIC( srcImage.format, pfGUID, true ) ) { // Case 1: Source format is supported by Windows Imaging Component hr = _PerformResizeUsingWIC( srcImage, filter, pfGUID, *rimage ); } else { // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back hr = _PerformResizeViaF32( srcImage, filter, *rimage ); } } else { hr = _PerformResizeUsingCustomFilters( srcImage, filter, *rimage ); } if ( FAILED(hr) ) { image.Release(); return hr; } return S_OK; }
//=============================================================================================================================== HRESULT TextureManager::LoadDDSTextureFromFile(LPCWSTR tex_filename, ID3D11ShaderResourceView** srv) { HRESULT hr; TexMetadata imageMetadata; ScratchImage* image = new ScratchImage(); hr = LoadFromDDSFile(tex_filename, DDS_FLAGS_NONE, &imageMetadata, *image); hr = CreateShaderResourceView(mD3DSystem->GetDevice11(), image->GetImages(), image->GetImageCount(), imageMetadata, srv); return hr; }
void SaveTextureAsDDS(ID3D11Resource* texture, const wchar* filePath) { ID3D11DevicePtr device; texture->GetDevice(&device); ID3D11DeviceContextPtr context; device->GetImmediateContext(&context); ScratchImage scratchImage; DXCall(CaptureTexture(device, context, texture, scratchImage)); DXCall(SaveToDDSFile(scratchImage.GetImages(), scratchImage.GetImageCount(), scratchImage.GetMetadata(), DDS_FLAGS_FORCE_DX10_EXT, filePath)); }
void SaveTextureAsPNG(ID3D11Resource* texture, const wchar* filePath) { ID3D11DevicePtr device; texture->GetDevice(&device); ID3D11DeviceContextPtr context; device->GetImmediateContext(&context); ScratchImage scratchImage; DXCall(CaptureTexture(device, context, texture, scratchImage)); DXCall(SaveToWICFile(scratchImage.GetImages(), scratchImage.GetImageCount(), WIC_FLAGS_NONE, GetWICCodec(WIC_CODEC_PNG), filePath)); }
//------------------------------------------------------------------------------------- // Decompression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image) { if (!IsCompressed(cImage.format) || IsCompressed(format)) return E_INVALIDARG; if (format == DXGI_FORMAT_UNKNOWN) { // Pick a default decompressed format based on BC input format format = DefaultDecompress(cImage.format); if (format == DXGI_FORMAT_UNKNOWN) { // Input is not a compressed format return E_INVALIDARG; } } else { if (!IsValid(format)) return E_INVALIDARG; if (IsTypeless(format) || IsPlanar(format) || IsPalettized(format)) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); } // Create decompressed image HRESULT hr = image.Initialize2D(format, cImage.width, cImage.height, 1, 1); if (FAILED(hr)) return hr; const Image *img = image.GetImage(0, 0, 0); if (!img) { image.Release(); return E_POINTER; } // Decompress single image hr = DecompressBC(cImage, *img); if (FAILED(hr)) image.Release(); return hr; }
//------------------------------------------------------------------------------------- // Compression //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float threshold, ScratchImage& image) { if (IsCompressed(srcImage.format) || !IsCompressed(format)) return E_INVALIDARG; if (IsTypeless(format) || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format)) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); // Create compressed image HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1); if (FAILED(hr)) return hr; const Image *img = image.GetImage(0, 0, 0); if (!img) { image.Release(); return E_POINTER; } // Compress single image if (compress & TEX_COMPRESS_PARALLEL) { #ifndef _OPENMP return E_NOTIMPL; #else hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold); #endif // _OPENMP } else { hr = CompressBC(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), threshold); } if (FAILED(hr)) image.Release(); return hr; }
//------------------------------------------------------------------------------------- // Converts to/from a premultiplied alpha version of the texture //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image) { if (!srcImage.pixels) return E_POINTER; if (IsCompressed(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) || IsTypeless(srcImage.format) || !HasAlpha(srcImage.format)) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX)) return E_INVALIDARG; HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1); if (FAILED(hr)) return hr; const Image *rimage = image.GetImage(0, 0, 0); if (!rimage) { image.Release(); return E_POINTER; } if (flags & TEX_PMALPHA_REVERSE) { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? DemultiplyAlpha(srcImage, *rimage) : DemultiplyAlphaLinear(srcImage, flags, *rimage); } else { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(srcImage, *rimage) : PremultiplyAlphaLinear(srcImage, flags, *rimage); } if (FAILED(hr)) { image.Release(); return hr; } return S_OK; }
// Executes the basic game loop. void Game::Tick() { m_timer.Tick([&]() { Update(m_timer); }); Render(); if (m_screenshot) { OutputDebugStringA("Saving screenshot...\n"); auto commandQ = m_deviceResources->GetCommandQueue(); DX::ThrowIfFailed( SaveDDSTextureToFile(commandQ, m_screenshot.Get(), L"screenshot.dds", D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_PRESENT) ); DX::ThrowIfFailed( SaveWICTextureToFile(commandQ, m_screenshot.Get(), GUID_ContainerFormatJpeg, L"screenshot.jpg", D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_PRESENT) ); ScratchImage image; DX::ThrowIfFailed(CaptureTexture(commandQ, m_screenshot.Get(), false, image, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_PRESENT)); DX::ThrowIfFailed(SaveToDDSFile(image.GetImages(), image.GetImageCount(), image.GetMetadata(), DDS_FLAGS_NONE, L"screenshot2.dds")); DX::ThrowIfFailed(SaveToWICFile(*image.GetImage(0, 0, 0), WIC_FLAGS_NONE, GUID_ContainerFormatJpeg, L"screenshot2.jpg")); m_screenshot.Reset(); } ++m_frame; }
//------------------------------------------------------------------------------------- // Converts to a premultiplied alpha version of the texture //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT PremultiplyAlpha( const Image& srcImage, ScratchImage& image ) { if ( !srcImage.pixels ) return E_POINTER; if ( IsCompressed(srcImage.format) || IsVideo(srcImage.format) || IsTypeless(srcImage.format) || !HasAlpha(srcImage.format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); #ifdef _M_X64 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *rimage = image.GetImage( 0, 0, 0 ); if ( !rimage ) { image.Release(); return E_POINTER; } hr = _PremultiplyAlpha( srcImage, *rimage ); if ( FAILED(hr) ) { image.Release(); return hr; } return S_OK; }
//------------------------------------------------------------------------------------- // Decompression //------------------------------------------------------------------------------------- HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image ) { if ( IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; if ( format == DXGI_FORMAT_UNKNOWN ) { // Pick a default decompressed format based on BC input format format = _DefaultDecompress( cImage.format ); if ( format == DXGI_FORMAT_UNKNOWN ) { // Input is not a compressed format return E_INVALIDARG; } } else if ( !IsCompressed(cImage.format) || !IsValid(format) ) return E_INVALIDARG; // Create decompressed image HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *img = image.GetImage( 0, 0, 0 ); if ( !img ) { image.Release(); return E_POINTER; } // Decompress single image hr = _DecompressBC( cImage, *img ); if ( FAILED(hr) ) image.Release(); return hr; }
//------------------------------------------------------------------------------------- // Do conversion, flip/rotate using WIC, conversion cycle //------------------------------------------------------------------------------------- static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage ) { if ( !srcImage.pixels || !destImage.pixels ) return E_POINTER; assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT ); assert( srcImage.format == destImage.format ); ScratchImage temp; HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp ); if ( FAILED(hr) ) return hr; const Image *tsrc = temp.GetImage( 0, 0, 0 ); if ( !tsrc ) return E_POINTER; ScratchImage rtemp; hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *tdest = rtemp.GetImage( 0, 0, 0 ); if ( !tdest ) return E_POINTER; hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest ); if ( FAILED(hr) ) return hr; temp.Release(); hr = _ConvertFromR32G32B32A32( *tdest, destImage ); if ( FAILED(hr) ) return hr; return S_OK; }
HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages ) { if ( !srcImages || !nimages ) return E_INVALIDARG; if ( !IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; // Image size must be a multiple of 4 (degenerate cases for mipmaps are allowed) size_t width = srcImages[0].width; if ( (width % 4) != 0 ) { if ( width != 1 && width != 2 ) return E_INVALIDARG; } size_t height = srcImages[0].height; if ( (height % 4) != 0 ) { if ( height != 1 && height != 2 ) return E_INVALIDARG; } cImages.Release(); TexMetadata mdata2 = metadata; mdata2.format = format; HRESULT hr = cImages.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != cImages.GetImageCount() ) { cImages.Release(); return E_FAIL; } const Image* dest = cImages.GetImages(); if ( !dest ) { cImages.Release(); return E_POINTER; } for( size_t index=0; index < nimages; ++index ) { assert( dest[ index ].format == format ); const Image& src = srcImages[ index ]; height = src.height; width = src.width; if ( width != dest[ index ].width || height != dest[ index ].height ) { cImages.Release(); return E_FAIL; } bool degenerate = ((height < 4) || (width < 4)) != 0; if ( (compress & TEX_COMPRESS_PARALLEL) && !degenerate) { #ifndef _OPENMP return E_NOTIMPL; #else if ( compress & TEX_COMPRESS_PARALLEL ) { hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } #endif // _OPENMP } else { hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), alphaRef, degenerate ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } } return S_OK; }
//------------------------------------------------------------------------------------- // Converts to a premultiplied alpha version of the texture (complex) //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, ScratchImage& result ) { if ( !srcImages || !nimages ) return E_INVALIDARG; if ( IsCompressed(metadata.format) || IsVideo(metadata.format) || IsTypeless(metadata.format) || !HasAlpha(metadata.format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); #ifdef _M_X64 if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif if ( metadata.IsPMAlpha() ) { // Already premultiplied return E_FAIL; } TexMetadata mdata2 = metadata; mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED); HRESULT hr = result.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != result.GetImageCount() ) { result.Release(); return E_FAIL; } const Image* dest = result.GetImages(); if ( !dest ) { result.Release(); return E_POINTER; } for( size_t index=0; index < nimages; ++index ) { const Image& src = srcImages[ index ]; if ( src.format != metadata.format ) { result.Release(); return E_FAIL; } #ifdef _M_X64 if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) ) return E_FAIL; #endif const Image& dst = dest[ index ]; assert( dst.format == metadata.format ); if ( src.width != dst.width || src.height != dst.height ) { result.Release(); return E_FAIL; } hr = _PremultiplyAlpha( src, dst ); if ( FAILED(hr) ) { result.Release(); return hr; } } return S_OK; }
//------------------------------------------------------------------------------------- // Converts to/from a premultiplied alpha version of the texture (complex) //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT DirectX::PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result) { if (!srcImages || !nimages) return E_INVALIDARG; if (IsCompressed(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) || IsTypeless(metadata.format) || !HasAlpha(metadata.format)) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX)) return E_INVALIDARG; if (metadata.IsPMAlpha() != ((flags & TEX_PMALPHA_REVERSE) != 0)) return E_FAIL; TexMetadata mdata2 = metadata; mdata2.SetAlphaMode((flags & TEX_PMALPHA_REVERSE) ? TEX_ALPHA_MODE_STRAIGHT : TEX_ALPHA_MODE_PREMULTIPLIED); HRESULT hr = result.Initialize(mdata2); if (FAILED(hr)) return hr; if (nimages != result.GetImageCount()) { result.Release(); return E_FAIL; } const Image* dest = result.GetImages(); if (!dest) { result.Release(); return E_POINTER; } for (size_t index = 0; index < nimages; ++index) { const Image& src = srcImages[index]; if (src.format != metadata.format) { result.Release(); return E_FAIL; } if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX)) return E_FAIL; const Image& dst = dest[index]; assert(dst.format == metadata.format); if (src.width != dst.width || src.height != dst.height) { result.Release(); return E_FAIL; } if (flags & TEX_PMALPHA_REVERSE) { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? DemultiplyAlpha(src, dst) : DemultiplyAlphaLinear(src, flags, dst); } else { hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(src, dst) : PremultiplyAlphaLinear(src, flags, dst); } if (FAILED(hr)) { result.Release(); return hr; } } return S_OK; }
void DDEngine::ModelObject::loadGeometry(std::vector<Mesh>& meshes) { Importer importer; const aiScene* scene = importer.ReadFile(modelPath, aiProcess_Triangulate | aiProcess_ConvertToLeftHanded | aiProcess_FlipUVs | aiProcess_SortByPType | aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph | aiProcess_FixInfacingNormals | aiProcess_CalcTangentSpace ); if (!scene) { Win32Utils::showMessage("Error during loading object.", importer.GetErrorString()); return; } const aiVector3D nullVec(0.0f, 0.0f, 0.0f); for (size_t i = 0; i < scene->mNumMeshes; i++) { const aiMesh* mesh = scene->mMeshes[i]; Mesh ddeMesh; for (size_t j = 0; j < mesh->mNumVertices; j++) { const aiVector3D* pos = &(mesh->mVertices[j]); const aiVector3D* nor = mesh->HasNormals() ? &(mesh->mNormals[j]) : &nullVec; const aiVector3D* tan = mesh->HasTangentsAndBitangents() ? &(mesh->mTangents[j]) : &nullVec; const aiVector3D* tex = mesh->HasTextureCoords(0) ? &(mesh->mTextureCoords[0][j]) : &nullVec; #define VB(x, y, z, u, v, nx, ny, nz, tx, ty, tz, tw) ddeMesh.VB(VertexPositionNormalTangentTexture(XMFLOAT3(x, y, z), XMFLOAT3(nx, ny, nz), XMFLOAT4(tx, ty, tz, tw), XMFLOAT2(u, v))) VB( pos->x, pos->y, pos->z, tex->x, tex->y, nor->x, nor->y, nor->z, tan->x, tan->y, tan->z, 0.0f ); ddeMesh.materialIndex = mesh->mMaterialIndex; } for (size_t j = 0; j < mesh->mNumFaces; j++) { const aiFace& face = mesh->mFaces[j]; switch (face.mNumIndices) { case 1: ddeMesh.topology = PrimitiveTopology::POINT_LIST; break; case 2: ddeMesh.topology = PrimitiveTopology::LINE_LIST; break; case 3: ddeMesh.topology = PrimitiveTopology::TRIANGLE_LIST; break; default: ddeMesh.topology = PrimitiveTopology::UNDEFINED; break; } for (size_t index = 0; index < face.mNumIndices; index++) { ddeMesh.IB(face.mIndices[index]); } } meshes.push_back(ddeMesh); } for (size_t i = 0; i < scene->mNumMaterials; i++) { const aiMaterial* material = scene->mMaterials[i]; Material ddeMaterial; ddeMaterial.index = i; if (material->GetTextureCount(aiTextureType_DIFFUSE) > 0) { aiString Path; if (material->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) { Texture tex; tex.type = Texture::TextureType::DIFFUSE; ShaderResourceView* texture = nullptr; std::string path = Path.data; std::size_t ext = path.find(".tga"); ScratchImage image; HRESULT hr = -1; std::string currentPath = FileUtils::getPath(modelPath) + "/"; tex.path = currentPath + path; if (ext != std::string::npos) { hr = LoadFromTGAFile(StringUtils::toWstring(currentPath + path).c_str(), nullptr, image); } else { texture = TextureUtils::createTexture(currentPath + path, *Ctx); } if (SUCCEEDED(hr)) { hr = CreateShaderResourceView(Ctx->device, image.GetImages(), image.GetImageCount(), image.GetMetadata(), &texture); } if (texture) { tex.texture = texture; ddeMaterial.textureArray[Texture::TextureType::DIFFUSE] = texture; ddeMaterial.textures.push_back(tex); } } } materials.push_back(ddeMaterial); } }
//------------------------------------------------------------------------------------- // CaptureTexture bool Test05() { ComPtr<ID3D11Device> device; ComPtr<ID3D11DeviceContext> context; HRESULT hr = CreateDevice(device.GetAddressOf(), context.GetAddressOf()); if (FAILED(hr)) { printe("Failed creating device (HRESULT %08X)\n", hr); return false; } bool success = true; size_t ncount = 0; size_t npass = 0; for (size_t index = 0; index < _countof(g_TestMedia); ++index) { if (g_TestMedia[index].options & FLAGS_NOT_SUPPORTED) { continue; } wchar_t szPath[MAX_PATH] = {}; DWORD ret = ExpandEnvironmentStringsW(g_TestMedia[index].fname, szPath, MAX_PATH); if (!ret || ret > MAX_PATH) { printe("ERROR: ExpandEnvironmentStrings FAILED\n"); return false; } #ifdef _DEBUG OutputDebugString(szPath); OutputDebugStringA("\n"); #endif // Form dest path wchar_t ext[_MAX_EXT]; wchar_t fname[_MAX_FNAME]; _wsplitpath_s(szPath, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, ext, _MAX_EXT); wchar_t tempDir[MAX_PATH] = {}; ret = ExpandEnvironmentStringsW(TEMP_PATH L"d3d11", tempDir, MAX_PATH); if (!ret || ret > MAX_PATH) { printe("ERROR: ExpandEnvironmentStrings FAILED\n"); return false; } CreateDirectoryW(tempDir, nullptr); wchar_t szDestPath[MAX_PATH] = {}; _wmakepath_s(szDestPath, MAX_PATH, nullptr, tempDir, fname, L".dds"); TexMetadata metadata; ScratchImage image; if (_wcsicmp(ext, L".dds") == 0) { hr = LoadFromDDSFile(szPath, DDS_FLAGS_NONE, &metadata, image); } else { hr = LoadFromWICFile(szPath, WIC_FLAGS_NONE, &metadata, image); } bool forceNoMips = false; const TexMetadata* check = &g_TestMedia[index].metadata; if (FAILED(hr)) { success = false; printe("Failed getting data from (HRESULT %08X):\n%ls\n", hr, szPath); } else if (memcmp(&metadata, check, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szPath); printmeta(&metadata); printmetachk(check); } else { bool pass = true; if (g_TestMedia[index].options & FLAGS_YUV) { if (!IsSupportedTexture(device.Get(), metadata)) { // Can't create video textures with mips on most hardware metadata.mipLevels = 1; forceNoMips = true; if (!IsSupportedTexture(device.Get(), metadata)) { print("WARNING: Format %u is not supported by this hardware\n", metadata.format); continue; } } } { ComPtr<ID3D11Resource> pResource; hr = CreateTexture(device.Get(), image.GetImages(), image.GetImageCount(), metadata, pResource.GetAddressOf()); if (FAILED(hr)) { success = false; printe("Failed creating texture from (HRESULT %08X):\n%ls\n", hr, szPath); } else { ScratchImage image2; hr = CaptureTexture(device.Get(), context.Get(), pResource.Get(), image2); if (FAILED(hr)) { success = false; printe("Failed capturing texture from (HRESULT %08X):\n%ls\n", hr, szPath); } else { const TexMetadata& mdata2 = image2.GetMetadata(); if (memcmp(&mdata2, &metadata, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szDestPath); printmeta(&mdata2); printmetachk(check); } else if (!forceNoMips && image.GetImageCount() != image2.GetImageCount()) { success = false; printe("Image count in captured texture (%zu) doesn't match source (%zu) in:\n%ls\n", image2.GetImageCount(), image.GetImageCount(), szDestPath); } else { hr = SaveToDDSFile(image2.GetImages(), image2.GetImageCount(), image2.GetMetadata(), DDS_FLAGS_NONE, szDestPath); if (FAILED(hr)) { success = false; pass = false; printe("Failed writing DDS to (HRESULT %08X):\n%ls\n", hr, szDestPath); } if (!IsPlanar(metadata.format)) { float mse, mseV[4]; hr = ComputeMSE(*image.GetImage(0, 0, 0), *image2.GetImage(0, 0, 0), mse, mseV); if (FAILED(hr)) { success = false; pass = false; printe("Failed comparing captured image (HRESULT %08X):\n%ls\n", hr, szPath); } else if (fabs(mse) > 0.000001f) { success = false; pass = false; printe("Failed comparing captured image MSE = %f (%f %f %f %f)... 0.f:\n%ls\n", mse, mseV[0], mseV[1], mseV[2], mseV[3], szPath); } } } } } } // Staging resource tests { ComPtr<ID3D11Resource> pStaging; hr = CreateTextureEx(device.Get(), image.GetImages(), image.GetImageCount(), metadata, D3D11_USAGE_STAGING, 0, D3D11_CPU_ACCESS_READ, 0, false, pStaging.GetAddressOf()); if (FAILED(hr)) { success = false; pass = false; printe("Failed creating test staging texture (HRESULT %08X):\n%ls\n", hr, szPath); } else { ScratchImage image2; hr = CaptureTexture(device.Get(), context.Get(), pStaging.Get(), image2); if (FAILED(hr)) { success = false; printe("Failed capturing texture from staging texture (HRESULT %08X):\n%ls\n", hr, szPath); } else { const TexMetadata& mdata2 = image2.GetMetadata(); if (memcmp(&mdata2, &metadata, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szDestPath); printmeta(&mdata2); printmetachk(check); } else if (!forceNoMips && image.GetImageCount() != image2.GetImageCount()) { success = false; printe("Image count in captured texture staging texture (%zu) doesn't match source (%zu) in:\n%ls\n", image2.GetImageCount(), image.GetImageCount(), szDestPath); } else { wchar_t tname[MAX_PATH] = {}; wcscpy_s(tname, fname); wcscat_s(tname, L"_staging"); wchar_t szDestPath2[MAX_PATH] = {}; _wmakepath_s(szDestPath2, MAX_PATH, nullptr, tempDir, tname, L".dds"); hr = SaveToDDSFile(image2.GetImages(), image2.GetImageCount(), image2.GetMetadata(), DDS_FLAGS_NONE, szDestPath2); if (FAILED(hr)) { success = false; pass = false; printe("Failed writing DDS to (HRESULT %08X):\n%ls\n", hr, szDestPath2); } if (!IsPlanar(metadata.format)) { float mse, mseV[4]; hr = ComputeMSE(*image.GetImage(0, 0, 0), *image2.GetImage(0, 0, 0), mse, mseV); if (FAILED(hr)) { success = false; pass = false; printe("Failed comparing captured image (HRESULT %08X):\n%ls\n", hr, szPath); } else if (fabs(mse) > 0.000001f) { success = false; pass = false; printe("Failed comparing captured image MSE = %f (%f %f %f %f)... 0.f:\n%ls\n", mse, mseV[0], mseV[1], mseV[2], mseV[3], szPath); } } } } } } // CaptureTexture of an MSAA resource is tested elsewhere if (pass) ++npass; } ++ncount; } print("%zu images tested, %zu images passed ", ncount, npass); return success; }
//------------------------------------------------------------------------------------- // Flip/rotate image //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image ) { if ( !srcImage.pixels ) return E_POINTER; if ( !flags ) return E_INVALIDARG; #ifdef _AMD64_ if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif if ( IsCompressed( srcImage.format ) ) { // We don't support flip/rotate operations on compressed images return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" ); static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" ); static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" ); static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" ); static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" ); static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" ); // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) ) { case 0: case TEX_FR_ROTATE90: case TEX_FR_ROTATE180: case TEX_FR_ROTATE270: break; default: return E_INVALIDARG; } size_t nwidth = srcImage.width; size_t nheight = srcImage.height; if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270)) { nwidth = srcImage.height; nheight = srcImage.width; } HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 ); if ( FAILED(hr) ) return hr; const Image *rimage = image.GetImage( 0, 0, 0 ); if ( !rimage ) return E_POINTER; WICPixelFormatGUID pfGUID; if ( _DXGIToWIC( srcImage.format, pfGUID ) ) { // Case 1: Source format is supported by Windows Imaging Component hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage ); } else { // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back hr = _PerformFlipRotateViaF32( srcImage, flags, *rimage ); } if ( FAILED(hr) ) { image.Release(); return hr; } return S_OK; }
_Use_decl_annotations_ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages ) { if ( !srcImages || !nimages ) return E_INVALIDARG; if ( IsCompressed(metadata.format) || !IsCompressed(format) ) return E_INVALIDARG; if ( IsTypeless(format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); cImages.Release(); TexMetadata mdata2 = metadata; mdata2.format = format; HRESULT hr = cImages.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != cImages.GetImageCount() ) { cImages.Release(); return E_FAIL; } const Image* dest = cImages.GetImages(); if ( !dest ) { cImages.Release(); return E_POINTER; } for( size_t index=0; index < nimages; ++index ) { assert( dest[ index ].format == format ); const Image& src = srcImages[ index ]; if ( src.width != dest[ index ].width || src.height != dest[ index ].height ) { cImages.Release(); return E_FAIL; } if ( (compress & TEX_COMPRESS_PARALLEL) ) { #ifndef _OPENMP return E_NOTIMPL; #else if ( compress & TEX_COMPRESS_PARALLEL ) { hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } #endif // _OPENMP } else { hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef ); if ( FAILED(hr) ) { cImages.Release(); return hr; } } } return S_OK; }
CMP_ERROR WINAPI GPU_DirectX::Decompress( const CMP_Texture* pSourceTexture, CMP_Texture* pDestTexture ) { HRESULT hr; TexMetadata mdata; memset(&mdata, 0, sizeof(TexMetadata)); mdata.height = pSourceTexture->dwHeight; mdata.width = pSourceTexture->dwWidth; mdata.depth = 1; mdata.arraySize = 1; mdata.mipLevels = 1; mdata.dimension = TEX_DIMENSION_TEXTURE2D; mdata.format = CMP2DXGIFormat(pSourceTexture->format); /*** Use this for debugging DDS file loads LPWSTR lpImageSrc = L""; ScratchImage image; hr = LoadFromDDSFile(lpImageSrc, DDS_FLAGS_NONE, &mdata, image); if (FAILED(hr)) { wchar_t buff[2048] = { 0 }; swprintf_s(buff, "Failed to load texture file\n\nFilename = %ls\nHRESULT %08X", lpImageSrc, hr); return 0; } ***/ if (FAILED(InitDevice(mdata, pDestTexture->format))) { CleanupDevice(); return CMP_ERR_UNABLE_TO_INIT_DECOMPRESSLIB; } if (mdata.dimension == TEX_DIMENSION_TEXTURE3D) { wchar_t buff[2048] = { 0 }; swprintf_s(buff, L"Arrays of volume textures are not supported\n\nArray size %Iu", mdata.arraySize); return CMP_ERR_GENERIC; } else { m_iMaxIndex = static_cast<UINT>(mdata.arraySize); } switch (mdata.format) { case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: case DXGI_FORMAT_BC6H_SF16: case DXGI_FORMAT_BC7_TYPELESS: case DXGI_FORMAT_BC7_UNORM: case DXGI_FORMAT_BC7_UNORM_SRGB: if (m_featureLevel < D3D_FEATURE_LEVEL_11_0) { wchar_t buff[2048] = { 0 }; swprintf_s(buff, L"BC6H/BC7 requires DirectX 11 hardware\n\nDXGI Format %d\nFeature Level %d", pSourceTexture->format, m_featureLevel); return CMP_ERR_GENERIC; } break; default: { UINT flags = 0; hr = m_pd3dDevice->CheckFormatSupport(mdata.format, &flags); if (FAILED(hr) || !(flags & (D3D11_FORMAT_SUPPORT_TEXTURE1D | D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D))) { wchar_t buff[2048] = { 0 }; swprintf_s(buff, L"Format not supported by DirectX hardware\n\nDXGI Format %d\nFeature Level %d\nHRESULT = %08X", mdata.format, m_featureLevel, hr); return CMP_ERR_GENERIC; } } break; } // Special case to make sure Texture cubes remain arrays mdata.miscFlags &= ~TEX_MISC_TEXTURECUBE; Image srcImage; // Set size to 4 pixel boundaries // Should check format is compressed for none compressed cases // where 4 pixel bound is not required. srcImage.width = ((pSourceTexture->dwWidth + 3) / 4) * 4; srcImage.height = ((pSourceTexture->dwHeight + 3) / 4) * 4; srcImage.format = mdata.format; srcImage.pixels = pSourceTexture->pData; ComputePitch(mdata.format, srcImage.width, srcImage.height, srcImage.rowPitch, srcImage.slicePitch, 0); hr = CreateShaderResourceView(m_pd3dDevice, &srcImage, 1, mdata, &m_pSRV); if (FAILED(hr)) { return CMP_ERR_GENERIC; } #ifdef SHOW_WINDOW // Activate the window: Use for debugging! ShowWindow(m_hWnd, SW_SHOW); #endif // Wait in Main message loop, until render is complete!! // then exit MSG msg = { 0 }; while (WM_QUIT != msg.message) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { Render(); break; } } m_pRenderTargetView->GetResource(&m_pResource); ScratchImage sratchimage; CaptureTexture(m_pd3dDevice, m_pImmediateContext,m_pResource, sratchimage); size_t pxsize = sratchimage.GetPixelsSize(); // Check the size matches our output if (pxsize == pDestTexture->dwDataSize) { uint8_t *pxdata = sratchimage.GetPixels(); memcpy(pDestTexture->pData, pxdata, pDestTexture->dwDataSize); } CleanupDevice(); return CMP_OK; // msg.wParam; }
HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, ScratchImage& images ) { if ( !cImages || !nimages ) return E_INVALIDARG; if ( IsCompressed(format) || IsTypeless(format) ) return E_INVALIDARG; if ( format == DXGI_FORMAT_UNKNOWN ) { // Pick a default decompressed format based on BC input format format = _DefaultDecompress( cImages[0].format ); if ( format == DXGI_FORMAT_UNKNOWN ) { // Input is not a compressed format return E_FAIL; } } else if ( !IsValid(format) ) return E_INVALIDARG; images.Release(); TexMetadata mdata2 = metadata; mdata2.format = format; HRESULT hr = images.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != images.GetImageCount() ) { images.Release(); return E_FAIL; } const Image* dest = images.GetImages(); if ( !dest ) { images.Release(); return E_POINTER; } for( size_t index=0; index < nimages; ++index ) { assert( dest[ index ].format == format ); const Image& src = cImages[ index ]; if ( !IsCompressed( src.format ) ) { images.Release(); return E_FAIL; } if ( src.width != dest[ index ].width || src.height != dest[ index ].height ) { images.Release(); return E_FAIL; } hr = _DecompressBC( src, dest[ index ] ); if ( FAILED(hr) ) { images.Release(); return hr; } } return S_OK; }
//------------------------------------------------------------------------------------- // Resize image (complex) //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metadata, size_t width, size_t height, DWORD filter, ScratchImage& result ) { if ( !srcImages || !nimages || width == 0 || height == 0 ) return E_INVALIDARG; #ifdef _M_X64 if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) ) return E_INVALIDARG; #endif TexMetadata mdata2 = metadata; mdata2.width = width; mdata2.height = height; mdata2.mipLevels = 1; HRESULT hr = result.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; bool usewic = _UseWICFiltering( metadata.format, filter ); WICPixelFormatGUID pfGUID = {0}; bool wicpf = ( usewic ) ? _DXGIToWIC( metadata.format, pfGUID, true ) : false; switch ( metadata.dimension ) { case TEX_DIMENSION_TEXTURE1D: case TEX_DIMENSION_TEXTURE2D: assert( metadata.depth == 1 ); for( size_t item = 0; item < metadata.arraySize; ++item ) { size_t srcIndex = metadata.ComputeIndex( 0, item, 0 ); if ( srcIndex >= nimages ) { result.Release(); return E_FAIL; } const Image* srcimg = &srcImages[ srcIndex ]; const Image* destimg = result.GetImage( 0, item, 0 ); if ( !srcimg || !destimg ) { result.Release(); return E_POINTER; } if ( srcimg->format != metadata.format ) { result.Release(); return E_FAIL; } #ifdef _M_X64 if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) ) { result.Release(); return E_FAIL; } #endif if ( usewic ) { if ( wicpf ) { // Case 1: Source format is supported by Windows Imaging Component hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg ); } else { // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back hr = _PerformResizeViaF32( *srcimg, filter, *destimg ); } } else { // Case 3: not using WIC resizing hr = _PerformResizeUsingCustomFilters( *srcimg, filter, *destimg ); } if ( FAILED(hr) ) { result.Release(); return hr; } } break; case TEX_DIMENSION_TEXTURE3D: assert( metadata.arraySize == 1 ); for( size_t slice = 0; slice < metadata.depth; ++slice ) { size_t srcIndex = metadata.ComputeIndex( 0, 0, slice ); if ( srcIndex >= nimages ) { result.Release(); return E_FAIL; } const Image* srcimg = &srcImages[ srcIndex ]; const Image* destimg = result.GetImage( 0, 0, slice ); if ( !srcimg || !destimg ) { result.Release(); return E_POINTER; } if ( srcimg->format != metadata.format ) { result.Release(); return E_FAIL; } #ifdef _M_X64 if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) ) { result.Release(); return E_FAIL; } #endif if ( usewic ) { if ( wicpf ) { // Case 1: Source format is supported by Windows Imaging Component hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg ); } else { // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back hr = _PerformResizeViaF32( *srcimg, filter, *destimg ); } } else { // Case 3: not using WIC resizing hr = _PerformResizeUsingCustomFilters( *srcimg, filter, *destimg ); } if ( FAILED(hr) ) { result.Release(); return hr; } } break; default: result.Release(); return E_FAIL; } return S_OK; }
//------------------------------------------------------------------------------------- // Flip/rotate image (complex) //------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result ) { if ( !srcImages || !nimages ) return E_INVALIDARG; if ( IsCompressed( metadata.format ) ) { // We don't support flip/rotate operations on compressed images return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" ); static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" ); static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" ); static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" ); static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" ); static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" ); // Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) ) { case 0: case TEX_FR_ROTATE90: case TEX_FR_ROTATE180: case TEX_FR_ROTATE270: break; default: return E_INVALIDARG; } TexMetadata mdata2 = metadata; bool flipwh = false; if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270)) { flipwh = true; mdata2.width = metadata.height; mdata2.height = metadata.width; } HRESULT hr = result.Initialize( mdata2 ); if ( FAILED(hr) ) return hr; if ( nimages != result.GetImageCount() ) { result.Release(); return E_FAIL; } const Image* dest = result.GetImages(); if ( !dest ) { result.Release(); return E_POINTER; } WICPixelFormatGUID pfGUID; bool wicpf = _DXGIToWIC( metadata.format, pfGUID ); for( size_t index=0; index < nimages; ++index ) { const Image& src = srcImages[ index ]; if ( src.format != metadata.format ) { result.Release(); return E_FAIL; } #ifdef _AMD64_ if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) ) return E_FAIL; #endif const Image& dst = dest[ index ]; assert( dst.format == metadata.format ); if ( flipwh ) { if ( src.width != dst.height || src.height != dst.width ) { result.Release(); return E_FAIL; } } else { if ( src.width != dst.width || src.height != dst.height ) { result.Release(); return E_FAIL; } } if (wicpf) { // Case 1: Source format is supported by Windows Imaging Component hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst ); } else { // Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back hr = _PerformFlipRotateViaF32( src, flags, dst ); } if ( FAILED(hr) ) { result.Release(); return hr; } } return S_OK; }
//------------------------------------------------------------------------------------- // CreateTexture bool Test02() { ComPtr<ID3D11Device> device; HRESULT hr = CreateDevice(device.GetAddressOf(), nullptr); if (FAILED(hr)) { printe("Failed creating device (HRESULT %08X)\n", hr); return false; } bool success = true; size_t ncount = 0; size_t npass = 0; for (size_t index = 0; index < _countof(g_TestMedia); ++index) { if (g_TestMedia[index].options & FLAGS_NOT_SUPPORTED) { continue; } wchar_t szPath[MAX_PATH] = {}; DWORD ret = ExpandEnvironmentStringsW(g_TestMedia[index].fname, szPath, MAX_PATH); if (!ret || ret > MAX_PATH) { printe("ERROR: ExpandEnvironmentStrings FAILED\n"); return false; } #ifdef _DEBUG OutputDebugString(szPath); OutputDebugStringA("\n"); #endif wchar_t ext[_MAX_EXT]; _wsplitpath_s(szPath, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT); TexMetadata metadata; ScratchImage image; if (_wcsicmp(ext, L".dds") == 0) { hr = LoadFromDDSFile(szPath, DDS_FLAGS_NONE, &metadata, image); } else { hr = LoadFromWICFile(szPath, WIC_FLAGS_NONE, &metadata, image); } const TexMetadata* check = &g_TestMedia[index].metadata; if (FAILED(hr)) { success = false; printe("Failed getting data from (HRESULT %08X):\n%ls\n", hr, szPath); } else if (memcmp(&metadata, check, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szPath); printmeta(&metadata); printmetachk(check); } else { if (g_TestMedia[index].options & FLAGS_YUV) { if (!IsSupportedTexture(device.Get(), metadata)) { // Can't create video textures with mips on most hardware metadata.mipLevels = 1; if (!IsSupportedTexture(device.Get(), metadata)) { print("WARNING: Format %u is not supported by this hardware\n", metadata.format); continue; } } } ComPtr<ID3D11Resource> pResource; hr = CreateTexture(device.Get(), image.GetImages(), image.GetImageCount(), metadata, pResource.GetAddressOf()); if (FAILED(hr)) { success = false; printe("Failed creating texture from (HRESULT %08X):\n%ls\n", hr, szPath); } else { hr = CreateTextureEx(device.Get(), image.GetImages(), image.GetImageCount(), metadata, D3D11_USAGE_IMMUTABLE, D3D11_BIND_SHADER_RESOURCE, 0, 0, true, pResource.ReleaseAndGetAddressOf()); if (FAILED(hr)) { success = false; printe("Failed creating texture ex from (HRESULT %08X):\n%ls\n", hr, szPath); } else { ++npass; } } } ++ncount; } print("%zu images tested, %zu images passed ", ncount, npass); return success; }
int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow ) { UNREFERENCED_PARAMETER( hPrevInstance ); UNREFERENCED_PARAMETER( lpCmdLine ); if ( !*lpCmdLine ) { MessageBox( NULL, L"Usage: ddsview <filename>", L"DDSView", MB_OK | MB_ICONEXCLAMATION ); return 0; } TexMetadata mdata; HRESULT hr = GetMetadataFromDDSFile( lpCmdLine, DDS_FLAGS_NONE, mdata ); if ( FAILED(hr) ) { WCHAR buff[2048]; swprintf_s( buff, L"Failed to open texture file\n\nFilename = %ls\nHRESULT %08X", lpCmdLine, hr ); MessageBox( NULL, buff, L"DDSView", MB_OK | MB_ICONEXCLAMATION ); return 0; } if( FAILED( InitWindow( hInstance, nCmdShow, mdata ) ) ) return 0; SetWindowTextW( g_hWnd, lpCmdLine ); if( FAILED( InitDevice( mdata ) ) ) { CleanupDevice(); return 0; } if (mdata.dimension == TEX_DIMENSION_TEXTURE3D) { if ( mdata.arraySize > 1 ) { WCHAR buff[2048]; swprintf_s( buff, L"Arrays of volume textures are not supported\n\nFilename = %ls\nArray size %Iu", lpCmdLine, mdata.arraySize ); MessageBox( NULL, buff, L"DDSView", MB_OK | MB_ICONEXCLAMATION ); return 0; } g_iMaxIndex = static_cast<UINT>( mdata.depth ); } else { g_iMaxIndex = static_cast<UINT>( mdata.arraySize ); } switch( mdata.format ) { case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: case DXGI_FORMAT_BC6H_SF16: case DXGI_FORMAT_BC7_TYPELESS: case DXGI_FORMAT_BC7_UNORM: case DXGI_FORMAT_BC7_UNORM_SRGB: if ( g_featureLevel < D3D_FEATURE_LEVEL_11_0 ) { WCHAR buff[2048]; swprintf_s( buff, L"BC6H/BC7 requires DirectX 11 hardware\n\nFilename = %ls\nDXGI Format %d\nFeature Level %d", lpCmdLine, mdata.format, g_featureLevel ); MessageBox( NULL, buff, L"DDSView", MB_OK | MB_ICONEXCLAMATION ); return 0; } break; default: { UINT flags = 0; hr = g_pd3dDevice->CheckFormatSupport ( mdata.format, &flags ); if ( FAILED(hr) || !(flags & (D3D11_FORMAT_SUPPORT_TEXTURE1D|D3D11_FORMAT_SUPPORT_TEXTURE2D|D3D11_FORMAT_SUPPORT_TEXTURE3D)) ) { WCHAR buff[2048]; swprintf_s( buff, L"Format not supported by DirectX hardware\n\nFilename = %ls\nDXGI Format %d\nFeature Level %d\nHRESULT = %08X", lpCmdLine, mdata.format, g_featureLevel, hr ); MessageBox( NULL, buff, L"DDSView", MB_OK | MB_ICONEXCLAMATION ); return 0; } } break; } ScratchImage image; hr = LoadFromDDSFile( lpCmdLine, DDS_FLAGS_NONE, &mdata, image ); if ( FAILED(hr) ) { WCHAR buff[2048]; swprintf_s( buff, L"Failed to load texture file\n\nFilename = %ls\nHRESULT %08X", lpCmdLine, hr ); MessageBox( NULL, buff, L"DDSView", MB_OK | MB_ICONEXCLAMATION ); return 0; } // Special case to make sure Texture cubes remain arrays mdata.miscFlags &= ~TEX_MISC_TEXTURECUBE; hr = CreateShaderResourceView( g_pd3dDevice, image.GetImages(), image.GetImageCount(), mdata, &g_pSRV ); if ( FAILED(hr) ) { WCHAR buff[2048]; swprintf_s( buff, L"Failed creating texture from file\n\nFilename = %ls\nHRESULT = %08X", lpCmdLine, hr ); MessageBox( NULL, buff, L"DDSView", MB_OK | MB_ICONEXCLAMATION ); return 0; } // Main message loop MSG msg = {0}; while( WM_QUIT != msg.message ) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } CleanupDevice(); return ( int )msg.wParam; }
//------------------------------------------------------------------------------------- // rendertest bool Test04() { ComPtr<ID3D11Device> device; HRESULT hr = SetupRenderTest(device.GetAddressOf(), nullptr); if (FAILED(hr)) { printe("Failed creating device (HRESULT %08X)\n", hr); return false; } bool success = true; size_t ncount = 0; size_t npass = 0; for (size_t index = 0; index < _countof(g_TestMedia); ++index) { if (g_TestMedia[index].options & (FLAGS_YUV | FLAGS_NOT_SUPPORTED)) { // Skip video textures which need special options to render continue; } wchar_t szPath[MAX_PATH] = {}; DWORD ret = ExpandEnvironmentStringsW(g_TestMedia[index].fname, szPath, MAX_PATH); if (!ret || ret > MAX_PATH) { printe("ERROR: ExpandEnvironmentStrings FAILED\n"); return false; } #ifdef _DEBUG OutputDebugString(szPath); OutputDebugStringA("\n"); #endif wchar_t ext[_MAX_EXT]; _wsplitpath_s(szPath, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT); TexMetadata metadata; ScratchImage image; if (_wcsicmp(ext, L".dds") == 0) { hr = LoadFromDDSFile(szPath, DDS_FLAGS_NONE, &metadata, image); } else { hr = LoadFromWICFile(szPath, WIC_FLAGS_NONE, &metadata, image); } const TexMetadata* check = &g_TestMedia[index].metadata; if (FAILED(hr)) { success = false; printe("Failed getting data from (HRESULT %08X):\n%ls\n", hr, szPath); } else if (memcmp(&metadata, check, sizeof(TexMetadata)) != 0) { success = false; printe("Metadata error in:\n%ls\n", szPath); printmeta(&metadata); printmetachk(check); } else { ComPtr<ID3D11ShaderResourceView> pSRV; hr = CreateShaderResourceView(device.Get(), image.GetImages(), image.GetImageCount(), metadata, pSRV.GetAddressOf()); if (FAILED(hr)) { success = false; printe("Failed creating SRV from (HRESULT %08X):\n%ls\n", hr, szPath); } else { print("Viewing %ls\n", szPath); RenderTest(metadata, pSRV.Get()); ++npass; } } ++ncount; } print("%zu images tested, %zu images passed ", ncount, npass); CleanupRenderTest(); return success; }