| /************************************************************************** |
| * |
| * 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 */ |