blob: 5f429d31f908b7147b6ab7b76594a76d782d4b39 [file] [log] [blame]
/**************************************************************************
*
* Copyright 2014 VMware, Inc.
* Copyright 2011 Jose Fonseca
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**************************************************************************/
#include <assert.h>
#include <iostream>
#include <algorithm>
#include "os.hpp"
#include "state_writer.hpp"
#include "image.hpp"
#include "com_ptr.hpp"
#include "d3d11imports.hpp"
#include "d3d11state.hpp"
#include "d3d10state.hpp"
#include "dxgistate.hpp"
namespace d3dstate {
struct ResourceDesc
{
D3D11_RESOURCE_DIMENSION Type;
UINT Width;
UINT Height;
UINT Depth;
UINT MipLevels;
UINT ArraySize;
DXGI_FORMAT Format;
DXGI_SAMPLE_DESC SampleDesc;
D3D11_USAGE Usage;
UINT BindFlags;
UINT CPUAccessFlags;
UINT MiscFlags;
UINT StructureByteStride;
};
static void
getResourceDesc(ID3D11Resource *pResource, ResourceDesc *pDesc)
{
pDesc->Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pDesc->Width = 0;
pDesc->Height = 1;
pDesc->Depth = 1;
pDesc->MipLevels = 1;
pDesc->ArraySize = 1;
pDesc->Format = DXGI_FORMAT_UNKNOWN;
pDesc->SampleDesc.Count = 1;
pDesc->SampleDesc.Quality = 0;
pDesc->Usage = D3D11_USAGE_DEFAULT;
pDesc->BindFlags = 0;
pDesc->CPUAccessFlags = 0;
pDesc->MiscFlags = 0;
pDesc->StructureByteStride = 0;
pResource->GetType(&pDesc->Type);
switch (pDesc->Type) {
case D3D11_RESOURCE_DIMENSION_BUFFER:
{
D3D11_BUFFER_DESC Desc;
static_cast<ID3D11Buffer *>(pResource)->GetDesc(&Desc);
pDesc->Width = Desc.ByteWidth;
pDesc->Usage = Desc.Usage;
pDesc->BindFlags = Desc.BindFlags;
pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
pDesc->MiscFlags = Desc.MiscFlags;
pDesc->StructureByteStride = Desc.StructureByteStride;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
{
D3D11_TEXTURE1D_DESC Desc;
static_cast<ID3D11Texture1D *>(pResource)->GetDesc(&Desc);
pDesc->Width = Desc.Width;
pDesc->MipLevels = Desc.MipLevels;
pDesc->ArraySize = Desc.ArraySize;
pDesc->Format = Desc.Format;
pDesc->Usage = Desc.Usage;
pDesc->BindFlags = Desc.BindFlags;
pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
{
D3D11_TEXTURE2D_DESC Desc;
static_cast<ID3D11Texture2D *>(pResource)->GetDesc(&Desc);
pDesc->Width = Desc.Width;
pDesc->Height = Desc.Height;
pDesc->MipLevels = Desc.MipLevels;
pDesc->ArraySize = Desc.ArraySize;
pDesc->Format = Desc.Format;
pDesc->SampleDesc = Desc.SampleDesc;
pDesc->Usage = Desc.Usage;
pDesc->BindFlags = Desc.BindFlags;
pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
{
D3D11_TEXTURE3D_DESC Desc;
static_cast<ID3D11Texture3D *>(pResource)->GetDesc(&Desc);
pDesc->Width = Desc.Width;
pDesc->Height = Desc.Height;
pDesc->Depth = Desc.Depth;
pDesc->MipLevels = Desc.MipLevels;
pDesc->Format = Desc.Format;
pDesc->Usage = Desc.Usage;
pDesc->BindFlags = Desc.BindFlags;
pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
pDesc->MiscFlags = Desc.MiscFlags;
}
break;
default:
assert(0);
break;
}
}
static HRESULT
createResource(ID3D11Device *pDevice, const ResourceDesc *pDesc, ID3D11Resource **ppResource)
{
switch (pDesc->Type) {
case D3D11_RESOURCE_DIMENSION_BUFFER:
{
D3D11_BUFFER_DESC Desc;
Desc.ByteWidth = pDesc->Width;
Desc.Usage = pDesc->Usage;
Desc.BindFlags = pDesc->BindFlags;
Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
Desc.MiscFlags = pDesc->MiscFlags;
return pDevice->CreateBuffer(&Desc, NULL, reinterpret_cast<ID3D11Buffer **>(ppResource));
}
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
{
D3D11_TEXTURE1D_DESC Desc;
Desc.Width = pDesc->Width;
Desc.MipLevels = pDesc->MipLevels;
Desc.ArraySize = pDesc->ArraySize;
Desc.Format = pDesc->Format;
Desc.Usage = pDesc->Usage;
Desc.BindFlags = pDesc->BindFlags;
Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
Desc.MiscFlags = pDesc->MiscFlags;
return pDevice->CreateTexture1D(&Desc, NULL, reinterpret_cast<ID3D11Texture1D **>(ppResource));
}
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
{
D3D11_TEXTURE2D_DESC Desc;
Desc.Width = pDesc->Width;
Desc.Height = pDesc->Height;
Desc.MipLevels = pDesc->MipLevels;
Desc.ArraySize = pDesc->ArraySize;
Desc.Format = pDesc->Format;
Desc.SampleDesc = pDesc->SampleDesc;
Desc.Usage = pDesc->Usage;
Desc.BindFlags = pDesc->BindFlags;
Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
Desc.MiscFlags = pDesc->MiscFlags;
return pDevice->CreateTexture2D(&Desc, NULL, reinterpret_cast<ID3D11Texture2D **>(ppResource));
}
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
{
D3D11_TEXTURE3D_DESC Desc;
Desc.Width = pDesc->Width;
Desc.Height = pDesc->Height;
Desc.Depth = pDesc->Depth;
Desc.MipLevels = pDesc->MipLevels;
Desc.Format = pDesc->Format;
Desc.Usage = pDesc->Usage;
Desc.BindFlags = pDesc->BindFlags;
Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
Desc.MiscFlags = pDesc->MiscFlags;
return pDevice->CreateTexture3D(&Desc, NULL, reinterpret_cast<ID3D11Texture3D **>(ppResource));
}
default:
assert(0);
*ppResource = NULL;
return E_NOTIMPL;
}
}
image::Image *
getSubResourceImage(ID3D11DeviceContext *pDeviceContext,
ID3D11Resource *pResource,
DXGI_FORMAT Format,
UINT ArraySlice,
UINT MipSlice,
UINT NumElements)
{
image::Image *image = NULL;
UINT SubResource;
D3D11_MAPPED_SUBRESOURCE MappedSubResource;
HRESULT hr;
if (!pResource) {
return NULL;
}
assert(pDeviceContext->GetType() != D3D11_DEVICE_CONTEXT_DEFERRED);
com_ptr<ID3D11Device> pDevice;
pDeviceContext->GetDevice(&pDevice);
ResourceDesc Desc;
getResourceDesc(pResource, &Desc);
assert(ArraySlice < Desc.ArraySize);
assert(MipSlice < Desc.MipLevels);
assert(Desc.SampleDesc.Count > 0);
SubResource = ArraySlice*Desc.MipLevels + MipSlice;
/*
* Resolve the subresource.
*/
ResourceDesc ResolvedDesc = Desc;
ResolvedDesc.Width = std::max(Desc.Width >> MipSlice, 1U);
ResolvedDesc.Height = std::max(Desc.Height >> MipSlice, 1U);
ResolvedDesc.Depth = std::max(Desc.Depth >> MipSlice, 1U);
ResolvedDesc.ArraySize = 1;
ResolvedDesc.MipLevels = 1;
ResolvedDesc.SampleDesc.Count = 1;
ResolvedDesc.SampleDesc.Quality = 0;
ResolvedDesc.Usage = D3D11_USAGE_DEFAULT;
ResolvedDesc.BindFlags = 0;
ResolvedDesc.CPUAccessFlags = 0;
ResolvedDesc.MiscFlags = 0;
com_ptr<ID3D11Resource> pResolvedResource;
if (Desc.SampleDesc.Count == 1) {
pResolvedResource = pResource;
} else {
hr = createResource(pDevice, &ResolvedDesc, &pResolvedResource);
if (FAILED(hr)) {
return NULL;
}
pDeviceContext->ResolveSubresource(pResolvedResource, 0, pResource, SubResource, Format);
SubResource = 0;
}
/*
* Stage the subresource.
*/
ResourceDesc StagingDesc = ResolvedDesc;
StagingDesc.Usage = D3D11_USAGE_STAGING;
StagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
com_ptr<ID3D11Resource> pStagingResource;
hr = createResource(pDevice, &StagingDesc, &pStagingResource);
if (FAILED(hr)) {
return NULL;
}
pDeviceContext->CopySubresourceRegion(pStagingResource, 0, 0, 0, 0, pResolvedResource, SubResource, NULL);
/*
* Map and read the subresource.
*/
hr = pDeviceContext->Map(pStagingResource, 0, D3D11_MAP_READ, 0, &MappedSubResource);
if (FAILED(hr)) {
return nullptr;
}
UINT Width = StagingDesc.Width;
UINT Height = StagingDesc.Height;
if (NumElements) {
assert(StagingDesc.Height == 1);
Width = NumElements;
}
if (Desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
assert(Format == DXGI_FORMAT_UNKNOWN);
Format = DXGI_FORMAT_R32_UINT;
assert(Desc.StructureByteStride > 0);
assert(Desc.StructureByteStride % 4 == 0);
Width = Desc.StructureByteStride / 4;
assert(NumElements);
Height = NumElements;
MappedSubResource.RowPitch = Desc.StructureByteStride;
}
image = ConvertImage(Format,
MappedSubResource.pData,
MappedSubResource.RowPitch,
Width, Height,
Desc.BindFlags & D3D11_BIND_DEPTH_STENCIL);
pDeviceContext->Unmap(pStagingResource, 0);
if (image) {
image->label = getObjectName(pResource);
}
return image;
}
static void
dumpShaderResourceViewImage(StateWriter &writer,
ID3D11DeviceContext *pDevice,
ID3D11ShaderResourceView *pShaderResourceView,
const char *shader,
UINT stage)
{
if (!pShaderResourceView) {
return;
}
com_ptr<ID3D11Resource> pResource;
pShaderResourceView->GetResource(&pResource);
assert(pResource);
D3D11_SHADER_RESOURCE_VIEW_DESC Desc;
pShaderResourceView->GetDesc(&Desc);
UINT MipSlice = 0;
UINT NumElements = 0;
UINT FirstArraySlice = 0;
UINT ArraySize = 1;
switch (Desc.ViewDimension) {
case D3D11_SRV_DIMENSION_BUFFER:
NumElements = Desc.Buffer.NumElements;
break;
case D3D11_SRV_DIMENSION_BUFFEREX:
NumElements = Desc.BufferEx.NumElements;
if (Desc.BufferEx.Flags & D3D11_BUFFER_UAV_FLAG_RAW) {
// Raw buffers
assert(Desc.Format == DXGI_FORMAT_R32_TYPELESS);
Desc.Format = DXGI_FORMAT_R32_UINT;
}
break;
case D3D11_SRV_DIMENSION_TEXTURE1D:
MipSlice = Desc.Texture1D.MostDetailedMip;
break;
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
MipSlice = Desc.Texture1DArray.MostDetailedMip;
FirstArraySlice = Desc.Texture1DArray.FirstArraySlice;
ArraySize = Desc.Texture1DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2D:
MipSlice = Desc.Texture2D.MostDetailedMip;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
MipSlice = Desc.Texture2DArray.MostDetailedMip;
FirstArraySlice = Desc.Texture2DArray.FirstArraySlice;
ArraySize = Desc.Texture2DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMS:
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
FirstArraySlice = Desc.Texture2DMSArray.FirstArraySlice;
ArraySize = Desc.Texture2DMSArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE3D:
MipSlice = Desc.Texture3D.MostDetailedMip;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBE:
MipSlice = Desc.TextureCube.MostDetailedMip;
ArraySize = 6;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
MipSlice = Desc.TextureCubeArray.MostDetailedMip;
FirstArraySlice = Desc.TextureCubeArray.First2DArrayFace;
ArraySize = 6 * Desc.TextureCubeArray.NumCubes;
break;
case D3D11_SRV_DIMENSION_UNKNOWN:
default:
assert(0);
return;
}
for (UINT ArraySlice = FirstArraySlice; ArraySlice < FirstArraySlice + ArraySize; ++ArraySlice) {
image::Image *image;
image = getSubResourceImage(pDevice, pResource, Desc.Format, ArraySlice, MipSlice, NumElements);
if (image) {
char label[64];
_snprintf(label, sizeof label,
"%s_RESOURCE_%u_ARRAY_%u_LEVEL_%u",
shader, stage, ArraySlice, MipSlice);
StateWriter::ImageDesc imgDesc;
imgDesc.depth = 1;
imgDesc.format = getDXGIFormatName(Desc.Format);
writer.beginMember(label);
writer.writeImage(image, imgDesc);
writer.endMember(); // *_RESOURCE_*
delete image;
}
}
}
static image::Image *
getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
ID3D11RenderTargetView *pRenderTargetView,
DXGI_FORMAT *dxgiFormat)
{
if (!pRenderTargetView) {
return NULL;
}
com_ptr<ID3D11Resource> pResource;
pRenderTargetView->GetResource(&pResource);
assert(pResource);
D3D11_RENDER_TARGET_VIEW_DESC Desc;
pRenderTargetView->GetDesc(&Desc);
if (dxgiFormat) {
*dxgiFormat = Desc.Format;
}
// TODO: Take the slice in consideration
UINT MipSlice;
switch (Desc.ViewDimension) {
case D3D11_RTV_DIMENSION_BUFFER:
MipSlice = 0;
break;
case D3D11_RTV_DIMENSION_TEXTURE1D:
MipSlice = Desc.Texture1D.MipSlice;
break;
case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
MipSlice = Desc.Texture1DArray.MipSlice;
break;
case D3D11_RTV_DIMENSION_TEXTURE2D:
MipSlice = Desc.Texture2D.MipSlice;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
MipSlice = Desc.Texture2DArray.MipSlice;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMS:
MipSlice = 0;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
MipSlice = 0;
break;
case D3D11_RTV_DIMENSION_TEXTURE3D:
MipSlice = Desc.Texture3D.MipSlice;
break;
case D3D11_RTV_DIMENSION_UNKNOWN:
default:
assert(0);
return NULL;
}
return getSubResourceImage(pDevice, pResource, Desc.Format, 0, MipSlice);
}
static image::Image *
getDepthStencilViewImage(ID3D11DeviceContext *pDevice,
ID3D11DepthStencilView *pDepthStencilView,
DXGI_FORMAT *dxgiFormat)
{
if (!pDepthStencilView) {
return NULL;
}
com_ptr<ID3D11Resource> pResource;
pDepthStencilView->GetResource(&pResource);
assert(pResource);
D3D11_DEPTH_STENCIL_VIEW_DESC Desc;
pDepthStencilView->GetDesc(&Desc);
if (dxgiFormat) {
*dxgiFormat = Desc.Format;
}
// TODO: Take the slice in consideration
UINT MipSlice;
switch (Desc.ViewDimension) {
case D3D11_DSV_DIMENSION_TEXTURE1D:
MipSlice = Desc.Texture1D.MipSlice;
break;
case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
MipSlice = Desc.Texture1DArray.MipSlice;
break;
case D3D11_DSV_DIMENSION_TEXTURE2D:
MipSlice = Desc.Texture2D.MipSlice;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
MipSlice = Desc.Texture2DArray.MipSlice;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMS:
MipSlice = 0;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
MipSlice = 0;
break;
case D3D11_DSV_DIMENSION_UNKNOWN:
default:
assert(0);
return NULL;
}
return getSubResourceImage(pDevice, pResource, Desc.Format, 0, MipSlice);
}
static image::Image *
getUnorderedAccessViewImage(ID3D11DeviceContext *pDevice,
ID3D11UnorderedAccessView *pUAView,
DXGI_FORMAT *dxgiFormat)
{
if (!pUAView) {
return nullptr;
}
com_ptr<ID3D11Resource> pResource;
pUAView->GetResource(&pResource);
assert(pResource);
D3D11_UNORDERED_ACCESS_VIEW_DESC Desc;
pUAView->GetDesc(&Desc);
if (dxgiFormat) {
*dxgiFormat = Desc.Format;
}
UINT MipSlice;
UINT NumElements = 0;
switch (Desc.ViewDimension) {
case D3D11_UAV_DIMENSION_BUFFER:
MipSlice = 0;
if (Desc.Buffer.Flags & D3D11_BUFFER_UAV_FLAG_RAW) {
// Raw buffers
assert(Desc.Format == DXGI_FORMAT_R32_TYPELESS);
Desc.Format = DXGI_FORMAT_R32_UINT;
}
NumElements = Desc.Buffer.NumElements;
break;
case D3D11_UAV_DIMENSION_TEXTURE1D:
MipSlice = Desc.Texture1D.MipSlice;
break;
case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
MipSlice = Desc.Texture1DArray.MipSlice;
break;
case D3D11_UAV_DIMENSION_TEXTURE2D:
MipSlice = Desc.Texture2D.MipSlice;
break;
case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
MipSlice = Desc.Texture2DArray.MipSlice;
break;
case D3D11_UAV_DIMENSION_TEXTURE3D:
MipSlice = Desc.Texture3D.MipSlice;
break;
case D3D11_UAV_DIMENSION_UNKNOWN:
default:
assert(0);
return nullptr;
}
return getSubResourceImage(pDevice, pResource, Desc.Format, 0, MipSlice, NumElements);
}
static void
dumpStageTextures(StateWriter &writer, ID3D11DeviceContext *pDevice, const char *stageName,
UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
for (UINT i = 0; i < NumViews; ++i) {
if (!ppShaderResourceViews[i]) {
continue;
}
dumpShaderResourceViewImage(writer, pDevice, ppShaderResourceViews[i], stageName, i);
ppShaderResourceViews[i]->Release();
}
}
void
dumpTextures(StateWriter &writer, ID3D11DeviceContext *pDevice)
{
writer.beginMember("textures");
writer.beginObject();
if (pDevice->GetType() != D3D11_DEVICE_CONTEXT_DEFERRED) {
ID3D11ShaderResourceView *pShaderResourceViews[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
pDevice->VSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
dumpStageTextures(writer, pDevice, "VS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->HSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
dumpStageTextures(writer, pDevice, "HS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->DSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
dumpStageTextures(writer, pDevice, "DS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->GSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
dumpStageTextures(writer, pDevice, "GS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
dumpStageTextures(writer, pDevice, "PS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->CSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
dumpStageTextures(writer, pDevice, "CS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
}
writer.endObject();
writer.endMember(); // textures
}
image::Image *
getRenderTargetImage(ID3D11DeviceContext *pDevice,
DXGI_FORMAT *dxgiFormat)
{
image::Image *image = nullptr;
if (pDevice->GetType() != D3D11_DEVICE_CONTEXT_DEFERRED) {
com_ptr<ID3D11RenderTargetView> pRenderTargetView;
pDevice->OMGetRenderTargets(1, &pRenderTargetView, nullptr);
if (pRenderTargetView) {
image = getRenderTargetViewImage(pDevice, pRenderTargetView, dxgiFormat);
}
}
return image;
}
void
dumpFramebuffer(StateWriter &writer, ID3D11DeviceContext *pDevice)
{
writer.beginMember("framebuffer");
writer.beginObject();
if (pDevice->GetType() != D3D11_DEVICE_CONTEXT_DEFERRED) {
ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
ID3D11DepthStencilView *pDepthStencilView;
pDevice->OMGetRenderTargets(ARRAYSIZE(pRenderTargetViews), pRenderTargetViews,
&pDepthStencilView);
for (UINT i = 0; i < ARRAYSIZE(pRenderTargetViews); ++i) {
if (!pRenderTargetViews[i]) {
continue;
}
image::Image *image;
DXGI_FORMAT dxgiFormat;
image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i],
&dxgiFormat);
if (image) {
char label[64];
_snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
StateWriter::ImageDesc imgDesc;
imgDesc.depth = 1;
imgDesc.format = getDXGIFormatName(dxgiFormat);
writer.beginMember(label);
writer.writeImage(image, imgDesc);
writer.endMember(); // RENDER_TARGET_*
delete image;
}
pRenderTargetViews[i]->Release();
}
if (pDepthStencilView) {
image::Image *image;
DXGI_FORMAT dxgiFormat;
image = getDepthStencilViewImage(pDevice, pDepthStencilView,
&dxgiFormat);
if (image) {
StateWriter::ImageDesc imgDesc;
imgDesc.depth = 1;
imgDesc.format = getDXGIFormatName(dxgiFormat);
writer.beginMember("DEPTH_STENCIL");
writer.writeImage(image, imgDesc);
writer.endMember();
delete image;
}
pDepthStencilView->Release();
}
ID3D11UnorderedAccessView *pUAViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
pDevice->OMGetRenderTargetsAndUnorderedAccessViews(0, nullptr, nullptr,
0, ARRAYSIZE(pUAViews), pUAViews);
for (UINT i = 0; i < ARRAYSIZE(pUAViews); ++i) {
if (!pUAViews[i]) {
continue;
}
image::Image *image;
DXGI_FORMAT dxgiFormat;
image = getUnorderedAccessViewImage(pDevice, pUAViews[i],
&dxgiFormat);
if (image) {
char label[64];
_snprintf(label, sizeof label, "UNORDERED_ACCESS_%u", i);
StateWriter::ImageDesc imgDesc;
imgDesc.depth = 1;
imgDesc.format = getDXGIFormatName(dxgiFormat);
writer.beginMember(label);
writer.writeImage(image, imgDesc);
writer.endMember();
delete image;
}
pUAViews[i]->Release();
}
ID3D11UnorderedAccessView *pCSUAViews[D3D11_1_UAV_SLOT_COUNT];
pDevice->CSGetUnorderedAccessViews(0, ARRAYSIZE(pCSUAViews), pCSUAViews);
for (UINT i = 0; i < ARRAYSIZE(pCSUAViews); ++i) {
if (!pCSUAViews[i]) {
continue;
}
image::Image *image;
DXGI_FORMAT dxgiFormat;
image = getUnorderedAccessViewImage(pDevice, pCSUAViews[i],
&dxgiFormat);
if (image) {
char label[64];
_snprintf(label, sizeof label, "CSUNORDERED_ACCESS_%u", i);
StateWriter::ImageDesc imgDesc;
imgDesc.depth = 1;
imgDesc.format = getDXGIFormatName(dxgiFormat);
writer.beginMember(label);
writer.writeImage(image, imgDesc);
writer.endMember();
delete image;
}
pCSUAViews[i]->Release();
}
}
writer.endObject();
writer.endMember(); // framebuffer
}
} /* namespace d3dstate */