diff options
Diffstat (limited to 'demo/d3d12/meshRendererD3D12.cpp')
| -rw-r--r-- | demo/d3d12/meshRendererD3D12.cpp | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/demo/d3d12/meshRendererD3D12.cpp b/demo/d3d12/meshRendererD3D12.cpp new file mode 100644 index 0000000..3ea4012 --- /dev/null +++ b/demo/d3d12/meshRendererD3D12.cpp @@ -0,0 +1,419 @@ + +// this +#include "meshRendererD3D12.h" + +namespace FlexSample { + +/* static */ 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 } +}; + +/* static */ 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 }, +}; + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Dx12RenderMesh !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +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"); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Dx12MeshRenderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + + +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; + + // Copy taking into account stride difference + 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); + + // Set up the allocation block + 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; +} + + +/* static */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, 0, 0, 0); + } + else + { + commandList->DrawInstanced((UINT)allocIn.m_numPrimitives, 1, 0, 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; +} + +} // namespace FlexSample
\ No newline at end of file |