mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-23 14:15:42 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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``.
|
||||
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -729,9 +729,9 @@ void ReplayProxy::InitPostVSBuffers(const std::vector<uint32_t> &events)
|
||||
}
|
||||
|
||||
template <typename ParamSerialiser, typename ReturnSerialiser>
|
||||
MeshFormat ReplayProxy::Proxied_GetPostVSBuffers(ParamSerialiser ¶mser,
|
||||
ReturnSerialiser &retser, uint32_t eventId,
|
||||
uint32_t instID, MeshDataStage stage)
|
||||
MeshFormat ReplayProxy::Proxied_GetPostVSBuffers(ParamSerialiser ¶mser, 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 ¶mser,
|
||||
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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -274,6 +274,8 @@ struct VulkanCreationInfo
|
||||
vector<VkImageLayout> inputLayouts;
|
||||
vector<VkImageLayout> colorLayouts;
|
||||
VkImageLayout depthstencilLayout;
|
||||
|
||||
std::vector<uint32_t> multiviews;
|
||||
};
|
||||
vector<Subpass> subpasses;
|
||||
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user