|
|
#include "meshRendererD3D12.h" |
|
|
|
|
|
namespace FlexSample { |
|
|
|
|
|
const D3D12_INPUT_ELEMENT_DESC MeshRendererD3D12::MeshInputElementDescs[4] = |
|
|
{ |
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, |
|
|
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, |
|
|
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, |
|
|
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 3, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } |
|
|
}; |
|
|
|
|
|
const D3D12_INPUT_ELEMENT_DESC MeshRendererD3D12::PointInputElementDescs[3] = |
|
|
{ |
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, |
|
|
{ "DENSITY", 0, DXGI_FORMAT_R32_FLOAT, 1, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, |
|
|
{ "PHASE", 0, DXGI_FORMAT_R32_SINT, 2, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
RenderMeshD3D12::RenderMeshD3D12() |
|
|
{ |
|
|
m_numVertices = 0; |
|
|
m_numFaces = 0; |
|
|
} |
|
|
|
|
|
int RenderMeshD3D12::initialize(const RenderStateD3D12& state, const MeshData& meshData) |
|
|
{ |
|
|
NV_RETURN_ON_FAIL(m_positionBuffer.init(state, sizeof(Vec3), meshData.numVertices, meshData.positions)); |
|
|
NV_RETURN_ON_FAIL(m_normalBuffer.init(state, sizeof(Vec3), meshData.numVertices, meshData.normals)); |
|
|
NV_RETURN_ON_FAIL(m_texcoordBuffer.init(state, sizeof(Vec2), meshData.numVertices, meshData.texcoords)); |
|
|
NV_RETURN_ON_FAIL(m_colorBuffer.init(state, sizeof(Vec4), meshData.numVertices, meshData.colors)); |
|
|
NV_RETURN_ON_FAIL(m_indexBuffer.init(state, sizeof(uint32_t), meshData.numFaces * 3, meshData.indices)); |
|
|
|
|
|
m_numVertices = meshData.numVertices; |
|
|
m_numFaces = meshData.numFaces; |
|
|
|
|
|
_setBufferNames(); |
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
int RenderMeshD3D12::initialize(const RenderStateD3D12& state, const MeshData2& meshData) |
|
|
{ |
|
|
NV_RETURN_ON_FAIL(m_positionBuffer.init(state, sizeof(Vec4), sizeof(Vec3), meshData.numVertices, meshData.positions)); |
|
|
NV_RETURN_ON_FAIL(m_normalBuffer.init(state, sizeof(Vec4), sizeof(Vec3), meshData.numVertices, meshData.normals)); |
|
|
NV_RETURN_ON_FAIL(m_texcoordBuffer.init(state, sizeof(Vec2), meshData.numVertices, meshData.texcoords)); |
|
|
NV_RETURN_ON_FAIL(m_colorBuffer.init(state, sizeof(Vec4), meshData.numVertices, meshData.colors)); |
|
|
NV_RETURN_ON_FAIL(m_indexBuffer.init(state, sizeof(uint32_t), meshData.numFaces * 3, meshData.indices)); |
|
|
|
|
|
m_numVertices = meshData.numVertices; |
|
|
m_numFaces = meshData.numFaces; |
|
|
|
|
|
_setBufferNames(); |
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
void RenderMeshD3D12::_setBufferNames() |
|
|
{ |
|
|
m_positionBuffer.setDebugName(L"positions"); |
|
|
m_normalBuffer.setDebugName(L"normals"); |
|
|
m_texcoordBuffer.setDebugName(L"texcoords"); |
|
|
m_colorBuffer.setDebugName(L"colors"); |
|
|
m_indexBuffer.setDebugName(L"indices"); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
MeshRendererD3D12::MeshRendererD3D12() |
|
|
{ |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::initialize(const RenderStateD3D12& state) |
|
|
{ |
|
|
m_renderState = state; |
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
D3D12_VERTEX_BUFFER_VIEW MeshRendererD3D12::_newImmediateVertexBuffer(const void* data, int stride, ptrdiff_t numVertices) |
|
|
{ |
|
|
D3D12_VERTEX_BUFFER_VIEW view = {}; |
|
|
if (data) |
|
|
{ |
|
|
const size_t bufferSize = stride * numVertices; |
|
|
NvCo::Dx12CircularResourceHeap::Cursor cursor = m_renderState.m_constantHeap->allocateVertexBuffer(bufferSize); |
|
|
|
|
|
memcpy(cursor.m_position, data, bufferSize); |
|
|
|
|
|
view.BufferLocation = m_renderState.m_constantHeap->getGpuHandle(cursor); |
|
|
view.SizeInBytes = UINT(bufferSize); |
|
|
view.StrideInBytes = stride; |
|
|
} |
|
|
return view; |
|
|
} |
|
|
|
|
|
D3D12_VERTEX_BUFFER_VIEW MeshRendererD3D12::_newStridedImmediateVertexBuffer(const void* data, int srcStride, int dstStride, ptrdiff_t numElements) |
|
|
{ |
|
|
if (srcStride == dstStride) |
|
|
{ |
|
|
return _newImmediateVertexBuffer(data, srcStride, numElements); |
|
|
} |
|
|
|
|
|
D3D12_VERTEX_BUFFER_VIEW view = {}; |
|
|
if (srcStride == 4 * 4 && dstStride == 4 * 3) |
|
|
{ |
|
|
const size_t bufferSize = dstStride * numElements; |
|
|
NvCo::Dx12CircularResourceHeap::Cursor cursor = m_renderState.m_constantHeap->allocateVertexBuffer(bufferSize); |
|
|
|
|
|
uint32_t* dst = (uint32_t*)cursor.m_position; |
|
|
const uint32_t* src = (const uint32_t*)data; |
|
|
|
|
|
|
|
|
for (ptrdiff_t i = 0; i < numElements; i++, dst += 3, src += 4) |
|
|
{ |
|
|
dst[0] = src[0]; |
|
|
dst[1] = src[1]; |
|
|
dst[2] = src[2]; |
|
|
} |
|
|
|
|
|
view.BufferLocation = m_renderState.m_constantHeap->getGpuHandle(cursor); |
|
|
view.SizeInBytes = UINT(bufferSize); |
|
|
view.StrideInBytes = dstStride; |
|
|
|
|
|
return view; |
|
|
} |
|
|
|
|
|
printf("Unhandled conversion"); |
|
|
return view; |
|
|
} |
|
|
|
|
|
D3D12_INDEX_BUFFER_VIEW MeshRendererD3D12::_newImmediateIndexBuffer(const void* data, int stride, ptrdiff_t numIndices) |
|
|
{ |
|
|
assert(stride == sizeof(uint32_t)); |
|
|
D3D12_INDEX_BUFFER_VIEW view = {}; |
|
|
|
|
|
if (data) |
|
|
{ |
|
|
const size_t bufferSize = stride * numIndices; |
|
|
NvCo::Dx12CircularResourceHeap::Cursor cursor = m_renderState.m_constantHeap->allocateVertexBuffer(bufferSize); |
|
|
|
|
|
memcpy(cursor.m_position, data, bufferSize); |
|
|
|
|
|
view.BufferLocation = m_renderState.m_constantHeap->getGpuHandle(cursor); |
|
|
view.SizeInBytes = UINT(bufferSize); |
|
|
view.Format = DXGI_FORMAT_R32_UINT; |
|
|
} |
|
|
|
|
|
return view; |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::draw(RenderMesh* meshIn, RenderPipeline* pipeline, const void* params) |
|
|
{ |
|
|
RenderMeshD3D12* mesh = static_cast<RenderMeshD3D12*>(meshIn); |
|
|
|
|
|
|
|
|
MeshRenderAllocationD3D12 alloc; |
|
|
alloc.init(PRIMITIVE_TRIANGLE); |
|
|
|
|
|
alloc.m_vertexBufferViews[0] = mesh->m_positionBuffer.m_vertexBufferView; |
|
|
alloc.m_vertexBufferViews[1] = mesh->m_normalBuffer.m_vertexBufferView; |
|
|
alloc.m_vertexBufferViews[2] = mesh->m_texcoordBuffer.m_vertexBufferView; |
|
|
alloc.m_vertexBufferViews[3] = mesh->m_colorBuffer.m_vertexBufferView; |
|
|
|
|
|
alloc.m_indexBufferView = mesh->m_indexBuffer.m_indexBufferView; |
|
|
alloc.m_numPrimitives = mesh->m_numFaces; |
|
|
alloc.m_numPositions = mesh->m_numVertices; |
|
|
|
|
|
return drawTransitory(alloc, sizeof(MeshRenderAllocationD3D12), pipeline, params); |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::drawImmediate(const MeshData& mesh, RenderPipeline* pipeline, const void* params) |
|
|
{ |
|
|
MeshRenderAllocationD3D12 alloc; |
|
|
allocateTransitory(mesh, alloc, sizeof(alloc)); |
|
|
return drawTransitory(alloc, sizeof(alloc), pipeline, params); |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::drawImmediate(const MeshData2& mesh, RenderPipeline* pipeline, const void* params) |
|
|
{ |
|
|
MeshRenderAllocationD3D12 alloc; |
|
|
allocateTransitory(mesh, alloc, sizeof(alloc)); |
|
|
return drawTransitory(alloc, sizeof(alloc), pipeline, params); |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::drawImmediate(const LineData& lineData, RenderPipeline* pipeline, const void* params) |
|
|
{ |
|
|
LineRenderAllocationD3D12 alloc; |
|
|
allocateTransitory(lineData, alloc, sizeof(alloc)); |
|
|
return drawTransitory(alloc, sizeof(alloc), pipeline, params); |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::drawImmediate(const PointData& pointData, RenderPipeline* pipeline, const void* params) |
|
|
{ |
|
|
PointRenderAllocationD3D12 alloc; |
|
|
allocateTransitory(pointData, alloc, sizeof(alloc)); |
|
|
return drawTransitory(alloc, sizeof(alloc), pipeline, params); |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::allocateTransitory(const PointData& pointData, RenderAllocation& allocIn, size_t sizeOfAlloc) |
|
|
{ |
|
|
typedef PointRenderAllocationD3D12 Alloc; |
|
|
|
|
|
assert(sizeof(Alloc) == sizeOfAlloc); |
|
|
|
|
|
Alloc& alloc = static_cast<Alloc&>(allocIn); |
|
|
alloc.init(PRIMITIVE_POINT); |
|
|
|
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_POSITION] = _newImmediateVertexBuffer(pointData.positions, sizeof(Vec4), pointData.numPoints); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_DENSITY] = _newImmediateVertexBuffer(pointData.density, sizeof(float), pointData.numPoints); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_PHASE] = _newImmediateVertexBuffer(pointData.phase, sizeof(int), pointData.numPoints); |
|
|
|
|
|
if (pointData.anisotropy[0]) |
|
|
{ |
|
|
for (int i = 0; i < 3; i++) |
|
|
{ |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY1 + i] = _newImmediateVertexBuffer(pointData.anisotropy[i], sizeof(Vec4), pointData.numPoints); |
|
|
} |
|
|
} |
|
|
|
|
|
alloc.m_indexBufferView = _newImmediateIndexBuffer(pointData.indices, sizeof(uint32_t), pointData.numIndices); |
|
|
|
|
|
alloc.m_numPrimitives = pointData.numIndices; |
|
|
alloc.m_numPositions = pointData.numPoints; |
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::allocateTransitory(const MeshData2& mesh, RenderAllocation& allocIn, size_t sizeOfAlloc) |
|
|
{ |
|
|
typedef MeshRenderAllocationD3D12 Alloc; |
|
|
assert(sizeof(Alloc) == sizeOfAlloc); |
|
|
|
|
|
Alloc& alloc = static_cast<Alloc&>(allocIn); |
|
|
alloc.init(PRIMITIVE_TRIANGLE); |
|
|
|
|
|
const int numIndices = int(mesh.numFaces * 3); |
|
|
alloc.m_indexBufferView = _newImmediateIndexBuffer(mesh.indices, sizeof(uint32_t), numIndices); |
|
|
|
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_POSITION] = _newStridedImmediateVertexBuffer(mesh.positions, sizeof(Vec4), sizeof(Vec3), mesh.numVertices); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_NORMAL] = _newStridedImmediateVertexBuffer(mesh.normals, sizeof(Vec4), sizeof(Vec3), mesh.numVertices); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_TEX_COORDS] = _newImmediateVertexBuffer(mesh.texcoords, sizeof(Vec2), mesh.numVertices); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_COLOR] = _newImmediateVertexBuffer(mesh.colors, sizeof(Vec4), mesh.numVertices); |
|
|
|
|
|
alloc.m_numPrimitives = mesh.numFaces; |
|
|
alloc.m_numPositions = mesh.numVertices; |
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::allocateTransitory(const LineData& lineData, RenderAllocation& allocIn, size_t sizeOfAlloc) |
|
|
{ |
|
|
typedef LineRenderAllocationD3D12 Alloc; |
|
|
assert(sizeof(Alloc) == sizeOfAlloc); |
|
|
|
|
|
Alloc& alloc = static_cast<Alloc&>(allocIn); |
|
|
alloc.init(PRIMITIVE_LINE); |
|
|
|
|
|
alloc.m_vertexBufferView = _newImmediateVertexBuffer(lineData.vertices, sizeof(LineData::Vertex), lineData.numVertices); |
|
|
alloc.m_indexBufferView = _newImmediateIndexBuffer(lineData.indices, sizeof(uint32_t), lineData.numLines * 2); |
|
|
|
|
|
alloc.m_numPrimitives = lineData.numLines; |
|
|
alloc.m_numPositions = lineData.numVertices; |
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::allocateTransitory(const MeshData& mesh, RenderAllocation& allocIn, size_t sizeOfAlloc) |
|
|
{ |
|
|
typedef MeshRenderAllocationD3D12 Alloc; |
|
|
assert(sizeof(Alloc) == sizeOfAlloc); |
|
|
|
|
|
Alloc& alloc = static_cast<Alloc&>(allocIn); |
|
|
|
|
|
alloc.init(PRIMITIVE_TRIANGLE); |
|
|
|
|
|
const int numIndices = int(mesh.numFaces * 3); |
|
|
alloc.m_indexBufferView = _newImmediateIndexBuffer(mesh.indices, sizeof(uint32_t), numIndices); |
|
|
|
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_POSITION] = _newImmediateVertexBuffer(mesh.positions, sizeof(Vec3), mesh.numVertices); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_NORMAL] = _newImmediateVertexBuffer(mesh.normals, sizeof(Vec3), mesh.numVertices); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_TEX_COORDS] = _newImmediateVertexBuffer(mesh.texcoords, sizeof(Vec2), mesh.numVertices); |
|
|
alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_COLOR] = _newImmediateVertexBuffer(mesh.colors, sizeof(Vec4), mesh.numVertices); |
|
|
|
|
|
alloc.m_numPrimitives = mesh.numFaces; |
|
|
alloc.m_numPositions = mesh.numVertices; |
|
|
|
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::drawTransitory(RenderAllocation& allocIn, size_t sizeOfAlloc, RenderPipeline* pipeline, const void* params) |
|
|
{ |
|
|
if (allocIn.m_primitiveType == PRIMITIVE_UNKNOWN) |
|
|
{ |
|
|
return NV_OK; |
|
|
} |
|
|
if (allocIn.m_primitiveType != pipeline->getPrimitiveType()) |
|
|
{ |
|
|
printf("Wrong pipeline primitive type"); |
|
|
return NV_FAIL; |
|
|
} |
|
|
|
|
|
NV_RETURN_ON_FAIL(pipeline->bind(params, &m_renderState)); |
|
|
NV_RETURN_ON_FAIL(pipeline->draw(allocIn, sizeOfAlloc, &m_renderState)); |
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
RenderMesh* MeshRendererD3D12::createMesh(const MeshData& meshData) |
|
|
{ |
|
|
RenderMeshD3D12* mesh = new RenderMeshD3D12; |
|
|
if (NV_FAILED(mesh->initialize(m_renderState, meshData))) |
|
|
{ |
|
|
delete mesh; |
|
|
return nullptr; |
|
|
} |
|
|
return mesh; |
|
|
} |
|
|
|
|
|
RenderMesh* MeshRendererD3D12::createMesh(const MeshData2& meshData) |
|
|
{ |
|
|
RenderMeshD3D12* mesh = new RenderMeshD3D12; |
|
|
if (NV_FAILED(mesh->initialize(m_renderState, meshData))) |
|
|
{ |
|
|
delete mesh; |
|
|
return nullptr; |
|
|
} |
|
|
return mesh; |
|
|
} |
|
|
|
|
|
int MeshRendererD3D12::defaultDraw(const RenderAllocation& allocIn, size_t sizeOfAlloc, const void* platformState) |
|
|
{ |
|
|
const RenderStateD3D12& state = *(RenderStateD3D12*)platformState; |
|
|
ID3D12GraphicsCommandList* commandList = state.m_commandList; |
|
|
|
|
|
switch (allocIn.m_primitiveType) |
|
|
{ |
|
|
case PRIMITIVE_POINT: |
|
|
{ |
|
|
typedef PointRenderAllocationD3D12 Alloc; |
|
|
const RenderStateD3D12& state = *(RenderStateD3D12*)platformState; |
|
|
|
|
|
assert(sizeof(Alloc) == sizeOfAlloc); |
|
|
const Alloc& alloc = static_cast<const Alloc&>(allocIn); |
|
|
|
|
|
assert(allocIn.m_numPrimitives >= 0); |
|
|
|
|
|
ID3D12GraphicsCommandList* commandList = state.m_commandList; |
|
|
|
|
|
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST); |
|
|
commandList->IASetVertexBuffers(0, Alloc::NUM_DEFAULT_VERTEX_VIEWS, alloc.m_vertexBufferViews); |
|
|
commandList->IASetIndexBuffer(&alloc.m_indexBufferView); |
|
|
|
|
|
if (alloc.m_indexBufferView.SizeInBytes) |
|
|
{ |
|
|
commandList->DrawIndexedInstanced((UINT)allocIn.m_numPrimitives, 1, (UINT)allocIn.m_offset, 0, 0); |
|
|
} |
|
|
else |
|
|
{ |
|
|
commandList->DrawInstanced((UINT)allocIn.m_numPrimitives, 1, (UINT)allocIn.m_offset, 0); |
|
|
} |
|
|
break; |
|
|
} |
|
|
case PRIMITIVE_LINE: |
|
|
{ |
|
|
typedef LineRenderAllocationD3D12 Alloc; |
|
|
assert(sizeof(Alloc) == sizeOfAlloc); |
|
|
const Alloc& alloc = static_cast<const Alloc&>(allocIn); |
|
|
|
|
|
assert(alloc.m_numPrimitives >= 0); |
|
|
|
|
|
const int numIndices = int(alloc.m_numPrimitives * 2); |
|
|
|
|
|
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINELIST); |
|
|
commandList->IASetVertexBuffers(0, 1, &alloc.m_vertexBufferView); |
|
|
|
|
|
if (alloc.m_indexBufferView.SizeInBytes) |
|
|
{ |
|
|
commandList->IASetIndexBuffer(nullptr); |
|
|
commandList->DrawIndexedInstanced((UINT)numIndices, 1, 0, 0, 0); |
|
|
} |
|
|
else |
|
|
{ |
|
|
commandList->IASetIndexBuffer(&alloc.m_indexBufferView); |
|
|
commandList->DrawInstanced((UINT)numIndices, 1, 0, 0); |
|
|
} |
|
|
break; |
|
|
} |
|
|
case PRIMITIVE_TRIANGLE: |
|
|
{ |
|
|
typedef MeshRenderAllocationD3D12 Alloc; |
|
|
assert(sizeof(Alloc) == sizeOfAlloc); |
|
|
const Alloc& alloc = static_cast<const Alloc&>(allocIn); |
|
|
|
|
|
const int numIndices = int(alloc.m_numPrimitives * 3); |
|
|
|
|
|
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); |
|
|
commandList->IASetVertexBuffers(0, _countof(alloc.m_vertexBufferViews), alloc.m_vertexBufferViews); |
|
|
commandList->IASetIndexBuffer(&alloc.m_indexBufferView); |
|
|
|
|
|
if (alloc.m_indexBufferView.SizeInBytes) |
|
|
{ |
|
|
commandList->DrawIndexedInstanced((UINT)numIndices, 1, 0, 0, 0); |
|
|
} |
|
|
else |
|
|
{ |
|
|
commandList->DrawInstanced((UINT)numIndices, 1, 0, 0); |
|
|
} |
|
|
break; |
|
|
} |
|
|
default: |
|
|
{ |
|
|
printf("Unhandled primitive type"); |
|
|
} |
|
|
} |
|
|
|
|
|
return NV_OK; |
|
|
} |
|
|
|
|
|
} |
|
|
|