Added ScreenGrab for DX12

This commit is contained in:
Chuck Walbourn 2016-07-07 18:36:23 -07:00
parent 64c5bc5893
commit 16ca163519
4 changed files with 1968 additions and 631 deletions

View File

@ -25,6 +25,8 @@
// For 2D array textures and cubemaps, it captures only the first image in the array // For 2D array textures and cubemaps, it captures only the first image in the array
#include "ScreenGrab.h"
#include <dxgiformat.h> #include <dxgiformat.h>
#include <assert.h> #include <assert.h>
@ -35,12 +37,6 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include "ScreenGrab.h"
#ifndef IID_GRAPHICS_PPV_ARGS
#define IID_GRAPHICS_PPV_ARGS(x) IID_PPV_ARGS(x)
#endif
using Microsoft::WRL::ComPtr; using Microsoft::WRL::ComPtr;
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -57,6 +53,8 @@ using Microsoft::WRL::ComPtr;
// //
// See DDS.h in the 'Texconv' sample and the 'DirectXTex' library // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
namespace
{
#pragma pack(push,1) #pragma pack(push,1)
#define DDS_MAGIC 0x20534444 // "DDS " #define DDS_MAGIC 0x20534444 // "DDS "
@ -120,87 +118,85 @@ typedef struct
#pragma pack(pop) #pragma pack(pop)
static const DDS_PIXELFORMAT DDSPF_DXT1 = const DDS_PIXELFORMAT DDSPF_DXT1 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_DXT3 = const DDS_PIXELFORMAT DDSPF_DXT3 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_DXT5 = const DDS_PIXELFORMAT DDSPF_DXT5 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_BC4_UNORM = const DDS_PIXELFORMAT DDSPF_BC4_UNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_BC4_SNORM = const DDS_PIXELFORMAT DDSPF_BC4_SNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_BC5_UNORM = const DDS_PIXELFORMAT DDSPF_BC5_UNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_BC5_SNORM = const DDS_PIXELFORMAT DDSPF_BC5_SNORM =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_YUY2 = const DDS_PIXELFORMAT DDSPF_YUY2 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 };
static const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
static const DDS_PIXELFORMAT DDSPF_X8R8G8B8 = const DDS_PIXELFORMAT DDSPF_X8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
static const DDS_PIXELFORMAT DDSPF_A8B8G8R8 = const DDS_PIXELFORMAT DDSPF_A8B8G8R8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
static const DDS_PIXELFORMAT DDSPF_G16R16 = const DDS_PIXELFORMAT DDSPF_G16R16 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 };
static const DDS_PIXELFORMAT DDSPF_R5G6B5 = const DDS_PIXELFORMAT DDSPF_R5G6B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }; { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
static const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }; { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
static const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 }; { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };
static const DDS_PIXELFORMAT DDSPF_L8 = const DDS_PIXELFORMAT DDSPF_L8 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 };
static const DDS_PIXELFORMAT DDSPF_L16 = const DDS_PIXELFORMAT DDSPF_L16 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 }; { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 };
static const DDS_PIXELFORMAT DDSPF_A8L8 = const DDS_PIXELFORMAT DDSPF_A8L8 =
{ sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 }; { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 };
static const DDS_PIXELFORMAT DDSPF_A8 = const DDS_PIXELFORMAT DDSPF_A8 =
{ sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff }; { sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff };
static const DDS_PIXELFORMAT DDSPF_V8U8 = const DDS_PIXELFORMAT DDSPF_V8U8 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000 }; { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000 };
static const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 = const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
static const DDS_PIXELFORMAT DDSPF_V16U16 = const DDS_PIXELFORMAT DDSPF_V16U16 =
{ sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 };
// DXGI_FORMAT_R10G10B10A2_UNORM should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue // DXGI_FORMAT_R10G10B10A2_UNORM should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue
// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) // This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)
static const DDS_PIXELFORMAT DDSPF_DX10 = const DDS_PIXELFORMAT DDSPF_DX10 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 }; { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 };
//--------------------------------------------------------------------------------- //-----------------------------------------------------------------------------
namespace
{
struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } }; struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };
typedef public std::unique_ptr<void, handle_closer> ScopedHandle; typedef public std::unique_ptr<void, handle_closer> ScopedHandle;
@ -252,12 +248,11 @@ namespace
auto_delete_file_wic(const auto_delete_file_wic&) = delete; auto_delete_file_wic(const auto_delete_file_wic&) = delete;
auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete; auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete;
}; };
}
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Return the BPP for a particular format // Return the BPP for a particular format
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static size_t BitsPerPixel( _In_ DXGI_FORMAT fmt ) size_t BitsPerPixel( _In_ DXGI_FORMAT fmt )
{ {
switch( fmt ) switch( fmt )
{ {
@ -407,7 +402,7 @@ static size_t BitsPerPixel( _In_ DXGI_FORMAT fmt )
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Determines if the format is block compressed // Determines if the format is block compressed
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static bool IsCompressed( _In_ DXGI_FORMAT fmt ) bool IsCompressed( _In_ DXGI_FORMAT fmt )
{ {
switch ( fmt ) switch ( fmt )
{ {
@ -443,7 +438,8 @@ static bool IsCompressed( _In_ DXGI_FORMAT fmt )
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Get surface information for a particular format // Get surface information for a particular format
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static void GetSurfaceInfo( _In_ size_t width, void GetSurfaceInfo(
_In_ size_t width,
_In_ size_t height, _In_ size_t height,
_In_ DXGI_FORMAT fmt, _In_ DXGI_FORMAT fmt,
_Out_opt_ size_t* outNumBytes, _Out_opt_ size_t* outNumBytes,
@ -573,7 +569,7 @@ static void GetSurfaceInfo( _In_ size_t width,
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static DXGI_FORMAT EnsureNotTypeless( DXGI_FORMAT fmt ) DXGI_FORMAT EnsureNotTypeless( DXGI_FORMAT fmt )
{ {
// Assumes UNORM or FLOAT; doesn't use UINT or SINT // Assumes UNORM or FLOAT; doesn't use UINT or SINT
switch( fmt ) switch( fmt )
@ -603,7 +599,8 @@ static DXGI_FORMAT EnsureNotTypeless( DXGI_FORMAT fmt )
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static HRESULT CaptureTexture( _In_ ID3D11DeviceContext* pContext, HRESULT CaptureTexture(
_In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource, _In_ ID3D11Resource* pSource,
_Inout_ D3D11_TEXTURE2D_DESC& desc, _Inout_ D3D11_TEXTURE2D_DESC& desc,
_Inout_ ComPtr<ID3D11Texture2D>& pStaging ) _Inout_ ComPtr<ID3D11Texture2D>& pStaging )
@ -618,7 +615,7 @@ static HRESULT CaptureTexture( _In_ ID3D11DeviceContext* pContext,
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
ComPtr<ID3D11Texture2D> pTexture; ComPtr<ID3D11Texture2D> pTexture;
HRESULT hr = pSource->QueryInterface( IID_GRAPHICS_PPV_ARGS( pTexture.GetAddressOf() ) ); HRESULT hr = pSource->QueryInterface( IID_PPV_ARGS( pTexture.GetAddressOf() ) );
if ( FAILED(hr) ) if ( FAILED(hr) )
return hr; return hr;
@ -699,11 +696,10 @@ static HRESULT CaptureTexture( _In_ ID3D11DeviceContext* pContext,
return S_OK; return S_OK;
} }
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static bool g_WIC2 = false; bool g_WIC2 = false;
static IWICImagingFactory* _GetWIC() IWICImagingFactory* _GetWIC()
{ {
static IWICImagingFactory* s_Factory = nullptr; static IWICImagingFactory* s_Factory = nullptr;
@ -756,6 +752,7 @@ static IWICImagingFactory* _GetWIC()
return s_Factory; return s_Factory;
} }
} // anonymous namespace
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -22,9 +22,9 @@
#pragma once #pragma once
#include <d3d11_1.h> #include <d3d11_1.h>
#include <ocidl.h> #include <ocidl.h>
#include <stdint.h> #include <stdint.h>
#include <functional> #include <functional>
@ -34,14 +34,10 @@ namespace DirectX
_In_ ID3D11Resource* pSource, _In_ ID3D11Resource* pSource,
_In_z_ LPCWSTR fileName ); _In_z_ LPCWSTR fileName );
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (_WIN32_WINNT > _WIN32_WINNT_WIN8)
HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext, HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource, _In_ ID3D11Resource* pSource,
_In_ REFGUID guidContainerFormat, _In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR fileName, _In_z_ LPCWSTR fileName,
_In_opt_ const GUID* targetFormat = nullptr, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps = nullptr ); _In_opt_ std::function<void(IPropertyBag2*)> setCustomProps = nullptr );
#endif
} }

1295
ScreenGrab/ScreenGrab12.cpp Normal file

File diff suppressed because it is too large Load Diff

49
ScreenGrab/ScreenGrab12.h Normal file
View File

@ -0,0 +1,49 @@
//--------------------------------------------------------------------------------------
// File: ScreenGrab12.h
//
// Function for capturing a 2D texture and saving it to a file (aka a 'screenshot'
// when used on a Direct3D 12 Render Target).
//
// Note these functions are useful as a light-weight runtime screen grabber. For
// full-featured texture capture, DDS writer, and texture processing pipeline,
// see the 'Texconv' sample and the 'DirectXTex' library.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
// http://go.microsoft.com/fwlink/?LinkID=615561
//--------------------------------------------------------------------------------------
#pragma once
#include <d3d12.h>
#include <ocidl.h>
#include <stdint.h>
#include <functional>
namespace DirectX
{
HRESULT __cdecl SaveDDSTextureToFile(
_In_ ID3D12CommandQueue* pCommandQueue,
_In_ ID3D12Resource* pSource,
_In_z_ const wchar_t* fileName,
D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_RENDER_TARGET);
HRESULT __cdecl SaveWICTextureToFile(
_In_ ID3D12CommandQueue* pCommandQ,
_In_ ID3D12Resource* pSource,
REFGUID guidContainerFormat,
_In_z_ const wchar_t* fileName,
D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_RENDER_TARGET,
_In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr);
}