// to fix min max windows macros #define NOMINMAX #include "meshRendererD3D12.h" // Pipelines #include "meshRenderPipelineD3D12.h" #include "pointRenderPipelineD3D12.h" #include "fluidThicknessRenderPipelineD3D12.h" #include "fluidEllipsoidRenderPipelineD3D12.h" #include "fluidSmoothRenderPipelineD3D12.h" #include "fluidCompositeRenderPipelineD3D12.h" #include "diffusePointRenderPipelineD3D12.h" #include "lineRenderPipelineD3D12.h" #include "meshUtil.h" #include // SDL #include #include "shadersDemoContext.h" // Flex #include "core/maths.h" #include "core/extrude.h" #define NOMINMAX #include #include #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); m_renderStateManager = new RenderStateManagerD3D12; } template void inline COMRelease(T& t) { if (t) t->Release(); t = nullptr; } DemoContextD3D12::~DemoContextD3D12() { imguiGraphDestroy(); AppGraphCtxRelease(m_appGraphCtx); delete m_renderStateManager; COMRelease(m_graphicsCompleteFence); COMRelease(m_queryHeap); COMRelease(m_queryResults); COMRelease(m_bufferStage); // Explicitly delete these, so we can call D3D memory leak checker at bottom of this destructor m_meshPipeline.reset(); m_pointPipeline.reset(); m_fluidPointPipeline.reset(); m_fluidSmoothPipeline.reset(); m_fluidCompositePipeline.reset(); m_diffusePointPipeline.reset(); m_linePipeline.reset(); m_fluidThicknessRenderTarget.reset(); m_fluidPointRenderTarget.reset(); m_fluidSmoothRenderTarget.reset(); m_fluidResolvedTarget.reset(); m_screenQuadMesh.reset(); m_shadowMap.reset(); } 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) ? 15 : 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 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(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 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 pipeline(new PointRenderPipelineD3D12); NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, m_shadowMapLinearSamplerIndex, m_shadowMap.get())); m_pointPipeline = std::move(pipeline); } // FluidThickness { std::unique_ptr pipeline(new FluidThicknessRenderPipelineD3D12); NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath, m_fluidThicknessRenderTarget.get())); m_fluidThicknessPipeline = std::move(pipeline); } // FluidPoint { std::unique_ptr 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 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 pipeline(new FluidCompositeRenderPipelineD3D12); NV_RETURN_ON_FAIL(pipeline->initialize(m_renderState, m_shadersPath)); m_fluidCompositePipeline = std::move(pipeline); } // DiffusePoint { std::unique_ptr 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 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(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))); D3D12_RESOURCE_DESC texDesc = {}; texDesc.MipLevels = 1u; texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texDesc.Width = renderContext->m_winW; texDesc.Height = renderContext->m_winH; texDesc.Flags = D3D12_RESOURCE_FLAG_NONE; texDesc.DepthOrArraySize = 1u; texDesc.SampleDesc.Count = 1u; texDesc.SampleDesc.Quality = 0u; texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; // get footprint information m_footprint = {}; UINT64 uploadHeapSize = 0u; device->GetCopyableFootprints(&texDesc, 0u, 1u, 0u, &m_footprint, nullptr, nullptr, &uploadHeapSize); D3D12_RESOURCE_DESC bufferDesc = texDesc; bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; bufferDesc.Alignment = 0u; bufferDesc.Width = uploadHeapSize; bufferDesc.Height = 1u; bufferDesc.DepthOrArraySize = 1u; bufferDesc.MipLevels = 1; bufferDesc.Format = DXGI_FORMAT_UNKNOWN; bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; bufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; NV_RETURN_ON_FAIL(device->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_bufferStage))); } return NV_OK; } int DemoContextD3D12::_initFluidRenderTargets() { AppGraphCtxD3D12* renderContext = getRenderContext(); ID3D12Device* device = renderContext->m_device; // Fluid thickness { { std::unique_ptr 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 Thickness"); m_fluidThicknessRenderTarget = std::move(target); } } // Fluid point render target { { std::unique_ptr 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 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 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); m_fluidThicknessRenderTarget->createSrv(device, heap, NvCo::Dx12RenderTarget::BUFFER_TARGET, m_fluidPointDepthSrvIndex + 1); } { // 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_fluidThicknessRenderTarget.reset(); m_fluidPointRenderTarget.reset(); m_fluidSmoothRenderTarget.reset(); m_fluidResolvedTarget.reset(); AppGraphCtxUpdateSize(m_appGraphCtx, m_window, false, m_msaaSamples); // 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]); } // copy to staging buffer { { nvidia::Common::Dx12BarrierSubmitter submitter(renderContext->m_commandList); backBuffer.transition(D3D12_RESOURCE_STATE_COPY_SOURCE, submitter); } D3D12_TEXTURE_COPY_LOCATION dstCopy = {}; D3D12_TEXTURE_COPY_LOCATION srcCopy = {}; dstCopy.pResource = m_bufferStage; dstCopy.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dstCopy.PlacedFootprint = m_footprint; srcCopy.pResource = backBuffer; srcCopy.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; srcCopy.SubresourceIndex = 0u; renderContext->m_commandList->CopyTextureRegion(&dstCopy, 0, 0, 0, &srcCopy, nullptr); } { 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, 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::readFrame(int* buffer, int width, int height) { AppGraphCtxD3D12* renderContext = getRenderContext(); AppGraphCtxWaitForGPU(renderContext); int *pData; m_bufferStage->Map(0, nullptr, (void**)&pData); // y-coordinate is flipped for DirectX for (int i = 0; i < height; i++) { memcpy(buffer + (width * i), ((int *)pData) + (width * (height - i)), width * sizeof(int)); } m_bufferStage->Unmap(0, nullptr); } 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(buffersIn); if (n == 0) return; typedef PointRenderAllocationD3D12 Alloc; Alloc alloc; alloc.init(PRIMITIVE_POINT); alloc.m_numPrimitives = n; alloc.m_numPositions = 0; // unused param alloc.m_offset = offset; 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_NONE;// 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); // make sprites larger to get smoother thickness texture const float thicknessScale = 4.0f; params.pointRadius = thicknessScale * radius; params.debug = 0; params.shadowMap = nullptr; { m_fluidThicknessRenderTarget->toWritable(renderContext); m_fluidThicknessRenderTarget->bindAndClear(renderContext); m_meshRenderer->drawTransitory(alloc, sizeof(Alloc), m_fluidThicknessPipeline.get(), ¶ms); m_fluidThicknessRenderTarget->toReadable(renderContext); } { 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; params.m_sampleDescriptorBase = m_linearSamplerIndex; 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); } 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); } { NvCo::Dx12BarrierSubmitter submitter(commandList); targetResource->transition(D3D12_RESOURCE_STATE_RENDER_TARGET, submitter); fluidResolvedTarget.transition(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, submitter); } } //--------------------------------------------------------------- // 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(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(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 vertices; std::vector normals; std::vector triangles; // flatten curve std::vector 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 vertices; std::vector normals; std::vector 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(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_vertexBufferViews[PointRenderAllocationD3D12::VERTEX_VIEW_PHASE] = buffers->m_densitiesView; pointAlloc.m_indexBufferView = buffers->m_indicesView; pointAlloc.m_numPrimitives = n; pointAlloc.m_numPositions = 0; // unused param pointAlloc.m_offset = offset; 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, D3D12_QUERY_TYPE_TIMESTAMP, 0); } void DemoContextD3D12::graphicsTimerEnd() { ID3D12GraphicsCommandList* commandList = m_renderContext->m_commandList; commandList->EndQuery(m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, 1); commandList->ResolveQueryData(m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, 0, 2, m_queryResults, 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; D3D12_RANGE readRange = { 0, 2 }; 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(buffersIn); if (n == 0) return; typedef PointRenderAllocationD3D12 Alloc; Alloc alloc; alloc.init(PRIMITIVE_POINT); alloc.m_numPrimitives = n; alloc.m_numPositions = 0; // unused param alloc.m_offset = 0; // unused param 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(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(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(m); } DiffuseRenderBuffers* DemoContextD3D12::createDiffuseRenderBuffers(int numDiffuseParticles, bool& enableInterop) { return reinterpret_cast(new DiffuseRenderBuffersD3D12(numDiffuseParticles)); } void DemoContextD3D12::destroyDiffuseRenderBuffers(DiffuseRenderBuffers* buffers) { delete reinterpret_cast(buffers); } int DemoContextD3D12::getNumDiffuseRenderParticles(DiffuseRenderBuffers* buffers) { return reinterpret_cast(buffers)->m_numParticles; } void DemoContextD3D12::updateDiffuseRenderBuffers(DiffuseRenderBuffers* buffersIn, Vec4* diffusePositions, Vec4* diffuseVelocities, int numDiffuseParticles) { DiffuseRenderBuffersD3D12& buffers = *reinterpret_cast(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(); } } // namespace FlexSample