aboutsummaryrefslogtreecommitdiff
path: root/demo/d3d12/meshRendererD3D12.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'demo/d3d12/meshRendererD3D12.cpp')
-rw-r--r--demo/d3d12/meshRendererD3D12.cpp419
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