Render mesh data with instanced properties correctly.

This commit is contained in:
baldurk
2018-01-24 16:14:22 +00:00
parent f05cfe9454
commit 8f405a2197
7 changed files with 94 additions and 8 deletions
+6
View File
@@ -2129,6 +2129,9 @@ void BufferViewer::updatePreviewColumns()
{
const FormatElement &el = m_ModelVSIn->columns[elIdx];
m_VSInPosition.instanced = el.perinstance;
m_VSInPosition.instStepRate = el.instancerate;
if(el.buffer < vbs.count())
{
m_VSInPosition.vertexResourceId = vbs[el.buffer].resourceId;
@@ -2152,6 +2155,9 @@ void BufferViewer::updatePreviewColumns()
{
const FormatElement &el = m_ModelVSIn->columns[elIdx];
m_VSInSecondary.instanced = el.perinstance;
m_VSInSecondary.instStepRate = el.instancerate;
if(el.buffer < vbs.count())
{
m_VSInSecondary.vertexResourceId = vbs[el.buffer].resourceId;
+7
View File
@@ -40,10 +40,12 @@ struct MeshFormat
baseVertex = 0;
vertexByteOffset = 0;
vertexByteStride = 0;
instStepRate = 1;
showAlpha = false;
topology = Topology::Unknown;
numIndices = 0;
unproject = false;
instanced = false;
nearPlane = farPlane = 0.0f;
}
@@ -75,6 +77,8 @@ struct MeshFormat
Topology topology;
DOCUMENT("The number of vertices in the mesh.");
uint32_t numIndices;
DOCUMENT("The number of instances to render with the same value. See :data:`instanced`.");
uint32_t instStepRate;
DOCUMENT("The near plane for the projection matrix.");
float nearPlane;
@@ -83,6 +87,9 @@ struct MeshFormat
DOCUMENT("``True`` if this mesh element contains post-projection positional data.");
bool unproject;
DOCUMENT("``True`` if this mesh element comes from instanced data. See :data:`instStepRate`.");
bool instanced;
DOCUMENT("``True`` if the alpha component of this element should be used.");
bool showAlpha;
};
+12 -2
View File
@@ -89,7 +89,8 @@ void D3D11Replay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &seconda
layoutdesc[0].Format = MakeDXGIFormat(resFmt);
layoutdesc[0].AlignedByteOffset = 0; // offset will be handled by vertex buffer offset
layoutdesc[0].InputSlot = 0;
layoutdesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
layoutdesc[0].InputSlotClass =
cfg.position.instanced ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
layoutdesc[0].InstanceDataStepRate = 0;
layoutdesc[1].SemanticName = "sec";
@@ -99,7 +100,8 @@ void D3D11Replay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &seconda
layoutdesc[1].Format = MakeDXGIFormat(resFmt2);
layoutdesc[1].AlignedByteOffset = 0;
layoutdesc[1].InputSlot = 1;
layoutdesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
layoutdesc[1].InputSlotClass =
cfg.second.instanced ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
layoutdesc[1].InstanceDataStepRate = 0;
HRESULT hr = m_pDevice->CreateInputLayout(layoutdesc, 2, m_MeshRender.MeshVSBytecode,
@@ -221,6 +223,14 @@ void D3D11Replay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &seconda
UINT str[] = {cfg.position.vertexByteStride, cfg.second.vertexByteStride};
UINT offs[] = {(UINT)cfg.position.vertexByteOffset, (UINT)cfg.second.vertexByteOffset};
// we source all data from the first instanced value in the instanced case, so make sure we
// offset correctly here.
if(cfg.position.instanced)
offs[0] += cfg.position.vertexByteStride * (cfg.curInstance / cfg.position.instStepRate);
if(cfg.second.instanced)
offs[1] += cfg.second.vertexByteStride * (cfg.curInstance / cfg.second.instStepRate);
{
auto it = WrappedID3D11Buffer::m_BufferList.find(cfg.position.vertexResourceId);
+28 -1
View File
@@ -72,6 +72,17 @@ MeshDisplayPipelines D3D12DebugManager::CacheMeshDisplayPipelines(const MeshForm
}
bit += 16;
if(primary.instanced)
key |= 1ULL << bit;
bit++;
if(secondary.instanced)
key |= 1ULL << bit;
bit++;
// only 64 bits, make sure they all fit
RDCASSERT(bit < 64);
MeshDisplayPipelines &cache = m_CachedMeshPipelines[key];
if(cache.pipes[(uint32_t)SolidShade::NoSolid] != NULL)
@@ -113,6 +124,8 @@ MeshDisplayPipelines D3D12DebugManager::CacheMeshDisplayPipelines(const MeshForm
D3D12_INPUT_ELEMENT_DESC ia[2] = {};
ia[0].SemanticName = "pos";
ia[0].Format = primaryFmt;
ia[0].InputSlotClass = primary.instanced ? D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA
: D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
ia[1].SemanticName = "sec";
ia[1].InputSlot = 1;
ia[1].Format = secondaryFmt == DXGI_FORMAT_UNKNOWN ? primaryFmt : secondaryFmt;
@@ -171,7 +184,8 @@ MeshDisplayPipelines D3D12DebugManager::CacheMeshDisplayPipelines(const MeshForm
if(secondary.vertexResourceId != ResourceId())
{
// pull secondary information from second vertex buffer
ia[1].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
ia[1].InputSlotClass = secondary.instanced ? D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA
: D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
RDCASSERT(secondaryFmt != DXGI_FORMAT_UNKNOWN);
hr = m_pDevice->CreateGraphicsPipelineState(
@@ -336,6 +350,12 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &seconda
m_pDevice->GetResourceManager()->GetCurrentAs<ID3D12Resource>(cfg.position.vertexResourceId);
UINT64 offs = cfg.position.vertexByteOffset;
// we source all data from the first instanced value in the instanced case, so make sure we
// offset correctly here.
if(cfg.position.instanced)
offs += cfg.position.vertexByteStride * (cfg.curInstance / cfg.position.instStepRate);
D3D12_VERTEX_BUFFER_VIEW view;
view.BufferLocation = vb->GetGPUVirtualAddress() + offs;
view.StrideInBytes = cfg.position.vertexByteStride;
@@ -363,10 +383,17 @@ void D3D12Replay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &seconda
m_pDevice->GetResourceManager()->GetCurrentAs<ID3D12Resource>(cfg.position.vertexResourceId);
UINT64 offs = cfg.second.vertexByteOffset;
// we source all data from the first instanced value in the instanced case, so make sure we
// offset correctly here.
if(cfg.second.instanced)
offs += cfg.second.vertexByteStride * (cfg.curInstance / cfg.second.instStepRate);
D3D12_VERTEX_BUFFER_VIEW view;
view.BufferLocation = vb->GetGPUVirtualAddress() + offs;
view.StrideInBytes = cfg.second.vertexByteStride;
view.SizeInBytes = UINT(vb->GetDesc().Width - offs);
list->IASetVertexBuffers(1, 1, &view);
}
+11 -2
View File
@@ -235,10 +235,19 @@ void GLReplay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &secondaryD
gl.glVertexAttribLFormat(i, meshData[i]->format.compCount, eGL_DOUBLE, 0);
}
GLintptr offs = (GLintptr)meshData[i]->vertexByteOffset;
if(meshData[i]->instanced)
offs += meshData[i]->vertexByteStride * (cfg.curInstance / meshData[i]->instStepRate);
GLuint vb =
m_pDriver->GetResourceManager()->GetCurrentResource(meshData[i]->vertexResourceId).name;
gl.glBindVertexBuffer(i, vb, (GLintptr)meshData[i]->vertexByteOffset,
meshData[i]->vertexByteStride);
gl.glBindVertexBuffer(i, vb, offs, meshData[i]->vertexByteStride);
if(meshData[i]->instanced)
gl.glVertexAttribDivisor(i, 1);
else
gl.glVertexAttribDivisor(i, 0);
}
// enable position attribute
+27 -2
View File
@@ -75,6 +75,17 @@ MeshDisplayPipelines VulkanDebugManager::CacheMeshDisplayPipelines(VkPipelineLay
}
bit += 16;
if(primary.instanced)
key |= 1ULL << bit;
bit++;
if(secondary.instanced)
key |= 1ULL << bit;
bit++;
// only 64 bits, make sure they all fit
RDCASSERT(bit < 64);
MeshDisplayPipelines &cache = m_CachedMeshPipelines[key];
if(cache.pipes[(uint32_t)SolidShade::NoSolid] != VK_NULL_HANDLE)
@@ -88,9 +99,11 @@ MeshDisplayPipelines VulkanDebugManager::CacheMeshDisplayPipelines(VkPipelineLay
VkVertexInputBindingDescription binds[] = {
// primary
{0, primary.vertexByteStride, VK_VERTEX_INPUT_RATE_VERTEX},
{0, primary.vertexByteStride,
primary.instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX},
// secondary
{1, secondary.vertexByteStride, VK_VERTEX_INPUT_RATE_VERTEX}};
{1, secondary.vertexByteStride,
secondary.instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX}};
RDCASSERT(primaryFmt != VK_FORMAT_UNDEFINED);
@@ -526,6 +539,12 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &second
m_pDriver->GetResourceManager()->GetCurrentHandle<VkBuffer>(cfg.position.vertexResourceId);
VkDeviceSize offs = cfg.position.vertexByteOffset;
// we source all data from the first instanced value in the instanced case, so make sure we
// offset correctly here.
if(cfg.position.instanced)
offs += cfg.position.vertexByteStride * (cfg.curInstance / cfg.position.instStepRate);
vt->CmdBindVertexBuffers(Unwrap(cmd), 0, 1, UnwrapPtr(vb), &offs);
}
@@ -541,6 +560,12 @@ void VulkanReplay::RenderMesh(uint32_t eventId, const vector<MeshFormat> &second
m_pDriver->GetResourceManager()->GetCurrentHandle<VkBuffer>(cfg.second.vertexResourceId);
VkDeviceSize offs = cfg.second.vertexByteOffset;
// we source all data from the first instanced value in the instanced case, so make sure we
// offset correctly here.
if(cfg.second.instanced)
offs += cfg.second.vertexByteStride * (cfg.curInstance / cfg.second.instStepRate);
vt->CmdBindVertexBuffers(Unwrap(cmd), 1, 1, UnwrapPtr(vb), &offs);
}
+3 -1
View File
@@ -706,11 +706,13 @@ void DoSerialise(SerialiserType &ser, MeshFormat &el)
SERIALISE_MEMBER(showAlpha);
SERIALISE_MEMBER(topology);
SERIALISE_MEMBER(numIndices);
SERIALISE_MEMBER(instStepRate);
SERIALISE_MEMBER(unproject);
SERIALISE_MEMBER(instanced);
SERIALISE_MEMBER(nearPlane);
SERIALISE_MEMBER(farPlane);
SIZE_CHECK(88);
SIZE_CHECK(96);
}
template <typename SerialiserType>