Support mesh output from different view indices on vulkan

* When using VK_KHR_multiview you can select which view to view the mesh data from.
This commit is contained in:
baldurk
2018-06-19 20:48:30 +01:00
parent ad2673965d
commit 53364adeef
31 changed files with 220 additions and 70 deletions
+2
View File
@@ -134,6 +134,8 @@ struct MeshDisplay
bool showWholePass;
DOCUMENT("The index of the currently selected instance in the drawcall.");
uint32_t curInstance;
DOCUMENT("The index of the currently selected multiview view in the drawcall.");
uint32_t curView;
DOCUMENT("The index of the vertex to highlight, or :data:`NoHighlight` to select no vertex.");
uint32_t highlightVert;
+3
View File
@@ -133,6 +133,9 @@ public:
return false;
}
DOCUMENT("Returns the number of views being broadcast to simultaneously during rendering.");
uint32_t MultiviewBroadcastCount() const;
DOCUMENT(R"(Determines whether or not the current capture supports binding arrays of resources.
:return: A boolean indicating if binding arrays of resources is supported.
+10
View File
@@ -382,6 +382,16 @@ ResourceId PipeState::GetGraphicsPipelineObject() const
return ResourceId();
}
uint32_t PipeState::MultiviewBroadcastCount() const
{
if(IsCaptureLoaded() && IsCaptureVK())
{
return std::max((uint32_t)m_Vulkan->currentPass.renderpass.multiviews.size(), 1U);
}
return 1;
}
rdcstr PipeState::GetShaderEntryPoint(ShaderStage stage) const
{
if(IsCaptureLoaded() && IsCaptureVK())
+3 -2
View File
@@ -1124,12 +1124,13 @@ texture to something compatible with the target file format.
DOCUMENT(R"(Retrieve the generated data from one of the geometry processing shader stages.
:param int instance: The index of the instance to retrieve data for.
:param int instance: The index of the instance to retrieve data for, or 0 for non-instanced draws.
:param int view: The index of the multiview view to retrieve data for, or 0 if multiview is disabled.
:param MeshDataStage stage: The stage of the geometry processing pipeline to retrieve data from.
:return: The information describing where the post-transform data is stored.
:rtype: MeshFormat
)");
virtual MeshFormat GetPostVSData(uint32_t instance, MeshDataStage stage) = 0;
virtual MeshFormat GetPostVSData(uint32_t instance, uint32_t view, MeshDataStage stage) = 0;
DOCUMENT(R"(Retrieve the contents of a range of a buffer as a ``bytes``.
+7
View File
@@ -573,6 +573,13 @@ struct RenderPass
If there is no depth-stencil attachment, this index is ``-1``.
)");
int32_t depthstencilAttachment = -1;
DOCUMENT(R"(If multiview is enabled, contains a list of view indices to be broadcast to during
rendering.
If the list is empty, multiview is disabled and rendering is as normal.
)");
rdcarray<uint32_t> multiviews;
};
DOCUMENT("Describes a single attachment in a framebuffer object.");
+1 -1
View File
@@ -196,7 +196,7 @@ public:
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &retData) {}
void InitPostVSBuffers(uint32_t eventId) {}
void InitPostVSBuffers(const vector<uint32_t> &eventId) {}
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage)
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID, MeshDataStage stage)
{
MeshFormat ret;
RDCEraseEl(ret);
+9 -7
View File
@@ -729,9 +729,9 @@ void ReplayProxy::InitPostVSBuffers(const std::vector<uint32_t> &events)
}
template <typename ParamSerialiser, typename ReturnSerialiser>
MeshFormat ReplayProxy::Proxied_GetPostVSBuffers(ParamSerialiser &paramser,
ReturnSerialiser &retser, uint32_t eventId,
uint32_t instID, MeshDataStage stage)
MeshFormat ReplayProxy::Proxied_GetPostVSBuffers(ParamSerialiser &paramser, ReturnSerialiser &retser,
uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage)
{
const ReplayProxyPacket packet = eReplayProxy_GetPostVS;
MeshFormat ret = {};
@@ -740,21 +740,23 @@ MeshFormat ReplayProxy::Proxied_GetPostVSBuffers(ParamSerialiser &paramser,
BEGIN_PARAMS();
SERIALISE_ELEMENT(eventId);
SERIALISE_ELEMENT(instID);
SERIALISE_ELEMENT(viewID);
SERIALISE_ELEMENT(stage);
END_PARAMS();
}
if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored)
ret = m_Remote->GetPostVSBuffers(eventId, instID, stage);
ret = m_Remote->GetPostVSBuffers(eventId, instID, viewID, stage);
SERIALISE_RETURN(ret);
return ret;
}
MeshFormat ReplayProxy::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage)
MeshFormat ReplayProxy::GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage)
{
PROXY_FUNCTION(GetPostVSBuffers, eventId, instID, stage);
PROXY_FUNCTION(GetPostVSBuffers, eventId, instID, viewID, stage);
}
template <typename ParamSerialiser, typename ReturnSerialiser>
@@ -2058,7 +2060,7 @@ bool ReplayProxy::Tick(int type)
InitPostVSBuffers(dummy);
break;
}
case eReplayProxy_GetPostVS: GetPostVSBuffers(0, 0, MeshDataStage::Unknown); break;
case eReplayProxy_GetPostVS: GetPostVSBuffers(0, 0, 0, MeshDataStage::Unknown); break;
case eReplayProxy_BuildTargetShader:
BuildTargetShader("", "", ShaderCompileFlags(), ShaderStage::Vertex, NULL, NULL);
break;
+1 -1
View File
@@ -466,7 +466,7 @@ public:
IMPLEMENT_FUNCTION_PROXIED(void, InitPostVSBuffers, uint32_t eventId);
IMPLEMENT_FUNCTION_PROXIED(void, InitPostVSBuffers, const std::vector<uint32_t> &passEvents);
IMPLEMENT_FUNCTION_PROXIED(MeshFormat, GetPostVSBuffers, uint32_t eventId, uint32_t instID,
MeshDataStage stage);
uint32_t viewID, MeshDataStage stage);
IMPLEMENT_FUNCTION_PROXIED(ResourceId, RenderOverlay, ResourceId texid, CompType typeHint,
DebugOverlay overlay, uint32_t eventId,
+2 -2
View File
@@ -681,9 +681,9 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, CompType typeHint, Debug
for(uint32_t inst = 0; draw && inst < RDCMAX(1U, draw->numInstances); inst++)
{
MeshFormat fmt = GetPostVSBuffers(events[i], inst, MeshDataStage::GSOut);
MeshFormat fmt = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::GSOut);
if(fmt.vertexResourceId == ResourceId())
fmt = GetPostVSBuffers(events[i], inst, MeshDataStage::VSOut);
fmt = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::VSOut);
if(fmt.vertexResourceId != ResourceId())
{
+5 -1
View File
@@ -97,11 +97,15 @@ void D3D11Replay::ClearPostVSCache()
m_PostVSData.clear();
}
MeshFormat D3D11Replay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage)
MeshFormat D3D11Replay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage)
{
D3D11PostVSData postvs;
RDCEraseEl(postvs);
// no multiview support
(void)viewID;
if(m_PostVSData.find(eventId) != m_PostVSData.end())
postvs = m_PostVSData[eventId];
+2 -1
View File
@@ -169,7 +169,8 @@ public:
CompType typeHint, float minval, float maxval, bool channels[4],
vector<uint32_t> &histogram);
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage);
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage);
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &retData);
void GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
+2 -2
View File
@@ -906,9 +906,9 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, CompType typeHint, Debug
for(uint32_t inst = 0; draw && inst < RDCMAX(1U, draw->numInstances); inst++)
{
MeshFormat fmt = GetPostVSBuffers(events[i], inst, MeshDataStage::GSOut);
MeshFormat fmt = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::GSOut);
if(fmt.vertexResourceId == ResourceId())
fmt = GetPostVSBuffers(events[i], inst, MeshDataStage::VSOut);
fmt = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::VSOut);
if(fmt.vertexResourceId != ResourceId())
{
+5 -1
View File
@@ -1338,7 +1338,8 @@ void D3D12Replay::InitPostVSBuffers(const vector<uint32_t> &events)
m_pDevice->ReplayLog(events.front(), events.back(), eReplay_Full);
}
MeshFormat D3D12Replay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage)
MeshFormat D3D12Replay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage)
{
// go through any aliasing
if(m_PostVSAlias.find(eventId) != m_PostVSAlias.end())
@@ -1347,6 +1348,9 @@ MeshFormat D3D12Replay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, Mesh
D3D12PostVSData postvs;
RDCEraseEl(postvs);
// no multiview support
(void)viewID;
if(m_PostVSData.find(eventId) != m_PostVSData.end())
postvs = m_PostVSData[eventId];
+2 -1
View File
@@ -129,7 +129,8 @@ public:
CompType typeHint, float minval, float maxval, bool channels[4],
vector<uint32_t> &histogram);
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage);
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage);
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &retData);
void GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
+2 -2
View File
@@ -975,9 +975,9 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeHint, DebugOve
for(uint32_t inst = 0; draw && inst < RDCMAX(1U, draw->numInstances); inst++)
{
MeshFormat postvs = GetPostVSBuffers(events[i], inst, MeshDataStage::GSOut);
MeshFormat postvs = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::GSOut);
if(postvs.vertexResourceId == ResourceId())
postvs = GetPostVSBuffers(events[i], inst, MeshDataStage::VSOut);
postvs = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::VSOut);
if(postvs.vertexResourceId != ResourceId())
{
+5 -1
View File
@@ -1420,11 +1420,15 @@ void GLReplay::InitPostVSBuffers(const vector<uint32_t> &passEvents)
}
}
MeshFormat GLReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage)
MeshFormat GLReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage)
{
GLPostVSData postvs;
RDCEraseEl(postvs);
// no multiview support
(void)viewID;
ContextPair ctx = {m_ReplayCtx.ctx, m_pDriver->ShareCtx(m_ReplayCtx.ctx)};
if(m_PostVSData.find(eventId) != m_PostVSData.end())
+2 -1
View File
@@ -162,7 +162,8 @@ public:
CompType typeHint, float minval, float maxval, bool channels[4],
vector<uint32_t> &histogram);
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage);
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage);
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &ret);
void GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
+15
View File
@@ -510,6 +510,11 @@ void VulkanCreationInfo::RenderPass::Init(VulkanResourceManager *resourceMan,
for(uint32_t i = 0; i < pCreateInfo->attachmentCount; i++)
attachments.push_back(pCreateInfo->pAttachments[i]);
// VK_KHR_multiview
const VkRenderPassMultiviewCreateInfo *multiview =
(const VkRenderPassMultiviewCreateInfo *)FindNextStruct(
pCreateInfo, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO);
subpasses.resize(pCreateInfo->subpassCount);
for(uint32_t subp = 0; subp < pCreateInfo->subpassCount; subp++)
{
@@ -544,6 +549,16 @@ void VulkanCreationInfo::RenderPass::Init(VulkanResourceManager *resourceMan,
src.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED
? src.pDepthStencilAttachment->layout
: VK_IMAGE_LAYOUT_UNDEFINED);
if(multiview && multiview->subpassCount > 0)
{
uint32_t mask = multiview->pViewMasks[subp];
for(uint32_t i = 0; i < 32; i++)
{
if(mask & (1 << i))
dst.multiviews.push_back(i);
}
}
}
}
+2
View File
@@ -274,6 +274,8 @@ struct VulkanCreationInfo
vector<VkImageLayout> inputLayouts;
vector<VkImageLayout> colorLayouts;
VkImageLayout depthstencilLayout;
std::vector<uint32_t> multiviews;
};
vector<Subpass> subpasses;
+2 -2
View File
@@ -2095,9 +2095,9 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, CompType typeHint, Debu
for(uint32_t inst = 0; draw && inst < RDCMAX(1U, draw->numInstances); inst++)
{
MeshFormat fmt = GetPostVSBuffers(events[i], inst, MeshDataStage::GSOut);
MeshFormat fmt = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::GSOut);
if(fmt.vertexResourceId == ResourceId())
fmt = GetPostVSBuffers(events[i], inst, MeshDataStage::VSOut);
fmt = GetPostVSBuffers(events[i], inst, 0, MeshDataStage::VSOut);
if(fmt.vertexResourceId != ResourceId())
{
+70 -28
View File
@@ -35,10 +35,11 @@ static const char *PatchedMeshOutputEntryPoint = "rdc";
static const uint32_t MeshOutputDispatchWidth = 128;
static const uint32_t MeshOutputTBufferArraySize = 16;
static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRVPatchData &patchData,
const char *entryName, std::vector<uint32_t> instDivisor,
uint32_t &descSet, const DrawcallDescription *draw,
int32_t indexOffset, uint64_t numFetchVerts, uint32_t numVerts,
static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
const SPIRVPatchData &patchData, const char *entryName,
std::vector<uint32_t> instDivisor, uint32_t &descSet,
const DrawcallDescription *draw, int32_t indexOffset,
uint64_t numFetchVerts, uint32_t numVerts, uint32_t numViews,
std::vector<uint32_t> &modSpirv, uint32_t &bufStride)
{
SPIRVEditor editor(modSpirv);
@@ -550,10 +551,12 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
SPIRVId numFetchVertsConstID = editor.AddConstantImmediate((int32_t)numFetchVerts);
SPIRVId numVertsConstID = editor.AddConstantImmediate((int32_t)numVerts);
SPIRVId numInstConstID = editor.AddConstantImmediate((int32_t)draw->numInstances);
SPIRVId numViewsConstID = editor.AddConstantImmediate((int32_t)numViews);
editor.SetName(numFetchVertsConstID, "numFetchVerts");
editor.SetName(numVertsConstID, "numVerts");
editor.SetName(numInstConstID, "numInsts");
editor.SetName(numViewsConstID, "numViews");
// declare the output buffer and its type
{
@@ -716,17 +719,27 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
editor.SetName(intInvocationID, "invocation");
// int inst = intInvocationID / numFetchVerts
// int viewinst = intInvocationID / numFetchVerts
uint32_t viewinstID = editor.MakeId();
ops.push_back(SPIRVOperation(spv::OpSDiv,
{sint32ID, viewinstID, intInvocationID, numFetchVertsConstID}));
editor.SetName(viewinstID, "viewInstance");
uint32_t instID = editor.MakeId();
ops.push_back(
SPIRVOperation(spv::OpSDiv, {sint32ID, instID, intInvocationID, numFetchVertsConstID}));
ops.push_back(SPIRVOperation(spv::OpSMod, {sint32ID, instID, viewinstID, numInstConstID}));
editor.SetName(instID, "instanceID");
// bool inBounds = inst < numInstances;
uint32_t viewID = editor.MakeId();
ops.push_back(SPIRVOperation(spv::OpSDiv, {sint32ID, viewID, viewinstID, numInstConstID}));
editor.SetName(viewID, "viewID");
// bool inBounds = viewID < numViews;
uint32_t inBounds = editor.MakeId();
ops.push_back(SPIRVOperation(
spv::OpULessThan, {editor.DeclareType(scalar<bool>()), inBounds, instID, numInstConstID}));
ops.push_back(SPIRVOperation(spv::OpULessThan, {editor.DeclareType(scalar<bool>()), inBounds,
viewID, numViewsConstID}));
// if(inBounds) goto continueLabel; else goto killLabel;
uint32_t killLabel = editor.MakeId();
@@ -769,9 +782,10 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
ops.push_back(SPIRVOperation(spv::OpBitcast, {sint32ID, vertexIndex, uintIndex}));
}
// int arraySlotID = inst * numVerts;
// int arraySlotID = viewinst * numVerts;
uint32_t arraySlotTempID = editor.MakeId();
ops.push_back(SPIRVOperation(spv::OpIMul, {sint32ID, arraySlotTempID, instID, numVertsConstID}));
ops.push_back(
SPIRVOperation(spv::OpIMul, {sint32ID, arraySlotTempID, viewinstID, numVertsConstID}));
// arraySlotID = arraySlotID + vertexIndex;
uint32_t arraySlotTemp2ID = editor.MakeId();
@@ -826,8 +840,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
}
else if(builtin == ShaderBuiltin::ViewportIndex)
{
ops.push_back(SPIRVOperation(
spv::OpStore, {ins[i].variableID, editor.AddConstantImmediate(int32_t(0))}));
ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, viewID}));
}
else if(builtin == ShaderBuiltin::BaseVertex)
{
@@ -1150,6 +1163,7 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
m_PostVSData[eventId].vsout.buf = VK_NULL_HANDLE;
m_PostVSData[eventId].vsout.instStride = 0;
m_PostVSData[eventId].vsout.vertStride = 0;
m_PostVSData[eventId].vsout.numViews = 1;
m_PostVSData[eventId].vsout.nearPlane = 0.0f;
m_PostVSData[eventId].vsout.farPlane = 0.0f;
m_PostVSData[eventId].vsout.useIndices = false;
@@ -1198,6 +1212,21 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
uint64_t numFetchVerts = drawcall->numIndices;
VkDeviceSize bufSize = 0;
uint32_t numViews = 1;
{
const VulkanCreationInfo::RenderPass &rp = creationInfo.m_RenderPass[state.renderPass];
if(state.subpass < rp.subpasses.size())
{
numViews = RDCMAX(numViews, (uint32_t)rp.subpasses[state.subpass].multiviews.size());
}
else
{
RDCERR("Subpass is out of bounds to renderpass creation info");
}
}
uint32_t idxsize = state.ibuffer.bytewidth;
int32_t baseVertex = 0;
@@ -1703,9 +1732,9 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
m_pDriver->vkUpdateDescriptorSets(dev, numWrites, descWrites, 0, NULL);
}
ConvertToMeshOutputCompute(*refl, *pipeInfo.shaders[0].patchData,
pipeInfo.shaders[0].entryPoint.c_str(), attrInstDivisor, descSet,
drawcall, baseVertex, numFetchVerts, numVerts, modSpirv, bufStride);
ConvertToMeshOutputCompute(
*refl, *pipeInfo.shaders[0].patchData, pipeInfo.shaders[0].entryPoint.c_str(), attrInstDivisor,
descSet, drawcall, baseVertex, numFetchVerts, numVerts, numViews, modSpirv, bufStride);
VkComputePipelineCreateInfo compPipeInfo = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO};
@@ -1790,10 +1819,11 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
// have a compact 0-based index to index into the buffer. We must use
// index-minIndex which is 0-based but potentially sparse, so this buffer may
// be more or less wasteful
VkBufferCreateInfo bufInfo = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, 0,
numVerts * drawcall->numInstances * bufStride, 0,
};
VkBufferCreateInfo bufInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
// set bufSize
bufSize = bufInfo.size = uint64_t(numVerts) * uint64_t(drawcall->numInstances) *
uint64_t(bufStride) * uint64_t(numViews);
bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
@@ -1864,9 +1894,6 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
// finish.
DoPipelineBarrier(cmd, 1, &globalbarrier);
// set bufSize
bufSize = numVerts * drawcall->numInstances * bufStride;
// vkUpdateDescriptorSet desc set to point to buffer
VkDescriptorBufferInfo fetchdesc = {0};
fetchdesc.buffer = meshBuffer;
@@ -1880,7 +1907,7 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
// do single draw
modifiedstate.BindPipeline(cmd, VulkanRenderState::BindCompute, true);
uint64_t totalVerts = numFetchVerts * uint64_t(drawcall->numInstances);
uint64_t totalVerts = numFetchVerts * uint64_t(drawcall->numInstances) * uint64_t(numViews);
// the validation layers will probably complain about this dispatch saying some arrays aren't
// fully updated. That's because they don't statically analyse that only fixed indices are
@@ -2017,6 +2044,8 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
m_PostVSData[eventId].vsout.baseVertex = baseVertex + drawcall->baseVertex;
m_PostVSData[eventId].vsout.numViews = numViews;
m_PostVSData[eventId].vsout.vertStride = bufStride;
m_PostVSData[eventId].vsout.nearPlane = nearp;
m_PostVSData[eventId].vsout.farPlane = farp;
@@ -2026,7 +2055,7 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId)
m_PostVSData[eventId].vsout.instStride = 0;
if(drawcall->flags & DrawFlags::Instanced)
m_PostVSData[eventId].vsout.instStride = uint32_t(bufSize / drawcall->numInstances);
m_PostVSData[eventId].vsout.instStride = uint32_t(bufSize / (drawcall->numInstances * numViews));
m_PostVSData[eventId].vsout.idxBuf = ResourceId();
if(m_PostVSData[eventId].vsout.useIndices && state.ibuffer.buf != ResourceId())
@@ -2098,7 +2127,8 @@ void VulkanReplay::InitPostVSBuffers(const vector<uint32_t> &events)
m_pDriver->ReplayLog(events.front(), events.back(), eReplay_Full);
}
MeshFormat VulkanReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage)
MeshFormat VulkanReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage)
{
// go through any aliasing
if(m_PostVSAlias.find(eventId) != m_PostVSAlias.end())
@@ -2110,8 +2140,20 @@ MeshFormat VulkanReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, Mes
if(m_PostVSData.find(eventId) != m_PostVSData.end())
postvs = m_PostVSData[eventId];
const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eventId);
uint32_t numInstances = 1;
if(drawcall && (drawcall->flags & DrawFlags::Instanced))
numInstances = drawcall->numInstances;
VulkanPostVSData::StageData s = postvs.GetStage(stage);
// clamp viewID
if(s.numViews > 1)
viewID = RDCMIN(viewID, s.numViews - 1);
else
viewID = 0;
MeshFormat ret;
if(s.useIndices && s.idxBuf != ResourceId())
@@ -2132,7 +2174,7 @@ MeshFormat VulkanReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, Mes
else
ret.vertexResourceId = ResourceId();
ret.vertexByteOffset = s.instStride * instID;
ret.vertexByteOffset = s.instStride * (instID + viewID * numInstances);
ret.vertexByteStride = s.vertStride;
ret.format.compCount = 4;
+3
View File
@@ -1124,6 +1124,9 @@ void VulkanReplay::SavePipelineState()
c.m_RenderPass[state.renderPass].subpasses[state.subpass].resolveAttachments;
m_VulkanPipelineState.currentPass.renderpass.depthstencilAttachment =
c.m_RenderPass[state.renderPass].subpasses[state.subpass].depthstencilAttachment;
m_VulkanPipelineState.currentPass.renderpass.multiviews =
c.m_RenderPass[state.renderPass].subpasses[state.subpass].multiviews;
}
m_VulkanPipelineState.currentPass.framebuffer.resourceId = rm->GetOriginalID(state.framebuffer);
+4 -1
View File
@@ -140,6 +140,8 @@ struct VulkanPostVSData
uint32_t vertStride;
uint32_t instStride;
uint32_t numViews;
bool useIndices;
ResourceId idxBuf;
VkDeviceSize idxOffset;
@@ -251,7 +253,8 @@ public:
void AliasPostVSBuffers(uint32_t eventId, uint32_t alias) { m_PostVSAlias[alias] = eventId; }
void ClearPostVSCache();
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage);
MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage);
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &retData);
void GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
+4 -3
View File
@@ -1969,8 +1969,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::RenderPass &el)
SERIALISE_MEMBER(colorAttachments);
SERIALISE_MEMBER(resolveAttachments);
SERIALISE_MEMBER(depthstencilAttachment);
SERIALISE_MEMBER(multiviews);
SIZE_CHECK(72);
SIZE_CHECK(88);
}
template <typename SerialiserType>
@@ -2020,7 +2021,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::CurrentPass &el)
SERIALISE_MEMBER(framebuffer);
SERIALISE_MEMBER(renderArea);
SIZE_CHECK(128);
SIZE_CHECK(144);
}
template <typename SerialiserType>
@@ -2073,7 +2074,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::State &el)
SERIALISE_MEMBER(images);
SIZE_CHECK(1328);
SIZE_CHECK(1344);
}
#pragma endregion Vulkan pipeline state
+2 -2
View File
@@ -557,7 +557,7 @@ rdcarray<EventUsage> ReplayController::GetUsage(ResourceId id)
return m_pDevice->GetUsage(id);
}
MeshFormat ReplayController::GetPostVSData(uint32_t instID, MeshDataStage stage)
MeshFormat ReplayController::GetPostVSData(uint32_t instID, uint32_t viewID, MeshDataStage stage)
{
DrawcallDescription *draw = GetDrawcallByEID(m_EventID);
@@ -571,7 +571,7 @@ MeshFormat ReplayController::GetPostVSData(uint32_t instID, MeshDataStage stage)
m_pDevice->InitPostVSBuffers(draw->eventId);
return m_pDevice->GetPostVSBuffers(draw->eventId, instID, stage);
return m_pDevice->GetPostVSBuffers(draw->eventId, instID, viewID, stage);
}
bytebuf ReplayController::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len)
+1 -1
View File
@@ -180,7 +180,7 @@ public:
ShaderDebugTrace *DebugThread(const uint32_t groupid[3], const uint32_t threadid[3]);
void FreeTrace(ShaderDebugTrace *trace);
MeshFormat GetPostVSData(uint32_t instID, MeshDataStage stage);
MeshFormat GetPostVSData(uint32_t instID, uint32_t viewID, MeshDataStage stage);
rdcarray<EventUsage> GetUsage(ResourceId id);
+2 -1
View File
@@ -130,7 +130,8 @@ public:
virtual ResourceId GetLiveID(ResourceId id) = 0;
virtual MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDataStage stage) = 0;
virtual MeshFormat GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_t viewID,
MeshDataStage stage) = 0;
virtual void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &retData) = 0;
virtual void GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
+13 -7
View File
@@ -449,14 +449,16 @@ rdcpair<uint32_t, uint32_t> ReplayOutput::PickVertex(uint32_t eventId, uint32_t
// used for post-VS output, calculate the offset of the element we're using as position,
// relative to 0
MeshFormat fmt = m_pDevice->GetPostVSBuffers(
draw->eventId, m_RenderData.meshDisplay.curInstance, m_RenderData.meshDisplay.type);
MeshFormat fmt =
m_pDevice->GetPostVSBuffers(draw->eventId, m_RenderData.meshDisplay.curInstance,
m_RenderData.meshDisplay.curView, m_RenderData.meshDisplay.type);
uint64_t elemOffset = cfg.position.vertexByteOffset - fmt.vertexByteOffset;
for(uint32_t inst = firstInst; inst < maxInst; inst++)
{
// find the start of this buffer, and apply the element offset, then pick in that instance
fmt = m_pDevice->GetPostVSBuffers(draw->eventId, inst, m_RenderData.meshDisplay.type);
fmt = m_pDevice->GetPostVSBuffers(draw->eventId, inst, m_RenderData.meshDisplay.curView,
m_RenderData.meshDisplay.type);
if(fmt.vertexResourceId != ResourceId())
cfg.position.vertexByteOffset = fmt.vertexByteOffset + elemOffset;
@@ -819,9 +821,11 @@ void ReplayOutput::DisplayMesh()
for(uint32_t inst = 0; inst < RDCMAX(1U, d->numInstances); inst++)
{
// get the 'most final' stage
MeshFormat fmt = m_pDevice->GetPostVSBuffers(passEvents[i], inst, MeshDataStage::GSOut);
MeshFormat fmt = m_pDevice->GetPostVSBuffers(
passEvents[i], inst, m_RenderData.meshDisplay.curView, MeshDataStage::GSOut);
if(fmt.vertexResourceId == ResourceId())
fmt = m_pDevice->GetPostVSBuffers(passEvents[i], inst, MeshDataStage::VSOut);
fmt = m_pDevice->GetPostVSBuffers(passEvents[i], inst, m_RenderData.meshDisplay.curView,
MeshDataStage::VSOut);
fmt.meshColor = passDraws;
@@ -844,9 +848,11 @@ void ReplayOutput::DisplayMesh()
for(uint32_t inst = 0; inst < maxInst; inst++)
{
// get the 'most final' stage
MeshFormat fmt = m_pDevice->GetPostVSBuffers(draw->eventId, inst, MeshDataStage::GSOut);
MeshFormat fmt = m_pDevice->GetPostVSBuffers(
draw->eventId, inst, m_RenderData.meshDisplay.curView, MeshDataStage::GSOut);
if(fmt.vertexResourceId == ResourceId())
fmt = m_pDevice->GetPostVSBuffers(draw->eventId, inst, MeshDataStage::VSOut);
fmt = m_pDevice->GetPostVSBuffers(draw->eventId, inst, m_RenderData.meshDisplay.curView,
MeshDataStage::VSOut);
fmt.meshColor = otherInstances;