diff options
Diffstat (limited to 'demo/d3d12/demoContextD3D12.cpp')
| -rw-r--r-- | demo/d3d12/demoContextD3D12.cpp | 1410 |
1 files changed, 1410 insertions, 0 deletions
diff --git a/demo/d3d12/demoContextD3D12.cpp b/demo/d3d12/demoContextD3D12.cpp new file mode 100644 index 0000000..8a698f7 --- /dev/null +++ b/demo/d3d12/demoContextD3D12.cpp @@ -0,0 +1,1410 @@ +// to fix min max windows macros +#define NOMINMAX + +#include "meshRendererD3D12.h" + +// Pipelines + +#include "meshRenderPipelineD3D12.h" +#include "pointRenderPipelineD3D12.h" +#include "fluidEllipsoidRenderPipelineD3D12.h" +#include "fluidSmoothRenderPipelineD3D12.h" +#include "fluidCompositeRenderPipelineD3D12.h" +#include "diffusePointRenderPipelineD3D12.h" +#include "lineRenderPipelineD3D12.h" + +#include "meshUtil.h" + +#include <NvCoDx12RenderTarget.h> + +// SDL +#include <SDL_syswm.h> + +#include "d3d/shadersDemoContext.h" + +// Flex +#include "core/maths.h" +#include "core/extrude.h" + +#define NOMINMAX +#include <d3d12.h> +#include <d3dcompiler.h> + +#include "imguiGraphD3D12.h" + +#include "../d3d/loader.h" + +#include "demoContextD3D12.h" + +// include the Direct3D Library file +#pragma comment (lib, "d3d12.lib") +#pragma comment (lib, "DXGI.lib") + +using namespace DirectX; + +static float gSpotMin = 0.5f; +static float gSpotMax = 1.0f; +static float gShadowBias = 0.075f; +static const int kShadowResolution = 2048; + +// Global externally +extern Colour g_colors[]; + +#define NV_PRINT_F_U64 "%I64u" + +DemoContext* CreateDemoContextD3D12() +{ + return new FlexSample::DemoContextD3D12; +} + +namespace FlexSample { + +DemoContextD3D12::DemoContextD3D12() +{ + m_shadowMapLinearSamplerIndex = -1; + m_fluidPointDepthSrvIndex = -1; + m_currentShadowMap = nullptr; + m_targetShadowMap = nullptr; + + m_inLineDraw = false; + memset(&m_meshDrawParams, 0, sizeof(m_meshDrawParams)); + + m_hwnd = nullptr; + m_window = nullptr; + + // Allocate space for all debug vertices + m_debugLineVertices.resize(MAX_DEBUG_LINE_SIZE); +} + +DemoContextD3D12::~DemoContextD3D12() +{ + imguiGraphDestroy(); +} + +bool DemoContextD3D12::initialize(const RenderInitOptions& options) +{ + // must always have at least one sample + m_msaaSamples = Max(1, options.numMsaaSamples); + + { + // Load external modules + loadModules(APP_CONTEXT_D3D12); + } + + m_appGraphCtx = AppGraphCtxCreate(0); + m_renderContext = cast_to_AppGraphCtxD3D12(m_appGraphCtx); + + AppGraphCtxUpdateSize(m_appGraphCtx, options.window, options.fullscreen, m_msaaSamples); + + using namespace NvCo; + // Get the hwnd + m_hwnd = nullptr; + m_window = options.window; + { + // get Windows handle to this SDL window + SDL_SysWMinfo winInfo; + SDL_VERSION(&winInfo.version); + if (SDL_GetWindowWMInfo(options.window, &winInfo)) + { + if (winInfo.subsystem == SDL_SYSWM_WINDOWS) + { + m_hwnd = winInfo.info.win.window; + } + } + } + + { + WCHAR buffer[_MAX_PATH]; + DWORD size = GetModuleFileNameW(nullptr, buffer, _MAX_PATH); + if (size == 0 || size == _MAX_PATH) + { + // Method failed or path was truncated. + return false; + } + std::wstring path; + path += buffer; + const size_t lastSlash = path.find_last_of(L"\\"); + if (lastSlash >= 0) + { + path.resize(lastSlash + 1); + } + + m_executablePath.swap(path); + } + + { + m_shadersPath = m_executablePath; + m_shadersPath += L"../../demo/d3d/shaders/"; + } + + int width, height; + SDL_GetWindowSize(m_window, &width, &height); + + { + ScopeGpuWork scope(getRenderContext()); + NV_RETURN_FALSE_ON_FAIL(_initRenderResources(options)); + + { + // create imgui, connect to app graph context + ImguiGraphDescD3D12 desc; + desc.device = m_renderContext->m_device; + desc.commandList = m_renderContext->m_commandList; + desc.lastFenceCompleted = 0; + desc.nextFenceValue = 1; + desc.winW = m_renderContext->m_winW; + desc.winW = m_renderContext->m_winH; + desc.numMSAASamples = options.numMsaaSamples; + desc.dynamicHeapCbvSrvUav.userdata = this; + desc.dynamicHeapCbvSrvUav.reserveDescriptors = NULL; + + int defaultFontHeight = (options.defaultFontHeight <= 0) ? 13 : options.defaultFontHeight; + + if (!imguiGraphInit("../../data/DroidSans.ttf", float(defaultFontHeight), (ImguiGraphDesc*)&desc)) + { + return false; + } + } + } + + return true; +} + +int DemoContextD3D12::_initRenderResources(const RenderInitOptions& options) +{ + AppGraphCtxD3D12* renderContext = getRenderContext(); + ID3D12Device* device = renderContext->m_device; + + { + // https://msdn.microsoft.com/en-us/library/windows/desktop/dn859253(v=vs.85).aspx + // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476876(v=vs.85).aspx#Overview + D3D12_FEATURE_DATA_D3D12_OPTIONS options; + device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)); + } + + { + // Make enough space for largest _single_ dynamic buffer allocation + NV_RETURN_ON_FAIL(m_renderStateManager.initialize(renderContext, 16 * 1024 * 1024)); + m_renderState = m_renderStateManager.getState(); + } + + // Create the renderer + { + std::unique_ptr<MeshRendererD3D12> renderer(new MeshRendererD3D12); + NV_RETURN_ON_FAIL(renderer->initialize(m_renderState)); + m_meshRenderer = std::move(renderer); + } + + { + // NOTE! Must be in this order, as compositePS expects s0, s1 = linear, shadow samplers, in that order + m_linearSamplerIndex = m_renderState.m_samplerDescriptorHeap->allocate(); + m_shadowMapLinearSamplerIndex = m_renderState.m_samplerDescriptorHeap->allocate(); + + { + // linear sampler with comparator - used for shadow map sampling + D3D12_SAMPLER_DESC desc = + { + D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + 0.0f, 0, D3D12_COMPARISON_FUNC_LESS_EQUAL, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, + }; + device->CreateSampler(&desc, m_renderState.m_samplerDescriptorHeap->getCpuHandle(m_shadowMapLinearSamplerIndex)); + } + { + // A regular linear sampler + D3D12_SAMPLER_DESC desc = + { + D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + 0.0, 0, D3D12_COMPARISON_FUNC_NEVER, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, + }; + device->CreateSampler(&desc, m_renderState.m_samplerDescriptorHeap->getCpuHandle(m_linearSamplerIndex)); + } + } + + // Allocate the srvs used for fluid render targets + { + m_fluidPointDepthSrvIndex = m_renderState.m_srvCbvUavDescriptorHeap->allocate(); + m_fluidCompositeSrvBaseIndex = m_renderState.m_srvCbvUavDescriptorHeap->allocate(NUM_COMPOSITE_SRVS); + } + + // Create the shadow map + { + m_shadowMap = std::unique_ptr<NvCo::Dx12RenderTarget>(new NvCo::Dx12RenderTarget); + + NvCo::Dx12RenderTarget::Desc desc; + desc.init(kShadowResolution, kShadowResolution); + desc.m_targetFormat = DXGI_FORMAT_UNKNOWN; + desc.m_depthStencilFormat = DXGI_FORMAT_R32_TYPELESS; + + // Make a small shadow map so we can configure pipeline correctly + NV_RETURN_ON_FAIL(m_shadowMap->init(renderContext, desc)); + + m_shadowMap->setDebugName(L"ShadowMap"); + + if (m_shadowMap->allocateSrvView(NvCo::Dx12RenderTarget::BUFFER_DEPTH_STENCIL, device, *m_renderState.m_srvCbvUavDescriptorHeap) < 0) + { + printf("Unable to allocate shadow buffer srv index"); + + return NV_FAIL; + } + } + + // Init fluid resources + NV_RETURN_ON_FAIL(_initFluidRenderTargets()); + + // Create pipelines + { + + // Mesh + { + std::unique_ptr<MeshRenderPipelineD3D12> pipeline(new MeshRenderPipelineD3D12); + NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, FRONT_WINDING_COUNTER_CLOCKWISE, m_shadowMapLinearSamplerIndex, m_shadowMap.get(), options.asyncComputeBenchmark)); + m_meshPipeline = std::move(pipeline); + } + // Point + { + std::unique_ptr<PointRenderPipelineD3D12> pipeline(new PointRenderPipelineD3D12); + NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, m_shadowMapLinearSamplerIndex, m_shadowMap.get())); + m_pointPipeline = std::move(pipeline); + } + // FluidPoint + { + std::unique_ptr<FluidEllipsoidRenderPipelineD3D12> pipeline(new FluidEllipsoidRenderPipelineD3D12); + NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, m_fluidPointRenderTarget.get())); + m_fluidPointPipeline = std::move(pipeline); + } + // FluidSmooth + { + std::unique_ptr<FluidSmoothRenderPipelineD3D12> pipeline(new FluidSmoothRenderPipelineD3D12(m_fluidPointDepthSrvIndex)); + NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, m_fluidSmoothRenderTarget.get())); + m_fluidSmoothPipeline = std::move(pipeline); + } + // FluidComposite + { + std::unique_ptr<FluidCompositeRenderPipelineD3D12> pipeline(new FluidCompositeRenderPipelineD3D12); + NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath)); + m_fluidCompositePipeline = std::move(pipeline); + } + // DiffusePoint + { + std::unique_ptr<DiffusePointRenderPipelineD3D12> pipeline(new DiffusePointRenderPipelineD3D12); + NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, m_linearSamplerIndex, m_shadowMap.get())); + m_diffusePointPipeline = std::move(pipeline); + } + // Line + { + std::unique_ptr<LineRenderPipelineD3D12> pipeline(new LineRenderPipelineD3D12); + NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, m_shadowMap.get())); + m_linePipeline = std::move(pipeline); + } + } + + { + // Create a passthru screen quad + uint32_t indices[] = { 0, 1, 2, 0, 2, 3 }; + Vec3 pos[] = { { -1, -1, 0} , {1, -1, 0}, {1, 1, 0}, {-1, 1, 0} }; + Vec2 uvs[] = { { 0, 0}, {1, 0}, {1, 1}, {0, 1} }; + + MeshData mesh; + mesh.init(); + + mesh.indices = indices; + mesh.positions = pos; + mesh.texcoords = uvs; + mesh.numFaces = _countof(indices) / 3; + mesh.numVertices = _countof(pos); + + m_screenQuadMesh = std::unique_ptr<FlexSample::RenderMesh>(m_meshRenderer->createMesh(mesh)); + } + + // create synchronization objects + { + m_graphicsCompleteEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (!m_graphicsCompleteEvent) + { + return E_FAIL; + } + NV_RETURN_ON_FAIL(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_graphicsCompleteFence))); + m_graphicsCompleteFenceValue = 1; + } + + { + // Query heap and results buffer + + // Create timestamp query heap and results buffer + const int queryCount = 2; + D3D12_QUERY_HEAP_DESC queryHeapDesc = { D3D12_QUERY_HEAP_TYPE_TIMESTAMP, queryCount, 0 /* NodeMask */ }; + NV_RETURN_ON_FAIL(device->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_queryHeap))); + + D3D12_HEAP_PROPERTIES heapProps = + { + D3D12_HEAP_TYPE_READBACK, + D3D12_CPU_PAGE_PROPERTY_UNKNOWN, + D3D12_MEMORY_POOL_UNKNOWN, + 0, + 0 + }; + + D3D12_RESOURCE_DESC queryBufDesc = + { + D3D12_RESOURCE_DIMENSION_BUFFER, + 0u, + queryCount * sizeof(uint64_t), + 1u, + 1u, + 1, + DXGI_FORMAT_UNKNOWN, + { 1u, 0u }, + D3D12_TEXTURE_LAYOUT_ROW_MAJOR, + D3D12_RESOURCE_FLAG_NONE + }; + + NV_RETURN_ON_FAIL(device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &queryBufDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_queryResults))); + } + return NV_OK; +} + +int DemoContextD3D12::_initFluidRenderTargets() +{ + AppGraphCtxD3D12* renderContext = getRenderContext(); + ID3D12Device* device = renderContext->m_device; + + // Fluid point render target + { + { + std::unique_ptr<NvCo::Dx12RenderTarget> target(new NvCo::Dx12RenderTarget); + NvCo::Dx12RenderTarget::Desc desc; + desc.init(renderContext->m_winW, renderContext->m_winH, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS); + for(int i=0;i!=4;i++) desc.m_targetClearColor[i] = 0; + + NV_RETURN_ON_FAIL(target->init(renderContext, desc)); + + target->setDebugName(L"Fluid Point"); + m_fluidPointRenderTarget = std::move(target); + } + + } + + // Fluid smooth + { + std::unique_ptr<NvCo::Dx12RenderTarget> target(new NvCo::Dx12RenderTarget); + NvCo::Dx12RenderTarget::Desc desc; + desc.init(renderContext->m_winW, renderContext->m_winH, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN); + for (int i = 0; i != 4; i++) desc.m_targetClearColor[i] = 0; + + NV_RETURN_ON_FAIL(target->init(renderContext, desc)); + + target->setDebugName(L"Fluid Smooth"); + m_fluidSmoothRenderTarget = std::move(target); + } + + // The resolved target for final compose + { + std::unique_ptr<NvCo::Dx12RenderTarget> target(new NvCo::Dx12RenderTarget); + NvCo::Dx12RenderTarget::Desc desc; + Vec4 clearColor = { 1, 0, 1, 1 }; + desc.m_targetClearColor = clearColor; + desc.init(renderContext->m_winW, renderContext->m_winH, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + NV_RETURN_ON_FAIL(target->init(renderContext, desc)); + + target->setDebugName(L"Fluid Resolved Target"); + m_fluidResolvedTarget = std::move(target); + } + + // Init all of the srvs!!!! + + { + NvCo::Dx12DescriptorHeap& heap = *m_renderState.m_srvCbvUavDescriptorHeap; + // Set up the srv for accessing this buffer + { + m_fluidPointRenderTarget->createSrv(device, heap, NvCo::Dx12RenderTarget::BUFFER_TARGET, m_fluidPointDepthSrvIndex); + } + + { + // 0 - is the depth texture m_fluidSmoothRenderTarget (target) + // 1 - is the 'composite' scene texture m_fluidResolvedTarget (target) + // 2 - shadow texture m_shadowMap (depth stencil) + + m_fluidSmoothRenderTarget->createSrv(device, heap, NvCo::Dx12RenderTarget::BUFFER_TARGET, m_fluidCompositeSrvBaseIndex + 0); + m_fluidResolvedTarget->createSrv(device, heap, NvCo::Dx12RenderTarget::BUFFER_TARGET, m_fluidCompositeSrvBaseIndex + 1); + m_shadowMap->createSrv(device, heap, NvCo::Dx12RenderTarget::BUFFER_DEPTH_STENCIL, m_fluidCompositeSrvBaseIndex + 2); + } + } + + return NV_OK; +} + +void DemoContextD3D12::onSizeChanged(int width, int height, bool minimized) +{ + // Free any set render targets + m_fluidPointRenderTarget.reset(); + m_fluidSmoothRenderTarget.reset(); + m_fluidResolvedTarget.reset(); + + // Will need to create the render targets.. + _initFluidRenderTargets(); +} + +void DemoContextD3D12::startFrame(FlexVec4 colorIn) +{ + AppGraphCtxD3D12* renderContext = getRenderContext(); + + // Work out what what can be recovered, as GPU no longer accessing + m_renderStateManager.updateCompleted(); + + AppGraphColor clearColor = { colorIn.x, colorIn.y, colorIn.z, colorIn.w }; + AppGraphCtxFrameStart(cast_from_AppGraphCtxD3D12(renderContext), clearColor); + + { + MeshDrawParamsD3D& params = m_meshDrawParams; + memset(¶ms, 0, sizeof(MeshDrawParamsD3D)); + params.renderStage = MESH_DRAW_LIGHT; + params.renderMode = MESH_RENDER_SOLID; + params.cullMode = MESH_CULL_BACK; + params.projection = XMMatrixIdentity(); + params.view = XMMatrixIdentity(); + params.model = DirectX::XMMatrixMultiply( + DirectX::XMMatrixScaling(1.0f, 1.0f, 1.0f), + DirectX::XMMatrixTranslation(0.0f, 0.0f, 0.0f) + ); + } +} + +void DemoContextD3D12::endFrame() +{ + { + ImguiGraphDescD3D12 desc; + desc.device = m_renderContext->m_device; + desc.commandList = m_renderContext->m_commandList; + desc.winW = m_renderContext->m_winW; + desc.winH = m_renderContext->m_winH; + + imguiGraphUpdate((ImguiGraphDesc*)&desc); + } + + AppGraphCtxD3D12* renderContext = getRenderContext(); + + nvidia::Common::Dx12Resource& backBuffer = renderContext->m_backBuffers[renderContext->m_renderTargetIndex]; + if (renderContext->m_numMsaaSamples > 1) + { + // MSAA resolve + nvidia::Common::Dx12Resource& renderTarget = *renderContext->m_renderTargets[renderContext->m_renderTargetIndex]; + assert(&renderTarget != &backBuffer); + // Barriers to wait for the render target, and the backbuffer to be in correct state + { + nvidia::Common::Dx12BarrierSubmitter submitter(renderContext->m_commandList); + renderTarget.transition(D3D12_RESOURCE_STATE_RESOLVE_SOURCE, submitter); + backBuffer.transition(D3D12_RESOURCE_STATE_RESOLVE_DEST, submitter); + } + // Do the resolve... + renderContext->m_commandList->ResolveSubresource(backBuffer, 0, renderTarget, 0, renderContext->m_targetInfo.m_renderTargetFormats[0]); + } + + { + nvidia::Common::Dx12BarrierSubmitter submitter(renderContext->m_commandList); + backBuffer.transition(D3D12_RESOURCE_STATE_PRESENT, submitter); + } + + renderContext->m_commandList->Close(); + + // submit command list + ID3D12CommandList* cmdLists[] = { renderContext->m_commandList }; + renderContext->m_commandQueue->ExecuteCommandLists(1, cmdLists); + + renderContext->m_commandListOpenCount = 0; + + // Inform the manager that the work has been submitted + m_renderStateManager.onGpuWorkSubmitted(renderContext->m_commandQueue); + + HANDLE completeEvent = m_graphicsCompleteEvent; + + renderContext->m_commandQueue->Signal(m_graphicsCompleteFence.Get(), m_graphicsCompleteFenceValue); +} + +void DemoContextD3D12::getRenderDevice(void** device, void** context) +{ + *device = m_renderContext->m_device; + *context = m_renderContext->m_commandQueue; +} + +void DemoContextD3D12::startGpuWork() +{ + AppGraphCtxBeginGpuWork(m_renderContext); +} + +void DemoContextD3D12::endGpuWork() +{ + AppGraphCtxEndGpuWork(m_renderContext); +} + +void DemoContextD3D12::presentFrame(bool fullsync) +{ + AppGraphCtxFramePresent(cast_from_AppGraphCtxD3D12(m_renderContext), fullsync); +} + +void DemoContextD3D12::getViewRay(int x, int y, FlexVec3& origin, FlexVec3& dir) +{ + //using namespace DirectX; + AppGraphCtxD3D12* renderContext = getRenderContext(); + + int width = renderContext->m_winW; + int height = renderContext->m_winH; + + XMVECTOR nearVector = XMVector3Unproject(XMVectorSet(float(x), float(height - y), 0.0f, 0.0f), 0.0f, 0.0f, (float)width, (float)height, 0.0f, 1.0f, (XMMATRIX)m_proj, XMMatrixIdentity(), (XMMATRIX)m_view); + XMVECTOR farVector = XMVector3Unproject(XMVectorSet(float(x), float(height - y), 1.0f, 0.0f), 0.0f, 0.0f, (float)width, (float)height, 0.0f, 1.0f, (XMMATRIX)m_proj, XMMatrixIdentity(), (XMMATRIX)m_view); + + origin = FlexVec3(XMVectorGetX(nearVector), XMVectorGetY(nearVector), XMVectorGetZ(nearVector)); + XMVECTOR tmp = farVector - nearVector; + dir = Normalize(FlexVec3(XMVectorGetX(tmp), XMVectorGetY(tmp), XMVectorGetZ(tmp))); +} + +void DemoContextD3D12::setView(Matrix44 view, Matrix44 projection) +{ + Matrix44 vp = projection*view; + MeshDrawParamsD3D& params = m_meshDrawParams; + + params.model = XMMatrixIdentity(); + params.view = (XMMATRIX)view; + params.projection = (XMMATRIX)(RenderParamsUtilD3D::convertGLToD3DProjection(projection)); + + m_view = view; + m_proj = RenderParamsUtilD3D::convertGLToD3DProjection(projection); +} + +void DemoContextD3D12::renderEllipsoids(FluidRenderer* renderer, FluidRenderBuffers* buffersIn, int n, int offset, float radius, float screenWidth, float screenAspect, float fov, FlexVec3 lightPos, FlexVec3 lightTarget, Matrix44 lightTransform, ::ShadowMap* shadowMap, FlexVec4 color, float blur, float ior, bool debug) +{ + FluidRenderBuffersD3D12& buffers = *reinterpret_cast<FluidRenderBuffersD3D12*>(buffersIn); + if (n == 0) + return; + + typedef PointRenderAllocationD3D12 Alloc; + + Alloc alloc; + alloc.init(PRIMITIVE_POINT); + + alloc.m_numPrimitives = buffers.m_numParticles; + alloc.m_numPositions = 0; ///? We don't know here yet... + + alloc.m_indexBufferView = buffers.m_indicesView; + alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_DENSITY] = buffers.m_densitiesView; + alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_POSITION] = buffers.m_positionsView; + alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY1] = buffers.m_anisotropiesViewArr[0]; + alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY2] = buffers.m_anisotropiesViewArr[1]; + alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY3] = buffers.m_anisotropiesViewArr[2]; + + AppGraphCtxD3D12* renderContext = getRenderContext(); + + FluidDrawParamsD3D params; + + params.renderMode = FLUID_RENDER_SOLID; + params.cullMode = FLUID_CULL_BACK; + params.model = XMMatrixIdentity(); + params.view = (XMMATRIX&)m_view; + params.projection = (XMMATRIX&)m_proj; + + params.offset = offset; + params.n = n; + params.renderStage = FLUID_DRAW_LIGHT; + + const float viewHeight = tanf(fov / 2.0f); + params.invViewport = Hlsl::float3(1.0f / screenWidth, screenAspect / screenWidth, 1.0f); + params.invProjection = Hlsl::float3(screenAspect * viewHeight, viewHeight, 1.0f); + params.debug = 0; + + params.shadowMap = nullptr; + + { + m_fluidPointRenderTarget->toWritable(renderContext); + m_fluidPointRenderTarget->bindAndClear(renderContext); + + // Draw the ellipsoids + m_meshRenderer->drawTransitory(alloc, sizeof(Alloc), m_fluidPointPipeline.get(), ¶ms); + + m_fluidPointRenderTarget->toReadable(renderContext); + } + + //--------------------------------------------------------------- + // build smooth depth + + { + m_fluidSmoothRenderTarget->toWritable(renderContext); + m_fluidSmoothRenderTarget->bind(renderContext); + + params.blurRadiusWorld = radius * 0.5f; + params.blurScale = screenWidth / screenAspect * (1.0f / (tanf(fov * 0.5f))); + params.invTexScale = Hlsl::float4(1.0f / screenAspect, 1.0f, 0.0f, 0.0f); + params.blurFalloff = blur; + params.debug = debug; + + m_meshRenderer->draw(m_screenQuadMesh.get(), m_fluidSmoothPipeline.get(), ¶ms); + + m_fluidSmoothRenderTarget->toReadable(renderContext); + } + + // First lets resolve the render target + ID3D12GraphicsCommandList* commandList = m_renderContext->m_commandList; + { + // Lets take what's rendered so far and + NvCo::Dx12ResourceBase* targetResource = m_renderContext->m_renderTargets[m_renderContext->m_renderTargetIndex]; + NvCo::Dx12ResourceBase& fluidResolvedTarget = m_fluidResolvedTarget->getResource(NvCo::Dx12RenderTarget::BUFFER_TARGET); + + if (m_renderContext->m_numMsaaSamples > 1) + { + // If enabled can stop/reduce flickering issues on some GPUs related to a problem around ResolveSubresource/ + //m_renderContext->submitGpuWork(); + + { + NvCo::Dx12BarrierSubmitter submitter(commandList); + targetResource->transition(D3D12_RESOURCE_STATE_RESOLVE_SOURCE, submitter); + fluidResolvedTarget.transition(D3D12_RESOURCE_STATE_RESOLVE_DEST, submitter); + } + // Do the resolve + const DXGI_FORMAT format = fluidResolvedTarget.getResource()->GetDesc().Format; + commandList->ResolveSubresource(fluidResolvedTarget, 0, *targetResource, 0, format); + { + NvCo::Dx12BarrierSubmitter submitter(commandList); + targetResource->transition(D3D12_RESOURCE_STATE_RENDER_TARGET, submitter); + fluidResolvedTarget.transition(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, submitter); + } + } + else + { + { + NvCo::Dx12BarrierSubmitter submitter(commandList); + targetResource->transition(D3D12_RESOURCE_STATE_COPY_SOURCE, submitter); + fluidResolvedTarget.transition(D3D12_RESOURCE_STATE_COPY_DEST, submitter); + } + commandList->CopyResource(fluidResolvedTarget, *targetResource); + } + } + + //--------------------------------------------------------------- + // composite + + { + m_shadowMap->toReadable(renderContext); + + AppGraphCtxPrepareRenderTarget(renderContext); + + FlexVec4 aspectWork(1.0f / screenWidth, screenAspect / screenWidth, 0, 0); + params.invTexScale = (Hlsl::float4&)aspectWork; + FlexVec4 clipPosToEyeWork(tanf(fov*0.5f)*screenAspect, tanf(fov*0.5f), 0, 0); + params.clipPosToEye = (Hlsl::float4&)clipPosToEyeWork; + params.color = (Hlsl::float4&)color; + params.ior = ior; + params.spotMin = gSpotMin; + params.spotMax = gSpotMax; + params.debug = debug; + + params.lightPos = (Hlsl::float3&)lightPos; + FlexVec3 lightDirWork = -Normalize(lightTarget - lightPos); + params.lightDir = (Hlsl::float3&)lightDirWork; + Matrix44 lightTransformWork = RenderParamsUtilD3D::convertGLToD3DProjection(lightTransform); + params.lightTransform = (XMMATRIX&)lightTransformWork; + + params.m_srvDescriptorBase = m_fluidCompositeSrvBaseIndex; + params.m_sampleDescriptorBase = m_linearSamplerIndex; + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + m_meshRenderer->draw(m_screenQuadMesh.get(), m_fluidCompositePipeline.get(), ¶ms); + } +} + +void DemoContextD3D12::updateFluidRenderBuffers(FluidRenderBuffers* buffersIn, FlexVec4* particles, float* densities, FlexVec4* anisotropy1, FlexVec4* anisotropy2, FlexVec4* anisotropy3, int numParticles, int* indices, int numIndices) +{ + FluidRenderBuffersD3D12& buffers = *reinterpret_cast<FluidRenderBuffersD3D12*>(buffersIn); + + typedef PointRenderAllocationD3D12 Alloc; + Alloc alloc; + + PointData pointData; + + pointData.positions = (const Vec4*)particles; + pointData.density = densities; + pointData.phase = nullptr; + pointData.indices = (uint32_t*)indices; + pointData.numIndices = numIndices; + pointData.numPoints = numParticles; + pointData.anisotropy[0] = (const Vec4*)anisotropy1; + pointData.anisotropy[1] = (const Vec4*)anisotropy2; + pointData.anisotropy[2] = (const Vec4*)anisotropy3; + + m_meshRenderer->allocateTransitory(pointData, alloc, sizeof(alloc)); + + buffers.m_positionsView = alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_POSITION]; + buffers.m_densitiesView = alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_DENSITY]; + + buffers.m_anisotropiesViewArr[0] = alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY1]; + buffers.m_anisotropiesViewArr[1] = alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY2]; + buffers.m_anisotropiesViewArr[2] = alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY3]; + + buffers.m_indicesView = alloc.m_indexBufferView; + + buffers.m_numParticles = numIndices; +} + +void DemoContextD3D12::shadowBegin(::ShadowMap* map) +{ + assert(map); + assert(m_targetShadowMap == nullptr); + + AppGraphCtxD3D12* renderContext = getRenderContext(); + NvCo::Dx12RenderTarget* shadowMap = reinterpret_cast<NvCo::Dx12RenderTarget*>(map); + + shadowMap->toWritable(renderContext); + shadowMap->bindAndClear(renderContext); + + m_targetShadowMap = shadowMap; + + m_meshDrawParams.renderStage = MESH_DRAW_SHADOW; +} + +void DemoContextD3D12::shadowEnd() +{ + AppGraphCtxD3D12* renderContext = getRenderContext(); + NvCo::Dx12RenderTarget* shadowMap = m_targetShadowMap; + shadowMap->toReadable(renderContext); + m_targetShadowMap = nullptr; + + // Restore to regular render target + AppGraphCtxPrepareRenderTarget(renderContext); + + m_meshDrawParams.renderStage = MESH_DRAW_NULL; +} + +void DemoContextD3D12::drawMesh(const Mesh* m, FlexVec3 color) +{ + MeshDrawParamsD3D& params = m_meshDrawParams; + + if (m) + { + MeshData meshData; + + meshData.positions = (Vec3*)&m->m_positions[0]; + meshData.normals = (Vec3*)&m->m_normals[0]; + meshData.colors = nullptr; + meshData.texcoords = nullptr; + meshData.indices = (uint32_t*)&m->m_indices[0]; + meshData.numFaces = m->GetNumFaces(); + meshData.numVertices = m->GetNumVertices(); + + params.colorArray = 0; + if (m->m_colours.size()) + { + params.colorArray = 1; + meshData.colors = (Vec4*)&m->m_colours[0]; + } + + params.color = Hlsl::float4(color.x, color.y, color.z, 1); + params.secondaryColor = params.color; + params.objectTransform = (Hlsl::float4x4&)Matrix44::kIdentity; + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + m_meshRenderer->drawImmediate(meshData, m_meshPipeline.get(), ¶ms); + + if (m->m_colours.size()) + { + params.colorArray = 0; + } + } +} + +void DemoContextD3D12::drawCloth(const FlexVec4* positions, const FlexVec4* normals, const float* uvs, const int* indices, int numTris, int numPositions, int colorIndex, float expand, bool twosided, bool smooth) +{ + if (!numTris) + return; + + MeshData2 meshData; + + meshData.positions = (const Vec4*)positions; + meshData.normals = (const Vec4*)normals; + meshData.texcoords = nullptr; /* (const Vec2*)uvs; */ + meshData.colors = nullptr; + meshData.numFaces = numTris; + meshData.indices = (const uint32_t*)indices; + meshData.numVertices = numPositions; + + if (twosided) + SetCullMode(false); + + MeshDrawParamsD3D& params = m_meshDrawParams; + + params.bias = 0.0f; + params.expand = expand; + + params.color = (Hlsl::float4&)(g_colors[colorIndex + 1] * 1.5f); + params.secondaryColor = (Hlsl::float4&)(g_colors[colorIndex] * 1.5f); + params.objectTransform = (Hlsl::float4x4&)Matrix44::kIdentity; + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + m_meshRenderer->drawImmediate(meshData, m_meshPipeline.get(), ¶ms); + + if (twosided) + SetCullMode(true); + + params.bias = gShadowBias; + params.expand = 0.0f; +} + +void DemoContextD3D12::drawRope(FlexVec4* positions, int* indices, int numIndices, float radius, int color) +{ + if (numIndices < 2) + return; + + std::vector<FlexVec3> vertices; + std::vector<FlexVec3> normals; + std::vector<int> triangles; + + // flatten curve + std::vector<FlexVec3> curve(numIndices); + for (int i = 0; i < numIndices; ++i) + { + curve[i] = FlexVec3(positions[indices[i]]); + } + + const int resolution = 8; + const int smoothing = 3; + + vertices.reserve(resolution*numIndices*smoothing); + normals.reserve(resolution*numIndices*smoothing); + triangles.reserve(numIndices*resolution * 6 * smoothing); + + Extrude(&curve[0], int(curve.size()), vertices, normals, triangles, radius, resolution, smoothing); + + SetCullMode(false); + + MeshDrawParamsD3D& params = m_meshDrawParams; + + params.color = (Hlsl::float4&)(g_colors[color % 8] * 1.5f); + params.secondaryColor = (Hlsl::float4&)(g_colors[color % 8] * 1.5f); + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + MeshData meshData; + + meshData.positions = (const Vec3*)&vertices[0]; + meshData.normals = (const Vec3*)&normals[0]; + meshData.texcoords = nullptr; + meshData.colors = nullptr; + meshData.indices = (const uint32_t*)&triangles[0]; + meshData.numFaces = int(triangles.size()) / 3; + meshData.numVertices = int(vertices.size()); + + m_meshRenderer->drawImmediate(meshData, m_meshPipeline.get(), ¶ms); + + SetCullMode(true); +} + +void DemoContextD3D12::drawPlane(const FlexVec4& p, bool color) +{ + std::vector<FlexVec3> vertices; + std::vector<FlexVec3> normals; + std::vector<int> indices; + + FlexVec3 u, v; + BasisFromVector(FlexVec3(p.x, p.y, p.z), &u, &v); + + FlexVec3 c = FlexVec3(p.x, p.y, p.z)*-p.w; + + MeshDrawParamsD3D& params = m_meshDrawParams; + + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + if (color) + params.color = (Hlsl::float4&)(p * 0.5f + FlexVec4(0.5f, 0.5f, 0.5f, 0.5f)); + + const float kSize = 200.0f; + const int kGrid = 3; + + // draw a grid of quads, otherwise z precision suffers + for (int x = -kGrid; x <= kGrid; ++x) + { + for (int y = -kGrid; y <= kGrid; ++y) + { + FlexVec3 coff = c + u*float(x)*kSize*2.0f + v*float(y)*kSize*2.0f; + + int indexStart = int(vertices.size()); + + vertices.push_back(FlexVec3(coff + u*kSize + v*kSize)); + vertices.push_back(FlexVec3(coff - u*kSize + v*kSize)); + vertices.push_back(FlexVec3(coff - u*kSize - v*kSize)); + vertices.push_back(FlexVec3(coff + u*kSize - v*kSize)); + + normals.push_back(FlexVec3(p.x, p.y, p.z)); + normals.push_back(FlexVec3(p.x, p.y, p.z)); + normals.push_back(FlexVec3(p.x, p.y, p.z)); + normals.push_back(FlexVec3(p.x, p.y, p.z)); + + + indices.push_back(indexStart + 0); + indices.push_back(indexStart + 1); + indices.push_back(indexStart + 2); + + indices.push_back(indexStart + 2); + indices.push_back(indexStart + 3); + indices.push_back(indexStart + 0); + } + } + + MeshData meshData; + meshData.texcoords = nullptr; + meshData.colors = nullptr; + meshData.positions = (Vec3*)&vertices[0]; + meshData.normals = (Vec3*)&normals[0]; + meshData.indices = (uint32_t*)&indices[0]; + meshData.numFaces = int(indices.size() / 3); + meshData.numVertices = int(vertices.size()); + + m_meshRenderer->drawImmediate(meshData, m_meshPipeline.get(), ¶ms); +} + +void DemoContextD3D12::drawPlanes(FlexVec4* planes, int n, float bias) +{ + MeshDrawParamsD3D& params = m_meshDrawParams; + + params.color = (Hlsl::float4&)FlexVec4(0.9f, 0.9f, 0.9f, 1.0f); + + params.bias = 0.0f; + params.grid = 1; + params.expand = 0; + + for (int i = 0; i < n; ++i) + { + FlexVec4 p = planes[i]; + p.w -= bias; + + drawPlane(p, false); + } + + params.grid = 0; + params.bias = gShadowBias; +} + +void DemoContextD3D12::drawPoints(FluidRenderBuffers* buffersIn, int n, int offset, float radius, float screenWidth, float screenAspect, float fov, FlexVec3 lightPos, FlexVec3 lightTarget, Matrix44 lightTransform, ::ShadowMap* shadowTex, bool showDensity) +{ + FluidRenderBuffersD3D12* buffers = reinterpret_cast<FluidRenderBuffersD3D12*>(buffersIn); + // Okay we can draw the particles here. The update can copy the point positions into the heap, so here we just draw them + + if (n == 0) + return; + + PointRenderAllocationD3D12 pointAlloc; + pointAlloc.init(PRIMITIVE_POINT); + pointAlloc.m_vertexBufferViews[PointRenderAllocationD3D12::VERTEX_VIEW_POSITION] = buffers->m_positionsView; + // It says 'color' as the parameter but actually its the 'density' parameter that is passed in here + pointAlloc.m_vertexBufferViews[PointRenderAllocationD3D12::VERTEX_VIEW_DENSITY] = buffers->m_densitiesView; + pointAlloc.m_indexBufferView = buffers->m_indicesView; + // TODO: JS - I don't know the amount of positions/colors... but the render call doesn't need to know. So just set to 0 for now + pointAlloc.m_numPositions = 0; + pointAlloc.m_numPrimitives = n; + + PointDrawParamsD3D params; + + params.renderMode = POINT_RENDER_SOLID; + params.cullMode = POINT_CULL_BACK; + params.model = XMMatrixIdentity(); + params.view = (XMMATRIX&)m_view; + params.projection = (XMMATRIX&)m_proj; + + params.pointRadius = radius; + params.pointScale = screenWidth / screenAspect * (1.0f / (tanf(fov * 0.5f))); + params.spotMin = gSpotMin; + params.spotMax = gSpotMax; + + int mode = 0; + if (showDensity) + mode = 1; + if (shadowTex == 0) + mode = 2; + params.mode = mode; + + for (int i = 0; i < 8; i++) + params.colors[i] = *((Hlsl::float4*)&g_colors[i].r); + + // set shadow parameters + ShadowParamsD3D shadow; + RenderParamsUtilD3D::calcShadowParams(lightPos, lightTarget, lightTransform, gShadowBias, &shadow); + params.lightTransform = shadow.lightTransform; + params.lightDir = shadow.lightDir; + params.lightPos = shadow.lightPos; + memcpy(params.shadowTaps, shadow.shadowTaps, sizeof(shadow.shadowTaps)); + + if (m_meshDrawParams.renderStage == MESH_DRAW_SHADOW) + { + params.renderStage = POINT_DRAW_SHADOW; + params.mode = 2; + } + else + params.renderStage = POINT_DRAW_LIGHT; + + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + m_meshRenderer->drawTransitory(pointAlloc, sizeof(pointAlloc), m_pointPipeline.get(), ¶ms); +} + +void DemoContextD3D12::graphicsTimerBegin() +{ + ID3D12GraphicsCommandList* commandList = m_renderContext->m_commandList; + + commandList->EndQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, 0); +} + +void DemoContextD3D12::graphicsTimerEnd() +{ + ID3D12GraphicsCommandList* commandList = m_renderContext->m_commandList; + + commandList->EndQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, 1); + commandList->ResolveQueryData(m_queryHeap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, 0, 2, m_queryResults.Get(), 0); +} + +float DemoContextD3D12::rendererGetDeviceTimestamps(unsigned long long* begin, unsigned long long* end, unsigned long long* freq) +{ + AppGraphCtxD3D12* renderContext = getRenderContext(); + ID3D12CommandQueue* commandQueue = m_renderContext->m_commandQueue; + + AppGraphCtxWaitForGPU(renderContext); + + // Get timer frequency + static uint64_t frequency = 0; + + if (frequency == 0) + { + commandQueue->GetTimestampFrequency(&frequency); + } + + //Get render timestamps + uint64_t* times; + //m_queryResults->Map(0, nullptr, (void**)×); + D3D12_RANGE readRange = { 0, 1 }; + m_queryResults->Map(0, &readRange, (void**)×); + uint64_t renderBegin = times[0]; + uint64_t renderEnd = times[1]; + D3D12_RANGE writtenRange = { 0, 0 }; // nothing was written + m_queryResults->Unmap(0, &writtenRange); + + double renderTime = double(renderEnd - renderBegin) / double(frequency); + + if (begin) *begin = renderBegin; + if (end) *end = renderEnd; + if (freq) *freq = frequency; + + return float(renderTime); +} + +void DemoContextD3D12::bindSolidShader(FlexVec3 lightPos, FlexVec3 lightTarget, Matrix44 lightTransform, ::ShadowMap* shadowMap, float bias, FlexVec4 fogColor) +{ + MeshDrawParamsD3D& params = m_meshDrawParams; + + params.renderStage = MESH_DRAW_LIGHT; + + params.grid = 0; + params.spotMin = gSpotMin; + params.spotMax = gSpotMax; + params.fogColor = (Hlsl::float4&)fogColor; + + params.objectTransform = (Hlsl::float4x4&)Matrix44::kIdentity; + + ShadowParamsD3D shadow; + RenderParamsUtilD3D::calcShadowParams(lightPos, lightTarget, lightTransform, gShadowBias, &shadow); + params.lightTransform = shadow.lightTransform; + params.lightDir = shadow.lightDir; + params.lightPos = shadow.lightPos; + params.bias = shadow.bias; + memcpy(params.shadowTaps, shadow.shadowTaps, sizeof(shadow.shadowTaps)); + + m_currentShadowMap = (NvCo::Dx12RenderTarget*)shadowMap; +} + +void DemoContextD3D12::drawGpuMesh(GpuMesh* m, const Matrix44& xform, const FlexVec3& color) +{ + if (m) + { + MeshDrawParamsD3D params(m_meshDrawParams); + + params.color = (Hlsl::float4&)color; + params.secondaryColor = (Hlsl::float4&)color; + params.objectTransform = (Hlsl::float4x4&)xform; + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + RenderMesh* renderMesh = (RenderMesh*)m; + + m_meshRenderer->draw(renderMesh, m_meshPipeline.get(), ¶ms); + } +} + +void DemoContextD3D12::drawGpuMeshInstances(GpuMesh* m, const Matrix44* xforms, int n, const FlexVec3& color) +{ + if (m) + { + MeshDrawParamsD3D& contextParams = m_meshDrawParams; + + contextParams.color = (Hlsl::float4&)color; + contextParams.secondaryColor = (Hlsl::float4&)color; + contextParams.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + // copy params + MeshDrawParamsD3D params(contextParams); + + for (int i = 0; i < n; ++i) + { + params.objectTransform = (Hlsl::float4x4&)xforms[i]; + RenderMesh* renderMesh = (RenderMesh*)m; + m_meshRenderer->draw(renderMesh, m_meshPipeline.get(), ¶ms); + } + } +} + +void DemoContextD3D12::drawDiffuse(FluidRenderer* render, const DiffuseRenderBuffers* buffersIn, int n, float radius, float screenWidth, float screenAspect, float fov, FlexVec4 color, FlexVec3 lightPos, FlexVec3 lightTarget, Matrix44 lightTransform, ShadowMap* shadowMap, float motionBlur, float inscatter, float outscatter, bool shadowEnabled, bool front) +{ + const DiffuseRenderBuffersD3D12& buffers = *reinterpret_cast<const DiffuseRenderBuffersD3D12*>(buffersIn); + if (n == 0) + return; + + typedef PointRenderAllocationD3D12 Alloc; + Alloc alloc; + alloc.init(PRIMITIVE_POINT); + + alloc.m_numPrimitives = buffers.m_numParticles; + alloc.m_numPositions = 0; // ! We don't know + alloc.m_indexBufferView = buffers.m_indicesView; + alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_POSITION] = buffers.m_positionsView; + alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY1] = buffers.m_velocitiesView; // Velocity stored in ANISO1 + + DiffuseDrawParamsD3D params; + + params.model = XMMatrixIdentity(); + params.view = (const XMMATRIX&)m_view; + params.projection = (const XMMATRIX&)m_proj; + params.diffuseRadius = screenWidth / screenAspect * (1.0f / (tanf(fov * 0.5f))); + params.diffuseScale = radius; + params.spotMin = gSpotMin; + params.spotMax = gSpotMax; + params.color = Hlsl::float4(1.0f, 1.0f, 1.0f, 1.0f); + params.motionScale = motionBlur; + + // set shadow parameters + ShadowParamsD3D shadow; + RenderParamsUtilD3D::calcShadowParams(lightPos, lightTarget, lightTransform, gShadowBias, &shadow); + params.lightTransform = shadow.lightTransform; + params.lightDir = shadow.lightDir; + params.lightPos = shadow.lightPos; + params.shadowMap = (ShadowMapD3D*)m_currentShadowMap; + + memcpy(params.shadowTaps, shadow.shadowTaps, sizeof(shadow.shadowTaps)); + + m_meshRenderer->drawTransitory(alloc, sizeof(alloc), m_diffusePointPipeline.get(), ¶ms); +} + +void DemoContextD3D12::beginLines() +{ + assert(!m_inLineDraw); + m_inLineDraw = true; + m_debugLineVertices.clear(); +} + +void DemoContextD3D12::drawLine(const Vec3& p, const Vec3& q, const Vec4& color) +{ + assert(m_inLineDraw); + + if (m_debugLineVertices.size() + 2 > MAX_DEBUG_LINE_SIZE) + { + _flushDebugLines(); + } + + LineData::Vertex dst[2]; + dst[0].position = (const Vec3&)p; + dst[0].color = (const Vec4&)color; + dst[1].position = (const Vec3&)q; + dst[1].color = (const Vec4&)color; + + m_debugLineVertices.push_back(dst[0]); + m_debugLineVertices.push_back(dst[1]); +} + +void DemoContextD3D12::_flushDebugLines() +{ + assert(m_inLineDraw); + + if (m_debugLineVertices.size() > 0) + { + LineDrawParams params; + + const Matrix44 modelWorldProjection = ((Matrix44&)(m_meshDrawParams.projection)) * ((Matrix44&)(m_meshDrawParams.view)); + // draw + params.m_modelWorldProjection = (const Hlsl::float4x4&)modelWorldProjection; + params.m_drawStage = (m_targetShadowMap) ? LINE_DRAW_SHADOW : LINE_DRAW_NORMAL; + + LineData lineData; + lineData.init(); + lineData.vertices = &m_debugLineVertices.front(); + lineData.numVertices = m_debugLineVertices.size(); + lineData.numLines = lineData.numVertices / 2; + + m_meshRenderer->drawImmediate(lineData, m_linePipeline.get(), ¶ms); + + m_debugLineVertices.clear(); + } +} + +void DemoContextD3D12::endLines() +{ + _flushDebugLines(); + // No longer in line drawing + m_inLineDraw = false; +} + +void DemoContextD3D12::flushGraphicsAndWait() +{ + AppGraphCtxWaitForGPU(getRenderContext()); +} + +FluidRenderer* DemoContextD3D12::createFluidRenderer(uint32_t width, uint32_t height) +{ + // It's always created.. so just return the context + return (FluidRenderer*)this; +} + +void DemoContextD3D12::destroyFluidRenderer(FluidRenderer* renderer) +{ + /// Don't need to do anything, as will be destroyed with context +} + +FluidRenderBuffers* DemoContextD3D12::createFluidRenderBuffers(int numParticles, bool enableInterop) +{ + return reinterpret_cast<FluidRenderBuffers*>(new FluidRenderBuffersD3D12(numParticles)); +} + +void DemoContextD3D12::updateFluidRenderBuffers(FluidRenderBuffers* buffers, NvFlexSolver* flex, bool anisotropy, bool density) +{ + printf("Not implemented"); + assert(0); +} + +void DemoContextD3D12::destroyFluidRenderBuffers(FluidRenderBuffers* buffers) +{ + delete reinterpret_cast<FluidRenderBuffersD3D12*>(buffers); +} + +ShadowMap* DemoContextD3D12::shadowCreate() +{ + // Currently only allows single shadow map, which is pre created + return (::ShadowMap*)m_shadowMap.get(); +} + +void DemoContextD3D12::shadowDestroy(ShadowMap* map) +{ + assert(map); + assert(m_shadowMap.get() == (NvCo::Dx12RenderTarget*)map); +} + +void DemoContextD3D12::unbindSolidShader() +{ + m_meshDrawParams.renderStage = MESH_DRAW_NULL; + + // !!! Other code appears to assume that this will be set + //context->m_currentShadowMap = nullptr; +} + +GpuMesh* DemoContextD3D12::createGpuMesh(const Mesh* m) +{ + if (m) + { + return (GpuMesh*)MeshUtil::createRenderMesh(m_meshRenderer.get(), *m); + } + return nullptr; +} + +void DemoContextD3D12::destroyGpuMesh(GpuMesh* m) +{ + delete reinterpret_cast<RenderMesh*>(m); +} + + +DiffuseRenderBuffers* DemoContextD3D12::createDiffuseRenderBuffers(int numDiffuseParticles, bool& enableInterop) +{ + return reinterpret_cast<DiffuseRenderBuffers*>(new DiffuseRenderBuffersD3D12(numDiffuseParticles)); +} + +void DemoContextD3D12::destroyDiffuseRenderBuffers(DiffuseRenderBuffers* buffers) +{ + delete reinterpret_cast<DiffuseRenderBuffersD3D12*>(buffers); +} + +int DemoContextD3D12::getNumDiffuseRenderParticles(DiffuseRenderBuffers* buffers) +{ + return reinterpret_cast<DiffuseRenderBuffersD3D12*>(buffers)->m_numParticles; +} + +void DemoContextD3D12::updateDiffuseRenderBuffers(DiffuseRenderBuffers* buffersIn, Vec4* diffusePositions, Vec4* diffuseVelocities, int numDiffuseParticles) +{ + DiffuseRenderBuffersD3D12& buffers = *reinterpret_cast<DiffuseRenderBuffersD3D12*>(buffersIn); + + typedef PointRenderAllocationD3D12 Alloc; + + Alloc alloc; + + PointData pointData; + pointData.init(); + pointData.numIndices = numDiffuseParticles; + pointData.positions = (Vec4*)diffusePositions; + pointData.anisotropy[0] = (Vec4*)diffuseVelocities; // We'll store the velocities in the anisotropy buffer, cos it's the right size + pointData.numPoints = buffers.m_numParticles; + + m_meshRenderer->allocateTransitory(pointData, alloc, sizeof(alloc)); + + buffers.m_indicesView = alloc.m_indexBufferView; + buffers.m_positionsView = alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_POSITION]; + buffers.m_velocitiesView = alloc.m_vertexBufferViews[Alloc::VERTEX_VIEW_ANISOTROPY1]; // The velocity + + buffers.m_numParticles = numDiffuseParticles; +} + +void DemoContextD3D12::updateDiffuseRenderBuffers(DiffuseRenderBuffers* buffers, NvFlexSolver* solver) +{ + printf("Not implemented"); + assert(0); +} + +void* DemoContextD3D12::getGraphicsCommandQueue() +{ + return m_renderContext->m_commandQueue; +} + +void DemoContextD3D12::setFillMode(bool wire) +{ + m_meshDrawParams.renderMode = wire ? MESH_RENDER_WIREFRAME : MESH_RENDER_SOLID; +} + +void DemoContextD3D12::setCullMode(bool enabled) +{ + m_meshDrawParams.cullMode = enabled ? MESH_CULL_BACK : MESH_CULL_NONE; +} + +void DemoContextD3D12::drawImguiGraph() +{ + imguiGraphDraw(); + /* + const imguiGfxCmd* cmds = imguiGetRenderQueue(); + int numCmds = imguiGetRenderQueueSize(); + m_imguiGraphContext->draw(cmds, numCmds); */ +} + + +} // namespace FlexSample + + + |