mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-20 22:41:36 +00:00
Render mesh data with instanced properties correctly.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user