Files
renderdoc/renderdoc/driver/d3d11/d3d11_context_wrap.cpp
T
baldurk 851a88133a Remove the 'save all initials' option. Behave as if it's always enabled
* This option has always been a mixed bag - when originally written captures
  weren't compressed at all so saving the cost of a initial contents on a
  gbuffer would have a significant savings.
* Now with compression the savings are lesser, and it's a source of
  bugs/confusion for the case where either a bug is caused by leaking data from
  the previous frame or worse still the contents are discarded incorrectly.
* D3D11 will now behave as the other APIs will - saving initial contents
  whenever needed even if they seem like they might not be used.
2018-05-23 16:08:44 +01:00

7746 lines
257 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015-2018 Baldur Karlsson
* Copyright (c) 2014 Crytek
*
* 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 "d3d11_context.h"
#include "3rdparty/tinyfiledialogs/tinyfiledialogs.h"
#include "driver/dx/official/dxgi1_3.h"
#include "strings/string_utils.h"
#include "d3d11_debug.h"
#include "d3d11_renderstate.h"
#include "d3d11_resources.h"
#ifndef DXGI_ERROR_INVALID_CALL
#define DXGI_ERROR_INVALID_CALL MAKE_DXGI_HRESULT(1)
#endif
uint32_t NullCBOffsets[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
uint32_t NullCBCounts[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
#pragma region D3DPERF
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_SetMarker(SerialiserType &ser, uint32_t Color,
const wchar_t *MarkerNameW)
{
SERIALISE_ELEMENT(Color);
SERIALISE_ELEMENT_LOCAL(MarkerName, StringFormat::Wide2UTF8(MarkerNameW ? MarkerNameW : L""));
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
D3D11MarkerRegion::Set(MarkerName);
if(IsLoading(m_State))
{
DrawcallDescription draw;
draw.name = MarkerName;
draw.flags |= DrawFlags::SetMarker;
byte alpha = (Color >> 24) & 0xff;
byte red = (Color >> 16) & 0xff;
byte green = (Color >> 8) & 0xff;
byte blue = (Color >> 0) & 0xff;
draw.markerColor[0] = float(red) / 255.0f;
draw.markerColor[1] = float(green) / 255.0f;
draw.markerColor[2] = float(blue) / 255.0f;
draw.markerColor[3] = float(alpha) / 255.0f;
AddEvent();
AddDrawcall(draw, false);
}
}
return true;
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PushMarker(SerialiserType &ser, uint32_t Color,
const wchar_t *MarkerNameW)
{
SERIALISE_ELEMENT(Color);
SERIALISE_ELEMENT_LOCAL(MarkerName, StringFormat::Wide2UTF8(MarkerNameW ? MarkerNameW : L""));
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
D3D11MarkerRegion::Begin(MarkerName);
m_pDevice->ReplayPushEvent();
if(IsLoading(m_State))
{
DrawcallDescription draw;
draw.name = MarkerName;
draw.flags |= DrawFlags::PushMarker;
byte alpha = (Color >> 24) & 0xff;
byte red = (Color >> 16) & 0xff;
byte green = (Color >> 8) & 0xff;
byte blue = (Color >> 0) & 0xff;
draw.markerColor[0] = float(red) / 255.0f;
draw.markerColor[1] = float(green) / 255.0f;
draw.markerColor[2] = float(blue) / 255.0f;
draw.markerColor[3] = float(alpha) / 255.0f;
AddEvent();
AddDrawcall(draw, false);
}
}
return true;
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PopMarker(SerialiserType &ser)
{
if(IsReplayingAndReading())
{
D3D11MarkerRegion::End();
m_pDevice->ReplayPopEvent();
if(IsLoading(m_State) && !m_CurEvents.empty())
{
DrawcallDescription draw;
draw.name = "API Calls";
draw.flags |= DrawFlags::APICalls;
AddEvent();
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::SetMarker(uint32_t Color, const wchar_t *MarkerName)
{
SERIALISE_TIME_CALL();
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::SetMarker);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_SetMarker(GET_SERIALISER, Color, MarkerName);
m_ContextRecord->AddChunk(scope.Get());
}
}
int WrappedID3D11DeviceContext::PushMarker(uint32_t Color, const wchar_t *MarkerName)
{
SERIALISE_TIME_CALL();
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PushMarker);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PushMarker(GET_SERIALISER, Color, MarkerName);
m_ContextRecord->AddChunk(scope.Get());
}
return m_MarkerIndentLevel++;
}
int WrappedID3D11DeviceContext::PopMarker()
{
SERIALISE_TIME_CALL();
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PopMarker);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PopMarker(GET_SERIALISER);
m_ContextRecord->AddChunk(scope.Get());
}
return --m_MarkerIndentLevel;
}
void WrappedID3D11DeviceContext::ThreadSafe_SetMarker(uint32_t col, const wchar_t *name)
{
Annotation annot;
annot.m_Type = Annotation::ANNOT_SETMARKER;
annot.m_Col = col;
annot.m_Name = name;
{
SCOPED_LOCK(m_AnnotLock);
m_AnnotationQueue.push_back(annot);
}
}
int WrappedID3D11DeviceContext::ThreadSafe_BeginEvent(uint32_t col, const wchar_t *name)
{
Annotation annot;
annot.m_Type = Annotation::ANNOT_BEGINEVENT;
annot.m_Col = col;
annot.m_Name = name;
{
SCOPED_LOCK(m_AnnotLock);
m_AnnotationQueue.push_back(annot);
}
// not thread safe but I don't want to lock over access to this - if people use D3DPERF + MT
// they shouldn't rely on this return value anyway :).
return m_MarkerIndentLevel;
}
int WrappedID3D11DeviceContext::ThreadSafe_EndEvent()
{
Annotation annot;
annot.m_Type = Annotation::ANNOT_ENDEVENT;
{
SCOPED_LOCK(m_AnnotLock);
m_AnnotationQueue.push_back(annot);
}
// not thread safe but I don't want to lock over access to this - if people use D3DPERF + MT
// they shouldn't rely on this return value anyway :).
return m_MarkerIndentLevel - 1;
}
void WrappedID3D11DeviceContext::DrainAnnotationQueue()
{
if(!IsActiveCapturing(m_State))
return;
m_AnnotLock.Lock();
// fastest possible early-out
if(m_AnnotationQueue.empty())
{
m_AnnotLock.Unlock();
return;
}
std::vector<Annotation> annotations;
annotations.swap(m_AnnotationQueue);
m_AnnotLock.Unlock();
for(size_t i = 0; i < annotations.size(); i++)
{
const Annotation &a = annotations[i];
switch(a.m_Type)
{
case Annotation::ANNOT_SETMARKER: SetMarker(a.m_Col, a.m_Name.c_str()); break;
case Annotation::ANNOT_BEGINEVENT: PushMarker(a.m_Col, a.m_Name.c_str()); break;
case Annotation::ANNOT_ENDEVENT: PopMarker(); break;
}
}
}
#pragma endregion D3DPERF
#pragma region Input Assembly
void WrappedID3D11DeviceContext::IAGetInputLayout(ID3D11InputLayout **ppInputLayout)
{
if(ppInputLayout)
{
ID3D11InputLayout *real = NULL;
m_pRealContext->IAGetInputLayout(&real);
SAFE_RELEASE_NOCLEAR(real);
*ppInputLayout = (ID3D11InputLayout *)m_pDevice->GetResourceManager()->GetWrapper(real);
SAFE_ADDREF(*ppInputLayout);
RDCASSERT(*ppInputLayout == m_CurrentPipelineState->IA.Layout);
}
}
void WrappedID3D11DeviceContext::IAGetVertexBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer **ppVertexBuffers, UINT *pStrides,
UINT *pOffsets)
{
ID3D11Buffer *real[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] = {0};
m_pRealContext->IAGetVertexBuffers(StartSlot, NumBuffers, real, pStrides, pOffsets);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
if(ppVertexBuffers)
{
ppVertexBuffers[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppVertexBuffers[i]);
RDCASSERT(ppVertexBuffers[i] == m_CurrentPipelineState->IA.VBs[i + StartSlot]);
}
// D3D11 really inconsistently tracks these.
// RDCASSERT(pStrides[i] == m_CurrentPipelineState->IA.Strides[i+StartSlot]);
// RDCASSERT(pOffsets[i] == m_CurrentPipelineState->IA.Offsets[i+StartSlot]);
}
}
void WrappedID3D11DeviceContext::IAGetIndexBuffer(ID3D11Buffer **pIndexBuffer, DXGI_FORMAT *Format,
UINT *Offset)
{
if(pIndexBuffer)
{
ID3D11Buffer *real = NULL;
m_pRealContext->IAGetIndexBuffer(&real, Format, Offset);
SAFE_RELEASE_NOCLEAR(real);
*pIndexBuffer = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real);
SAFE_ADDREF(*pIndexBuffer);
RDCASSERT(*pIndexBuffer == m_CurrentPipelineState->IA.IndexBuffer);
if(Format)
RDCASSERT(*Format == m_CurrentPipelineState->IA.IndexFormat);
if(Offset)
RDCASSERT(*Offset == m_CurrentPipelineState->IA.IndexOffset);
}
}
void WrappedID3D11DeviceContext::IAGetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY *pTopology)
{
m_pRealContext->IAGetPrimitiveTopology(pTopology);
if(pTopology)
RDCASSERT(*pTopology == m_CurrentPipelineState->IA.Topo);
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_IASetPrimitiveTopology(SerialiserType &ser,
D3D11_PRIMITIVE_TOPOLOGY Topology)
{
SERIALISE_ELEMENT(Topology);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.Topo, Topology);
m_pRealContext->IASetPrimitiveTopology(Topology);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topology)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->IASetPrimitiveTopology(Topology));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::IASetPrimitiveTopology);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_IASetPrimitiveTopology(GET_SERIALISER, Topology);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.Topo, Topology);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_IASetInputLayout(SerialiserType &ser,
ID3D11InputLayout *pInputLayout)
{
SERIALISE_ELEMENT(pInputLayout);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordLayoutBindStats(pInputLayout);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->IA.Layout, pInputLayout);
m_pRealContext->IASetInputLayout(UNWRAP(WrappedID3D11InputLayout, pInputLayout));
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::IASetInputLayout(ID3D11InputLayout *pInputLayout)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(
m_pRealContext->IASetInputLayout(UNWRAP(WrappedID3D11InputLayout, pInputLayout)));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::IASetInputLayout);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_IASetInputLayout(GET_SERIALISER, pInputLayout);
MarkResourceReferenced(GetIDForResource(pInputLayout), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->IA.Layout, pInputLayout);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_IASetVertexBuffers(SerialiserType &ser, UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer *const *ppVertexBuffers,
const UINT *pStrides,
const UINT *pOffsets)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppVertexBuffers, NumBuffers);
SERIALISE_ELEMENT_ARRAY(pStrides, NumBuffers);
SERIALISE_ELEMENT_ARRAY(pOffsets, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordVertexBindStats(NumBuffers, ppVertexBuffers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->IA.VBs, ppVertexBuffers,
StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.Strides, pStrides, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.Offsets, pOffsets, StartSlot,
NumBuffers);
ID3D11Buffer *bufs[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumBuffers; i++)
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppVertexBuffers[i]);
m_pRealContext->IASetVertexBuffers(StartSlot, NumBuffers, bufs, pStrides, pOffsets);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::IASetVertexBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer *const *ppVertexBuffers,
const UINT *pStrides, const UINT *pOffsets)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppVertexBuffers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppVertexBuffers[i]), eFrameRef_Read);
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppVertexBuffers[i]);
}
SERIALISE_TIME_CALL(
m_pRealContext->IASetVertexBuffers(StartSlot, NumBuffers, bufs, pStrides, pOffsets));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::IASetVertexBuffers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_IASetVertexBuffers(GET_SERIALISER, StartSlot, NumBuffers, ppVertexBuffers, pStrides,
pOffsets);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->IA.VBs, ppVertexBuffers, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.Strides, pStrides, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.Offsets, pOffsets, StartSlot, NumBuffers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_IASetIndexBuffer(SerialiserType &ser,
ID3D11Buffer *pIndexBuffer,
DXGI_FORMAT Format, UINT Offset)
{
SERIALISE_ELEMENT(pIndexBuffer);
SERIALISE_ELEMENT(Format);
SERIALISE_ELEMENT(Offset);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordIndexBindStats(pIndexBuffer);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->IA.IndexBuffer, pIndexBuffer);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.IndexFormat, Format);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.IndexOffset, Offset);
m_pRealContext->IASetIndexBuffer(UNWRAP(WrappedID3D11Buffer, pIndexBuffer), Format, Offset);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::IASetIndexBuffer(ID3D11Buffer *pIndexBuffer, DXGI_FORMAT Format,
UINT Offset)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(
m_pRealContext->IASetIndexBuffer(UNWRAP(WrappedID3D11Buffer, pIndexBuffer), Format, Offset));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::IASetIndexBuffer);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_IASetIndexBuffer(GET_SERIALISER, pIndexBuffer, Format, Offset);
m_ContextRecord->AddChunk(scope.Get());
}
if(pIndexBuffer && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(pIndexBuffer), eFrameRef_Read);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->IA.IndexBuffer, pIndexBuffer);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.IndexFormat, Format);
m_CurrentPipelineState->Change(m_CurrentPipelineState->IA.IndexOffset, Offset);
VerifyState();
}
#pragma endregion Input Assembly
#pragma region Vertex Shader
void WrappedID3D11DeviceContext::VSGetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer **ppConstantBuffers)
{
if(ppConstantBuffers)
{
ID3D11Buffer *real[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
m_pRealContext->VSGetConstantBuffers(StartSlot, NumBuffers, real);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppConstantBuffers[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppConstantBuffers[i]);
RDCASSERT(ppConstantBuffers[i] == m_CurrentPipelineState->VS.ConstantBuffers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::VSGetShaderResources(UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
if(ppShaderResourceViews)
{
ID3D11ShaderResourceView *real[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {0};
m_pRealContext->VSGetShaderResources(StartSlot, NumViews, real);
for(UINT i = 0; i < NumViews; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppShaderResourceViews[i] =
(ID3D11ShaderResourceView *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppShaderResourceViews[i]);
RDCASSERT(ppShaderResourceViews[i] == m_CurrentPipelineState->VS.SRVs[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::VSGetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState **ppSamplers)
{
if(ppSamplers)
{
ID3D11SamplerState *real[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {0};
m_pRealContext->VSGetSamplers(StartSlot, NumSamplers, real);
for(UINT i = 0; i < NumSamplers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppSamplers[i] = (ID3D11SamplerState *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppSamplers[i]);
RDCASSERT(ppSamplers[i] == m_CurrentPipelineState->VS.Samplers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::VSGetShader(ID3D11VertexShader **ppVertexShader,
ID3D11ClassInstance **ppClassInstances,
UINT *pNumClassInstances)
{
if(ppVertexShader == NULL && ppClassInstances == NULL && pNumClassInstances == NULL)
return;
ID3D11ClassInstance *realInsts[D3D11_SHADER_MAX_INTERFACES] = {0};
UINT numInsts = 0;
ID3D11VertexShader *realShader = NULL;
m_pRealContext->VSGetShader(&realShader, realInsts, &numInsts);
SAFE_RELEASE_NOCLEAR(realShader);
for(UINT i = 0; i < numInsts; i++)
SAFE_RELEASE_NOCLEAR(realInsts[i]);
if(ppVertexShader)
{
*ppVertexShader = (ID3D11VertexShader *)m_pDevice->GetResourceManager()->GetWrapper(realShader);
SAFE_ADDREF(*ppVertexShader);
RDCASSERT(*ppVertexShader == m_CurrentPipelineState->VS.Object);
}
if(ppClassInstances)
{
for(UINT i = 0; i < numInsts; i++)
{
ppClassInstances[i] =
(ID3D11ClassInstance *)m_pDevice->GetResourceManager()->GetWrapper(realInsts[i]);
SAFE_ADDREF(ppClassInstances[i]);
RDCASSERT(ppClassInstances[i] == m_CurrentPipelineState->VS.Instances[i]);
}
}
if(pNumClassInstances)
{
*pNumClassInstances = numInsts;
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_VSSetConstantBuffers(SerialiserType &ser, UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppConstantBuffers, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordConstantStats(ShaderStage::Vertex, NumBuffers, ppConstantBuffers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->VS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->VS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
m_pRealContext->VSSetConstantBuffers(StartSlot, NumBuffers, bufs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::VSSetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppConstantBuffers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppConstantBuffers[i]), eFrameRef_Read);
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->VSSetConstantBuffers(StartSlot, NumBuffers, bufs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::VSSetConstantBuffers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_VSSetConstantBuffers(GET_SERIALISER, StartSlot, NumBuffers, ppConstantBuffers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->VS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->VS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_VSSetShaderResources(
SerialiserType &ser, UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumViews);
SERIALISE_ELEMENT_ARRAY(ppShaderResourceViews, NumViews);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordResourceStats(ShaderStage::Vertex, NumViews, ppShaderResourceViews);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
m_pRealContext->VSSetShaderResources(StartSlot, NumViews, SRVs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::VSSetShaderResources(
UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
{
if(ppShaderResourceViews[i] && IsActiveCapturing(m_State))
{
MarkResourceReferenced(GetIDForResource(ppShaderResourceViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppShaderResourceViews[i]), eFrameRef_Read);
}
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->VSSetShaderResources(StartSlot, NumViews, SRVs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::VSSetShaderResources);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_VSSetShaderResources(GET_SERIALISER, StartSlot, NumViews, ppShaderResourceViews);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_VSSetSamplers(SerialiserType &ser, UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumSamplers);
SERIALISE_ELEMENT_ARRAY(ppSamplers, NumSamplers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordSamplerStats(ShaderStage::Vertex, NumSamplers, ppSamplers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.Samplers, ppSamplers,
StartSlot, NumSamplers);
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
m_pRealContext->VSSetSamplers(StartSlot, NumSamplers, samps);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::VSSetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
{
if(ppSamplers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppSamplers[i]), eFrameRef_Read);
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->VSSetSamplers(StartSlot, NumSamplers, samps));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::VSSetSamplers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_VSSetSamplers(GET_SERIALISER, StartSlot, NumSamplers, ppSamplers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.Samplers, ppSamplers, StartSlot,
NumSamplers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_VSSetShader(SerialiserType &ser,
ID3D11VertexShader *pShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
SERIALISE_ELEMENT(pShader);
SERIALISE_ELEMENT_ARRAY(ppClassInstances, NumClassInstances);
SERIALISE_ELEMENT(NumClassInstances);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordShaderStats(ShaderStage::Vertex, m_CurrentPipelineState->VS.Object, pShader);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.Instances, ppClassInstances, 0,
NumClassInstances);
m_CurrentPipelineState->Change(m_CurrentPipelineState->VS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.Object,
(ID3D11DeviceChild *)pShader);
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
m_pRealContext->VSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11VertexShader>, pShader), insts,
NumClassInstances);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::VSSetShader(ID3D11VertexShader *pVertexShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
if(ppClassInstances && NumClassInstances > 0)
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
SERIALISE_TIME_CALL(m_pRealContext->VSSetShader(
UNWRAP(WrappedID3D11Shader<ID3D11VertexShader>, pVertexShader), insts, NumClassInstances));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::VSSetShader);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_VSSetShader(GET_SERIALISER, pVertexShader, ppClassInstances, NumClassInstances);
MarkResourceReferenced(GetIDForResource(pVertexShader), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.Object,
(ID3D11DeviceChild *)pVertexShader);
m_CurrentPipelineState->Change(m_CurrentPipelineState->VS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.Instances, ppClassInstances, 0,
NumClassInstances);
VerifyState();
}
#pragma endregion Vertex Shader
#pragma region Hull Shader
void WrappedID3D11DeviceContext::HSGetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer **ppConstantBuffers)
{
if(ppConstantBuffers)
{
ID3D11Buffer *real[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
m_pRealContext->HSGetConstantBuffers(StartSlot, NumBuffers, real);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppConstantBuffers[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppConstantBuffers[i]);
RDCASSERT(ppConstantBuffers[i] == m_CurrentPipelineState->HS.ConstantBuffers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::HSGetShaderResources(UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
if(ppShaderResourceViews)
{
ID3D11ShaderResourceView *real[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {0};
m_pRealContext->HSGetShaderResources(StartSlot, NumViews, real);
for(UINT i = 0; i < NumViews; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppShaderResourceViews[i] =
(ID3D11ShaderResourceView *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppShaderResourceViews[i]);
RDCASSERT(ppShaderResourceViews[i] == m_CurrentPipelineState->HS.SRVs[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::HSGetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState **ppSamplers)
{
if(ppSamplers)
{
ID3D11SamplerState *real[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {0};
m_pRealContext->HSGetSamplers(StartSlot, NumSamplers, real);
for(UINT i = 0; i < NumSamplers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppSamplers[i] = (ID3D11SamplerState *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppSamplers[i]);
RDCASSERT(ppSamplers[i] == m_CurrentPipelineState->HS.Samplers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::HSGetShader(ID3D11HullShader **ppHullShader,
ID3D11ClassInstance **ppClassInstances,
UINT *pNumClassInstances)
{
if(ppHullShader == NULL && ppClassInstances == NULL && pNumClassInstances == NULL)
return;
ID3D11ClassInstance *realInsts[D3D11_SHADER_MAX_INTERFACES] = {0};
UINT numInsts = 0;
ID3D11HullShader *realShader = NULL;
m_pRealContext->HSGetShader(&realShader, realInsts, &numInsts);
SAFE_RELEASE_NOCLEAR(realShader);
for(UINT i = 0; i < numInsts; i++)
SAFE_RELEASE_NOCLEAR(realInsts[i]);
if(ppHullShader)
{
*ppHullShader = (ID3D11HullShader *)m_pDevice->GetResourceManager()->GetWrapper(realShader);
SAFE_ADDREF(*ppHullShader);
RDCASSERT(*ppHullShader == m_CurrentPipelineState->HS.Object);
}
if(ppClassInstances)
{
for(UINT i = 0; i < numInsts; i++)
{
ppClassInstances[i] =
(ID3D11ClassInstance *)m_pDevice->GetResourceManager()->GetWrapper(realInsts[i]);
SAFE_ADDREF(ppClassInstances[i]);
RDCASSERT(ppClassInstances[i] == m_CurrentPipelineState->HS.Instances[i]);
}
}
if(pNumClassInstances)
{
*pNumClassInstances = numInsts;
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_HSSetConstantBuffers(SerialiserType &ser, UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppConstantBuffers, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordConstantStats(ShaderStage::Hull, NumBuffers, ppConstantBuffers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->HS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->HS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
m_pRealContext->HSSetConstantBuffers(StartSlot, NumBuffers, bufs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::HSSetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppConstantBuffers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppConstantBuffers[i]), eFrameRef_Read);
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->HSSetConstantBuffers(StartSlot, NumBuffers, bufs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::HSSetConstantBuffers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_HSSetConstantBuffers(GET_SERIALISER, StartSlot, NumBuffers, ppConstantBuffers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->HS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->HS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_HSSetShaderResources(
SerialiserType &ser, UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumViews);
SERIALISE_ELEMENT_ARRAY(ppShaderResourceViews, NumViews);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordResourceStats(ShaderStage::Hull, NumViews, ppShaderResourceViews);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
m_pRealContext->HSSetShaderResources(StartSlot, NumViews, SRVs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::HSSetShaderResources(
UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
{
if(ppShaderResourceViews[i] && IsActiveCapturing(m_State))
{
MarkResourceReferenced(GetIDForResource(ppShaderResourceViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppShaderResourceViews[i]), eFrameRef_Read);
}
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->HSSetShaderResources(StartSlot, NumViews, SRVs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::HSSetShaderResources);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_HSSetShaderResources(GET_SERIALISER, StartSlot, NumViews, ppShaderResourceViews);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_HSSetSamplers(SerialiserType &ser, UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumSamplers);
SERIALISE_ELEMENT_ARRAY(ppSamplers, NumSamplers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordSamplerStats(ShaderStage::Hull, NumSamplers, ppSamplers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.Samplers, ppSamplers,
StartSlot, NumSamplers);
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
m_pRealContext->HSSetSamplers(StartSlot, NumSamplers, samps);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::HSSetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
{
if(ppSamplers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppSamplers[i]), eFrameRef_Read);
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->HSSetSamplers(StartSlot, NumSamplers, samps));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::HSSetSamplers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_HSSetSamplers(GET_SERIALISER, StartSlot, NumSamplers, ppSamplers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.Samplers, ppSamplers, StartSlot,
NumSamplers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_HSSetShader(SerialiserType &ser, ID3D11HullShader *pShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
SERIALISE_ELEMENT(pShader);
SERIALISE_ELEMENT_ARRAY(ppClassInstances, NumClassInstances);
SERIALISE_ELEMENT(NumClassInstances);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordShaderStats(ShaderStage::Hull, m_CurrentPipelineState->HS.Object, pShader);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.Instances, ppClassInstances, 0,
NumClassInstances);
m_CurrentPipelineState->Change(m_CurrentPipelineState->HS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.Object,
(ID3D11DeviceChild *)pShader);
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
m_pRealContext->HSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11HullShader>, pShader), insts,
NumClassInstances);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::HSSetShader(ID3D11HullShader *pHullShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
if(ppClassInstances && NumClassInstances > 0)
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
SERIALISE_TIME_CALL(m_pRealContext->HSSetShader(
UNWRAP(WrappedID3D11Shader<ID3D11HullShader>, pHullShader), insts, NumClassInstances));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::HSSetShader);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_HSSetShader(GET_SERIALISER, pHullShader, ppClassInstances, NumClassInstances);
MarkResourceReferenced(GetIDForResource(pHullShader), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.Object,
(ID3D11DeviceChild *)pHullShader);
m_CurrentPipelineState->Change(m_CurrentPipelineState->HS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.Instances, ppClassInstances, 0,
NumClassInstances);
VerifyState();
}
#pragma endregion Hull Shader
#pragma region Domain Shader
void WrappedID3D11DeviceContext::DSGetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer **ppConstantBuffers)
{
if(ppConstantBuffers)
{
ID3D11Buffer *real[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
m_pRealContext->DSGetConstantBuffers(StartSlot, NumBuffers, real);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppConstantBuffers[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppConstantBuffers[i]);
RDCASSERT(ppConstantBuffers[i] == m_CurrentPipelineState->DS.ConstantBuffers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::DSGetShaderResources(UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
if(ppShaderResourceViews)
{
ID3D11ShaderResourceView *real[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {0};
m_pRealContext->DSGetShaderResources(StartSlot, NumViews, real);
for(UINT i = 0; i < NumViews; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppShaderResourceViews[i] =
(ID3D11ShaderResourceView *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppShaderResourceViews[i]);
RDCASSERT(ppShaderResourceViews[i] == m_CurrentPipelineState->DS.SRVs[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::DSGetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState **ppSamplers)
{
if(ppSamplers)
{
ID3D11SamplerState *real[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {0};
m_pRealContext->DSGetSamplers(StartSlot, NumSamplers, real);
for(UINT i = 0; i < NumSamplers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppSamplers[i] = (ID3D11SamplerState *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppSamplers[i]);
RDCASSERT(ppSamplers[i] == m_CurrentPipelineState->DS.Samplers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::DSGetShader(ID3D11DomainShader **ppDomainShader,
ID3D11ClassInstance **ppClassInstances,
UINT *pNumClassInstances)
{
if(ppDomainShader == NULL && ppClassInstances == NULL && pNumClassInstances == NULL)
return;
ID3D11ClassInstance *realInsts[D3D11_SHADER_MAX_INTERFACES] = {0};
UINT numInsts = 0;
ID3D11DomainShader *realShader = NULL;
m_pRealContext->DSGetShader(&realShader, realInsts, &numInsts);
SAFE_RELEASE_NOCLEAR(realShader);
for(UINT i = 0; i < numInsts; i++)
SAFE_RELEASE_NOCLEAR(realInsts[i]);
if(ppDomainShader)
{
*ppDomainShader = (ID3D11DomainShader *)m_pDevice->GetResourceManager()->GetWrapper(realShader);
SAFE_ADDREF(*ppDomainShader);
RDCASSERT(*ppDomainShader == m_CurrentPipelineState->DS.Object);
}
if(ppClassInstances)
{
for(UINT i = 0; i < numInsts; i++)
{
ppClassInstances[i] =
(ID3D11ClassInstance *)m_pDevice->GetResourceManager()->GetWrapper(realInsts[i]);
SAFE_ADDREF(ppClassInstances[i]);
RDCASSERT(ppClassInstances[i] == m_CurrentPipelineState->DS.Instances[i]);
}
}
if(pNumClassInstances)
{
*pNumClassInstances = numInsts;
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DSSetConstantBuffers(SerialiserType &ser, UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppConstantBuffers, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordConstantStats(ShaderStage::Domain, NumBuffers, ppConstantBuffers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->DS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->DS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
m_pRealContext->DSSetConstantBuffers(StartSlot, NumBuffers, bufs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::DSSetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppConstantBuffers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppConstantBuffers[i]), eFrameRef_Read);
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->DSSetConstantBuffers(StartSlot, NumBuffers, bufs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DSSetConstantBuffers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DSSetConstantBuffers(GET_SERIALISER, StartSlot, NumBuffers, ppConstantBuffers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->DS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->DS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DSSetShaderResources(
SerialiserType &ser, UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumViews);
SERIALISE_ELEMENT_ARRAY(ppShaderResourceViews, NumViews);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordResourceStats(ShaderStage::Domain, NumViews, ppShaderResourceViews);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
m_pRealContext->DSSetShaderResources(StartSlot, NumViews, SRVs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::DSSetShaderResources(
UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
{
if(ppShaderResourceViews[i] && IsActiveCapturing(m_State))
{
MarkResourceReferenced(GetIDForResource(ppShaderResourceViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppShaderResourceViews[i]), eFrameRef_Read);
}
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->DSSetShaderResources(StartSlot, NumViews, SRVs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DSSetShaderResources);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DSSetShaderResources(GET_SERIALISER, StartSlot, NumViews, ppShaderResourceViews);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DSSetSamplers(SerialiserType &ser, UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumSamplers);
SERIALISE_ELEMENT_ARRAY(ppSamplers, NumSamplers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordSamplerStats(ShaderStage::Domain, NumSamplers, ppSamplers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.Samplers, ppSamplers,
StartSlot, NumSamplers);
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
m_pRealContext->DSSetSamplers(StartSlot, NumSamplers, samps);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::DSSetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
{
if(ppSamplers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppSamplers[i]), eFrameRef_Read);
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->DSSetSamplers(StartSlot, NumSamplers, samps));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DSSetSamplers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DSSetSamplers(GET_SERIALISER, StartSlot, NumSamplers, ppSamplers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.Samplers, ppSamplers, StartSlot,
NumSamplers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DSSetShader(SerialiserType &ser,
ID3D11DomainShader *pShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
SERIALISE_ELEMENT(pShader);
SERIALISE_ELEMENT_ARRAY(ppClassInstances, NumClassInstances);
SERIALISE_ELEMENT(NumClassInstances);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordShaderStats(ShaderStage::Domain, m_CurrentPipelineState->DS.Object, pShader);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.Instances, ppClassInstances, 0,
NumClassInstances);
m_CurrentPipelineState->Change(m_CurrentPipelineState->DS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.Object,
(ID3D11DeviceChild *)pShader);
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
m_pRealContext->DSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11DomainShader>, pShader), insts,
NumClassInstances);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::DSSetShader(ID3D11DomainShader *pDomainShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
if(ppClassInstances && NumClassInstances > 0)
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
SERIALISE_TIME_CALL(m_pRealContext->DSSetShader(
UNWRAP(WrappedID3D11Shader<ID3D11DomainShader>, pDomainShader), insts, NumClassInstances));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DSSetShader);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DSSetShader(GET_SERIALISER, pDomainShader, ppClassInstances, NumClassInstances);
MarkResourceReferenced(GetIDForResource(pDomainShader), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.Object,
(ID3D11DeviceChild *)pDomainShader);
m_CurrentPipelineState->Change(m_CurrentPipelineState->DS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.Instances, ppClassInstances, 0,
NumClassInstances);
VerifyState();
}
#pragma endregion Domain Shader
#pragma region Geometry Shader
void WrappedID3D11DeviceContext::GSGetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer **ppConstantBuffers)
{
if(ppConstantBuffers)
{
ID3D11Buffer *real[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
m_pRealContext->GSGetConstantBuffers(StartSlot, NumBuffers, real);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppConstantBuffers[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppConstantBuffers[i]);
RDCASSERT(ppConstantBuffers[i] == m_CurrentPipelineState->GS.ConstantBuffers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::GSGetShaderResources(UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
if(ppShaderResourceViews)
{
ID3D11ShaderResourceView *real[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {0};
m_pRealContext->GSGetShaderResources(StartSlot, NumViews, real);
for(UINT i = 0; i < NumViews; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppShaderResourceViews[i] =
(ID3D11ShaderResourceView *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppShaderResourceViews[i]);
RDCASSERT(ppShaderResourceViews[i] == m_CurrentPipelineState->GS.SRVs[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::GSGetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState **ppSamplers)
{
if(ppSamplers)
{
ID3D11SamplerState *real[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {0};
m_pRealContext->GSGetSamplers(StartSlot, NumSamplers, real);
for(UINT i = 0; i < NumSamplers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppSamplers[i] = (ID3D11SamplerState *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppSamplers[i]);
RDCASSERT(ppSamplers[i] == m_CurrentPipelineState->GS.Samplers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::GSGetShader(ID3D11GeometryShader **ppGeometryShader,
ID3D11ClassInstance **ppClassInstances,
UINT *pNumClassInstances)
{
if(ppGeometryShader == NULL && ppClassInstances == NULL && pNumClassInstances == NULL)
return;
ID3D11ClassInstance *realInsts[D3D11_SHADER_MAX_INTERFACES] = {0};
UINT numInsts = 0;
ID3D11GeometryShader *realShader = NULL;
m_pRealContext->GSGetShader(&realShader, realInsts, &numInsts);
SAFE_RELEASE_NOCLEAR(realShader);
for(UINT i = 0; i < numInsts; i++)
SAFE_RELEASE_NOCLEAR(realInsts[i]);
if(ppGeometryShader)
{
*ppGeometryShader =
(ID3D11GeometryShader *)m_pDevice->GetResourceManager()->GetWrapper(realShader);
SAFE_ADDREF(*ppGeometryShader);
RDCASSERT(*ppGeometryShader == m_CurrentPipelineState->GS.Object);
}
if(ppClassInstances)
{
for(UINT i = 0; i < numInsts; i++)
{
ppClassInstances[i] =
(ID3D11ClassInstance *)m_pDevice->GetResourceManager()->GetWrapper(realInsts[i]);
SAFE_ADDREF(ppClassInstances[i]);
RDCASSERT(ppClassInstances[i] == m_CurrentPipelineState->GS.Instances[i]);
}
}
if(pNumClassInstances)
{
*pNumClassInstances = numInsts;
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_GSSetConstantBuffers(SerialiserType &ser, UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppConstantBuffers, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordConstantStats(ShaderStage::Geometry, NumBuffers, ppConstantBuffers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->GS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->GS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
m_pRealContext->GSSetConstantBuffers(StartSlot, NumBuffers, bufs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::GSSetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppConstantBuffers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppConstantBuffers[i]), eFrameRef_Read);
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->GSSetConstantBuffers(StartSlot, NumBuffers, bufs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::GSSetConstantBuffers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_GSSetConstantBuffers(GET_SERIALISER, StartSlot, NumBuffers, ppConstantBuffers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->GS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->GS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_GSSetShaderResources(
SerialiserType &ser, UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumViews);
SERIALISE_ELEMENT_ARRAY(ppShaderResourceViews, NumViews);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordResourceStats(ShaderStage::Geometry, NumViews, ppShaderResourceViews);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
m_pRealContext->GSSetShaderResources(StartSlot, NumViews, SRVs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::GSSetShaderResources(
UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
{
if(ppShaderResourceViews[i] && IsActiveCapturing(m_State))
{
MarkResourceReferenced(GetIDForResource(ppShaderResourceViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppShaderResourceViews[i]), eFrameRef_Read);
}
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->GSSetShaderResources(StartSlot, NumViews, SRVs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::GSSetShaderResources);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_GSSetShaderResources(GET_SERIALISER, StartSlot, NumViews, ppShaderResourceViews);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_GSSetSamplers(SerialiserType &ser, UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumSamplers);
SERIALISE_ELEMENT_ARRAY(ppSamplers, NumSamplers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordSamplerStats(ShaderStage::Geometry, NumSamplers, ppSamplers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.Samplers, ppSamplers,
StartSlot, NumSamplers);
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
m_pRealContext->GSSetSamplers(StartSlot, NumSamplers, samps);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::GSSetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
{
if(ppSamplers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppSamplers[i]), eFrameRef_Read);
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->GSSetSamplers(StartSlot, NumSamplers, samps));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::GSSetSamplers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_GSSetSamplers(GET_SERIALISER, StartSlot, NumSamplers, ppSamplers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.Samplers, ppSamplers, StartSlot,
NumSamplers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_GSSetShader(SerialiserType &ser,
ID3D11GeometryShader *pShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
SERIALISE_ELEMENT(pShader);
SERIALISE_ELEMENT_ARRAY(ppClassInstances, NumClassInstances);
SERIALISE_ELEMENT(NumClassInstances);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordShaderStats(ShaderStage::Geometry, m_CurrentPipelineState->GS.Object, pShader);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.Instances, ppClassInstances, 0,
NumClassInstances);
m_CurrentPipelineState->Change(m_CurrentPipelineState->GS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.Object,
(ID3D11DeviceChild *)pShader);
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
m_pRealContext->GSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11GeometryShader>, pShader), insts,
NumClassInstances);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::GSSetShader(ID3D11GeometryShader *pShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
if(ppClassInstances && NumClassInstances > 0)
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
SERIALISE_TIME_CALL(m_pRealContext->GSSetShader(
UNWRAP(WrappedID3D11Shader<ID3D11GeometryShader>, pShader), insts, NumClassInstances));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::GSSetShader);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_GSSetShader(GET_SERIALISER, pShader, ppClassInstances, NumClassInstances);
MarkResourceReferenced(GetIDForResource(pShader), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.Object,
(ID3D11DeviceChild *)pShader);
m_CurrentPipelineState->Change(m_CurrentPipelineState->GS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.Instances, ppClassInstances, 0,
NumClassInstances);
VerifyState();
}
#pragma endregion Geometry Shader
#pragma region Stream Out
void WrappedID3D11DeviceContext::SOGetTargets(UINT NumBuffers, ID3D11Buffer **ppSOTargets)
{
if(ppSOTargets)
{
ID3D11Buffer *real[D3D11_SO_BUFFER_SLOT_COUNT] = {0};
m_pRealContext->SOGetTargets(NumBuffers, real);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppSOTargets[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppSOTargets[i]);
RDCASSERT(ppSOTargets[i] == m_CurrentPipelineState->SO.Buffers[i]);
}
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_SOSetTargets(SerialiserType &ser, UINT NumBuffers,
ID3D11Buffer *const *ppSOTargets,
const UINT *pOffsets)
{
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppSOTargets, NumBuffers);
SERIALISE_ELEMENT_ARRAY(pOffsets, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// "If less than four [buffers] are defined by the call, the remaining buffer slots are set to
// NULL."
ID3D11Buffer *setbufs[D3D11_SO_STREAM_COUNT] = {0};
UINT setoffs[D3D11_SO_STREAM_COUNT] = {0};
for(UINT b = 0; b < NumBuffers; b++)
{
setbufs[b] = ppSOTargets ? ppSOTargets[b] : NULL;
// passing NULL for pOffsets seems to act like -1 => append
setoffs[b] = pOffsets ? pOffsets[b] : ~0U;
}
// end stream-out queries for outgoing targets
for(UINT b = 0; b < D3D11_SO_STREAM_COUNT; b++)
{
ID3D11Buffer *buf = m_CurrentPipelineState->SO.Buffers[b];
if(buf)
{
ResourceId id = GetIDForResource(buf);
m_pRealContext->End(m_StreamOutCounters[id].query);
m_StreamOutCounters[id].running = false;
}
}
// start new queries for incoming targets
for(UINT b = 0; b < D3D11_SO_STREAM_COUNT; b++)
{
ID3D11Buffer *buf = setbufs[b];
if(buf)
{
ResourceId id = GetIDForResource(buf);
// release any previous query as the hidden counter is overwritten
SAFE_RELEASE(m_StreamOutCounters[id].query);
D3D11_QUERY queryTypes[] = {
D3D11_QUERY_SO_STATISTICS_STREAM0, D3D11_QUERY_SO_STATISTICS_STREAM1,
D3D11_QUERY_SO_STATISTICS_STREAM2, D3D11_QUERY_SO_STATISTICS_STREAM3,
};
D3D11_QUERY_DESC qdesc;
qdesc.MiscFlags = 0;
qdesc.Query = queryTypes[b];
m_pDevice->GetReal()->CreateQuery(&qdesc, &m_StreamOutCounters[id].query);
m_pRealContext->Begin(m_StreamOutCounters[id].query);
m_StreamOutCounters[id].running = true;
}
}
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->SO.Buffers, setbufs, 0,
D3D11_SO_STREAM_COUNT);
m_CurrentPipelineState->Change(m_CurrentPipelineState->SO.Offsets, setoffs, 0,
D3D11_SO_STREAM_COUNT);
for(UINT i = 0; i < NumBuffers; i++)
setbufs[i] = UNWRAP(WrappedID3D11Buffer, setbufs[i]);
m_pRealContext->SOSetTargets(NumBuffers, setbufs, setoffs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::SOSetTargets(UINT NumBuffers, ID3D11Buffer *const *ppSOTargets,
const UINT *pOffsets)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppSOTargets && ppSOTargets[i])
{
// technically this isn't dirty until the draw call, but let's be conservative
// to avoid having to track "possibly" dirty resources.
// Besides, it's unlikely an application will set an output then not draw to it
if(IsActiveCapturing(m_State))
{
MarkResourceReferenced(GetIDForResource(ppSOTargets[i]), eFrameRef_Write);
m_MissingTracks.insert(GetIDForResource(ppSOTargets[i]));
}
else if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetIDForResource(ppSOTargets[i]));
}
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppSOTargets[i]);
}
}
SERIALISE_TIME_CALL(m_pRealContext->SOSetTargets(NumBuffers, bufs, pOffsets));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::SOSetTargets);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_SOSetTargets(GET_SERIALISER, NumBuffers, ppSOTargets, pOffsets);
m_ContextRecord->AddChunk(scope.Get());
}
// "If less than four [buffers] are defined by the call, the remaining buffer slots are set to
// NULL."
ID3D11Buffer *setbufs[D3D11_SO_STREAM_COUNT] = {0};
UINT setoffs[D3D11_SO_STREAM_COUNT] = {0};
for(UINT b = 0; b < NumBuffers; b++)
{
setbufs[b] = ppSOTargets ? ppSOTargets[b] : NULL;
// passing NULL for pOffsets seems to act like -1 => append
setoffs[b] = pOffsets ? pOffsets[b] : ~0U;
}
// end stream-out queries for outgoing targets
for(UINT b = 0; b < D3D11_SO_STREAM_COUNT; b++)
{
ID3D11Buffer *buf = m_CurrentPipelineState->SO.Buffers[b];
if(buf)
{
ResourceId id = GetIDForResource(buf);
m_pRealContext->End(m_StreamOutCounters[id].query);
m_StreamOutCounters[id].running = false;
}
}
// start new queries for incoming targets
for(UINT b = 0; b < D3D11_SO_STREAM_COUNT; b++)
{
ID3D11Buffer *buf = setbufs[b];
if(buf)
{
ResourceId id = GetIDForResource(buf);
// release any previous query as the hidden counter is overwritten
SAFE_RELEASE(m_StreamOutCounters[id].query);
D3D11_QUERY queryTypes[] = {
D3D11_QUERY_SO_STATISTICS_STREAM0, D3D11_QUERY_SO_STATISTICS_STREAM1,
D3D11_QUERY_SO_STATISTICS_STREAM2, D3D11_QUERY_SO_STATISTICS_STREAM3,
};
D3D11_QUERY_DESC qdesc;
qdesc.MiscFlags = 0;
qdesc.Query = queryTypes[b];
m_pDevice->GetReal()->CreateQuery(&qdesc, &m_StreamOutCounters[id].query);
m_pRealContext->Begin(m_StreamOutCounters[id].query);
m_StreamOutCounters[id].running = true;
}
}
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->SO.Buffers, setbufs, 0,
D3D11_SO_STREAM_COUNT);
m_CurrentPipelineState->Change(m_CurrentPipelineState->SO.Offsets, setoffs, 0,
D3D11_SO_STREAM_COUNT);
VerifyState();
}
#pragma endregion Stream Out
#pragma region Rasterizer
void WrappedID3D11DeviceContext::RSGetViewports(UINT *pNumViewports, D3D11_VIEWPORT *pViewports)
{
m_pRealContext->RSGetViewports(pNumViewports, pViewports);
if(pViewports)
RDCASSERT(memcmp(pViewports, m_CurrentPipelineState->RS.Viewports,
sizeof(D3D11_VIEWPORT) * (*pNumViewports)) == 0);
}
void WrappedID3D11DeviceContext::RSGetScissorRects(UINT *pNumRects, D3D11_RECT *pRects)
{
m_pRealContext->RSGetScissorRects(pNumRects, pRects);
if(pRects)
RDCASSERT(memcmp(pRects, m_CurrentPipelineState->RS.Scissors,
sizeof(D3D11_RECT) * (*pNumRects)) == 0);
}
void WrappedID3D11DeviceContext::RSGetState(ID3D11RasterizerState **ppRasterizerState)
{
if(ppRasterizerState)
{
ID3D11RasterizerState *real = NULL;
m_pRealContext->RSGetState(&real);
if(real != NULL)
{
real->Release();
ID3D11DeviceChild *state = m_pDevice->GetResourceManager()->GetWrapper(real);
*ppRasterizerState = (ID3D11RasterizerState *)state;
(*ppRasterizerState)->AddRef();
}
else
{
*ppRasterizerState = NULL;
}
RDCASSERT(*ppRasterizerState == m_CurrentPipelineState->RS.State);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_RSSetViewports(SerialiserType &ser, UINT NumViewports,
const D3D11_VIEWPORT *pViewports)
{
SERIALISE_ELEMENT(NumViewports);
SERIALISE_ELEMENT_ARRAY(pViewports, NumViewports);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordViewportStats(NumViewports, pViewports);
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.Viewports, pViewports, 0, NumViewports);
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.NumViews, NumViewports);
m_pRealContext->RSSetViewports(NumViewports, pViewports);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::RSSetViewports(UINT NumViewports, const D3D11_VIEWPORT *pViewports)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->RSSetViewports(NumViewports, pViewports));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::RSSetViewports);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_RSSetViewports(GET_SERIALISER, NumViewports, pViewports);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.Viewports, pViewports, 0, NumViewports);
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.NumViews, NumViewports);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_RSSetScissorRects(SerialiserType &ser, UINT NumRects,
const D3D11_RECT *pRects)
{
SERIALISE_ELEMENT(NumRects);
SERIALISE_ELEMENT_ARRAY(pRects, NumRects);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordScissorStats(NumRects, pRects);
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.Scissors, pRects, 0, NumRects);
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.NumScissors, NumRects);
m_pRealContext->RSSetScissorRects(NumRects, pRects);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::RSSetScissorRects(UINT NumRects, const D3D11_RECT *pRects)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->RSSetScissorRects(NumRects, pRects));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::RSSetScissorRects);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_RSSetScissorRects(GET_SERIALISER, NumRects, pRects);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.Scissors, pRects, 0, NumRects);
m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.NumScissors, NumRects);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_RSSetState(SerialiserType &ser,
ID3D11RasterizerState *pRasterizerState)
{
SERIALISE_ELEMENT(pRasterizerState);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordRasterizationStats(pRasterizerState);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->RS.State, pRasterizerState);
m_pRealContext->RSSetState(UNWRAP(WrappedID3D11RasterizerState2, pRasterizerState));
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::RSSetState(ID3D11RasterizerState *pRasterizerState)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->RSSetState(
(ID3D11RasterizerState *)UNWRAP(WrappedID3D11RasterizerState2, pRasterizerState)));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::RSSetState);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_RSSetState(GET_SERIALISER, pRasterizerState);
MarkResourceReferenced(GetIDForResource(pRasterizerState), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->RS.State, pRasterizerState);
VerifyState();
}
#pragma endregion Rasterizer
#pragma region Pixel Shader
void WrappedID3D11DeviceContext::PSGetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer **ppConstantBuffers)
{
if(ppConstantBuffers)
{
ID3D11Buffer *real[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
m_pRealContext->PSGetConstantBuffers(StartSlot, NumBuffers, real);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppConstantBuffers[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppConstantBuffers[i]);
RDCASSERT(ppConstantBuffers[i] == m_CurrentPipelineState->PS.ConstantBuffers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::PSGetShaderResources(UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
if(ppShaderResourceViews)
{
ID3D11ShaderResourceView *real[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {0};
m_pRealContext->PSGetShaderResources(StartSlot, NumViews, real);
for(UINT i = 0; i < NumViews; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppShaderResourceViews[i] =
(ID3D11ShaderResourceView *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppShaderResourceViews[i]);
RDCASSERT(ppShaderResourceViews[i] == m_CurrentPipelineState->PS.SRVs[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::PSGetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState **ppSamplers)
{
if(ppSamplers)
{
ID3D11SamplerState *real[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {0};
m_pRealContext->PSGetSamplers(StartSlot, NumSamplers, real);
for(UINT i = 0; i < NumSamplers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppSamplers[i] = (ID3D11SamplerState *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppSamplers[i]);
RDCASSERT(ppSamplers[i] == m_CurrentPipelineState->PS.Samplers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::PSGetShader(ID3D11PixelShader **ppPixelShader,
ID3D11ClassInstance **ppClassInstances,
UINT *pNumClassInstances)
{
if(ppPixelShader == NULL && ppClassInstances == NULL && pNumClassInstances == NULL)
return;
ID3D11ClassInstance *realInsts[D3D11_SHADER_MAX_INTERFACES] = {0};
UINT numInsts = 0;
ID3D11PixelShader *realShader = NULL;
m_pRealContext->PSGetShader(&realShader, realInsts, &numInsts);
SAFE_RELEASE_NOCLEAR(realShader);
for(UINT i = 0; i < numInsts; i++)
SAFE_RELEASE_NOCLEAR(realInsts[i]);
if(ppPixelShader)
{
*ppPixelShader = (ID3D11PixelShader *)m_pDevice->GetResourceManager()->GetWrapper(realShader);
SAFE_ADDREF(*ppPixelShader);
RDCASSERT(*ppPixelShader == m_CurrentPipelineState->PS.Object);
}
if(ppClassInstances)
{
for(UINT i = 0; i < numInsts; i++)
{
ppClassInstances[i] =
(ID3D11ClassInstance *)m_pDevice->GetResourceManager()->GetWrapper(realInsts[i]);
SAFE_ADDREF(ppClassInstances[i]);
RDCASSERT(ppClassInstances[i] == m_CurrentPipelineState->PS.Instances[i]);
}
}
if(pNumClassInstances)
{
*pNumClassInstances = numInsts;
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PSSetConstantBuffers(SerialiserType &ser, UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppConstantBuffers, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordConstantStats(ShaderStage::Pixel, NumBuffers, ppConstantBuffers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
m_pRealContext->PSSetConstantBuffers(StartSlot, NumBuffers, bufs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::PSSetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppConstantBuffers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppConstantBuffers[i]), eFrameRef_Read);
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->PSSetConstantBuffers(StartSlot, NumBuffers, bufs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PSSetConstantBuffers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PSSetConstantBuffers(GET_SERIALISER, StartSlot, NumBuffers, ppConstantBuffers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PSSetShaderResources(
SerialiserType &ser, UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumViews);
SERIALISE_ELEMENT_ARRAY(ppShaderResourceViews, NumViews);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordResourceStats(ShaderStage::Pixel, NumViews, ppShaderResourceViews);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
m_pRealContext->PSSetShaderResources(StartSlot, NumViews, SRVs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::PSSetShaderResources(
UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
{
if(ppShaderResourceViews[i] && IsActiveCapturing(m_State))
{
MarkResourceReferenced(GetIDForResource(ppShaderResourceViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppShaderResourceViews[i]), eFrameRef_Read);
}
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->PSSetShaderResources(StartSlot, NumViews, SRVs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PSSetShaderResources);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PSSetShaderResources(GET_SERIALISER, StartSlot, NumViews, ppShaderResourceViews);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PSSetSamplers(SerialiserType &ser, UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumSamplers);
SERIALISE_ELEMENT_ARRAY(ppSamplers, NumSamplers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordSamplerStats(ShaderStage::Pixel, NumSamplers, ppSamplers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.Samplers, ppSamplers,
StartSlot, NumSamplers);
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
m_pRealContext->PSSetSamplers(StartSlot, NumSamplers, samps);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::PSSetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
{
if(ppSamplers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppSamplers[i]), eFrameRef_Read);
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->PSSetSamplers(StartSlot, NumSamplers, samps));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PSSetSamplers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PSSetSamplers(GET_SERIALISER, StartSlot, NumSamplers, ppSamplers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.Samplers, ppSamplers, StartSlot,
NumSamplers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PSSetShader(SerialiserType &ser,
ID3D11PixelShader *pShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
SERIALISE_ELEMENT(pShader);
SERIALISE_ELEMENT_ARRAY(ppClassInstances, NumClassInstances);
SERIALISE_ELEMENT(NumClassInstances);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordShaderStats(ShaderStage::Pixel, m_CurrentPipelineState->PS.Object, pShader);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.Instances, ppClassInstances, 0,
NumClassInstances);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.Object,
(ID3D11DeviceChild *)pShader);
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
m_pRealContext->PSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11PixelShader>, pShader), insts,
NumClassInstances);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::PSSetShader(ID3D11PixelShader *pPixelShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
if(ppClassInstances && NumClassInstances > 0)
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
SERIALISE_TIME_CALL(m_pRealContext->PSSetShader(
UNWRAP(WrappedID3D11Shader<ID3D11PixelShader>, pPixelShader), insts, NumClassInstances));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PSSetShader);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PSSetShader(GET_SERIALISER, pPixelShader, ppClassInstances, NumClassInstances);
MarkResourceReferenced(GetIDForResource(pPixelShader), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.Object,
(ID3D11DeviceChild *)pPixelShader);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.Instances, ppClassInstances, 0,
NumClassInstances);
VerifyState();
}
#pragma endregion Pixel Shader
#pragma region Output Merger
void WrappedID3D11DeviceContext::OMGetRenderTargets(UINT NumViews,
ID3D11RenderTargetView **ppRenderTargetViews,
ID3D11DepthStencilView **ppDepthStencilView)
{
if(ppRenderTargetViews == NULL && ppDepthStencilView == NULL)
return;
ID3D11RenderTargetView *rtv[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
ID3D11DepthStencilView *dsv = NULL;
m_pRealContext->OMGetRenderTargets(NumViews, rtv, &dsv);
for(UINT i = 0; i < NumViews; i++)
SAFE_RELEASE_NOCLEAR(rtv[i]);
SAFE_RELEASE_NOCLEAR(dsv);
if(ppRenderTargetViews)
{
for(UINT i = 0; i < NumViews; i++)
{
ppRenderTargetViews[i] =
(ID3D11RenderTargetView *)m_pDevice->GetResourceManager()->GetWrapper(rtv[i]);
SAFE_ADDREF(ppRenderTargetViews[i]);
RDCASSERT(ppRenderTargetViews[i] == m_CurrentPipelineState->OM.RenderTargets[i]);
}
}
if(ppDepthStencilView)
{
*ppDepthStencilView = (ID3D11DepthStencilView *)m_pDevice->GetResourceManager()->GetWrapper(dsv);
SAFE_ADDREF(*ppDepthStencilView);
RDCASSERT(*ppDepthStencilView == m_CurrentPipelineState->OM.DepthView);
}
}
void WrappedID3D11DeviceContext::OMGetRenderTargetsAndUnorderedAccessViews(
UINT NumRTVs, ID3D11RenderTargetView **ppRenderTargetViews,
ID3D11DepthStencilView **ppDepthStencilView, UINT UAVStartSlot, UINT NumUAVs,
ID3D11UnorderedAccessView **ppUnorderedAccessViews)
{
if(ppRenderTargetViews == NULL && ppDepthStencilView == NULL && ppUnorderedAccessViews == NULL)
return;
ID3D11RenderTargetView *rtv[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
ID3D11UnorderedAccessView *uav[D3D11_1_UAV_SLOT_COUNT] = {0};
ID3D11DepthStencilView *dsv = NULL;
m_pRealContext->OMGetRenderTargetsAndUnorderedAccessViews(NumRTVs, rtv, &dsv, UAVStartSlot,
NumUAVs, uav);
for(UINT i = 0; i < NumRTVs; i++)
SAFE_RELEASE_NOCLEAR(rtv[i]);
SAFE_RELEASE_NOCLEAR(dsv);
for(UINT i = 0; i < NumUAVs; i++)
SAFE_RELEASE_NOCLEAR(uav[i]);
if(ppRenderTargetViews)
{
for(UINT i = 0; i < NumRTVs; i++)
{
ppRenderTargetViews[i] =
(ID3D11RenderTargetView *)m_pDevice->GetResourceManager()->GetWrapper(rtv[i]);
SAFE_ADDREF(ppRenderTargetViews[i]);
RDCASSERT(ppRenderTargetViews[i] == m_CurrentPipelineState->OM.RenderTargets[i]);
}
}
if(ppDepthStencilView)
{
*ppDepthStencilView = (ID3D11DepthStencilView *)m_pDevice->GetResourceManager()->GetWrapper(dsv);
SAFE_ADDREF(*ppDepthStencilView);
RDCASSERT(*ppDepthStencilView == m_CurrentPipelineState->OM.DepthView);
}
if(ppUnorderedAccessViews)
{
for(UINT i = 0; i < NumUAVs; i++)
{
ppUnorderedAccessViews[i] =
(ID3D11UnorderedAccessView *)m_pDevice->GetResourceManager()->GetWrapper(uav[i]);
SAFE_ADDREF(ppUnorderedAccessViews[i]);
RDCASSERT(ppUnorderedAccessViews[i] == m_CurrentPipelineState->OM.UAVs[i]);
}
}
}
void WrappedID3D11DeviceContext::OMGetBlendState(ID3D11BlendState **ppBlendState,
FLOAT BlendFactor[4], UINT *pSampleMask)
{
ID3D11BlendState *real = NULL;
m_pRealContext->OMGetBlendState(&real, BlendFactor, pSampleMask);
SAFE_RELEASE_NOCLEAR(real);
if(ppBlendState)
{
if(real != NULL)
{
ID3D11DeviceChild *state = m_pDevice->GetResourceManager()->GetWrapper(real);
*ppBlendState = (ID3D11BlendState *)state;
(*ppBlendState)->AddRef();
}
else
{
*ppBlendState = NULL;
}
RDCASSERT(*ppBlendState == m_CurrentPipelineState->OM.BlendState);
}
if(BlendFactor)
RDCASSERT(memcmp(BlendFactor, m_CurrentPipelineState->OM.BlendFactor, sizeof(float) * 4) == 0);
if(pSampleMask)
RDCASSERT(*pSampleMask == m_CurrentPipelineState->OM.SampleMask);
}
void WrappedID3D11DeviceContext::OMGetDepthStencilState(ID3D11DepthStencilState **ppDepthStencilState,
UINT *pStencilRef)
{
ID3D11DepthStencilState *real = NULL;
m_pRealContext->OMGetDepthStencilState(&real, pStencilRef);
SAFE_RELEASE_NOCLEAR(real);
if(ppDepthStencilState)
{
if(real != NULL)
{
*ppDepthStencilState =
(ID3D11DepthStencilState *)m_pDevice->GetResourceManager()->GetWrapper(real);
SAFE_ADDREF(*ppDepthStencilState);
}
else
{
*ppDepthStencilState = NULL;
}
RDCASSERT(*ppDepthStencilState == m_CurrentPipelineState->OM.DepthStencilState);
}
if(pStencilRef)
RDCASSERT(*pStencilRef == m_CurrentPipelineState->OM.StencRef);
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_OMSetRenderTargets(
SerialiserType &ser, UINT NumViews, ID3D11RenderTargetView *const *ppRenderTargetViews,
ID3D11DepthStencilView *pDepthStencilView)
{
SERIALISE_ELEMENT(NumViews);
SERIALISE_ELEMENT_ARRAY(ppRenderTargetViews, NumViews);
SERIALISE_ELEMENT(pDepthStencilView);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
ID3D11RenderTargetView *RTs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
for(UINT i = 0; i < NumViews; i++)
RTs[i] = ppRenderTargetViews[i];
if(m_CurrentPipelineState->ValidOutputMerger(ppRenderTargetViews, NumViews, pDepthStencilView,
NULL, 0))
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets, RTs, 0,
D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.DepthView, pDepthStencilView);
}
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT] = {0};
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs, UAVs, 0,
D3D11_1_UAV_SLOT_COUNT);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, NumViews);
for(UINT i = 0; i < NumViews; i++)
RTs[i] = UNWRAP(WrappedID3D11RenderTargetView1, RTs[i]);
if(IsLoading(m_State))
RecordOutputMergerStats(NumViews, RTs, pDepthStencilView, 0, 0, NULL);
m_pRealContext->OMSetRenderTargets(NumViews, RTs,
UNWRAP(WrappedID3D11DepthStencilView, pDepthStencilView));
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::OMSetRenderTargets(UINT NumViews,
ID3D11RenderTargetView *const *ppRenderTargetViews,
ID3D11DepthStencilView *pDepthStencilView)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11RenderTargetView *RTs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
for(UINT i = 0; i < NumViews && ppRenderTargetViews; i++)
RTs[i] = UNWRAP(WrappedID3D11RenderTargetView1, ppRenderTargetViews[i]);
SERIALISE_TIME_CALL(m_pRealContext->OMSetRenderTargets(
NumViews, RTs, UNWRAP(WrappedID3D11DepthStencilView, pDepthStencilView)));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::OMSetRenderTargets);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_OMSetRenderTargets(GET_SERIALISER, NumViews, ppRenderTargetViews, pDepthStencilView);
m_ContextRecord->AddChunk(scope.Get());
}
for(UINT i = 0; i < NumViews && ppRenderTargetViews; i++)
RTs[i] = ppRenderTargetViews[i];
// this function always sets all render targets
if(m_CurrentPipelineState->ValidOutputMerger(RTs, NumViews, pDepthStencilView, NULL, 0))
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets, RTs, 0,
D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.DepthView, pDepthStencilView);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, NumViews);
}
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT] = {0};
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs, UAVs, 0,
D3D11_1_UAV_SLOT_COUNT);
for(UINT i = 0; i < NumViews; i++)
{
if(ppRenderTargetViews && ppRenderTargetViews[i])
{
if(IsCaptureMode(m_State))
{
// technically this isn't dirty until the draw call, but let's be conservative
// to avoid having to track "possibly" dirty resources.
// Besides, it's unlikely an application will set an output then not draw to it
if(IsBackgroundCapturing(m_State))
MarkDirtyResource(GetViewResourceResID(ppRenderTargetViews[i]));
else if(IsActiveCapturing(m_State))
m_MissingTracks.insert(GetViewResourceResID(ppRenderTargetViews[i]));
}
RTs[i] = UNWRAP(WrappedID3D11RenderTargetView1, ppRenderTargetViews[i]);
}
}
if(pDepthStencilView && IsCaptureMode(m_State))
{
if(IsBackgroundCapturing(m_State))
MarkDirtyResource(GetViewResourceResID(pDepthStencilView));
else if(IsActiveCapturing(m_State))
m_MissingTracks.insert(GetViewResourceResID(pDepthStencilView));
}
if(IsActiveCapturing(m_State))
{
// make sure to mark resources referenced even if the OM state is invalid, so they aren't
// eliminated from the capture (which might make this combination valid on replay without some
// of the targets!)
for(UINT i = 0; i < NumViews; i++)
{
if(ppRenderTargetViews && ppRenderTargetViews[i])
{
MarkResourceReferenced(GetIDForResource(ppRenderTargetViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppRenderTargetViews[i]), eFrameRef_Write);
}
}
if(pDepthStencilView)
{
MarkResourceReferenced(GetIDForResource(pDepthStencilView), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(pDepthStencilView), eFrameRef_Write);
}
}
VerifyState();
}
// some helper enums with custom stringise to handle special cases
enum D3D11RTVCount
{
};
DECLARE_REFLECTION_ENUM(D3D11RTVCount);
template <>
std::string DoStringise(const D3D11RTVCount &el)
{
RDCCOMPILE_ASSERT(sizeof(D3D11RTVCount) == sizeof(uint32_t), "Enum isn't uint sized");
if(el == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
return "D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL";
return ToStr(uint32_t(el));
}
enum D3D11UAVCount
{
};
DECLARE_REFLECTION_ENUM(D3D11UAVCount);
template <>
std::string DoStringise(const D3D11UAVCount &el)
{
RDCCOMPILE_ASSERT(sizeof(D3D11UAVCount) == sizeof(uint32_t), "Enum isn't uint sized");
if(el == D3D11_KEEP_UNORDERED_ACCESS_VIEWS)
return "D3D11_KEEP_UNORDERED_ACCESS_VIEWS";
return ToStr(uint32_t(el));
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_OMSetRenderTargetsAndUnorderedAccessViews(
SerialiserType &ser, UINT NumRTVs, ID3D11RenderTargetView *const *ppRenderTargetViews,
ID3D11DepthStencilView *pDepthStencilView, UINT UAVStartSlot, UINT NumUAVs,
ID3D11UnorderedAccessView *const *ppUnorderedAccessViews, const UINT *pUAVInitialCounts)
{
// cast to a special enum so we print the two 'keep' constants nicely
SERIALISE_ELEMENT_TYPED(D3D11RTVCount, NumRTVs);
// handle special values for counts
const bool KeepRTVs = (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL);
const bool ModifyRTVs = !KeepRTVs;
if(!ModifyRTVs)
NumRTVs = 0;
SERIALISE_ELEMENT_ARRAY(ppRenderTargetViews, NumRTVs);
SERIALISE_ELEMENT(pDepthStencilView);
SERIALISE_ELEMENT(UAVStartSlot);
SERIALISE_ELEMENT_TYPED(D3D11UAVCount, NumUAVs);
const bool KeepUAVs = (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS);
const bool ModifyUAVs = !KeepUAVs;
if(!ModifyUAVs)
NumUAVs = 0;
SERIALISE_ELEMENT_ARRAY(ppUnorderedAccessViews, NumUAVs);
SERIALISE_ELEMENT_ARRAY(pUAVInitialCounts, NumUAVs);
RDCASSERT(ModifyRTVs || ModifyUAVs);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// any bind of RTVs or UAVs implicitly NULLs out the remaining slots, so we don't want to just
// change the bindings we were passed, we want to always change ALL bindings, and just set the
// subset that we were passed
ID3D11RenderTargetView *RTs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumRTVs && ModifyRTVs; i++)
RTs[i] = ppRenderTargetViews[i];
for(UINT i = 0; i < NumUAVs && ModifyUAVs; i++)
UAVs[i] = ppUnorderedAccessViews[i];
if(ModifyRTVs)
{
ID3D11UnorderedAccessView *const *srcUAVs = ppUnorderedAccessViews;
UINT srcUAVcount = NumUAVs;
if(!ModifyUAVs)
{
srcUAVs = m_CurrentPipelineState->OM.UAVs;
srcUAVcount = D3D11_1_UAV_SLOT_COUNT;
// if we're not modifying the UAVs but NumRTVs > oldUAVStartSlot then we unbind any
// overlapped UAVs.
if(NumRTVs > m_CurrentPipelineState->OM.UAVStartSlot)
{
UINT diff = NumRTVs - m_CurrentPipelineState->OM.UAVStartSlot;
srcUAVcount -= diff;
srcUAVs += diff;
}
}
if(m_CurrentPipelineState->ValidOutputMerger(ppRenderTargetViews, NumRTVs, pDepthStencilView,
srcUAVs, srcUAVcount))
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets, RTs, 0,
D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.DepthView,
pDepthStencilView);
if(!ModifyUAVs)
{
// set UAVStartSlot to NumRTVs
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, NumRTVs);
if(NumRTVs > m_CurrentPipelineState->OM.UAVStartSlot)
{
UINT diff = NumRTVs - m_CurrentPipelineState->OM.UAVStartSlot;
// release and unbind any UAVs that were unbound
for(UINT i = 0; i < diff; i++)
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs[i],
(ID3D11UnorderedAccessView *)NULL);
// move the array down *without* changing any refs
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
{
if(i < D3D11_1_UAV_SLOT_COUNT - diff)
{
m_CurrentPipelineState->OM.UAVs[i] = m_CurrentPipelineState->OM.UAVs[i + diff];
}
else
{
// NULL without ref'ing, since we just moved this down lower in the array
m_CurrentPipelineState->OM.UAVs[i] = NULL;
}
}
}
}
}
}
if(ModifyUAVs)
{
bool valid = false;
if(ModifyRTVs)
{
valid = m_CurrentPipelineState->ValidOutputMerger(
ppRenderTargetViews, NumRTVs, pDepthStencilView, ppUnorderedAccessViews, NumUAVs);
}
else
{
// if we're not modifying RTVs, any that are < UAVStartSlot get unbound so don't consider
// for validity
valid = m_CurrentPipelineState->ValidOutputMerger(
m_CurrentPipelineState->OM.RenderTargets, UAVStartSlot,
m_CurrentPipelineState->OM.DepthView, ppUnorderedAccessViews, NumUAVs);
}
if(valid)
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs, UAVs, 0,
D3D11_1_UAV_SLOT_COUNT);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, UAVStartSlot);
// unbind any conflicting RTVS
for(UINT i = UAVStartSlot; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets[i],
(ID3D11RenderTargetView *)NULL);
}
}
for(UINT i = 0; i < NumRTVs && ModifyRTVs; i++)
RTs[i] = UNWRAP(WrappedID3D11RenderTargetView1, RTs[i]);
for(UINT i = 0; i < NumUAVs && ModifyUAVs; i++)
UAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView1, UAVs[i]);
if(ModifyRTVs)
pDepthStencilView = UNWRAP(WrappedID3D11DepthStencilView, pDepthStencilView);
else
pDepthStencilView = NULL;
if(IsLoading(m_State))
RecordOutputMergerStats(NumRTVs, RTs, pDepthStencilView, UAVStartSlot, NumUAVs, UAVs);
m_pRealContext->OMSetRenderTargetsAndUnorderedAccessViews(
ModifyRTVs ? NumRTVs : D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, RTs, pDepthStencilView,
UAVStartSlot, ModifyUAVs ? NumUAVs : D3D11_KEEP_UNORDERED_ACCESS_VIEWS, UAVs,
pUAVInitialCounts);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(
UINT NumRTVs, ID3D11RenderTargetView *const *ppRenderTargetViews,
ID3D11DepthStencilView *pDepthStencilView, UINT UAVStartSlot, UINT NumUAVs,
ID3D11UnorderedAccessView *const *ppUnorderedAccessViews, const UINT *pUAVInitialCounts)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
UINT StartSlot = UAVStartSlot;
// D3D11 doesn't seem to complain about this case, but it messes our render state tracking so
// ensure we don't blat over any RTs with 'empty' UAVs.
if(NumUAVs == 0)
{
if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
UAVStartSlot = RDCMAX(NumRTVs, UAVStartSlot);
else
UAVStartSlot = RDCMAX(m_CurrentPipelineState->OM.UAVStartSlot, UAVStartSlot);
}
ID3D11RenderTargetView *RTs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT] = {0};
for(UINT i = 0;
ppRenderTargetViews && NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL && i < NumRTVs;
i++)
RTs[i] = UNWRAP(WrappedID3D11RenderTargetView1, ppRenderTargetViews[i]);
for(UINT i = 0;
ppUnorderedAccessViews && NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS && i < NumUAVs; i++)
UAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView1, ppUnorderedAccessViews[i]);
SERIALISE_TIME_CALL(m_pRealContext->OMSetRenderTargetsAndUnorderedAccessViews(
NumRTVs, ppRenderTargetViews ? RTs : NULL,
UNWRAP(WrappedID3D11DepthStencilView, pDepthStencilView), UAVStartSlot, NumUAVs,
ppUnorderedAccessViews ? UAVs : NULL, pUAVInitialCounts));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::OMSetRenderTargetsAndUnorderedAccessViews);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_OMSetRenderTargetsAndUnorderedAccessViews(GET_SERIALISER, NumRTVs, ppRenderTargetViews,
pDepthStencilView, UAVStartSlot, NumUAVs,
ppUnorderedAccessViews, pUAVInitialCounts);
m_ContextRecord->AddChunk(scope.Get());
}
for(UINT i = 0;
ppRenderTargetViews && NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL && i < NumRTVs;
i++)
RTs[i] = ppRenderTargetViews[i];
for(UINT i = 0;
ppUnorderedAccessViews && NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS && i < NumUAVs; i++)
UAVs[i] = ppUnorderedAccessViews[i];
const bool ModifyRTVs = NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL;
const bool ModifyUAVs = NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS;
if(ModifyRTVs)
{
ID3D11UnorderedAccessView **srcUAVs = ModifyUAVs ? UAVs : m_CurrentPipelineState->OM.UAVs;
UINT srcUAVcount = ModifyUAVs ? NumUAVs : D3D11_1_UAV_SLOT_COUNT;
if(m_CurrentPipelineState->ValidOutputMerger(ppRenderTargetViews, NumRTVs, pDepthStencilView,
srcUAVs, srcUAVcount))
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets, RTs, 0,
D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.DepthView, pDepthStencilView);
}
if(IsActiveCapturing(m_State))
{
// make sure to mark resources referenced if the OM state is invalid, so they aren't
// eliminated from the
// log (which might make this combination valid on replay without some of the targets!)
for(UINT i = 0; i < NumRTVs; i++)
{
if(ppRenderTargetViews && ppRenderTargetViews[i])
{
MarkResourceReferenced(GetIDForResource(ppRenderTargetViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppRenderTargetViews[i]), eFrameRef_Read);
}
}
if(pDepthStencilView)
{
MarkResourceReferenced(GetIDForResource(pDepthStencilView), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(pDepthStencilView), eFrameRef_Read);
}
}
}
if(ModifyUAVs)
{
bool valid = false;
if(ModifyRTVs)
valid =
m_CurrentPipelineState->ValidOutputMerger(RTs, NumRTVs, pDepthStencilView, UAVs, NumUAVs);
else
valid = m_CurrentPipelineState->ValidOutputMerger(
m_CurrentPipelineState->OM.RenderTargets, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT,
m_CurrentPipelineState->OM.DepthView, UAVs, NumUAVs);
if(valid)
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs, UAVs, 0,
D3D11_1_UAV_SLOT_COUNT);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, UAVStartSlot);
}
if(IsActiveCapturing(m_State))
{
// make sure to mark resources referenced if the OM state is invalid, so they aren't
// eliminated from the
// log (which might make this combination valid on replay without some of the targets!)
for(UINT i = 0; i < NumUAVs; i++)
{
if(UAVs[i])
{
MarkResourceReferenced(GetIDForResource(UAVs[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(UAVs[i]), eFrameRef_Read);
}
}
}
}
// invalid case where UAV/RTV overlap, UAV seems to take precedence
bool UAVOverlap = (NumUAVs > 0 && NumUAVs <= D3D11_1_UAV_SLOT_COUNT && NumRTVs > 0 &&
NumRTVs <= D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT && StartSlot < NumRTVs);
if(UAVOverlap)
{
ID3D11RenderTargetView *NullRTs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
// unset any RTs overlapping with the UAV range
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets, NullRTs,
StartSlot,
RDCMIN(NumUAVs, D3D11_1_UAV_SLOT_COUNT - StartSlot));
}
for(UINT i = 0;
ppRenderTargetViews && NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL && i < NumRTVs;
i++)
{
if(ppRenderTargetViews[i] && IsCaptureMode(m_State))
{
// technically this isn't dirty until the draw call, but let's be conservative
// to avoid having to track "possibly" dirty resources.
// Besides, it's unlikely an application will set an output then not draw to it
if(IsBackgroundCapturing(m_State))
MarkDirtyResource(GetViewResourceResID(ppRenderTargetViews[i]));
else if(IsActiveCapturing(m_State))
m_MissingTracks.insert(GetViewResourceResID(ppRenderTargetViews[i]));
}
RTs[i] = UNWRAP(WrappedID3D11RenderTargetView1, ppRenderTargetViews[i]);
}
for(UINT i = 0;
ppUnorderedAccessViews && NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS && i < NumUAVs; i++)
{
if(ppUnorderedAccessViews[i] && IsCaptureMode(m_State))
{
if(IsBackgroundCapturing(m_State))
MarkDirtyResource(GetViewResourceResID(ppUnorderedAccessViews[i]));
else if(IsActiveCapturing(m_State))
m_MissingTracks.insert(GetViewResourceResID(ppUnorderedAccessViews[i]));
}
UAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView1, ppUnorderedAccessViews[i]);
}
if(pDepthStencilView && IsCaptureMode(m_State))
{
if(IsBackgroundCapturing(m_State))
MarkDirtyResource(GetViewResourceResID(pDepthStencilView));
else if(IsActiveCapturing(m_State))
m_MissingTracks.insert(GetViewResourceResID(pDepthStencilView));
}
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_OMSetBlendState(SerialiserType &ser,
ID3D11BlendState *pBlendState,
const FLOAT BlendFactor[4],
UINT SampleMask)
{
SERIALISE_ELEMENT(pBlendState);
SERIALISE_ELEMENT_ARRAY(BlendFactor, 4);
SERIALISE_ELEMENT(SampleMask);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
FLOAT DefaultBlendFactor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
const FLOAT *SafeBlendFactor = BlendFactor ? BlendFactor : DefaultBlendFactor;
if(IsLoading(m_State))
RecordBlendStats(pBlendState, SafeBlendFactor, SampleMask);
{
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->OM.BlendState, pBlendState);
m_pRealContext->OMSetBlendState(UNWRAP(WrappedID3D11BlendState1, pBlendState), BlendFactor,
SampleMask);
}
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.BlendFactor, SafeBlendFactor, 0, 4);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.SampleMask, SampleMask);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::OMSetBlendState(ID3D11BlendState *pBlendState,
const FLOAT BlendFactor[4], UINT SampleMask)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->OMSetBlendState(
(ID3D11BlendState *)UNWRAP(WrappedID3D11BlendState1, pBlendState), BlendFactor, SampleMask));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::OMSetBlendState);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_OMSetBlendState(GET_SERIALISER, pBlendState, BlendFactor, SampleMask);
MarkResourceReferenced(GetIDForResource(pBlendState), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
FLOAT DefaultBlendFactor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->OM.BlendState, pBlendState);
if(BlendFactor != NULL)
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.BlendFactor, BlendFactor, 0, 4);
else
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.BlendFactor, DefaultBlendFactor, 0, 4);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.SampleMask, SampleMask);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_OMSetDepthStencilState(
SerialiserType &ser, ID3D11DepthStencilState *pDepthStencilState, UINT StencilRef)
{
SERIALISE_ELEMENT(pDepthStencilState);
SERIALISE_ELEMENT(StencilRef);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordDepthStencilStats(pDepthStencilState, StencilRef);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->OM.DepthStencilState,
pDepthStencilState);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.StencRef, StencilRef & 0xff);
m_pRealContext->OMSetDepthStencilState(
UNWRAP(WrappedID3D11DepthStencilState, pDepthStencilState), StencilRef);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::OMSetDepthStencilState(ID3D11DepthStencilState *pDepthStencilState,
UINT StencilRef)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->OMSetDepthStencilState(
UNWRAP(WrappedID3D11DepthStencilState, pDepthStencilState), StencilRef));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::OMSetDepthStencilState);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_OMSetDepthStencilState(GET_SERIALISER, pDepthStencilState, StencilRef);
MarkResourceReferenced(GetIDForResource(pDepthStencilState), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->OM.DepthStencilState,
pDepthStencilState);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.StencRef, StencilRef & 0xff);
VerifyState();
}
#pragma endregion Output Merger
#pragma region Draw
template <typename SerialiserType>
void WrappedID3D11DeviceContext::Serialise_DebugMessages(SerialiserType &ser)
{
std::vector<DebugMessage> DebugMessages;
m_EmptyCommandList = false;
// only grab debug messages for the immediate context, without serialising all
// API use there's no way to find out which messages come from which context :(.
if(ser.IsWriting() && IsActiveCapturing(m_State) && GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE)
{
DebugMessages = m_pDevice->GetDebugMessages();
}
SERIALISE_ELEMENT(DebugMessages);
// hide empty sets of messages.
if(ser.IsReading() && DebugMessages.empty())
ser.Hidden();
if(ser.IsReading() && IsLoading(m_State))
{
for(DebugMessage &msg : DebugMessages)
{
msg.eventId = m_CurEventID;
m_pDevice->AddDebugMessage(msg);
}
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DrawIndexedInstanced(
SerialiserType &ser, UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation,
INT BaseVertexLocation, UINT StartInstanceLocation)
{
SERIALISE_ELEMENT(IndexCountPerInstance);
SERIALISE_ELEMENT(InstanceCount);
SERIALISE_ELEMENT(StartIndexLocation);
SERIALISE_ELEMENT(BaseVertexLocation);
SERIALISE_ELEMENT(StartInstanceLocation);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_pRealContext->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation,
BaseVertexLocation, StartInstanceLocation);
if(IsLoading(m_State))
{
RecordDrawStats(true, false, InstanceCount);
AddEvent();
DrawcallDescription draw;
draw.name =
StringFormat::Fmt("DrawIndexedInstanced(%u, %u)", IndexCountPerInstance, InstanceCount);
draw.numIndices = IndexCountPerInstance;
draw.numInstances = InstanceCount;
draw.indexOffset = StartIndexLocation;
draw.baseVertex = BaseVertexLocation;
draw.instanceOffset = StartInstanceLocation;
draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::UseIBuffer;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::DrawIndexedInstanced(UINT IndexCountPerInstance, UINT InstanceCount,
UINT StartIndexLocation, INT BaseVertexLocation,
UINT StartInstanceLocation)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount,
StartIndexLocation, BaseVertexLocation,
StartInstanceLocation));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DrawIndexedInstanced);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DrawIndexedInstanced(GET_SERIALISER, IndexCountPerInstance, InstanceCount,
StartIndexLocation, BaseVertexLocation, StartInstanceLocation);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DrawInstanced(SerialiserType &ser,
UINT VertexCountPerInstance,
UINT InstanceCount, UINT StartVertexLocation,
UINT StartInstanceLocation)
{
SERIALISE_ELEMENT(VertexCountPerInstance);
SERIALISE_ELEMENT(InstanceCount);
SERIALISE_ELEMENT(StartVertexLocation);
SERIALISE_ELEMENT(StartInstanceLocation);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_pRealContext->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation,
StartInstanceLocation);
if(IsLoading(m_State))
{
RecordDrawStats(true, false, InstanceCount);
AddEvent();
DrawcallDescription draw;
draw.name = StringFormat::Fmt("DrawInstanced(%u, %u)", VertexCountPerInstance, InstanceCount);
draw.numIndices = VertexCountPerInstance;
draw.numInstances = InstanceCount;
draw.vertexOffset = StartVertexLocation;
draw.instanceOffset = StartInstanceLocation;
draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::DrawInstanced(UINT VertexCountPerInstance, UINT InstanceCount,
UINT StartVertexLocation, UINT StartInstanceLocation)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->DrawInstanced(VertexCountPerInstance, InstanceCount,
StartVertexLocation, StartInstanceLocation));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DrawInstanced);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DrawInstanced(GET_SERIALISER, VertexCountPerInstance, InstanceCount,
StartVertexLocation, StartInstanceLocation);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DrawIndexed(SerialiserType &ser, UINT IndexCount,
UINT StartIndexLocation,
INT BaseVertexLocation)
{
SERIALISE_ELEMENT(IndexCount);
SERIALISE_ELEMENT(StartIndexLocation);
SERIALISE_ELEMENT(BaseVertexLocation);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_pRealContext->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation);
if(IsLoading(m_State))
{
RecordDrawStats(false, false, 1);
AddEvent();
DrawcallDescription draw;
draw.name = StringFormat::Fmt("DrawIndexed(%u)", IndexCount);
draw.numIndices = IndexCount;
draw.baseVertex = BaseVertexLocation;
draw.indexOffset = StartIndexLocation;
draw.flags |= DrawFlags::Drawcall | DrawFlags::UseIBuffer;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::DrawIndexed(UINT IndexCount, UINT StartIndexLocation,
INT BaseVertexLocation)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DrawIndexed);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DrawIndexed(GET_SERIALISER, IndexCount, StartIndexLocation, BaseVertexLocation);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_Draw(SerialiserType &ser, UINT VertexCount,
UINT StartVertexLocation)
{
SERIALISE_ELEMENT(VertexCount);
SERIALISE_ELEMENT(StartVertexLocation);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_pRealContext->Draw(VertexCount, StartVertexLocation);
if(IsLoading(m_State))
{
RecordDrawStats(false, false, 1);
AddEvent();
DrawcallDescription draw;
draw.name = StringFormat::Fmt("Draw(%u)", VertexCount);
draw.numIndices = VertexCount;
draw.vertexOffset = StartVertexLocation;
draw.flags |= DrawFlags::Drawcall;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::Draw(UINT VertexCount, UINT StartVertexLocation)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->Draw(VertexCount, StartVertexLocation));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::Draw);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_Draw(GET_SERIALISER, VertexCount, StartVertexLocation);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DrawAuto(SerialiserType &ser)
{
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
uint64_t numVerts = 0;
if(IsReplayingAndReading())
{
// spec says that only the first vertex buffer is used
if(m_CurrentPipelineState->IA.VBs[0] == NULL)
{
m_pDevice->AddDebugMessage(MessageCategory::Execution, MessageSeverity::High,
MessageSource::IncorrectAPIUse,
"DrawAuto() with VB 0 set to NULL!");
}
else
{
ResourceId id = GetIDForResource(m_CurrentPipelineState->IA.VBs[0]);
StreamOutData &data = m_StreamOutCounters[id];
// if we have a query, the stream-out data for this DrawAuto was generated
// in the captured frame, so we can do a legitimate DrawAuto()
if(data.query)
{
// shouldn't still be bound on output
RDCASSERT(!data.running);
D3D11_QUERY_DATA_SO_STATISTICS numPrims;
HRESULT hr = S_FALSE;
do
{
hr = m_pRealContext->GetData(data.query, &numPrims,
sizeof(D3D11_QUERY_DATA_SO_STATISTICS), 0);
} while(hr == S_FALSE);
if(m_CurrentPipelineState->IA.Topo == D3D11_PRIMITIVE_TOPOLOGY_POINTLIST)
numVerts = numPrims.NumPrimitivesWritten;
else if(m_CurrentPipelineState->IA.Topo == D3D11_PRIMITIVE_TOPOLOGY_LINELIST)
numVerts = numPrims.NumPrimitivesWritten * 2;
else
numVerts = numPrims.NumPrimitivesWritten * 3;
m_pRealContext->DrawAuto();
}
else
{
// otherwise use the cached value from the previous frame.
if(m_CurrentPipelineState->IA.Topo == D3D11_PRIMITIVE_TOPOLOGY_POINTLIST)
numVerts = data.numPrims;
else if(m_CurrentPipelineState->IA.Topo == D3D11_PRIMITIVE_TOPOLOGY_LINELIST)
numVerts = data.numPrims * 2;
else
numVerts = data.numPrims * 3;
m_pRealContext->Draw((UINT)numVerts, 0);
}
}
if(IsLoading(m_State))
{
RecordDrawStats(false, false, 1);
AddEvent();
DrawcallDescription draw;
draw.name = StringFormat::Fmt("DrawAuto(<%u>)", numVerts);
draw.flags |= DrawFlags::Drawcall | DrawFlags::Auto;
draw.numIndices = (uint32_t)numVerts;
draw.vertexOffset = 0;
draw.indexOffset = 0;
draw.instanceOffset = 0;
draw.numInstances = 1;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::DrawAuto()
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->DrawAuto());
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DrawAuto);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DrawAuto(GET_SERIALISER);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DrawIndexedInstancedIndirect(SerialiserType &ser,
ID3D11Buffer *pBufferForArgs,
UINT AlignedByteOffsetForArgs)
{
SERIALISE_ELEMENT(pBufferForArgs);
SERIALISE_ELEMENT(AlignedByteOffsetForArgs);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pBufferForArgs)
{
m_pRealContext->DrawIndexedInstancedIndirect(UNWRAP(WrappedID3D11Buffer, pBufferForArgs),
AlignedByteOffsetForArgs);
}
if(IsLoading(m_State))
{
AddEvent();
DrawcallDescription draw;
std::string name = "DrawIndexedInstancedIndirect(-, -)";
if(pBufferForArgs)
{
struct DrawArgs
{
uint32_t IndexCountPerInstance;
uint32_t InstanceCount;
uint32_t StartIndexLocation;
int32_t BaseVertexLocation;
uint32_t StartInstanceLocation;
};
bytebuf argarray;
m_pDevice->GetDebugManager()->GetBufferData(pBufferForArgs, AlignedByteOffsetForArgs,
sizeof(DrawArgs), argarray);
if(argarray.size() >= sizeof(DrawArgs))
{
DrawArgs *args = (DrawArgs *)&argarray[0];
draw.numIndices = args->IndexCountPerInstance;
draw.numInstances = args->InstanceCount;
draw.indexOffset = args->StartIndexLocation;
draw.baseVertex = args->BaseVertexLocation;
draw.instanceOffset = args->StartInstanceLocation;
RecordDrawStats(true, true, draw.numInstances);
name = StringFormat::Fmt("DrawIndexedInstancedIndirect(<%u, %u>)", draw.numIndices,
draw.numInstances);
}
else
{
name = "DrawIndexedInstancedIndirect(<!, !>)";
D3D11_BUFFER_DESC bufDesc;
pBufferForArgs->GetDesc(&bufDesc);
if(AlignedByteOffsetForArgs >= bufDesc.ByteWidth)
{
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::High, MessageSource::IncorrectAPIUse,
StringFormat::Fmt("Call to DrawIndexedInstancedIndirect with buffer of %u "
"bytes, but byte offset specified is %u bytes.",
bufDesc.ByteWidth, AlignedByteOffsetForArgs));
}
else if(AlignedByteOffsetForArgs + sizeof(DrawArgs) >= bufDesc.ByteWidth)
{
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::High, MessageSource::IncorrectAPIUse,
StringFormat::Fmt("Call to DrawIndexedInstancedIndirect with buffer of %u "
"bytes at offset of %u bytes, which leaves less than %u bytes "
"for the arguments.",
bufDesc.ByteWidth, AlignedByteOffsetForArgs, sizeof(DrawArgs)));
}
}
m_ResourceUses[GetIDForResource(pBufferForArgs)].push_back(
EventUsage(m_CurEventID, ResourceUsage::Indirect));
}
draw.name = name;
draw.flags |=
DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::UseIBuffer | DrawFlags::Indirect;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::DrawIndexedInstancedIndirect(ID3D11Buffer *pBufferForArgs,
UINT AlignedByteOffsetForArgs)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->DrawIndexedInstancedIndirect(
UNWRAP(WrappedID3D11Buffer, pBufferForArgs), AlignedByteOffsetForArgs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DrawIndexedInstancedIndirect);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DrawIndexedInstancedIndirect(GET_SERIALISER, pBufferForArgs, AlignedByteOffsetForArgs);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
if(pBufferForArgs && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(pBufferForArgs), eFrameRef_Read);
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DrawInstancedIndirect(SerialiserType &ser,
ID3D11Buffer *pBufferForArgs,
UINT AlignedByteOffsetForArgs)
{
SERIALISE_ELEMENT(pBufferForArgs);
SERIALISE_ELEMENT(AlignedByteOffsetForArgs);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pBufferForArgs)
{
m_pRealContext->DrawInstancedIndirect(UNWRAP(WrappedID3D11Buffer, pBufferForArgs),
AlignedByteOffsetForArgs);
}
if(IsLoading(m_State))
{
AddEvent();
DrawcallDescription draw;
std::string name = "DrawInstancedIndirect(-, -)";
if(pBufferForArgs)
{
struct DrawArgs
{
uint32_t VertexCountPerInstance;
uint32_t InstanceCount;
uint32_t StartVertexLocation;
uint32_t StartInstanceLocation;
};
bytebuf argarray;
m_pDevice->GetDebugManager()->GetBufferData(pBufferForArgs, AlignedByteOffsetForArgs,
sizeof(DrawArgs), argarray);
if(argarray.size() >= sizeof(DrawArgs))
{
DrawArgs *args = (DrawArgs *)&argarray[0];
draw.numIndices = args->VertexCountPerInstance;
draw.numInstances = args->InstanceCount;
draw.vertexOffset = args->StartVertexLocation;
draw.instanceOffset = args->StartInstanceLocation;
RecordDrawStats(true, true, draw.numInstances);
name = StringFormat::Fmt("DrawInstancedIndirect(<%u, %u>)", draw.numIndices,
draw.numInstances);
}
else
{
name = "DrawInstancedIndirect(<!, !>)";
D3D11_BUFFER_DESC bufDesc;
pBufferForArgs->GetDesc(&bufDesc);
if(AlignedByteOffsetForArgs >= bufDesc.ByteWidth)
{
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::High, MessageSource::IncorrectAPIUse,
StringFormat::Fmt("Call to DrawIndexedInstancedIndirect with buffer of %u "
"bytes, but byte offset specified is %u bytes.",
bufDesc.ByteWidth, AlignedByteOffsetForArgs));
}
else if(AlignedByteOffsetForArgs + sizeof(DrawArgs) >= bufDesc.ByteWidth)
{
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::High, MessageSource::IncorrectAPIUse,
StringFormat::Fmt("Call to DrawIndexedInstancedIndirect with buffer of %u "
"bytes at offset of %u bytes, which leaves less than %u bytes "
"for the arguments.",
bufDesc.ByteWidth, AlignedByteOffsetForArgs, sizeof(DrawArgs)));
}
}
m_ResourceUses[GetIDForResource(pBufferForArgs)].push_back(
EventUsage(m_CurEventID, ResourceUsage::Indirect));
}
draw.name = name;
draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::Indirect;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::DrawInstancedIndirect(ID3D11Buffer *pBufferForArgs,
UINT AlignedByteOffsetForArgs)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->DrawInstancedIndirect(
UNWRAP(WrappedID3D11Buffer, pBufferForArgs), AlignedByteOffsetForArgs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DrawInstancedIndirect);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DrawInstancedIndirect(GET_SERIALISER, pBufferForArgs, AlignedByteOffsetForArgs);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
if(pBufferForArgs && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(pBufferForArgs), eFrameRef_Read);
}
#pragma endregion Draw
#pragma region Compute Shader
void WrappedID3D11DeviceContext::CSGetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer **ppConstantBuffers)
{
if(ppConstantBuffers)
{
ID3D11Buffer *real[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
m_pRealContext->CSGetConstantBuffers(StartSlot, NumBuffers, real);
for(UINT i = 0; i < NumBuffers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppConstantBuffers[i] = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppConstantBuffers[i]);
RDCASSERT(ppConstantBuffers[i] == m_CurrentPipelineState->CS.ConstantBuffers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::CSGetShaderResources(UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
if(ppShaderResourceViews)
{
ID3D11ShaderResourceView *real[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {0};
m_pRealContext->CSGetShaderResources(StartSlot, NumViews, real);
for(UINT i = 0; i < NumViews; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppShaderResourceViews[i] =
(ID3D11ShaderResourceView *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppShaderResourceViews[i]);
RDCASSERT(ppShaderResourceViews[i] == m_CurrentPipelineState->CS.SRVs[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::CSGetUnorderedAccessViews(
UINT StartSlot, UINT NumUAVs, ID3D11UnorderedAccessView **ppUnorderedAccessViews)
{
if(ppUnorderedAccessViews)
{
ID3D11UnorderedAccessView *real[D3D11_1_UAV_SLOT_COUNT] = {0};
m_pRealContext->CSGetUnorderedAccessViews(StartSlot, NumUAVs, real);
for(UINT i = 0; i < NumUAVs; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppUnorderedAccessViews[i] =
(ID3D11UnorderedAccessView *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppUnorderedAccessViews[i]);
RDCASSERT(ppUnorderedAccessViews[i] == m_CurrentPipelineState->CSUAVs[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::CSGetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState **ppSamplers)
{
if(ppSamplers)
{
ID3D11SamplerState *real[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {0};
m_pRealContext->CSGetSamplers(StartSlot, NumSamplers, real);
for(UINT i = 0; i < NumSamplers; i++)
{
SAFE_RELEASE_NOCLEAR(real[i]);
ppSamplers[i] = (ID3D11SamplerState *)m_pDevice->GetResourceManager()->GetWrapper(real[i]);
SAFE_ADDREF(ppSamplers[i]);
RDCASSERT(ppSamplers[i] == m_CurrentPipelineState->CS.Samplers[i + StartSlot]);
}
}
}
void WrappedID3D11DeviceContext::CSGetShader(ID3D11ComputeShader **ppComputeShader,
ID3D11ClassInstance **ppClassInstances,
UINT *pNumClassInstances)
{
if(ppComputeShader == NULL && ppClassInstances == NULL && pNumClassInstances == NULL)
return;
ID3D11ClassInstance *realInsts[D3D11_SHADER_MAX_INTERFACES] = {0};
UINT numInsts = 0;
ID3D11ComputeShader *realShader = NULL;
m_pRealContext->CSGetShader(&realShader, realInsts, &numInsts);
SAFE_RELEASE_NOCLEAR(realShader);
for(UINT i = 0; i < numInsts; i++)
SAFE_RELEASE_NOCLEAR(realInsts[i]);
if(ppComputeShader)
{
*ppComputeShader = (ID3D11ComputeShader *)m_pDevice->GetResourceManager()->GetWrapper(realShader);
SAFE_ADDREF(*ppComputeShader);
RDCASSERT(*ppComputeShader == m_CurrentPipelineState->CS.Object);
}
if(ppClassInstances)
{
for(UINT i = 0; i < numInsts; i++)
{
ppClassInstances[i] =
(ID3D11ClassInstance *)m_pDevice->GetResourceManager()->GetWrapper(realInsts[i]);
SAFE_ADDREF(ppClassInstances[i]);
RDCASSERT(ppClassInstances[i] == m_CurrentPipelineState->CS.Instances[i]);
}
}
if(pNumClassInstances)
{
*pNumClassInstances = numInsts;
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CSSetConstantBuffers(SerialiserType &ser, UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumBuffers);
SERIALISE_ELEMENT_ARRAY(ppConstantBuffers, NumBuffers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordConstantStats(ShaderStage::Compute, NumBuffers, ppConstantBuffers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->CS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->CS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
for(UINT i = 0; i < NumBuffers; i++)
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
m_pRealContext->CSSetConstantBuffers(StartSlot, NumBuffers, bufs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::CSSetConstantBuffers(UINT StartSlot, UINT NumBuffers,
ID3D11Buffer *const *ppConstantBuffers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11Buffer *bufs[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
for(UINT i = 0; i < NumBuffers; i++)
{
if(ppConstantBuffers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppConstantBuffers[i]), eFrameRef_Read);
bufs[i] = UNWRAP(WrappedID3D11Buffer, ppConstantBuffers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->CSSetConstantBuffers(StartSlot, NumBuffers, bufs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CSSetConstantBuffers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CSSetConstantBuffers(GET_SERIALISER, StartSlot, NumBuffers, ppConstantBuffers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.ConstantBuffers,
ppConstantBuffers, StartSlot, NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->CS.CBOffsets, NullCBOffsets, StartSlot,
NumBuffers);
m_CurrentPipelineState->Change(m_CurrentPipelineState->CS.CBCounts, NullCBCounts, StartSlot,
NumBuffers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CSSetShaderResources(
SerialiserType &ser, UINT StartSlot, UINT NumViews,
ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumViews);
SERIALISE_ELEMENT_ARRAY(ppShaderResourceViews, NumViews);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordResourceStats(ShaderStage::Compute, NumViews, ppShaderResourceViews);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
m_pRealContext->CSSetShaderResources(StartSlot, NumViews, SRVs);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::CSSetShaderResources(
UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ShaderResourceView *SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
for(UINT i = 0; i < NumViews; i++)
{
if(ppShaderResourceViews[i] && IsActiveCapturing(m_State))
{
MarkResourceReferenced(GetIDForResource(ppShaderResourceViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppShaderResourceViews[i]), eFrameRef_Read);
}
SRVs[i] = UNWRAP(WrappedID3D11ShaderResourceView1, ppShaderResourceViews[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->CSSetShaderResources(StartSlot, NumViews, SRVs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CSSetShaderResources);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CSSetShaderResources(GET_SERIALISER, StartSlot, NumViews, ppShaderResourceViews);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.SRVs, ppShaderResourceViews,
StartSlot, NumViews);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CSSetUnorderedAccessViews(
SerialiserType &ser, UINT StartSlot, UINT NumUAVs,
ID3D11UnorderedAccessView *const *ppUnorderedAccessViews, const UINT *pUAVInitialCounts)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumUAVs);
SERIALISE_ELEMENT_ARRAY(ppUnorderedAccessViews, NumUAVs);
SERIALISE_ELEMENT_ARRAY(pUAVInitialCounts, NumUAVs);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->CSUAVs, ppUnorderedAccessViews,
StartSlot, NumUAVs);
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT];
for(UINT i = 0; i < NumUAVs; i++)
UAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView1, ppUnorderedAccessViews[i]);
// #mivance this isn't strictly correct...
if(IsLoading(m_State))
RecordOutputMergerStats(0, NULL, NULL, StartSlot, NumUAVs, UAVs);
m_pRealContext->CSSetUnorderedAccessViews(StartSlot, NumUAVs, UAVs, pUAVInitialCounts);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::CSSetUnorderedAccessViews(
UINT StartSlot, UINT NumUAVs, ID3D11UnorderedAccessView *const *ppUnorderedAccessViews,
const UINT *pUAVInitialCounts)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT];
for(UINT i = 0; i < NumUAVs; i++)
{
if(ppUnorderedAccessViews[i] && IsCaptureMode(m_State))
{
if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetViewResourceResID(ppUnorderedAccessViews[i]));
}
else if(IsActiveCapturing(m_State))
{
m_MissingTracks.insert(GetViewResourceResID(ppUnorderedAccessViews[i]));
MarkResourceReferenced(GetIDForResource(ppUnorderedAccessViews[i]), eFrameRef_Read);
MarkResourceReferenced(GetViewResourceResID(ppUnorderedAccessViews[i]), eFrameRef_Read);
}
}
UAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView1, ppUnorderedAccessViews[i]);
}
SERIALISE_TIME_CALL(
m_pRealContext->CSSetUnorderedAccessViews(StartSlot, NumUAVs, UAVs, pUAVInitialCounts));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CSSetUnorderedAccessViews);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CSSetUnorderedAccessViews(GET_SERIALISER, StartSlot, NumUAVs, ppUnorderedAccessViews,
pUAVInitialCounts);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->CSUAVs, ppUnorderedAccessViews,
StartSlot, NumUAVs);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CSSetSamplers(SerialiserType &ser, UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
SERIALISE_ELEMENT(StartSlot);
SERIALISE_ELEMENT(NumSamplers);
SERIALISE_ELEMENT_ARRAY(ppSamplers, NumSamplers);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordSamplerStats(ShaderStage::Compute, NumSamplers, ppSamplers);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.Samplers, ppSamplers,
StartSlot, NumSamplers);
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
m_pRealContext->CSSetSamplers(StartSlot, NumSamplers, samps);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::CSSetSamplers(UINT StartSlot, UINT NumSamplers,
ID3D11SamplerState *const *ppSamplers)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11SamplerState *samps[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
for(UINT i = 0; i < NumSamplers; i++)
{
if(ppSamplers[i] && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(ppSamplers[i]), eFrameRef_Read);
samps[i] = UNWRAP(WrappedID3D11SamplerState, ppSamplers[i]);
}
SERIALISE_TIME_CALL(m_pRealContext->CSSetSamplers(StartSlot, NumSamplers, samps));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CSSetSamplers);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CSSetSamplers(GET_SERIALISER, StartSlot, NumSamplers, ppSamplers);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.Samplers, ppSamplers, StartSlot,
NumSamplers);
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CSSetShader(SerialiserType &ser,
ID3D11ComputeShader *pShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
SERIALISE_ELEMENT(pShader);
SERIALISE_ELEMENT_ARRAY(ppClassInstances, NumClassInstances);
SERIALISE_ELEMENT(NumClassInstances);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(IsLoading(m_State))
RecordShaderStats(ShaderStage::Compute, m_CurrentPipelineState->CS.Object, pShader);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.Instances, ppClassInstances, 0,
NumClassInstances);
m_CurrentPipelineState->Change(m_CurrentPipelineState->CS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.Object,
(ID3D11DeviceChild *)pShader);
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
m_pRealContext->CSSetShader(UNWRAP(WrappedID3D11Shader<ID3D11ComputeShader>, pShader), insts,
NumClassInstances);
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::CSSetShader(ID3D11ComputeShader *pComputeShader,
ID3D11ClassInstance *const *ppClassInstances,
UINT NumClassInstances)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ID3D11ClassInstance *insts[D3D11_SHADER_MAX_INTERFACES] = {0};
if(ppClassInstances && NumClassInstances > 0)
for(UINT i = 0; i < NumClassInstances; i++)
insts[i] = UNWRAP(WrappedID3D11ClassInstance, ppClassInstances[i]);
SERIALISE_TIME_CALL(m_pRealContext->CSSetShader(
UNWRAP(WrappedID3D11Shader<ID3D11ComputeShader>, pComputeShader), insts, NumClassInstances));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CSSetShader);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CSSetShader(GET_SERIALISER, pComputeShader, ppClassInstances, NumClassInstances);
MarkResourceReferenced(GetIDForResource(pComputeShader), eFrameRef_Read);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.Object,
(ID3D11DeviceChild *)pComputeShader);
m_CurrentPipelineState->Change(m_CurrentPipelineState->CS.NumInstances, NumClassInstances);
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.Instances, ppClassInstances, 0,
NumClassInstances);
VerifyState();
}
#pragma endregion Compute Shader
#pragma region Dispatch
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_Dispatch(SerialiserType &ser, UINT ThreadGroupCountX,
UINT ThreadGroupCountY, UINT ThreadGroupCountZ)
{
SERIALISE_ELEMENT(ThreadGroupCountX);
SERIALISE_ELEMENT(ThreadGroupCountY);
SERIALISE_ELEMENT(ThreadGroupCountZ);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
m_pRealContext->Dispatch(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ);
if(IsLoading(m_State))
{
RecordDispatchStats(false);
AddEvent();
DrawcallDescription draw;
draw.name = StringFormat::Fmt("Dispatch(%u, %u, %u)", ThreadGroupCountX, ThreadGroupCountY,
ThreadGroupCountZ);
draw.flags |= DrawFlags::Dispatch;
draw.dispatchDimension[0] = ThreadGroupCountX;
draw.dispatchDimension[1] = ThreadGroupCountY;
draw.dispatchDimension[2] = ThreadGroupCountZ;
if(ThreadGroupCountX == 0)
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::Medium, MessageSource::IncorrectAPIUse,
"Dispatch call has ThreadGroup count X=0. This will do nothing, "
"which is unusual for a non-indirect Dispatch. Did you mean X=1?");
if(ThreadGroupCountY == 0)
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::Medium, MessageSource::IncorrectAPIUse,
"Dispatch call has ThreadGroup count Y=0. This will do nothing, "
"which is unusual for a non-indirect Dispatch. Did you mean Y=1?");
if(ThreadGroupCountZ == 0)
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::Medium, MessageSource::IncorrectAPIUse,
"Dispatch call has ThreadGroup count Z=0. This will do nothing, "
"which is unusual for a non-indirect Dispatch. Did you mean Z=1?");
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::Dispatch(UINT ThreadGroupCountX, UINT ThreadGroupCountY,
UINT ThreadGroupCountZ)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(
m_pRealContext->Dispatch(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::Dispatch);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_Dispatch(GET_SERIALISER, ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_DispatchIndirect(SerialiserType &ser,
ID3D11Buffer *pBufferForArgs,
UINT AlignedByteOffsetForArgs)
{
SERIALISE_ELEMENT(pBufferForArgs);
SERIALISE_ELEMENT(AlignedByteOffsetForArgs);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pBufferForArgs)
{
m_pRealContext->DispatchIndirect(UNWRAP(WrappedID3D11Buffer, pBufferForArgs),
AlignedByteOffsetForArgs);
}
if(IsLoading(m_State))
{
RecordDispatchStats(true);
AddEvent();
DrawcallDescription draw;
std::string name = "DispatchIndirect(-, -, -)";
if(pBufferForArgs)
{
struct DispatchArgs
{
UINT ThreadGroupCountX;
UINT ThreadGroupCountY;
UINT ThreadGroupCountZ;
};
bytebuf argarray;
m_pDevice->GetDebugManager()->GetBufferData(pBufferForArgs, AlignedByteOffsetForArgs,
sizeof(DispatchArgs), argarray);
if(argarray.size() >= sizeof(DispatchArgs))
{
DispatchArgs *args = (DispatchArgs *)&argarray[0];
draw.dispatchDimension[0] = args->ThreadGroupCountX;
draw.dispatchDimension[1] = args->ThreadGroupCountY;
draw.dispatchDimension[2] = args->ThreadGroupCountZ;
name = StringFormat::Fmt("DispatchIndirect(<%u, %u, %u>)", args->ThreadGroupCountX,
args->ThreadGroupCountY, args->ThreadGroupCountZ);
}
else
{
name = "DispatchIndirect(<!, !, !>)";
D3D11_BUFFER_DESC bufDesc;
pBufferForArgs->GetDesc(&bufDesc);
if(AlignedByteOffsetForArgs >= bufDesc.ByteWidth)
{
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::High, MessageSource::IncorrectAPIUse,
StringFormat::Fmt("Call to DispatchIndirect with buffer of %u "
"bytes, but byte offset specified is %u bytes.",
bufDesc.ByteWidth, AlignedByteOffsetForArgs));
}
else if(AlignedByteOffsetForArgs + sizeof(DispatchArgs) >= bufDesc.ByteWidth)
{
m_pDevice->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::High, MessageSource::IncorrectAPIUse,
StringFormat::Fmt("Call to DispatchIndirect with buffer of %u "
"bytes at offset of %u bytes, which leaves less than %u bytes "
"for the arguments.",
bufDesc.ByteWidth, AlignedByteOffsetForArgs, sizeof(DispatchArgs)));
}
}
m_ResourceUses[GetIDForResource(pBufferForArgs)].push_back(
EventUsage(m_CurEventID, ResourceUsage::Indirect));
}
draw.name = name;
draw.flags |= DrawFlags::Dispatch | DrawFlags::Indirect;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::DispatchIndirect(ID3D11Buffer *pBufferForArgs,
UINT AlignedByteOffsetForArgs)
{
DrainAnnotationQueue();
MarkAPIActive();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->DispatchIndirect(UNWRAP(WrappedID3D11Buffer, pBufferForArgs),
AlignedByteOffsetForArgs));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::DispatchIndirect);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_DispatchIndirect(GET_SERIALISER, pBufferForArgs, AlignedByteOffsetForArgs);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
if(pBufferForArgs && IsActiveCapturing(m_State))
MarkResourceReferenced(GetIDForResource(pBufferForArgs), eFrameRef_Read);
}
#pragma endregion Dispatch
#pragma region Execute
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_ExecuteCommandList(SerialiserType &ser,
ID3D11CommandList *pCommandList,
BOOL RestoreContextState_)
{
SERIALISE_ELEMENT_LOCAL(CommandList, GetIDForResource(pCommandList))
.TypedAs("ID3D11CommandList *");
SERIALISE_ELEMENT_LOCAL(RestoreContextState, bool(RestoreContextState_ == TRUE));
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// The serialise of exec happens at the start of the inserted linearised commands from the
// deferred command list. So if we're going to restore context state afterwards, save off our
// current state. This will be restored in the Serialise_PostExecuteCommandList chunk.
if(RestoreContextState)
{
SAFE_DELETE(m_DeferredSavedState);
m_DeferredSavedState = new D3D11RenderState(this);
}
// From the Docs:
// "Immediate context state is cleared before and after a command list is executed. A command
// list has no concept of inheritance."
ClearState();
if(IsLoading(m_State))
{
DrawcallDescription draw;
draw.name = StringFormat::Fmt("ExecuteCommandList(List %s)", ToStr(CommandList).c_str());
draw.flags |= DrawFlags::CmdList;
AddDrawcall(draw, true);
}
}
return true;
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PostExecuteCommandList(SerialiserType &ser,
ID3D11CommandList *pCommandList,
BOOL RestoreContextState_)
{
SERIALISE_ELEMENT_LOCAL(CommandList, GetIDForResource(pCommandList))
.TypedAs("ID3D11CommandList *");
SERIALISE_ELEMENT_LOCAL(RestoreContextState, bool(RestoreContextState_ == TRUE));
// this is a 'fake' call we insert after executing, to give us a chance to restore the state.
if(IsReplayingAndReading())
{
if(RestoreContextState)
{
if(m_DeferredSavedState)
{
m_DeferredSavedState->ApplyState(this);
SAFE_DELETE(m_DeferredSavedState);
}
else
{
RDCERR("Expected to have saved state from before execute saved, but didn't find one.");
}
}
else
{
// if we don't restore the state, then it's cleared. There's no inheritance down from the
// deferred context's state to the immediate context.
ClearState();
}
}
return true;
}
void WrappedID3D11DeviceContext::ExecuteCommandList(ID3D11CommandList *pCommandList,
BOOL RestoreContextState)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
RDCASSERT(GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE);
SERIALISE_TIME_CALL(m_pRealContext->ExecuteCommandList(
UNWRAP(WrappedID3D11CommandList, pCommandList), RestoreContextState));
if(IsActiveCapturing(m_State))
{
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::ExecuteCommandList);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_ExecuteCommandList(GET_SERIALISER, pCommandList, RestoreContextState);
m_ContextRecord->AddChunk(scope.Get());
}
WrappedID3D11CommandList *wrapped = (WrappedID3D11CommandList *)pCommandList;
if(!wrapped->IsCaptured())
{
// we don't have this command list captured. This frame is no longer successful
RDCWARN("Don't have command list %llu captured! This frame is unsuccessful.",
wrapped->GetResourceID());
m_SuccessfulCapture = false;
m_FailureReason = CaptureFailed_UncappedCmdlist;
}
else
{
RDCDEBUG("Executed successful command list %llu", wrapped->GetResourceID());
ResourceId contextId = wrapped->GetResourceID();
D3D11ResourceRecord *cmdListRecord =
m_pDevice->GetResourceManager()->GetResourceRecord(contextId);
RDCASSERT(cmdListRecord);
// insert all the deferred chunks immediately following the execute chunk.
m_ContextRecord->AppendFrom(cmdListRecord);
cmdListRecord->AddResourceReferences(m_pDevice->GetResourceManager());
}
// still update dirty resources for subsequent captures
wrapped->MarkDirtyResources(m_MissingTracks);
{
// insert a chunk to let us know on replay that we finished the command list's
// chunks and we can restore the state
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PostExecuteCommandList);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PostExecuteCommandList(GET_SERIALISER, pCommandList, RestoreContextState);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->MarkReferenced(this, false);
}
else if(IsBackgroundCapturing(m_State))
{
WrappedID3D11CommandList *wrapped = (WrappedID3D11CommandList *)pCommandList;
wrapped->MarkDirtyResources(m_pDevice->GetResourceManager());
}
if(!RestoreContextState)
m_CurrentPipelineState->Clear();
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_FinishCommandList(SerialiserType &ser,
BOOL RestoreDeferredContextState_,
ID3D11CommandList **ppCommandList)
{
SERIALISE_ELEMENT_LOCAL(RestoreDeferredContextState, bool(RestoreDeferredContextState_ == TRUE));
SERIALISE_ELEMENT_LOCAL(pCommandList, GetIDForResource(*ppCommandList))
.TypedAs("ID3D11CommandList *");
Serialise_DebugMessages(GET_SERIALISER);
if(IsReplayingAndReading() && IsLoading(m_State))
{
AddEvent();
DrawcallDescription draw;
draw.name = StringFormat::Fmt("FinishCommandList(List %s)", ToStr(pCommandList).c_str());
draw.flags |= DrawFlags::CmdList;
AddDrawcall(draw, true);
m_pDevice->AddResource(pCommandList, ResourceType::CommandBuffer, "Command List");
// add the current deferred context ID as a parent
m_pDevice->GetReplay()->GetResourceDesc(m_CurContextId).derivedResources.push_back(pCommandList);
m_pDevice->GetReplay()->GetResourceDesc(pCommandList).parentResources.push_back(m_CurContextId);
// don't include this as an 'initialisation chunk'
m_pDevice->GetReplay()->GetResourceDesc(pCommandList).initialisationChunks.clear();
}
return true;
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_PostFinishCommandListSet(SerialiserType &ser,
ID3D11CommandList *pCommandList)
{
SERIALISE_ELEMENT_LOCAL(CommandList, GetIDForResource(pCommandList))
.TypedAs("ID3D11CommandList *");
D3D11RenderState RenderState(*m_CurrentPipelineState);
SERIALISE_ELEMENT(RenderState).Named("Initial Pipeline State");
SERIALISE_CHECK_READ_ERRORS();
// this is a 'fake' call we insert after finishing in a fresh deferred context, to allow us to
// preserve the state after a previous finish stole all the serialised chunks.
if(IsReplayingAndReading())
{
RenderState.ApplyState(this);
}
return true;
}
HRESULT WrappedID3D11DeviceContext::FinishCommandList(BOOL RestoreDeferredContextState,
ID3D11CommandList **ppCommandList)
{
if(GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE)
{
m_pDevice->AddDebugMessage(MessageCategory::Execution, MessageSeverity::High,
MessageSource::IncorrectAPIUse,
"It is invalid to call FinishCommandList on an immediate context. "
"The call has been dropped from the capture.");
return DXGI_ERROR_INVALID_CALL;
}
DrainAnnotationQueue();
ID3D11CommandList *real = NULL;
HRESULT hr;
SERIALISE_TIME_CALL(hr = m_pRealContext->FinishCommandList(RestoreDeferredContextState, &real));
RDCASSERT(GetType() == D3D11_DEVICE_CONTEXT_DEFERRED);
bool cmdListSuccessful = m_SuccessfulCapture;
if(!IsActiveCapturing(m_State) && !m_EmptyCommandList)
cmdListSuccessful = false;
WrappedID3D11CommandList *wrapped =
new WrappedID3D11CommandList(real, m_pDevice, this, cmdListSuccessful);
if(IsCaptureMode(m_State))
{
RDCASSERT(m_pDevice->GetResourceManager()->GetResourceRecord(wrapped->GetResourceID()) == NULL);
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
record->Length = 0;
record->ignoreSerialise = true;
if(IsActiveCapturing(m_State))
{
// if we got here and m_SuccessfulCapture is on, we have captured everything in this command
// list
if(m_SuccessfulCapture)
{
RDCDEBUG("Deferred Context %llu Finish()'d successfully! Got successful command list %llu",
GetResourceID(), wrapped->GetResourceID());
RDCASSERT(wrapped->IsCaptured());
ID3D11CommandList *w = wrapped;
// serialise the finish marker
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::FinishCommandList);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_FinishCommandList(GET_SERIALISER, RestoreDeferredContextState, &w);
m_ContextRecord->AddChunk(scope.Get());
}
D3D11ResourceRecord *r =
m_pDevice->GetResourceManager()->GetResourceRecord(wrapped->GetResourceID());
RDCASSERT(r);
// swap our chunks, references, and dirty resources with the 'baked' command list.
m_ContextRecord->SwapChunks(r);
wrapped->SwapReferences(m_DeferredReferences);
wrapped->SwapDirtyResources(m_DeferredDirty);
}
else // !m_SuccessfulCapture
{
RDCDEBUG(
"Deferred Context %llu wasn't successful, but now we've Finish()'d so it is! Produced "
"unsuccessful command list %llu.",
GetResourceID(), wrapped->GetResourceID());
RDCASSERT(!wrapped->IsCaptured());
// need to clear out anything we had serialised before
m_ContextRecord->LockChunks();
while(m_ContextRecord->HasChunks())
{
Chunk *chunk = m_ContextRecord->GetLastChunk();
SAFE_DELETE(chunk);
m_ContextRecord->PopChunk();
}
m_ContextRecord->UnlockChunks();
// clear the references, and delete the resource records so they aren't kept around forever
for(ResourceId id : m_DeferredReferences)
{
D3D11ResourceRecord *deferredRecord =
m_pDevice->GetResourceManager()->GetResourceRecord(id);
if(deferredRecord)
deferredRecord->Delete(m_pDevice->GetResourceManager());
}
m_DeferredReferences.clear();
// clear the dirty marks
m_DeferredDirty.clear();
// It's now 'successful' again, being empty
m_SuccessfulCapture = true;
}
// if we're supposed to restore, save the state to restore to now. This is because the next
// recording to this deferred context is expected to have the same state, but we don't have
// that state serialised right now. So we blat out the whole serialisation
if(RestoreDeferredContextState)
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::PostFinishCommandListSet);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_PostFinishCommandListSet(GET_SERIALISER, wrapped);
m_ContextRecord->AddChunk(scope.Get());
}
}
else // IsIdleCapturing(m_State)
{
// mark that this command list is empty so that if we immediately try and capture
// we pick up on that.
m_EmptyCommandList = true;
// still need to propagate up dirty resources to the immediate context
wrapped->SwapDirtyResources(m_DeferredDirty);
// clear the references and decref the resource records
for(ResourceId id : m_DeferredReferences)
{
D3D11ResourceRecord *deferredRecord = m_pDevice->GetResourceManager()->GetResourceRecord(id);
if(deferredRecord)
deferredRecord->Delete(m_pDevice->GetResourceManager());
}
m_DeferredReferences.clear();
RDCDEBUG(
"Deferred Context %llu not capturing at the moment, Produced unsuccessful command list "
"%llu.",
GetResourceID(), wrapped->GetResourceID());
}
}
if(!RestoreDeferredContextState)
m_CurrentPipelineState->Clear();
VerifyState();
if(ppCommandList)
*ppCommandList = wrapped;
return hr;
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_Flush(SerialiserType &ser)
{
if(IsReplayingAndReading())
{
m_pRealContext->Flush();
}
return true;
}
void WrappedID3D11DeviceContext::Flush()
{
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->Flush());
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::Flush);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_Flush(GET_SERIALISER);
m_ContextRecord->AddChunk(scope.Get());
m_CurrentPipelineState->MarkReferenced(this, false);
}
}
#pragma endregion Execute
#pragma region Copy
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CopySubresourceRegion(
SerialiserType &ser, ID3D11Resource *pDstResource, UINT DstSubresource, UINT DstX, UINT DstY,
UINT DstZ, ID3D11Resource *pSrcResource, UINT SrcSubresource, const D3D11_BOX *pSrcBox)
{
SERIALISE_ELEMENT(pDstResource);
SERIALISE_ELEMENT(DstSubresource);
SERIALISE_ELEMENT(DstX);
SERIALISE_ELEMENT(DstY);
SERIALISE_ELEMENT(DstZ);
SERIALISE_ELEMENT(pSrcResource);
SERIALISE_ELEMENT(SrcSubresource);
SERIALISE_ELEMENT_OPT(pSrcBox);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pDstResource && pSrcResource)
{
m_pRealContext->CopySubresourceRegion(
GetResourceManager()->UnwrapResource(pDstResource), DstSubresource, DstX, DstY, DstZ,
GetResourceManager()->UnwrapResource(pSrcResource), SrcSubresource, pSrcBox);
}
if(IsLoading(m_State))
{
ResourceId dstLiveID = GetIDForResource(pDstResource);
ResourceId srcLiveID = GetIDForResource(pSrcResource);
ResourceId dstOrigID = GetResourceManager()->GetOriginalID(dstLiveID);
ResourceId srcOrigID = GetResourceManager()->GetOriginalID(srcLiveID);
AddEvent();
DrawcallDescription draw;
draw.name = "CopySubresourceRegion(" + ToStr(dstOrigID) + ", " + ToStr(srcOrigID) + ")";
draw.flags |= DrawFlags::Copy;
if(pDstResource && pSrcResource)
{
draw.copySource = srcOrigID;
draw.copyDestination = dstOrigID;
if(m_CurEventID)
{
if(dstLiveID == srcLiveID)
{
m_ResourceUses[dstLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::Copy));
}
else
{
m_ResourceUses[dstLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::CopyDst));
m_ResourceUses[srcLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::CopySrc));
}
}
}
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::CopySubresourceRegion(ID3D11Resource *pDstResource,
UINT DstSubresource, UINT DstX, UINT DstY,
UINT DstZ, ID3D11Resource *pSrcResource,
UINT SrcSubresource, const D3D11_BOX *pSrcBox)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->CopySubresourceRegion(
m_pDevice->GetResourceManager()->UnwrapResource(pDstResource), DstSubresource, DstX, DstY,
DstZ, m_pDevice->GetResourceManager()->UnwrapResource(pSrcResource), SrcSubresource, pSrcBox));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CopySubresourceRegion);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CopySubresourceRegion(GET_SERIALISER, pDstResource, DstSubresource, DstX, DstY, DstZ,
pSrcResource, SrcSubresource, pSrcBox);
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pDstResource));
RDCASSERT(record);
D3D11ResourceRecord *srcRecord =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pSrcResource));
RDCASSERT(srcRecord);
record->AddParent(srcRecord);
m_ContextRecord->AddChunk(scope.Get());
m_MissingTracks.insert(GetIDForResource(pDstResource));
// assume partial update
MarkResourceReferenced(GetIDForResource(pDstResource), eFrameRef_Read);
MarkResourceReferenced(GetIDForResource(pDstResource), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pSrcResource), eFrameRef_Read);
}
else if(IsBackgroundCapturing(m_State))
{
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pDstResource));
RDCASSERT(record);
D3D11ResourceRecord *srcRecord =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pSrcResource));
RDCASSERT(srcRecord);
if(m_pDevice->GetResourceManager()->IsResourceDirty(GetIDForResource(pSrcResource)))
{
MarkDirtyResource(GetIDForResource(pDstResource));
}
else if(WrappedID3D11Buffer::IsAlloc(pDstResource) && WrappedID3D11Buffer::IsAlloc(pSrcResource))
{
// perform copy manually (since we have buffer contents locally)
RDCASSERT(record->DataInSerialiser);
RDCASSERT(srcRecord->DataInSerialiser);
byte *from = srcRecord->GetDataPtr();
byte *to = record->GetDataPtr();
to += DstX;
size_t length = (size_t)srcRecord->Length;
if(pSrcBox)
{
from += pSrcBox->left;
length = pSrcBox->right - pSrcBox->left;
}
if(length > 0)
{
memcpy(to, from, length);
}
}
else
{
// GPU dirty. Just let initial state handle this.
MarkDirtyResource(GetIDForResource(pDstResource));
}
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CopyResource(SerialiserType &ser,
ID3D11Resource *pDstResource,
ID3D11Resource *pSrcResource)
{
SERIALISE_ELEMENT(pDstResource);
SERIALISE_ELEMENT(pSrcResource);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pDstResource && pSrcResource)
{
m_pRealContext->CopyResource(m_pDevice->GetResourceManager()->UnwrapResource(pDstResource),
m_pDevice->GetResourceManager()->UnwrapResource(pSrcResource));
}
if(IsLoading(m_State))
{
ResourceId dstLiveID = GetIDForResource(pDstResource);
ResourceId srcLiveID = GetIDForResource(pSrcResource);
ResourceId dstOrigID = GetResourceManager()->GetOriginalID(dstLiveID);
ResourceId srcOrigID = GetResourceManager()->GetOriginalID(srcLiveID);
AddEvent();
DrawcallDescription draw;
draw.name = "CopyResource(" + ToStr(dstOrigID) + ", " + ToStr(srcOrigID) + ")";
draw.flags |= DrawFlags::Copy;
if(pDstResource && pSrcResource)
{
draw.copySource = srcOrigID;
draw.copyDestination = dstOrigID;
if(m_CurEventID)
{
if(dstLiveID == srcLiveID)
{
m_ResourceUses[dstLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::Copy));
}
else
{
m_ResourceUses[dstLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::CopyDst));
m_ResourceUses[srcLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::CopySrc));
}
}
}
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::CopyResource(ID3D11Resource *pDstResource,
ID3D11Resource *pSrcResource)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(
m_pRealContext->CopyResource(m_pDevice->GetResourceManager()->UnwrapResource(pDstResource),
m_pDevice->GetResourceManager()->UnwrapResource(pSrcResource)));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CopyResource);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CopyResource(GET_SERIALISER, pDstResource, pSrcResource);
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pDstResource));
RDCASSERT(record);
D3D11ResourceRecord *srcRecord =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pSrcResource));
RDCASSERT(srcRecord);
record->AddParent(srcRecord);
m_ContextRecord->AddChunk(scope.Get());
m_MissingTracks.insert(GetIDForResource(pDstResource));
MarkResourceReferenced(GetIDForResource(pDstResource), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pSrcResource), eFrameRef_Read);
}
else if(IsBackgroundCapturing(m_State))
{
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pDstResource));
RDCASSERT(record);
D3D11ResourceRecord *srcRecord =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pSrcResource));
RDCASSERT(srcRecord);
record->UpdateCount++;
if(record->UpdateCount > 5 ||
m_pDevice->GetResourceManager()->IsResourceDirty(GetIDForResource(pSrcResource)))
{
MarkDirtyResource(GetIDForResource(pDstResource));
}
else if(WrappedID3D11Buffer::IsAlloc(pDstResource) && WrappedID3D11Buffer::IsAlloc(pSrcResource))
{
// perform copy manually (since we have buffer contents locally)
RDCASSERT(record->DataInSerialiser);
RDCASSERT(srcRecord->DataInSerialiser);
byte *from = srcRecord->GetDataPtr();
byte *to = record->GetDataPtr();
memcpy(to, from, (size_t)record->Length);
}
else if((WrappedID3D11Texture1D::IsAlloc(pDstResource) &&
WrappedID3D11Texture1D::IsAlloc(pSrcResource)) ||
(WrappedID3D11Texture2D1::IsAlloc(pDstResource) &&
WrappedID3D11Texture2D1::IsAlloc(pSrcResource)) ||
(WrappedID3D11Texture3D1::IsAlloc(pDstResource) &&
WrappedID3D11Texture3D1::IsAlloc(pSrcResource)))
{
if(record->DataInSerialiser && srcRecord->DataInSerialiser)
{
RDCASSERT(record->NumSubResources == srcRecord->NumSubResources);
for(int i = 0; i < record->NumSubResources; i++)
{
byte *from = srcRecord->SubResources[i]->GetDataPtr();
byte *to = record->SubResources[i]->GetDataPtr();
memcpy(to, from, (size_t)record->SubResources[i]->Length);
}
}
else
{
// can't copy without data allocated
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CopyResource);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CopyResource(GET_SERIALISER, pDstResource, pSrcResource);
record->AddChunk(scope.Get());
record->AddParent(srcRecord);
}
}
else
{
RDCERR("Unexpected resource type");
}
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_UpdateSubresource(
SerialiserType &ser, ID3D11Resource *pDstResource, UINT DstSubresource,
const D3D11_BOX *pDstBox, const void *pSrcData, UINT SrcRowPitch, UINT SrcDepthPitch)
{
// pass ~0U as the flags to indicate this came for UpdateSubresource, so we know to apply
// deferred context workarounds or not
return Serialise_UpdateSubresource1(ser, pDstResource, DstSubresource, pDstBox, pSrcData,
SrcRowPitch, SrcDepthPitch, ~0U);
}
void WrappedID3D11DeviceContext::UpdateSubresource(ID3D11Resource *pDstResource, UINT DstSubresource,
const D3D11_BOX *pDstBox, const void *pSrcData,
UINT SrcRowPitch, UINT SrcDepthPitch)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->UpdateSubresource(
m_pDevice->GetResourceManager()->UnwrapResource(pDstResource), DstSubresource, pDstBox,
pSrcData, SrcRowPitch, SrcDepthPitch));
if(pDstBox && m_NeedUpdateSubWorkaround && GetType() == D3D11_DEVICE_CONTEXT_DEFERRED)
{
// we need to apply the *inverse* of the workaround, which matches the broken D3D behaviour
// so that we end up pointing at the expected data.
D3D11_BOX alignedBox = *pDstBox;
DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN;
if(WrappedID3D11Texture1D::IsAlloc(pDstResource))
{
D3D11_TEXTURE1D_DESC desc;
((WrappedID3D11Texture1D *)pDstResource)->GetDesc(&desc);
fmt = desc.Format;
}
else if(WrappedID3D11Texture2D1::IsAlloc(pDstResource))
{
D3D11_TEXTURE2D_DESC desc;
((WrappedID3D11Texture2D1 *)pDstResource)->GetDesc(&desc);
fmt = desc.Format;
}
else if(WrappedID3D11Texture3D1::IsAlloc(pDstResource))
{
D3D11_TEXTURE3D_DESC desc;
((WrappedID3D11Texture3D1 *)pDstResource)->GetDesc(&desc);
fmt = desc.Format;
}
else
{
RDCASSERT(WrappedID3D11Buffer::IsAlloc(pDstResource));
}
// convert from pixels to blocks
if(IsBlockFormat(fmt))
{
alignedBox.left /= 4;
alignedBox.right /= 4;
alignedBox.top /= 4;
alignedBox.bottom /= 4;
}
// if we couldn't get a format it's a buffer, so work in bytes
if(fmt != DXGI_FORMAT_UNKNOWN)
pSrcData = ((const BYTE *)pSrcData) + (alignedBox.front * SrcDepthPitch) +
(alignedBox.top * SrcRowPitch) + (alignedBox.left * GetByteSize(1, 1, 1, fmt, 0));
else
pSrcData = ((const BYTE *)pSrcData) + (alignedBox.left);
}
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::UpdateSubresource);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_UpdateSubresource(GET_SERIALISER, pDstResource, DstSubresource, pDstBox, pSrcData,
SrcRowPitch, SrcDepthPitch);
m_MissingTracks.insert(GetIDForResource(pDstResource));
m_ContextRecord->AddChunk(scope.Get());
}
else if(IsBackgroundCapturing(m_State))
{
ResourceId idx = GetIDForResource(pDstResource);
D3D11ResourceRecord *record = m_pDevice->GetResourceManager()->GetResourceRecord(idx);
RDCASSERT(record);
// buffers MUST update the whole resource, and don't have any subresources,
// so this effectively becomes just a map/unmap pair.
if(WrappedID3D11Buffer::IsAlloc(pDstResource))
{
RDCASSERT(record->NumSubResources == 0);
size_t offs = 0;
size_t length = (size_t)record->Length;
if(pDstBox)
{
offs += pDstBox->left;
length = RDCMIN((uint32_t)length, pDstBox->right - pDstBox->left);
}
RDCASSERT(record->DataInSerialiser);
void *ptr = record->GetDataPtr() + offs;
memcpy(ptr, pSrcData, length);
}
else if(WrappedID3D11Texture1D::IsAlloc(pDstResource) ||
WrappedID3D11Texture2D1::IsAlloc(pDstResource) ||
WrappedID3D11Texture3D1::IsAlloc(pDstResource))
{
RDCASSERT(record->Length == 1 && record->NumSubResources > 0);
if(DstSubresource >= (UINT)record->NumSubResources)
{
RDCERR("DstSubresource %u >= %u (num subresources)", DstSubresource, record->NumSubResources);
return;
}
// this record isn't in the log already, write out a chunk that we can update after.
if(!record->SubResources[DstSubresource]->DataInSerialiser)
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::UpdateSubresource);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_UpdateSubresource(GET_SERIALISER, pDstResource, DstSubresource, pDstBox, pSrcData,
SrcRowPitch, SrcDepthPitch);
Chunk *chunk = scope.Get();
record->AddChunk(chunk);
record->SubResources[DstSubresource]->SetDataPtr(chunk->GetData());
record->SubResources[DstSubresource]->DataInSerialiser = true;
}
{
RDCASSERT(record->SubResources[DstSubresource]->DataInSerialiser);
void *ptr = record->SubResources[DstSubresource]->GetDataPtr();
// if the box is empty, we don't have to do anything! hooray!
if(pDstBox && (pDstBox->back == pDstBox->front || pDstBox->left == pDstBox->right ||
pDstBox->top == pDstBox->bottom))
{
// empty, do nothing.
}
else
{
WrappedID3D11Texture1D *tex1 = WrappedID3D11Texture1D::IsAlloc(pDstResource)
? (WrappedID3D11Texture1D *)pDstResource
: NULL;
WrappedID3D11Texture2D1 *tex2 = WrappedID3D11Texture2D1::IsAlloc(pDstResource)
? (WrappedID3D11Texture2D1 *)pDstResource
: NULL;
WrappedID3D11Texture3D1 *tex3 = WrappedID3D11Texture3D1::IsAlloc(pDstResource)
? (WrappedID3D11Texture3D1 *)pDstResource
: NULL;
RDCASSERT(tex1 || tex2 || tex3);
DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN;
UINT subWidth = 1;
UINT subHeight = 1;
UINT subDepth = 1;
UINT mipLevel = GetMipForSubresource(pDstResource, DstSubresource);
if(tex1)
{
D3D11_TEXTURE1D_DESC desc = {0};
tex1->GetDesc(&desc);
fmt = desc.Format;
subWidth = RDCMAX(1U, desc.Width >> mipLevel);
}
else if(tex2)
{
D3D11_TEXTURE2D_DESC desc = {0};
tex2->GetDesc(&desc);
fmt = desc.Format;
subWidth = RDCMAX(1U, desc.Width >> mipLevel);
subHeight = RDCMAX(1U, desc.Height >> mipLevel);
}
else if(tex3)
{
D3D11_TEXTURE3D_DESC desc = {0};
tex3->GetDesc(&desc);
fmt = desc.Format;
subWidth = RDCMAX(1U, desc.Width >> mipLevel);
subHeight = RDCMAX(1U, desc.Height >> mipLevel);
subDepth = RDCMAX(1U, desc.Depth >> mipLevel);
}
UINT boxWidth = pDstBox ? pDstBox->right - pDstBox->left : subWidth;
UINT boxHeight = pDstBox ? pDstBox->bottom - pDstBox->top : subHeight;
UINT boxDepth = pDstBox ? pDstBox->back - pDstBox->front : subDepth;
UINT boxTop = pDstBox ? pDstBox->top : 0;
UINT DstRowPitch = GetByteSize(subWidth, 1, 1, fmt, 0);
UINT DstBoxRowPitch = GetByteSize(boxWidth, 1, 1, fmt, 0);
UINT DstSlicePitch = GetByteSize(subWidth, subHeight, 1, fmt, 0);
// for block formats, rows are in blocks (so height is squished essentially)
if(IsBlockFormat(fmt))
{
subWidth = AlignUp4(subWidth);
subHeight = AlignUp4(RDCMAX(1U, subHeight / 4));
boxHeight = RDCMAX(1U, boxHeight / 4);
boxTop = RDCMAX(0U, boxTop / 4);
}
RDCASSERT(boxWidth <= subWidth && boxHeight <= subHeight && boxDepth <= subDepth);
bool totalUpdate = false;
// if there is no box, it's a totalUpdate (boxwidth/height are equal by inspection from
// the initialisation above)
// if the box describes the whole subresource, it's a totalUpdate
if(boxWidth == subWidth && boxHeight == subHeight && boxDepth == subDepth)
totalUpdate = true;
// fast path for a total update from a source of the same size
if(totalUpdate &&
((tex1 && (UINT)record->SubResources[DstSubresource]->Length == SrcRowPitch) ||
(tex2 && (UINT)record->SubResources[DstSubresource]->Length == SrcRowPitch * subHeight) ||
(tex3 && (UINT)record->SubResources[DstSubresource]->Length == SrcDepthPitch * subDepth)))
{
memcpy(ptr, pSrcData, (size_t)record->SubResources[DstSubresource]->Length);
}
else
{
// need to fall back to copying row by row from the source
byte *dstBuf = (byte *)ptr;
byte *src = (byte *)pSrcData;
// if we have a box, skip to the front of it
if(pDstBox)
dstBuf += DstSlicePitch * pDstBox->front;
for(UINT slice = 0; slice < boxDepth; slice++)
{
byte *slicedst = dstBuf;
byte *slicesrc = src;
// if we have a box, skip to the top of it
if(pDstBox)
slicedst += DstRowPitch * boxTop;
for(UINT row = 0; row < boxHeight; row++)
{
byte *rowdst = slicedst;
// if we have a box, skip to the left of it
if(pDstBox && pDstBox->left > 0)
rowdst += GetByteSize(pDstBox->left, 1, 1, fmt, 0);
memcpy(rowdst, slicesrc, DstBoxRowPitch);
slicedst += DstRowPitch;
slicesrc += SrcRowPitch;
}
dstBuf += DstSlicePitch;
src += SrcDepthPitch;
}
}
}
}
}
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_CopyStructureCount(SerialiserType &ser,
ID3D11Buffer *pDstBuffer,
UINT DstAlignedByteOffset,
ID3D11UnorderedAccessView *pSrcView)
{
SERIALISE_ELEMENT(pDstBuffer);
SERIALISE_ELEMENT(DstAlignedByteOffset);
SERIALISE_ELEMENT(pSrcView);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading() && pDstBuffer && pSrcView)
{
m_pRealContext->CopyStructureCount(UNWRAP(WrappedID3D11Buffer, pDstBuffer), DstAlignedByteOffset,
UNWRAP(WrappedID3D11UnorderedAccessView1, pSrcView));
}
return true;
}
void WrappedID3D11DeviceContext::CopyStructureCount(ID3D11Buffer *pDstBuffer,
UINT DstAlignedByteOffset,
ID3D11UnorderedAccessView *pSrcView)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->CopyStructureCount(
UNWRAP(WrappedID3D11Buffer, pDstBuffer), DstAlignedByteOffset,
UNWRAP(WrappedID3D11UnorderedAccessView1, pSrcView)));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CopyStructureCount);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_CopyStructureCount(GET_SERIALISER, pDstBuffer, DstAlignedByteOffset, pSrcView);
m_ContextRecord->AddChunk(scope.Get());
m_MissingTracks.insert(GetIDForResource(pDstBuffer));
MarkResourceReferenced(GetIDForResource(pDstBuffer), eFrameRef_Read);
MarkResourceReferenced(GetIDForResource(pDstBuffer), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pSrcView), eFrameRef_Read);
}
else if(IsBackgroundCapturing(m_State))
{
// needs to go into device serialiser
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pDstBuffer));
RDCASSERT(record);
D3D11ResourceRecord *srcRecord =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pSrcView));
RDCASSERT(srcRecord);
record->AddParent(srcRecord);
MarkDirtyResource(GetViewResourceResID(pSrcView));
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_ResolveSubresource(SerialiserType &ser,
ID3D11Resource *pDstResource,
UINT DstSubresource,
ID3D11Resource *pSrcResource,
UINT SrcSubresource, DXGI_FORMAT Format)
{
SERIALISE_ELEMENT(pDstResource);
SERIALISE_ELEMENT(DstSubresource);
SERIALISE_ELEMENT(pSrcResource);
SERIALISE_ELEMENT(SrcSubresource);
SERIALISE_ELEMENT(Format);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pDstResource && pSrcResource)
{
m_pRealContext->ResolveSubresource(
m_pDevice->GetResourceManager()->UnwrapResource(pDstResource), DstSubresource,
m_pDevice->GetResourceManager()->UnwrapResource(pSrcResource), SrcSubresource, Format);
}
if(IsLoading(m_State))
{
ResourceId dstLiveID = GetIDForResource(pDstResource);
ResourceId srcLiveID = GetIDForResource(pSrcResource);
ResourceId dstOrigID = GetResourceManager()->GetOriginalID(dstLiveID);
ResourceId srcOrigID = GetResourceManager()->GetOriginalID(srcLiveID);
AddEvent();
DrawcallDescription draw;
draw.name = "ResolveSubresource(" + ToStr(dstOrigID) + ", " + ToStr(srcOrigID) + ")";
draw.flags |= DrawFlags::Resolve;
if(pDstResource && pSrcResource)
{
draw.copySource = srcOrigID;
draw.copyDestination = dstOrigID;
if(m_CurEventID)
{
if(dstLiveID == srcLiveID)
{
m_ResourceUses[dstLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::Resolve));
}
else
{
m_ResourceUses[dstLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::ResolveDst));
m_ResourceUses[srcLiveID].push_back(EventUsage(m_CurEventID, ResourceUsage::ResolveSrc));
}
}
}
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::ResolveSubresource(ID3D11Resource *pDstResource,
UINT DstSubresource, ID3D11Resource *pSrcResource,
UINT SrcSubresource, DXGI_FORMAT Format)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->ResolveSubresource(
m_pDevice->GetResourceManager()->UnwrapResource(pDstResource), DstSubresource,
m_pDevice->GetResourceManager()->UnwrapResource(pSrcResource), SrcSubresource, Format));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::ResolveSubresource);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_ResolveSubresource(GET_SERIALISER, pDstResource, DstSubresource, pSrcResource,
SrcSubresource, Format);
m_ContextRecord->AddChunk(scope.Get());
m_MissingTracks.insert(GetIDForResource(pDstResource));
MarkResourceReferenced(GetIDForResource(pDstResource), eFrameRef_Read);
MarkResourceReferenced(GetIDForResource(pDstResource), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pSrcResource), eFrameRef_Read);
}
else if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetIDForResource(pDstResource));
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_GenerateMips(SerialiserType &ser,
ID3D11ShaderResourceView *pShaderResourceView)
{
SERIALISE_ELEMENT(pShaderResourceView);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pShaderResourceView)
{
m_pRealContext->GenerateMips(UNWRAP(WrappedID3D11ShaderResourceView1, pShaderResourceView));
}
if(IsLoading(m_State))
{
WrappedID3D11ShaderResourceView1 *view =
(WrappedID3D11ShaderResourceView1 *)pShaderResourceView;
if(view)
{
m_ResourceUses[view->GetResourceResID()].push_back(
EventUsage(m_CurEventID, ResourceUsage::GenMips, view->GetResourceID()));
}
AddEvent();
DrawcallDescription draw;
draw.name =
"GenerateMips(" +
ToStr(GetResourceManager()->GetOriginalID(GetIDForResource(pShaderResourceView))) + ")";
draw.flags |= DrawFlags::GenMips;
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::GenerateMips(ID3D11ShaderResourceView *pShaderResourceView)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
if(!pShaderResourceView)
return;
SERIALISE_TIME_CALL(
m_pRealContext->GenerateMips(UNWRAP(WrappedID3D11ShaderResourceView1, pShaderResourceView)));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::GenerateMips);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_GenerateMips(GET_SERIALISER, pShaderResourceView);
m_ContextRecord->AddChunk(scope.Get());
ResourceId id = GetViewResourceResID(pShaderResourceView);
m_MissingTracks.insert(id);
MarkResourceReferenced(id, eFrameRef_Read);
MarkResourceReferenced(id, eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pShaderResourceView), eFrameRef_Read);
}
else if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetViewResourceResID(pShaderResourceView));
}
}
#pragma endregion Copy
#pragma region Clear
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_ClearState(SerialiserType &ser)
{
if(IsReplayingAndReading())
{
m_CurrentPipelineState->Clear();
m_pRealContext->ClearState();
VerifyState();
}
return true;
}
void WrappedID3D11DeviceContext::ClearState()
{
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->ClearState());
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::ClearState);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_ClearState(GET_SERIALISER);
m_ContextRecord->AddChunk(scope.Get());
}
m_CurrentPipelineState->Clear();
VerifyState();
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_ClearRenderTargetView(
SerialiserType &ser, ID3D11RenderTargetView *pRenderTargetView, const FLOAT ColorRGBA[4])
{
SERIALISE_ELEMENT(pRenderTargetView);
SERIALISE_ELEMENT_ARRAY(ColorRGBA, 4);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pRenderTargetView)
{
m_pRealContext->ClearRenderTargetView(
UNWRAP(WrappedID3D11RenderTargetView1, pRenderTargetView), ColorRGBA);
}
if(IsLoading(m_State))
{
AddEvent();
WrappedID3D11RenderTargetView1 *view = (WrappedID3D11RenderTargetView1 *)pRenderTargetView;
DrawcallDescription draw;
draw.name = StringFormat::Fmt("ClearRenderTargetView(%f, %f, %f, %f)", ColorRGBA[0],
ColorRGBA[1], ColorRGBA[2], ColorRGBA[3]);
draw.flags |= DrawFlags::Clear | DrawFlags::ClearColor;
if(view)
{
m_ResourceUses[view->GetResourceResID()].push_back(
EventUsage(m_CurEventID, ResourceUsage::Clear, view->GetResourceID()));
draw.copyDestination =
m_pDevice->GetResourceManager()->GetOriginalID(view->GetResourceResID());
}
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::ClearRenderTargetView(ID3D11RenderTargetView *pRenderTargetView,
const FLOAT ColorRGBA[4])
{
DrainAnnotationQueue();
if(pRenderTargetView == NULL)
return;
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->ClearRenderTargetView(
UNWRAP(WrappedID3D11RenderTargetView1, pRenderTargetView), ColorRGBA));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::ClearRenderTargetView);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_ClearRenderTargetView(GET_SERIALISER, pRenderTargetView, ColorRGBA);
if(pRenderTargetView)
{
MarkResourceReferenced(GetViewResourceResID(pRenderTargetView), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pRenderTargetView), eFrameRef_Read);
}
m_MissingTracks.insert(GetViewResourceResID(pRenderTargetView));
m_ContextRecord->AddChunk(scope.Get());
}
else if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetViewResourceResID(pRenderTargetView));
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_ClearUnorderedAccessViewUint(
SerialiserType &ser, ID3D11UnorderedAccessView *pUnorderedAccessView, const UINT Values[4])
{
SERIALISE_ELEMENT(pUnorderedAccessView);
SERIALISE_ELEMENT_ARRAY(Values, 4);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pUnorderedAccessView)
{
m_pRealContext->ClearUnorderedAccessViewUint(
UNWRAP(WrappedID3D11UnorderedAccessView1, pUnorderedAccessView), Values);
}
if(IsLoading(m_State))
{
AddEvent();
WrappedID3D11UnorderedAccessView1 *view =
(WrappedID3D11UnorderedAccessView1 *)pUnorderedAccessView;
DrawcallDescription draw;
draw.name = StringFormat::Fmt("ClearUnorderedAccessViewUint(%u, %u, %u, %u)", Values[0],
Values[1], Values[2], Values[3]);
draw.flags |= DrawFlags::Clear;
if(view)
{
m_ResourceUses[view->GetResourceResID()].push_back(
EventUsage(m_CurEventID, ResourceUsage::Clear, view->GetResourceID()));
draw.copyDestination =
m_pDevice->GetResourceManager()->GetOriginalID(view->GetResourceResID());
}
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::ClearUnorderedAccessViewUint(
ID3D11UnorderedAccessView *pUnorderedAccessView, const UINT Values[4])
{
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->ClearUnorderedAccessViewUint(
UNWRAP(WrappedID3D11UnorderedAccessView1, pUnorderedAccessView), Values));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::ClearUnorderedAccessViewUint);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_ClearUnorderedAccessViewUint(GET_SERIALISER, pUnorderedAccessView, Values);
if(pUnorderedAccessView)
{
MarkResourceReferenced(GetViewResourceResID(pUnorderedAccessView), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pUnorderedAccessView), eFrameRef_Read);
}
m_MissingTracks.insert(GetViewResourceResID(pUnorderedAccessView));
m_ContextRecord->AddChunk(scope.Get());
}
else if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetViewResourceResID(pUnorderedAccessView));
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_ClearUnorderedAccessViewFloat(
SerialiserType &ser, ID3D11UnorderedAccessView *pUnorderedAccessView, const FLOAT Values[4])
{
SERIALISE_ELEMENT(pUnorderedAccessView);
SERIALISE_ELEMENT_ARRAY(Values, 4);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pUnorderedAccessView)
{
m_pRealContext->ClearUnorderedAccessViewFloat(
UNWRAP(WrappedID3D11UnorderedAccessView1, pUnorderedAccessView), Values);
}
if(IsLoading(m_State))
{
AddEvent();
WrappedID3D11UnorderedAccessView1 *view =
(WrappedID3D11UnorderedAccessView1 *)pUnorderedAccessView;
DrawcallDescription draw;
draw.name = StringFormat::Fmt("ClearUnorderedAccessViewFloat(%f, %f, %f, %f)", Values[0],
Values[1], Values[2], Values[3]);
draw.flags |= DrawFlags::Clear;
if(view)
{
m_ResourceUses[view->GetResourceResID()].push_back(
EventUsage(m_CurEventID, ResourceUsage::Clear, view->GetResourceID()));
draw.copyDestination =
m_pDevice->GetResourceManager()->GetOriginalID(view->GetResourceResID());
}
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::ClearUnorderedAccessViewFloat(
ID3D11UnorderedAccessView *pUnorderedAccessView, const FLOAT Values[4])
{
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->ClearUnorderedAccessViewFloat(
UNWRAP(WrappedID3D11UnorderedAccessView1, pUnorderedAccessView), Values));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::ClearUnorderedAccessViewFloat);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_ClearUnorderedAccessViewFloat(GET_SERIALISER, pUnorderedAccessView, Values);
if(pUnorderedAccessView)
{
MarkResourceReferenced(GetViewResourceResID(pUnorderedAccessView), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pUnorderedAccessView), eFrameRef_Read);
}
m_MissingTracks.insert(GetViewResourceResID(pUnorderedAccessView));
m_ContextRecord->AddChunk(scope.Get());
}
else if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetViewResourceResID(pUnorderedAccessView));
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_ClearDepthStencilView(
SerialiserType &ser, ID3D11DepthStencilView *pDepthStencilView, UINT ClearFlags, FLOAT Depth,
UINT8 Stencil)
{
SERIALISE_ELEMENT(pDepthStencilView);
SERIALISE_ELEMENT_TYPED(D3D11_CLEAR_FLAG, ClearFlags);
SERIALISE_ELEMENT(Depth);
SERIALISE_ELEMENT(Stencil);
Serialise_DebugMessages(GET_SERIALISER);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pDepthStencilView)
{
m_pRealContext->ClearDepthStencilView(
UNWRAP(WrappedID3D11DepthStencilView, pDepthStencilView), ClearFlags, Depth, Stencil);
}
if(IsLoading(m_State))
{
AddEvent();
WrappedID3D11DepthStencilView *view = (WrappedID3D11DepthStencilView *)pDepthStencilView;
DrawcallDescription draw;
if(ClearFlags == (D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL))
draw.name = StringFormat::Fmt("ClearDepthStencilView(D=%f, S=%02hhx)", Depth, Stencil);
else if(ClearFlags == D3D11_CLEAR_DEPTH)
draw.name = StringFormat::Fmt("ClearDepthStencilView(D=%f)", Depth);
else if(ClearFlags == D3D11_CLEAR_STENCIL)
draw.name = StringFormat::Fmt("ClearDepthStencilView(S=%02hhx)", Stencil);
else
draw.name = "ClearDepthStencilView(None)";
draw.flags |= DrawFlags::Clear | DrawFlags::ClearDepthStencil;
if(view)
{
m_ResourceUses[view->GetResourceResID()].push_back(
EventUsage(m_CurEventID, ResourceUsage::Clear, view->GetResourceID()));
draw.copyDestination =
m_pDevice->GetResourceManager()->GetOriginalID(view->GetResourceResID());
}
AddDrawcall(draw, true);
}
}
return true;
}
void WrappedID3D11DeviceContext::ClearDepthStencilView(ID3D11DepthStencilView *pDepthStencilView,
UINT ClearFlags, FLOAT Depth, UINT8 Stencil)
{
DrainAnnotationQueue();
if(pDepthStencilView == NULL)
return;
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->ClearDepthStencilView(
UNWRAP(WrappedID3D11DepthStencilView, pDepthStencilView), ClearFlags, Depth, Stencil));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
GET_SERIALISER.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::ClearDepthStencilView);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_ClearDepthStencilView(GET_SERIALISER, pDepthStencilView, ClearFlags, Depth, Stencil);
if(pDepthStencilView)
{
MarkResourceReferenced(GetViewResourceResID(pDepthStencilView), eFrameRef_Write);
MarkResourceReferenced(GetIDForResource(pDepthStencilView), eFrameRef_Read);
}
m_MissingTracks.insert(GetViewResourceResID(pDepthStencilView));
m_ContextRecord->AddChunk(scope.Get());
}
else if(IsBackgroundCapturing(m_State))
{
MarkDirtyResource(GetViewResourceResID(pDepthStencilView));
}
}
#pragma endregion Clear
#pragma region Misc
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_Begin(SerialiserType &ser, ID3D11Asynchronous *pAsync)
{
SERIALISE_ELEMENT(pAsync);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading() && pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
// only replay predicates which can affect rendering, don't re-submit queries or counters (that
// might even interfere with queries we want to run)
if(WrappedID3D11Predicate::IsAlloc(pAsync))
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
// if you change this to replay other types, check with Serialise_CreateCounter which creates
// dummy queries to ensure it always succeeds.
if(unwrapped)
m_pRealContext->Begin(unwrapped);
}
return true;
}
void WrappedID3D11DeviceContext::Begin(ID3D11Asynchronous *pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
ResourceId id;
if(WrappedID3D11Query1::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Query1, pAsync);
id = ((WrappedID3D11Query1 *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Predicate::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
id = ((WrappedID3D11Predicate *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Counter::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Counter, pAsync);
id = ((WrappedID3D11Counter *)pAsync)->GetResourceID();
}
else
{
RDCERR("Unexpected ID3D11Asynchronous");
}
SERIALISE_TIME_CALL(m_pRealContext->Begin(unwrapped));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::Begin);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_Begin(GET_SERIALISER, pAsync);
m_ContextRecord->AddChunk(scope.Get());
MarkResourceReferenced(id, eFrameRef_Read);
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_End(SerialiserType &ser, ID3D11Asynchronous *pAsync)
{
SERIALISE_ELEMENT(pAsync);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading() && pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
// only replay predicates which can affect rendering, don't re-submit queries or counters (that
// might even interfere with queries we want to run)
if(WrappedID3D11Predicate::IsAlloc(pAsync))
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
// if you change this to replay other types, check with Serialise_CreateCounter which creates
// dummy queries to ensure it always succeeds.
if(unwrapped)
m_pRealContext->End(unwrapped);
}
return true;
}
void WrappedID3D11DeviceContext::End(ID3D11Asynchronous *pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
ResourceId id;
if(WrappedID3D11Query1::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Query1, pAsync);
id = ((WrappedID3D11Query1 *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Predicate::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
id = ((WrappedID3D11Predicate *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Counter::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Counter, pAsync);
id = ((WrappedID3D11Counter *)pAsync)->GetResourceID();
}
else
{
RDCERR("Unexpected ID3D11Asynchronous");
}
SERIALISE_TIME_CALL(m_pRealContext->End(unwrapped));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::End);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_End(GET_SERIALISER, pAsync);
m_ContextRecord->AddChunk(scope.Get());
MarkResourceReferenced(id, eFrameRef_Read);
}
}
HRESULT WrappedID3D11DeviceContext::GetData(ID3D11Asynchronous *pAsync, void *pData, UINT DataSize,
UINT GetDataFlags)
{
ID3D11Asynchronous *unwrapped = NULL;
if(WrappedID3D11Query1::IsAlloc(pAsync))
unwrapped = UNWRAP(WrappedID3D11Query1, pAsync);
else if(WrappedID3D11Predicate::IsAlloc(pAsync))
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
else if(WrappedID3D11Counter::IsAlloc(pAsync))
unwrapped = UNWRAP(WrappedID3D11Counter, pAsync);
else
RDCERR("Unexpected ID3D11Asynchronous");
return m_pRealContext->GetData(unwrapped, pData, DataSize, GetDataFlags);
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_SetPredication(SerialiserType &ser,
ID3D11Predicate *pPredicate,
BOOL PredicateValue_)
{
SERIALISE_ELEMENT(pPredicate);
SERIALISE_ELEMENT_LOCAL(PredicateValue, PredicateValue_ == TRUE);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// we don't replay predication as it can be confusing and inconsistent. We just store the state
// so that we can manually check whether it *would* have passed or failed.
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->Predicate, pPredicate);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PredicateValue,
PredicateValue ? TRUE : FALSE);
/*
m_pRealContext->SetPredication(UNWRAP(WrappedID3D11Predicate, pPredicate),
PredicateValue ? TRUE : FALSE);
*/
}
return true;
}
void WrappedID3D11DeviceContext::SetPredication(ID3D11Predicate *pPredicate, BOOL PredicateValue)
{
m_EmptyCommandList = false;
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->Predicate, pPredicate);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PredicateValue, PredicateValue);
// on replay don't actually apply any predication. Just update the state and bail
if(IsReplayMode(m_State))
return;
SERIALISE_TIME_CALL(
m_pRealContext->SetPredication(UNWRAP(WrappedID3D11Predicate, pPredicate), PredicateValue));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::SetPredication);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_SetPredication(GET_SERIALISER, pPredicate, PredicateValue);
m_ContextRecord->AddChunk(scope.Get());
if(pPredicate)
{
ResourceId id = ((WrappedID3D11Predicate *)pPredicate)->GetResourceID();
MarkResourceReferenced(id, eFrameRef_Read);
}
}
}
FLOAT WrappedID3D11DeviceContext::GetResourceMinLOD(ID3D11Resource *pResource)
{
return m_pRealContext->GetResourceMinLOD(m_pDevice->GetResourceManager()->UnwrapResource(pResource));
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_SetResourceMinLOD(SerialiserType &ser,
ID3D11Resource *pResource, FLOAT MinLOD)
{
SERIALISE_ELEMENT(pResource);
SERIALISE_ELEMENT(MinLOD);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
if(pResource)
m_pRealContext->SetResourceMinLOD(pResource, MinLOD);
}
return true;
}
void WrappedID3D11DeviceContext::SetResourceMinLOD(ID3D11Resource *pResource, FLOAT MinLOD)
{
m_EmptyCommandList = false;
SERIALISE_TIME_CALL(m_pRealContext->SetResourceMinLOD(
m_pDevice->GetResourceManager()->UnwrapResource(pResource), MinLOD));
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::SetResourceMinLOD);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_SetResourceMinLOD(GET_SERIALISER, pResource, MinLOD);
m_ContextRecord->AddChunk(scope.Get());
}
}
void WrappedID3D11DeviceContext::GetPredication(ID3D11Predicate **ppPredicate, BOOL *pPredicateValue)
{
ID3D11Predicate *real = NULL;
m_pRealContext->GetPredication(&real, pPredicateValue);
SAFE_RELEASE_NOCLEAR(real);
if(ppPredicate)
{
if(real)
*ppPredicate = UNWRAP(WrappedID3D11Predicate, real);
else
*ppPredicate = NULL;
}
}
D3D11_DEVICE_CONTEXT_TYPE WrappedID3D11DeviceContext::GetType()
{
return m_pRealContext->GetType();
}
UINT WrappedID3D11DeviceContext::GetContextFlags()
{
return m_pRealContext->GetContextFlags();
}
#pragma endregion Misc
#pragma region Map
void MapIntercept::SetAppMemory(void *appMemory)
{
app.pData = appMemory;
}
void MapIntercept::SetD3D(D3D11_SUBRESOURCE_DATA d3dData)
{
D3D11_MAPPED_SUBRESOURCE d3dMap;
d3dMap.pData = (void *)d3dData.pSysMem;
d3dMap.RowPitch = d3dData.SysMemPitch;
d3dMap.DepthPitch = d3dData.SysMemSlicePitch;
d3d = d3dMap;
RDCASSERT(d3d.pData);
}
void MapIntercept::SetD3D(D3D11_MAPPED_SUBRESOURCE d3dMap)
{
d3d = d3dMap;
RDCASSERT(d3d.pData);
}
void MapIntercept::InitWrappedResource(ID3D11Resource *res, UINT sub, void *appMemory)
{
if(WrappedID3D11Buffer::IsAlloc(res))
Init((ID3D11Buffer *)res, appMemory);
else if(WrappedID3D11Texture1D::IsAlloc(res))
Init((ID3D11Texture1D *)res, sub, appMemory);
else if(WrappedID3D11Texture2D1::IsAlloc(res))
Init((ID3D11Texture2D *)res, sub, appMemory);
else if(WrappedID3D11Texture3D1::IsAlloc(res))
Init((ID3D11Texture3D *)res, sub, appMemory);
else
RDCERR("Unexpected resource type");
}
void MapIntercept::Init(ID3D11Buffer *buf, void *appMemory)
{
app.pData = appMemory;
if(buf == NULL)
return;
D3D11_BUFFER_DESC desc;
buf->GetDesc(&desc);
app.RowPitch = app.DepthPitch = desc.ByteWidth;
if(d3d.RowPitch == 0)
d3d.RowPitch = desc.ByteWidth;
if(d3d.DepthPitch == 0)
d3d.DepthPitch = desc.ByteWidth;
}
void MapIntercept::Init(ID3D11Texture1D *tex, UINT sub, void *appMemory)
{
app.pData = appMemory;
if(tex == NULL)
return;
D3D11_TEXTURE1D_DESC desc;
tex->GetDesc(&desc);
int width = desc.Width;
int height = 1;
DXGI_FORMAT fmt = desc.Format;
int mip = GetMipForSubresource(tex, sub);
// a row in block formats is a row of 4x4 blocks.
if(IsBlockFormat(fmt))
numRows /= 4;
numRows = RDCMAX(1, numRows >> mip);
numSlices = RDCMAX(1, numSlices >> mip);
app.RowPitch = GetByteSize(width, 1, 1, fmt, mip);
app.DepthPitch = GetByteSize(width, height, 1, fmt, mip);
if(d3d.DepthPitch == 0)
d3d.DepthPitch = app.RowPitch;
if(d3d.DepthPitch == 0)
d3d.DepthPitch = app.DepthPitch;
}
void MapIntercept::Init(ID3D11Texture2D *tex, UINT sub, void *appMemory)
{
app.pData = appMemory;
if(tex == NULL)
return;
D3D11_TEXTURE2D_DESC desc;
tex->GetDesc(&desc);
int width = desc.Width;
int height = numRows = desc.Height;
DXGI_FORMAT fmt = desc.Format;
int mip = GetMipForSubresource(tex, sub);
// a row in block formats is a row of 4x4 blocks.
if(IsBlockFormat(fmt))
numRows /= 4;
numRows = RDCMAX(1, numRows >> mip);
numSlices = RDCMAX(1, numSlices >> mip);
app.RowPitch = GetByteSize(width, 1, 1, fmt, mip);
app.DepthPitch = GetByteSize(width, height, 1, fmt, mip);
if(d3d.DepthPitch == 0)
d3d.DepthPitch = app.DepthPitch;
}
void MapIntercept::Init(ID3D11Texture3D *tex, UINT sub, void *appMemory)
{
app.pData = appMemory;
if(tex == NULL)
return;
D3D11_TEXTURE3D_DESC desc;
tex->GetDesc(&desc);
int width = desc.Width;
int height = numRows = desc.Height;
numSlices = desc.Depth;
DXGI_FORMAT fmt = desc.Format;
int mip = GetMipForSubresource(tex, sub);
// a row in block formats is a row of 4x4 blocks.
if(IsBlockFormat(fmt))
numRows /= 4;
numRows = RDCMAX(1, numRows >> mip);
numSlices = RDCMAX(1, numSlices >> mip);
app.RowPitch = GetByteSize(width, 1, 1, fmt, mip);
app.DepthPitch = GetByteSize(width, height, 1, fmt, mip);
}
void MapIntercept::CopyFromD3D()
{
byte *sliceSrc = (byte *)d3d.pData;
byte *sliceDst = (byte *)app.pData;
RDCASSERT(numSlices > 0 && numRows > 0 && (numRows == 1 || (app.RowPitch > 0 && d3d.RowPitch > 0)) &&
(numSlices == 1 || (app.DepthPitch > 0 && d3d.DepthPitch > 0)));
for(int slice = 0; slice < numSlices; slice++)
{
byte *rowSrc = sliceSrc;
byte *rowDst = sliceDst;
for(int row = 0; row < numRows; row++)
{
memcpy(rowDst, rowSrc, app.RowPitch);
rowSrc += d3d.RowPitch;
rowDst += app.RowPitch;
}
sliceSrc += d3d.DepthPitch;
sliceDst += app.DepthPitch;
}
}
void MapIntercept::CopyToD3D(size_t RangeStart, size_t RangeEnd)
{
byte *sliceSrc = (byte *)app.pData;
byte *sliceDst = (byte *)d3d.pData + RangeStart;
RDCASSERT(numSlices > 0 && numRows > 0 && app.RowPitch > 0 && d3d.RowPitch > 0 &&
app.DepthPitch > 0 && d3d.DepthPitch > 0);
for(int slice = 0; slice < numSlices; slice++)
{
byte *rowSrc = sliceSrc;
byte *rowDst = sliceDst;
for(int row = 0; row < numRows; row++)
{
size_t len = app.RowPitch;
if(RangeEnd > 0)
{
if(rowSrc + len > (byte *)app.pData + (RangeEnd - RangeStart))
len = (byte *)app.pData + (RangeEnd - RangeStart) - rowSrc;
}
memcpy(rowDst, rowSrc, len);
rowSrc += app.RowPitch;
rowDst += d3d.RowPitch;
if(RangeEnd > 0 && rowSrc > (byte *)app.pData + (RangeEnd - RangeStart))
return;
}
sliceSrc += app.DepthPitch;
sliceDst += d3d.DepthPitch;
}
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_Map(SerialiserType &ser, ID3D11Resource *pResource,
UINT Subresource, D3D11_MAP MapType, UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE *pMappedResource)
{
// unused - just for the user's benefit
SERIALISE_ELEMENT(pResource);
SERIALISE_ELEMENT(Subresource);
SERIALISE_ELEMENT(MapType);
SERIALISE_ELEMENT_TYPED(D3D11_MAP_FLAG, MapFlags);
SERIALISE_CHECK_READ_ERRORS();
// nothing to do on replay, all the work happens in Unmap.
if(ser.IsReading())
return true;
D3D11_MAPPED_SUBRESOURCE mappedResource = D3D11_MAPPED_SUBRESOURCE();
if(pMappedResource)
mappedResource = *pMappedResource;
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pResource));
RDCASSERT(record);
if(record->NumSubResources > (int)Subresource)
record = (D3D11ResourceRecord *)record->SubResources[Subresource];
MapIntercept intercept;
size_t mapLength = (size_t)record->Length;
if(IsActiveCapturing(m_State) || !record->DataInSerialiser)
{
ResourceId Resource = GetIDForResource(pResource);
RDCASSERT(m_OpenMaps.find(MappedResource(Resource, Subresource)) == m_OpenMaps.end());
ID3D11Resource *resMap = pResource;
RDCASSERT(resMap);
int ctxMapID = 0;
if(GetType() == D3D11_DEVICE_CONTEXT_DEFERRED)
{
if(m_MapResourceRecordAllocs[Resource] == 0)
m_MapResourceRecordAllocs[Resource] = record->GetContextID();
ctxMapID = m_MapResourceRecordAllocs[Resource];
RDCASSERT(ctxMapID != 0);
}
void *appMem = record->GetShadowPtr(ctxMapID, 0);
if(appMem == NULL)
{
record->AllocShadowStorage(ctxMapID, mapLength);
appMem = record->GetShadowPtr(ctxMapID, 0);
if(MapType != D3D11_MAP_WRITE_DISCARD)
{
if(m_pDevice->GetResourceManager()->IsResourceDirty(Resource))
{
ID3D11DeviceChild *initial =
m_pDevice->GetResourceManager()->GetInitialContents(Resource).resource;
if(WrappedID3D11Buffer::IsAlloc(pResource))
{
RDCASSERT(initial);
ID3D11Buffer *stage = (ID3D11Buffer *)initial;
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = m_pRealContext->Map(stage, 0, D3D11_MAP_READ, 0, &mapped);
if(FAILED(hr))
{
RDCERR("Failed to map while getting initial states HRESULT: %s", ToStr(hr).c_str());
}
else
{
intercept = MapIntercept();
intercept.SetD3D(mapped);
intercept.Init((ID3D11Buffer *)pResource, record->GetDataPtr());
intercept.CopyFromD3D();
RDCASSERT(mapLength == (size_t)record->Length);
memcpy(appMem, record->GetDataPtr(), mapLength);
m_pRealContext->Unmap(stage, 0);
}
}
else
{
// need to get initial contents out
RDCUNIMPLEMENTED("Not getting initial contents for non-buffer GPU dirty map");
RDCERR(
"CORRUPTION - Invalid/inaccurate initial data for Map() - non-buffer GPU dirty "
"data mapped");
}
}
else if(record->DataInSerialiser)
{
RDCASSERT(mapLength == (size_t)record->Length);
memcpy(appMem, record->GetDataPtr(), mapLength);
}
else
{
memset(appMem, 0, mapLength);
}
}
memcpy(record->GetShadowPtr(ctxMapID, 1), appMem, mapLength);
}
if(MapType == D3D11_MAP_WRITE_DISCARD)
{
memset(appMem, 0xcc, mapLength);
memcpy(record->GetShadowPtr(ctxMapID, 1), appMem, mapLength);
}
intercept = MapIntercept();
intercept.verifyWrite = (RenderDoc::Inst().GetCaptureOptions().verifyMapWrites != 0);
intercept.SetD3D(mappedResource);
intercept.InitWrappedResource(resMap, Subresource, appMem);
intercept.MapType = MapType;
intercept.MapFlags = MapFlags;
RDCASSERT(pMappedResource);
*pMappedResource = intercept.app;
m_OpenMaps[MappedResource(Resource, Subresource)] = intercept;
}
else if(IsBackgroundCapturing(m_State))
{
RDCASSERT(record->DataInSerialiser);
mapLength = (size_t)record->Length;
intercept = MapIntercept();
intercept.verifyWrite = (RenderDoc::Inst().GetCaptureOptions().verifyMapWrites != 0);
intercept.SetD3D(mappedResource);
intercept.MapType = MapType;
intercept.MapFlags = MapFlags;
if(intercept.verifyWrite)
{
int ctxMapID = 0;
ResourceId Resource = GetIDForResource(pResource);
if(GetType() == D3D11_DEVICE_CONTEXT_DEFERRED)
{
if(m_MapResourceRecordAllocs[Resource] == 0)
m_MapResourceRecordAllocs[Resource] = record->GetContextID();
ctxMapID = m_MapResourceRecordAllocs[Resource];
RDCASSERT(ctxMapID != 0);
}
byte *appMem = record->GetShadowPtr(ctxMapID, 0);
if(appMem == NULL)
{
record->AllocShadowStorage(ctxMapID, mapLength);
appMem = record->GetShadowPtr(ctxMapID, 0);
}
memcpy(appMem, record->GetDataPtr(), mapLength);
intercept.InitWrappedResource(pResource, Subresource, appMem);
}
else
{
intercept.InitWrappedResource(pResource, Subresource, record->GetDataPtr());
}
*pMappedResource = intercept.app;
m_OpenMaps[MappedResource(GetIDForResource(pResource), Subresource)] = intercept;
}
else
{
RDCERR("Unexpected and unhandled case");
RDCEraseEl(intercept);
}
// for read write fill out the buffer with what's on the mapped resource already
if(MapType == D3D11_MAP_READ_WRITE || MapType == D3D11_MAP_READ)
{
intercept.CopyFromD3D();
}
else if(MapType == D3D11_MAP_WRITE_DISCARD)
{
// the easy case!
}
else if(MapType == D3D11_MAP_WRITE || MapType == D3D11_MAP_WRITE_NO_OVERWRITE)
{
// For now we'll just assume that the buffer contents are perfectly accurate
// (which they are if no gpu writes to the buffer happens).
// could take the performance hit and just copy anyway, spec doesn't see if the
// data will be invalid but it will certainly be slow.
}
return true;
}
HRESULT WrappedID3D11DeviceContext::Map(ID3D11Resource *pResource, UINT Subresource,
D3D11_MAP MapType, UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE *pMappedResource)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ResourceId id = GetIDForResource(pResource);
bool directMap = false;
if(m_HighTrafficResources.find(id) != m_HighTrafficResources.end() && !IsActiveCapturing(m_State))
directMap = true;
if(m_pDevice->GetResourceManager()->IsResourceDirty(GetIDForResource(pResource)) &&
!IsActiveCapturing(m_State))
directMap = true;
if((!directMap && MapType == D3D11_MAP_WRITE_NO_OVERWRITE && !IsActiveCapturing(m_State)) ||
m_pRealContext->GetType() == D3D11_DEVICE_CONTEXT_DEFERRED)
{
directMap = true;
m_HighTrafficResources.insert(id);
if(!IsActiveCapturing(m_State))
MarkDirtyResource(id);
}
if(directMap && IsBackgroundCapturing(m_State))
{
return m_pRealContext->Map(m_pDevice->GetResourceManager()->UnwrapResource(pResource),
Subresource, MapType, MapFlags, pMappedResource);
}
// can't promise no-overwrite as we're going to blat the whole buffer!
HRESULT ret;
SERIALISE_TIME_CALL(ret = m_pRealContext->Map(
m_pDevice->GetResourceManager()->UnwrapResource(pResource), Subresource,
MapType == D3D11_MAP_WRITE_NO_OVERWRITE ? D3D11_MAP_WRITE_DISCARD : MapType,
MapFlags, pMappedResource));
if(SUCCEEDED(ret) && IsCaptureMode(m_State))
{
if(IsActiveCapturing(m_State))
{
if(MapType == D3D11_MAP_READ)
{
MapIntercept intercept;
intercept.MapType = MapType;
intercept.MapFlags = MapFlags;
m_OpenMaps[MappedResource(GetIDForResource(pResource), Subresource)] = intercept;
}
else
{
m_MissingTracks.insert(GetIDForResource(pResource));
// create a chunk purely for the user's benefit
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::Map);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_Map(GET_SERIALISER, pResource, Subresource, MapType, MapFlags, pMappedResource);
m_ContextRecord->AddChunk(scope.Get());
}
}
else // IsIdleCapturing(m_State)
{
RDCASSERT(WrappedID3D11Buffer::IsAlloc(pResource) ||
WrappedID3D11Texture1D::IsAlloc(pResource) ||
WrappedID3D11Texture2D1::IsAlloc(pResource) ||
WrappedID3D11Texture3D1::IsAlloc(pResource));
ResourceId Id = GetIDForResource(pResource);
D3D11ResourceRecord *record = m_pDevice->GetResourceManager()->GetResourceRecord(Id);
RDCASSERT(record);
if(record->NumSubResources > (int)Subresource)
record = (D3D11ResourceRecord *)record->SubResources[Subresource];
record->UpdateCount++;
if(record->UpdateCount > 60 && RenderDoc::Inst().GetCaptureOptions().verifyMapWrites == 0)
{
m_HighTrafficResources.insert(Id);
MarkDirtyResource(Id);
return ret;
}
// don't need to create a chunk but we do need to prepare the map.
Serialise_Map(m_ScratchSerialiser, pResource, Subresource, MapType, MapFlags, pMappedResource);
// throw away any serialised data
m_ScratchSerialiser.GetWriter()->Rewind();
}
}
return ret;
}
template <typename SerialiserType>
bool WrappedID3D11DeviceContext::Serialise_Unmap(SerialiserType &ser, ID3D11Resource *pResource,
UINT Subresource)
{
SERIALISE_ELEMENT(pResource);
SERIALISE_ELEMENT(Subresource);
MappedResource mapIdx(GetIDForResource(pResource), Subresource);
MapIntercept intercept;
int ctxMapID = 0;
D3D11ResourceRecord *record = NULL;
size_t len = 0;
uint32_t diffStart = 0;
uint32_t diffEnd = 0;
byte *MapWrittenData = NULL;
// handle book-keeping during capture mode
if(ser.IsWriting())
{
record = m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pResource));
RDCASSERT(record);
if((int)Subresource < record->NumSubResources)
record = (D3D11ResourceRecord *)record->SubResources[Subresource];
len = (size_t)record->Length;
diffEnd = (uint32_t)len;
// locate the intercept data and remove it from the open maps list
auto it = m_OpenMaps.find(mapIdx);
if(it != m_OpenMaps.end())
{
intercept = it->second;
m_OpenMaps.erase(it);
}
else
{
RDCERR("Couldn't find map for %llu/%u in open maps list", mapIdx.resource, mapIdx.subresource);
}
MapWrittenData = (byte *)intercept.app.pData;
// store the context ID we used for this map's shadow pointers
if(GetType() == D3D11_DEVICE_CONTEXT_DEFERRED &&
(IsActiveCapturing(m_State) || intercept.verifyWrite))
{
ctxMapID = m_MapResourceRecordAllocs[mapIdx.resource];
RDCASSERT(ctxMapID != 0);
}
// if we were verifying this map, then make sure the shadow storage is still safe
if(intercept.verifyWrite)
{
if(!record->VerifyShadowStorage(ctxMapID))
{
std::string msg = StringFormat::Fmt(
"Overwrite of %llu byte Map()'d buffer detected\n"
"Breakpoint now to see callstack,\nor click 'Yes' to debugbreak.",
record->Length);
int res = tinyfd_messageBox("Map() overwrite detected!", msg.c_str(), "yesno", "error", 1);
if(res == 1)
{
OS_DEBUG_BREAK();
}
}
if(IsBackgroundCapturing(m_State))
{
// if there was already backing store then normally the user wrote directly into it so we
// don't even have to update anything, except in the case where we were verifying map
// writes. Then we need to copy from the verification shadow buffer into the backing store.
memcpy(record->GetDataPtr(), intercept.app.pData, len);
}
}
// copy from the intercept buffer that the user wrote into, into D3D's real pointer
intercept.CopyToD3D();
// while actively capturing, on large buffers being updated, try to locate the range of data
// being
// updated and update the diffStart/diffEnd/len variables
if(IsActiveCapturing(m_State) && len > 512 && intercept.MapType != D3D11_MAP_WRITE_DISCARD)
{
size_t s = diffStart;
size_t e = diffEnd;
bool found = FindDiffRange(MapWrittenData, record->GetShadowPtr(ctxMapID, 1), len, s, e);
diffStart = (uint32_t)s;
diffEnd = (uint32_t)e;
if(found)
{
#if ENABLED(RDOC_DEVEL)
static size_t saved = 0;
saved += len - (diffEnd - diffStart);
RDCDEBUG("Mapped resource size %u, difference: %u -> %u. Total bytes saved so far: %u",
(uint32_t)len, (uint32_t)diffStart, (uint32_t)diffEnd, (uint32_t)saved);
#endif
len = diffEnd - diffStart;
}
else
{
diffStart = 0;
diffEnd = 0;
len = 0;
}
// update the data pointer to be rebased to the start of the diff data.
MapWrittenData += diffStart;
}
// update shadow stores for future diff'ing
if(IsActiveCapturing(m_State) && record->GetShadowPtr(ctxMapID, 1))
{
memcpy(record->GetShadowPtr(ctxMapID, 1) + diffStart, MapWrittenData, diffEnd - diffStart);
}
} // if(ser.IsWriting())
// if we're not actively capturing a frame, we'll skip serialising all this data for nothing as we
// aren't going to save the chunk anywhere. The exception is if there's no backing store for this
// resource - then we need to serialise into the chunk to allocate it
bool SerialiseMap = ser.IsReading() || (ser.IsWriting() && IsActiveCapturing(m_State)) ||
(ser.IsWriting() && !record->DataInSerialiser);
if(SerialiseMap)
{
SERIALISE_ELEMENT(intercept.MapType).Named("MapType");
SERIALISE_ELEMENT_TYPED(D3D11_MAP_FLAG, intercept.MapFlags).Named("MapFlags");
SERIALISE_ELEMENT(diffStart).Named("Byte offset to start of written data");
SERIALISE_ELEMENT(diffEnd).Named("Byte offset to end of written data");
SERIALISE_ELEMENT_ARRAY(MapWrittenData, len);
if(ser.IsWriting() && IsBackgroundCapturing(m_State) && !record->DataInSerialiser)
{
record->DataInSerialiser = true;
record->SetDataOffset(ser.GetWriter()->GetOffset() - (uint64_t)len);
}
else if(IsReplayingAndReading() && pResource)
{
// steal the allocated buffer, and manually release
intercept.app.pData = MapWrittenData;
MapWrittenData = NULL;
}
}
if(IsReplayingAndReading() && ser.IsErrored())
{
FreeAlignedBuffer(MapWrittenData);
}
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading() && pResource)
{
MapWrittenData = (byte *)intercept.app.pData;
if(IsLoading(m_State) && m_CurEventID > 0 && (diffStart < diffEnd))
RecordUpdateStats(pResource, diffEnd - diffStart, false);
if(diffStart >= diffEnd)
{
// do nothing
}
else if(intercept.MapType == D3D11_MAP_WRITE_NO_OVERWRITE)
{
RDCASSERT(WrappedID3D11Buffer::IsAlloc(pResource));
ID3D11Buffer *mapContents = NULL;
D3D11_BUFFER_DESC bdesc;
bdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bdesc.ByteWidth = diffEnd - diffStart;
bdesc.CPUAccessFlags = 0;
bdesc.MiscFlags = 0;
bdesc.StructureByteStride = 0;
bdesc.Usage = D3D11_USAGE_IMMUTABLE;
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = MapWrittenData;
data.SysMemPitch = bdesc.ByteWidth;
data.SysMemSlicePitch = bdesc.ByteWidth;
HRESULT hr = m_pDevice->GetReal()->CreateBuffer(&bdesc, &data, &mapContents);
if(FAILED(hr))
{
RDCERR("Failed to create temp Unmap() buffer HRESULT: %s", ToStr(hr).c_str());
}
else
{
m_pRealContext->CopySubresourceRegion(GetResourceManager()->UnwrapResource(pResource),
mapIdx.subresource, diffStart, 0, 0, mapContents, 0,
NULL);
SAFE_RELEASE(mapContents);
}
}
else
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
UINT flags = intercept.MapFlags & ~D3D11_MAP_FLAG_DO_NOT_WAIT;
HRESULT hr = m_pRealContext->Map(GetResourceManager()->UnwrapResource(pResource),
mapIdx.subresource, intercept.MapType, flags, &mappedResource);
RDCASSERT(mappedResource.pData);
if(FAILED(hr))
{
RDCERR("Failed to map resource, HRESULT: %s", ToStr(hr).c_str());
}
else
{
intercept.SetD3D(mappedResource);
intercept.InitWrappedResource(pResource, mapIdx.subresource, MapWrittenData);
intercept.CopyToD3D(diffStart, diffEnd);
m_pRealContext->Unmap(m_pDevice->GetResourceManager()->UnwrapResource(pResource),
mapIdx.subresource);
}
}
FreeAlignedBuffer(MapWrittenData);
}
return true;
}
void WrappedID3D11DeviceContext::Unmap(ID3D11Resource *pResource, UINT Subresource)
{
DrainAnnotationQueue();
m_EmptyCommandList = false;
ResourceId id = GetIDForResource(pResource);
auto it = m_OpenMaps.find(MappedResource(id, Subresource));
if(IsBackgroundCapturing(m_State) && m_HighTrafficResources.find(id) != m_HighTrafficResources.end())
{
// we intercepted this, even though we now don't need to serialise it. Time to finish what we
// started!
if(it != m_OpenMaps.end() && it->second.MapType != D3D11_MAP_READ)
{
it->second.CopyToD3D();
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(it->first.resource);
if(record)
record->FreeShadowStorage();
m_OpenMaps.erase(it);
}
else if(it != m_OpenMaps.end())
{
m_OpenMaps.erase(it);
}
}
else if(IsCaptureMode(m_State))
{
if(it == m_OpenMaps.end() && IsActiveCapturing(m_State))
{
RDCWARN(
"Saw an Unmap that we didn't capture the corresponding Map for - this frame is "
"unsuccessful");
m_SuccessfulCapture = false;
m_FailureReason = CaptureFailed_UncappedUnmap;
}
if(it != m_OpenMaps.end())
{
if(it->second.MapType == D3D11_MAP_READ)
{
m_OpenMaps.erase(it);
}
else if(IsActiveCapturing(m_State))
{
MarkResourceReferenced(it->first.resource, eFrameRef_Read);
MarkResourceReferenced(it->first.resource, eFrameRef_Write);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::Unmap);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_Unmap(GET_SERIALISER, pResource, Subresource);
m_ContextRecord->AddChunk(scope.Get());
}
else // IsIdleCapturing(m_State)
{
RDCASSERT(WrappedID3D11Buffer::IsAlloc(pResource) ||
WrappedID3D11Texture1D::IsAlloc(pResource) ||
WrappedID3D11Texture2D1::IsAlloc(pResource) ||
WrappedID3D11Texture3D1::IsAlloc(pResource));
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForResource(pResource));
RDCASSERT(record);
D3D11ResourceRecord *baserecord = record;
if(record->NumSubResources > (int)Subresource)
record = (D3D11ResourceRecord *)record->SubResources[Subresource];
if(record->DataInSerialiser)
{
Serialise_Unmap(m_ScratchSerialiser, pResource, Subresource);
// throw away any serialised data
m_ScratchSerialiser.GetWriter()->Rewind();
}
else
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D11Chunk::Unmap);
SERIALISE_ELEMENT(m_ResourceID).Named("Context").TypedAs("ID3D11DeviceContext *");
Serialise_Unmap(GET_SERIALISER, pResource, Subresource);
Chunk *chunk = scope.Get();
baserecord->AddChunk(chunk);
record->SetDataPtr(chunk->GetData());
record->DataInSerialiser = true;
}
record->FreeShadowStorage();
}
}
}
m_pRealContext->Unmap(m_pDevice->GetResourceManager()->UnwrapResource(pResource), Subresource);
}
#pragma endregion Map
#undef IMPLEMENT_FUNCTION_SERIALISED
#define IMPLEMENT_FUNCTION_SERIALISED(ret, func, ...) \
template bool WrappedID3D11DeviceContext::CONCAT(Serialise_, \
func(ReadSerialiser &ser, __VA_ARGS__)); \
template bool WrappedID3D11DeviceContext::CONCAT(Serialise_, \
func(WriteSerialiser &ser, __VA_ARGS__));
SERIALISED_ID3D11CONTEXT_FUNCTIONS();
SERIALISED_ID3D11CONTEXT_MARKER_FUNCTIONS();