diff options
Diffstat (limited to 'demo/d3d11/demoContextD3D11.cpp')
| -rw-r--r-- | demo/d3d11/demoContextD3D11.cpp | 1147 |
1 files changed, 1147 insertions, 0 deletions
diff --git a/demo/d3d11/demoContextD3D11.cpp b/demo/d3d11/demoContextD3D11.cpp new file mode 100644 index 0000000..0eaf0f4 --- /dev/null +++ b/demo/d3d11/demoContextD3D11.cpp @@ -0,0 +1,1147 @@ +#include "core/maths.h" +#include "core/extrude.h" + +#include "shaders.h" + +#include "meshRenderD3D11.h" +#include "pointRenderD3D11.h" +#include "fluidRenderD3D11.h" +#include "diffuseRenderD3D11.h" +#include "debugLineRenderD3D11.h" + +#include "shadowMapD3D11.h" +#include "renderTargetD3D11.h" + +#include "imguiGraphD3D11.h" + +#include "appD3D11Ctx.h" + +#include "../d3d/demoContext.h" +#include "../d3d/loader.h" + +#include <d3d11.h> +#include <d3dcompiler.h> + +#include <cstdlib> + +// this +#include "demoContextD3D11.h" + +namespace +{ +// COM object release utilities +template <class T> +void inline COMRelease(T& t) +{ + if (t) t->Release(); + t = nullptr; +} + +template <class T> +void inline COMRelease(T& t, UINT arraySize) +{ + for (UINT i = 0; i < arraySize; i++) + { + if (t[i]) t[i]->Release(); + t[i] = nullptr; + } +} +} + +extern Colour g_colors[]; +static const int kShadowResolution = 2048; + +DemoContext* CreateDemoContextD3D11() +{ + return new DemoContextD3D11; +} + +DemoContextD3D11::DemoContextD3D11() +{ + m_appGraphCtx = nullptr; + m_appGraphCtxD3D11 = nullptr; + memset(&m_meshDrawParams, 0, sizeof(m_meshDrawParams)); + + m_spotMin = 0.5f; + m_spotMax = 1.0f; + m_shadowBias = 0.075f; + + m_shadowMap = nullptr; + m_immediateMesh = nullptr; + + m_window = nullptr; + + m_msaaSamples = 1; + + m_renderTimerDisjoint = nullptr; + m_renderTimerBegin = nullptr; + m_renderTimerEnd = nullptr; + m_renderCompletionFence = nullptr; + + m_compositeBlendState = nullptr; + + m_fluidResolvedTarget = nullptr; + m_fluidResolvedTargetSRV = nullptr; + + m_debugLineRender = new DebugLineRenderD3D11; + m_meshRenderer = new MeshRendererD3D11; + m_pointRenderer = new PointRendererD3D11; + m_diffuseRenderer = new DiffuseRendererD3D11; +} + +// convert an OpenGL style projection matrix to D3D (clip z range [0, 1]) +Matrix44 ConvertToD3DProjection(const Matrix44& proj) +{ + Matrix44 scale = Matrix44::kIdentity; + scale.columns[2][2] = 0.5f; + + Matrix44 bias = Matrix44::kIdentity; + bias.columns[3][2] = 1.0f; + + return scale*bias*proj; +} + +#define checkDxErrors(err) __checkDxErrors (err, __FILE__, __LINE__) + +inline void __checkDxErrors(HRESULT err, const char *file, const int line) +{ + if (FAILED(err)) + { + char* lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + 0, NULL); + + fprintf(stdout, "DX Error = %04d \"%s\" from file <%s>, line %i.\n", + err, lpMsgBuf, file, line); + + exit(EXIT_FAILURE); + } +} + +DemoContextD3D11::~DemoContextD3D11() +{ + imguiGraphDestroy(); + + COMRelease(m_renderTimerBegin); + COMRelease(m_renderTimerEnd); + COMRelease(m_renderTimerDisjoint); + COMRelease(m_renderCompletionFence); + + COMRelease(m_compositeBlendState); + + COMRelease(m_fluidResolvedTarget); + COMRelease(m_fluidResolvedTargetSRV); + + delete m_immediateMesh; + delete m_debugLineRender; + delete m_meshRenderer; + delete m_pointRenderer; + delete m_diffuseRenderer; + + // do this first, since it flushes all GPU work + AppGraphCtxReleaseRenderTarget(m_appGraphCtx); + AppGraphCtxRelease(m_appGraphCtx); +} + +bool DemoContextD3D11::initialize(const RenderInitOptions& options) +{ + { + // Load external modules + loadModules(APP_CONTEXT_D3D11); + } + + // must always have at least one sample + m_msaaSamples = Max(1, options.numMsaaSamples); + // create app graph context + m_appGraphCtx = AppGraphCtxCreate(0); + m_appGraphCtxD3D11 = cast_to_AppGraphCtxD3D11(m_appGraphCtx); + + AppGraphCtxUpdateSize(m_appGraphCtx, options.window, options.fullscreen, m_msaaSamples); + _onWindowSizeChanged(m_appGraphCtxD3D11->m_winW, m_appGraphCtxD3D11->m_winH, false); + + //AppGraphCtxInitRenderTarget(m_appGraphCtx, options.window, options.fullscreen, m_msaaSamples); + //gScene = getScene(0); + + AppGraphColor clearVal = { 0.0f, 0.0f, 0.0f, 1.0f }; + AppGraphCtxFrameStart(m_appGraphCtx, clearVal); + + ID3D11Device* device = m_appGraphCtxD3D11->m_device; + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + + { + // create imgui, connect to app graph context + ImguiGraphDescD3D11 desc; + desc.device = device; + desc.deviceContext = deviceContext; + desc.winW = m_appGraphCtxD3D11->m_winW; + desc.winH = m_appGraphCtxD3D11->m_winH; + + // Use Dx11 context + const int defaultFontHeight = (options.defaultFontHeight <= 0) ? 15 : options.defaultFontHeight; + + if (!imguiGraphInit("../../data/DroidSans.ttf", float(defaultFontHeight), (ImguiGraphDesc*)&desc)) + { + return false; + } + } + + AppGraphCtxFramePresent(m_appGraphCtx, true); + + m_pointRenderer->init(device, deviceContext); + m_meshRenderer->init(device, deviceContext, options.asyncComputeBenchmark); + m_debugLineRender->init(device, deviceContext); + m_diffuseRenderer->init(device, deviceContext); + + { + // create blend state - used for composite phase of water rendering + D3D11_BLEND_DESC blendStateDesc = {}; + blendStateDesc.RenderTarget[0].BlendEnable = TRUE; + blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + blendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blendStateDesc.RenderTarget[0].RenderTargetWriteMask = 0x0f; + + if (FAILED(device->CreateBlendState(&blendStateDesc, &m_compositeBlendState))) + { + return false; + } + } + + // create a mesh for immediate mode rendering + m_immediateMesh = new GpuMeshD3D11(device, deviceContext); + + m_window = options.window; + + D3D11_QUERY_DESC tdesc; + ZeroMemory(&tdesc, sizeof(tdesc)); + tdesc.Query = D3D11_QUERY_TIMESTAMP; + device->CreateQuery(&tdesc, &m_renderTimerBegin); + device->CreateQuery(&tdesc, &m_renderTimerEnd); + + tdesc.Query = D3D11_QUERY_EVENT; + device->CreateQuery(&tdesc, &m_renderCompletionFence); + + ZeroMemory(&tdesc, sizeof(tdesc)); + tdesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; + device->CreateQuery(&tdesc, &m_renderTimerDisjoint); + + return true; +} + +void DemoContextD3D11::getRenderDevice(void** deviceOut, void** contextOut) +{ + *deviceOut = m_appGraphCtxD3D11->m_device; + *contextOut = m_appGraphCtxD3D11->m_deviceContext; +} + +void DemoContextD3D11::onSizeChanged(int width, int height, bool minimized) +{ + AppGraphCtxUpdateSize(m_appGraphCtx, m_window, false, m_msaaSamples); + _onWindowSizeChanged(m_appGraphCtxD3D11->m_winW, m_appGraphCtxD3D11->m_winH, false); +} + +void DemoContextD3D11::_onWindowSizeChanged(int width, int height, bool minimized) +{ + if (m_fluidResolvedTarget) + { + D3D11_TEXTURE2D_DESC desc; + m_fluidResolvedTarget->GetDesc(&desc); + if (desc.Width == width && desc.Height == height) + { + return; + } + + COMRelease(m_fluidResolvedTarget); + COMRelease(m_fluidResolvedTargetSRV); + } + + // Recreate... + + ID3D11Device* device = m_appGraphCtxD3D11->m_device; + + // resolved texture target (for refraction / scene sampling) + { + D3D11_TEXTURE2D_DESC texDesc = {}; + texDesc.Width = width; + texDesc.Height = height; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0u; + texDesc.Usage = D3D11_USAGE_DEFAULT; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texDesc.CPUAccessFlags = 0; + texDesc.MiscFlags = 0; + + if (FAILED(device->CreateTexture2D(&texDesc, nullptr, &m_fluidResolvedTarget))) + { + return; + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MostDetailedMip = 0; + + if (FAILED(device->CreateShaderResourceView(m_fluidResolvedTarget, &srvDesc, &m_fluidResolvedTargetSRV))) + { + return; + } + } +} + +void DemoContextD3D11::startFrame(Vec4 clear) +{ + AppGraphColor clearColor = { clear.x, clear.y, clear.z, clear.w }; + AppGraphCtxFrameStart(m_appGraphCtx, clearColor); + + MeshDrawParamsD3D& meshDrawParams = m_meshDrawParams; + + memset(&meshDrawParams, 0, sizeof(MeshDrawParamsD3D)); + meshDrawParams.renderStage = MESH_DRAW_LIGHT; + meshDrawParams.renderMode = MESH_RENDER_SOLID; + meshDrawParams.cullMode = MESH_CULL_BACK; + meshDrawParams.projection = (XMMATRIX)Matrix44::kIdentity; + meshDrawParams.view = (XMMATRIX)Matrix44::kIdentity; + meshDrawParams.model = DirectX::XMMatrixMultiply( + DirectX::XMMatrixScaling(1.0f, 1.0f, 1.0f), + DirectX::XMMatrixTranslation(0.0f, 0.0f, 0.0f) + ); +} + +void DemoContextD3D11::_flushFrame() +{ + m_appGraphCtxD3D11->m_deviceContext->Flush(); +} + +void DemoContextD3D11::endFrame() +{ + _flushFrame(); + + ImguiGraphDescD3D11 desc; + + desc.device = m_appGraphCtxD3D11->m_device; + desc.deviceContext = m_appGraphCtxD3D11->m_deviceContext; + desc.winW = m_appGraphCtxD3D11->m_winW; + desc.winH = m_appGraphCtxD3D11->m_winH; + + imguiGraphUpdate((ImguiGraphDesc*)&desc); + //m_imguiGraphContext->update(&desc); +} + +void DemoContextD3D11::presentFrame(bool fullsync) +{ + AppGraphCtxFramePresent(m_appGraphCtx, fullsync); +} + +void DemoContextD3D11::getViewRay(int x, int y, Vec3& origin, Vec3& dir) +{ + using namespace DirectX; + + XMVECTOR nearVector = XMVector3Unproject(XMVectorSet(float(x), float(m_appGraphCtxD3D11->m_winH-y), 0.0f, 0.0f), 0.0f, 0.0f, (float)m_appGraphCtxD3D11->m_winW, (float)m_appGraphCtxD3D11->m_winH, 0.0f, 1.0f, (XMMATRIX)m_proj, XMMatrixIdentity(), (XMMATRIX)m_view); + XMVECTOR farVector = XMVector3Unproject(XMVectorSet(float(x), float(m_appGraphCtxD3D11->m_winH-y), 1.0f, 0.0f), 0.0f, 0.0f, (float)m_appGraphCtxD3D11->m_winW, (float)m_appGraphCtxD3D11->m_winH, 0.0f, 1.0f, (XMMATRIX)m_proj, XMMatrixIdentity(), (XMMATRIX)m_view); + + origin = Vec3(XMVectorGetX(nearVector), XMVectorGetY(nearVector), XMVectorGetZ(nearVector)); + XMVECTOR tmp = farVector - nearVector; + dir = Normalize(Vec3(XMVectorGetX(tmp), XMVectorGetY(tmp), XMVectorGetZ(tmp))); +} + +void DemoContextD3D11::setFillMode(bool wire) +{ + m_meshDrawParams.renderMode = wire ? MESH_RENDER_WIREFRAME : MESH_RENDER_SOLID; +} + +void DemoContextD3D11::setCullMode(bool enabled) +{ + m_meshDrawParams.cullMode = enabled ? MESH_CULL_BACK : MESH_CULL_NONE; +} + +void DemoContextD3D11::setView(Matrix44 view, Matrix44 projection) +{ + Matrix44 vp = projection*view; + + m_meshDrawParams.model = (XMMATRIX)Matrix44::kIdentity; + m_meshDrawParams.view = (XMMATRIX)view; + m_meshDrawParams.projection = (XMMATRIX)(ConvertToD3DProjection(projection)); + + m_view = view; + m_proj = ConvertToD3DProjection(projection); +} + +FluidRenderer* DemoContextD3D11::createFluidRenderer(uint32_t width, uint32_t height) +{ + FluidRendererD3D11* renderer = new(_aligned_malloc(sizeof(FluidRendererD3D11), 16)) FluidRendererD3D11; + renderer->init(m_appGraphCtxD3D11->m_device, m_appGraphCtxD3D11->m_deviceContext, width, height); + return (FluidRenderer*)renderer; +} + +void DemoContextD3D11::destroyFluidRenderer(FluidRenderer* rendererIn) +{ + FluidRendererD3D11* renderer = (FluidRendererD3D11*)rendererIn; + renderer->~FluidRendererD3D11(); + _aligned_free(renderer); +} + +FluidRenderBuffers* DemoContextD3D11::createFluidRenderBuffers(int numParticles, bool enableInterop) +{ + FluidRenderBuffersD3D11* buffers = new FluidRenderBuffersD3D11; + buffers->m_numParticles = numParticles; + + ID3D11Device* device = m_appGraphCtxD3D11->m_device; + + { + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = numParticles*sizeof(Vec4); + bufDesc.Usage = D3D11_USAGE_DYNAMIC; + bufDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufDesc.MiscFlags = 0; + bufDesc.StructureByteStride = 0; + + device->CreateBuffer(&bufDesc, NULL, &buffers->m_positions); + + device->CreateBuffer(&bufDesc, NULL, &buffers->m_anisotropiesArr[0]); + device->CreateBuffer(&bufDesc, NULL, &buffers->m_anisotropiesArr[1]); + device->CreateBuffer(&bufDesc, NULL, &buffers->m_anisotropiesArr[2]); + + bufDesc.ByteWidth = numParticles*sizeof(float); + device->CreateBuffer(&bufDesc, NULL, &buffers->m_densities); + } + + { + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = numParticles * sizeof(int); + bufDesc.Usage = D3D11_USAGE_DYNAMIC; + bufDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufDesc.MiscFlags = 0; + bufDesc.StructureByteStride = 0; + + device->CreateBuffer(&bufDesc, NULL, &buffers->m_indices); + } + + if (enableInterop) + { + extern NvFlexLibrary* g_flexLib; + + buffers->m_positionsBuf = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_positions.Get(), numParticles, sizeof(Vec4)); + buffers->m_densitiesBuf = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_densities.Get(), numParticles, sizeof(float)); + buffers->m_indicesBuf = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_indices.Get(), numParticles, sizeof(int)); + + buffers->m_anisotropiesBufArr[0] = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_anisotropiesArr[0].Get(), numParticles, sizeof(Vec4)); + buffers->m_anisotropiesBufArr[1] = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_anisotropiesArr[1].Get(), numParticles, sizeof(Vec4)); + buffers->m_anisotropiesBufArr[2] = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_anisotropiesArr[2].Get(), numParticles, sizeof(Vec4)); + } + + return reinterpret_cast<FluidRenderBuffers*>(buffers); +} + +void DemoContextD3D11::updateFluidRenderBuffers(FluidRenderBuffers* buffersIn, NvFlexSolver* solver, bool anisotropy, bool density) +{ + FluidRenderBuffersD3D11& buffers = *reinterpret_cast<FluidRenderBuffersD3D11*>(buffersIn); + if (!anisotropy) + { + // regular particles + NvFlexGetParticles(solver, buffers.m_positionsBuf, NULL); + } + else + { + // fluid buffers + NvFlexGetSmoothParticles(solver, buffers.m_positionsBuf, NULL); + NvFlexGetAnisotropy(solver, buffers.m_anisotropiesBufArr[0], buffers.m_anisotropiesBufArr[1], buffers.m_anisotropiesBufArr[2], NULL); + } + + if (density) + { + NvFlexGetDensities(solver, buffers.m_densitiesBuf, NULL); + } + else + { + NvFlexGetPhases(solver, buffers.m_densitiesBuf, NULL); + } + + NvFlexGetActive(solver, buffers.m_indicesBuf, NULL); +} + +void DemoContextD3D11::updateFluidRenderBuffers(FluidRenderBuffers* buffersIn, Vec4* particles, float* densities, Vec4* anisotropy1, Vec4* anisotropy2, Vec4* anisotropy3, int numParticles, int* indices, int numIndices) +{ + FluidRenderBuffersD3D11& buffers = *reinterpret_cast<FluidRenderBuffersD3D11*>(buffersIn); + D3D11_MAPPED_SUBRESOURCE res; + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + + // vertices + if (particles) + { + deviceContext->Map(buffers.m_positions.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + memcpy(res.pData, particles, sizeof(Vec4)*numParticles); + deviceContext->Unmap(buffers.m_positions.Get(), 0); + } + + Vec4*const anisotropies[3] = + { + anisotropy1, + anisotropy2, + anisotropy3, + }; + + for (int i = 0; i < 3; i++) + { + const Vec4* anisotropy = anisotropies[i]; + if (anisotropy) + { + deviceContext->Map(buffers.m_anisotropiesArr[i].Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + memcpy(res.pData, anisotropy, sizeof(Vec4) * numParticles); + deviceContext->Unmap(buffers.m_anisotropiesArr[i].Get(), 0); + } + } + + if (densities) + { + deviceContext->Map(buffers.m_densities.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + memcpy(res.pData, densities, sizeof(float)*numParticles); + deviceContext->Unmap(buffers.m_densities.Get(), 0); + } + + // indices + if (indices) + { + deviceContext->Map(buffers.m_indices.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + memcpy(res.pData, indices, sizeof(int)*numIndices); + deviceContext->Unmap(buffers.m_indices.Get(), 0); + } +} + +void DemoContextD3D11::destroyFluidRenderBuffers(FluidRenderBuffers* buffers) +{ + delete reinterpret_cast<FluidRenderBuffersD3D11*>(buffers); +} + +ShadowMap* DemoContextD3D11::shadowCreate() +{ + ShadowMapD3D11* shadowMap = new(_aligned_malloc(sizeof(ShadowMapD3D11), 16)) ShadowMapD3D11; + shadowMap->init(m_appGraphCtxD3D11->m_device, kShadowResolution); + return (ShadowMap*)shadowMap; +} + +void DemoContextD3D11::shadowDestroy(ShadowMap* map) +{ + ShadowMapD3D11* shadowMap = (ShadowMapD3D11*)map; + shadowMap->~ShadowMapD3D11(); + _aligned_free(shadowMap); +} + +void DemoContextD3D11::shadowBegin(ShadowMap* map) +{ + ShadowMapD3D11* shadowMap = (ShadowMapD3D11*)map; + shadowMap->bindAndClear(m_appGraphCtxD3D11->m_deviceContext); + + m_meshDrawParams.renderStage = MESH_DRAW_SHADOW; + m_shadowMap = shadowMap; +} + +void DemoContextD3D11::shadowEnd() +{ + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + + // reset to main frame buffer + deviceContext->RSSetViewports(1, &m_appGraphCtxD3D11->m_viewport); + deviceContext->OMSetRenderTargets(1, &m_appGraphCtxD3D11->m_rtv, m_appGraphCtxD3D11->m_dsv); + deviceContext->OMSetDepthStencilState(m_appGraphCtxD3D11->m_depthState, 0u); + deviceContext->ClearDepthStencilView(m_appGraphCtxD3D11->m_dsv, D3D11_CLEAR_DEPTH, 1.0, 0); + + m_meshDrawParams.renderStage = MESH_DRAW_NULL; +} + +void DemoContextD3D11::bindSolidShader(Vec3 lightPos, Vec3 lightTarget, Matrix44 lightTransform, ShadowMap* shadowMap, float bias, Vec4 fogColor) +{ + m_meshDrawParams.renderStage = MESH_DRAW_LIGHT; + + m_meshDrawParams.grid = 0; + m_meshDrawParams.spotMin = m_spotMin; + m_meshDrawParams.spotMax = m_spotMax; + m_meshDrawParams.fogColor = (float4&)fogColor; + + m_meshDrawParams.objectTransform = (float4x4&)Matrix44::kIdentity; + + ShadowParamsD3D shadow; + RenderParamsUtilD3D::calcShadowParams(lightPos, lightTarget, lightTransform, m_shadowBias, &shadow); + + m_meshDrawParams.lightTransform = shadow.lightTransform; + m_meshDrawParams.lightDir = shadow.lightDir; + m_meshDrawParams.lightPos = shadow.lightPos; + m_meshDrawParams.bias = shadow.bias; + memcpy(m_meshDrawParams.shadowTaps, shadow.shadowTaps, sizeof(shadow.shadowTaps)); + + m_shadowMap = (ShadowMapD3D11*)shadowMap; +} + +void DemoContextD3D11::unbindSolidShader() +{ + m_meshDrawParams.renderStage = MESH_DRAW_NULL; +} + +void DemoContextD3D11::graphicsTimerBegin() +{ + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + deviceContext->Begin(m_renderTimerDisjoint); + deviceContext->End(m_renderTimerBegin); // yes End. +} + +void DemoContextD3D11::graphicsTimerEnd() +{ + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + deviceContext->End(m_renderTimerEnd); + deviceContext->End(m_renderTimerDisjoint); + m_timersSet = true; +} + +float DemoContextD3D11::rendererGetDeviceTimestamps(unsigned long long* begin, unsigned long long* end, unsigned long long* freq) +{ + float renderTime = 0.0f; + + if (m_timersSet) + { + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT tsDisjoint; + uint64_t renderBegin = 0; + uint64_t renderEnd = 0; + + while (S_OK != deviceContext->GetData(m_renderTimerDisjoint, &tsDisjoint, sizeof(tsDisjoint), 0)); + while (S_OK != deviceContext->GetData(m_renderTimerBegin, &renderBegin, sizeof(UINT64), 0)); + while (S_OK != deviceContext->GetData(m_renderTimerEnd, &renderEnd, sizeof(UINT64), 0)); + + float renderTime = float(renderEnd - renderBegin) / float(tsDisjoint.Frequency); + + if (begin) *begin = renderBegin; + if (end) *end = renderEnd; + if (freq) *freq = tsDisjoint.Frequency; + } + + return renderTime; +} + +void DemoContextD3D11::drawMesh(const Mesh* m, Vec3 color) +{ + if (m) + { + if (m->m_colours.size()) + { + m_meshDrawParams.colorArray = 1; + m_immediateMesh->updateData((Vec3*)&m->m_positions[0], &m->m_normals[0], NULL, (Vec4*)&m->m_colours[0], (int*)&m->m_indices[0], m->GetNumVertices(), int(m->GetNumFaces())); + } + else + { + m_meshDrawParams.colorArray = 0; + m_immediateMesh->updateData((Vec3*)&m->m_positions[0], &m->m_normals[0], NULL, NULL, (int*)&m->m_indices[0], m->GetNumVertices(), int(m->GetNumFaces())); + } + + m_meshDrawParams.color = (float4&)color; + m_meshDrawParams.secondaryColor = (float4&)color; + m_meshDrawParams.objectTransform = (float4x4&)Matrix44::kIdentity; + m_meshDrawParams.shadowMap = (ShadowMapD3D*)m_shadowMap; + + m_meshRenderer->draw(m_immediateMesh, &m_meshDrawParams); + + if (m->m_colours.size()) + m_meshDrawParams.colorArray = 0; + + } +} + +void DemoContextD3D11::drawCloth(const Vec4* positions, const Vec4* normals, const float* uvs, const int* indices, int numTris, int numPositions, int colorIndex, float expand, bool twosided, bool smooth) +{ + if (!numTris) + return; + + m_immediateMesh->updateData(positions, normals, NULL, NULL, indices, numPositions, numTris); + + if (twosided) + SetCullMode(false); + + m_meshDrawParams.bias = 0.0f; + m_meshDrawParams.expand = expand; + + m_meshDrawParams.color = (const float4&)(g_colors[colorIndex + 1] * 1.5f); + m_meshDrawParams.secondaryColor = (const float4&)(g_colors[colorIndex] * 1.5f); + m_meshDrawParams.objectTransform = (float4x4&)Matrix44::kIdentity; + m_meshDrawParams.shadowMap = (ShadowMapD3D*)m_shadowMap; + + m_meshRenderer->draw(m_immediateMesh, &m_meshDrawParams); + + if (twosided) + setCullMode(true); + + m_meshDrawParams.bias = m_shadowBias; + m_meshDrawParams.expand = 0.0f; +} + +void DemoContextD3D11::drawRope(Vec4* positions, int* indices, int numIndices, float radius, int color) +{ + if (numIndices < 2) + return; + + std::vector<Vec3> vertices; + std::vector<Vec3> normals; + std::vector<int> triangles; + + // flatten curve + std::vector<Vec3> curve(numIndices); + for (int i = 0; i < numIndices; ++i) + curve[i] = Vec3(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); + + m_immediateMesh->updateData(&vertices[0], &normals[0], NULL, NULL, &triangles[0], int(vertices.size()), int(triangles.size())/3); + + setCullMode(false); + + m_meshDrawParams.color = (const float4&)(g_colors[color % 8] * 1.5f); + m_meshDrawParams.secondaryColor = (const float4&)(g_colors[color % 8] * 1.5f); + m_meshDrawParams.objectTransform = (const float4x4&)Matrix44::kIdentity; + m_meshDrawParams.shadowMap = (ShadowMapD3D*)m_shadowMap; + + m_meshRenderer->draw(m_immediateMesh, &m_meshDrawParams); + + setCullMode(true); +} + +void DemoContextD3D11::drawPlane(const Vec4& p, bool color) +{ + std::vector<Vec3> vertices; + std::vector<Vec3> normals; + std::vector<int> indices; + + Vec3 u, v; + BasisFromVector(Vec3(p.x, p.y, p.z), &u, &v); + + Vec3 c = Vec3(p.x, p.y, p.z)*-p.w; + + m_meshDrawParams.shadowMap = (ShadowMapD3D*)m_shadowMap; + + if (color) + m_meshDrawParams.color = (const float4&)(p * 0.5f + Vec4(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) + { + Vec3 coff = c + u*float(x)*kSize*2.0f + v*float(y)*kSize*2.0f; + + int indexStart = int(vertices.size()); + + vertices.push_back(Vec3(coff + u*kSize + v*kSize)); + vertices.push_back(Vec3(coff - u*kSize + v*kSize)); + vertices.push_back(Vec3(coff - u*kSize - v*kSize)); + vertices.push_back(Vec3(coff + u*kSize - v*kSize)); + + normals.push_back(Vec3(p.x, p.y, p.z)); + normals.push_back(Vec3(p.x, p.y, p.z)); + normals.push_back(Vec3(p.x, p.y, p.z)); + normals.push_back(Vec3(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); + } + } + + m_immediateMesh->updateData(&vertices[0], &normals[0], NULL, NULL, &indices[0], int(vertices.size()), int(indices.size())/3); + m_meshRenderer->draw(m_immediateMesh, &m_meshDrawParams); +} + +void DemoContextD3D11::drawPlanes(Vec4* planes, int n, float bias) +{ + m_meshDrawParams.color = (float4&)Vec4(0.9f, 0.9f, 0.9f, 1.0f); + + m_meshDrawParams.bias = 0.0f; + m_meshDrawParams.grid = 1; + m_meshDrawParams.expand = 0; + + for (int i = 0; i < n; ++i) + { + Vec4 p = planes[i]; + p.w -= bias; + + drawPlane(p, false); + } + + m_meshDrawParams.grid = 0; + m_meshDrawParams.bias = m_shadowBias; + +} + +GpuMesh* DemoContextD3D11::createGpuMesh(const Mesh* m) +{ + GpuMeshD3D11* mesh = new GpuMeshD3D11(m_appGraphCtxD3D11->m_device, m_appGraphCtxD3D11->m_deviceContext); + mesh->updateData((Vec3*)&m->m_positions[0], &m->m_normals[0], NULL, NULL, (int*)&m->m_indices[0], m->GetNumVertices(), int(m->GetNumFaces())); + return (GpuMesh*)mesh; +} + +void DemoContextD3D11::destroyGpuMesh(GpuMesh* m) +{ + delete reinterpret_cast<GpuMeshD3D11*>(m); +} + +void DemoContextD3D11::drawGpuMesh(GpuMesh* meshIn, const Matrix44& xform, const Vec3& color) +{ + if (meshIn) + { + GpuMeshD3D11* mesh = (GpuMeshD3D11*)meshIn; + + MeshDrawParamsD3D params = m_meshDrawParams; + + params.color = (float4&)color; + params.secondaryColor = (float4&)color; + params.objectTransform = (float4x4&)xform; + params.shadowMap = (ShadowMapD3D*)m_shadowMap; + + m_meshRenderer->draw(mesh, ¶ms); + } +} + +void DemoContextD3D11::drawGpuMeshInstances(GpuMesh* meshIn, const Matrix44* xforms, int n, const Vec3& color) +{ + if (meshIn) + { + GpuMeshD3D11* mesh = (GpuMeshD3D11*)meshIn; + + m_meshDrawParams.color = (float4&)color; + m_meshDrawParams.secondaryColor = (float4&)color; + m_meshDrawParams.shadowMap = (ShadowMapD3D*)m_shadowMap; + + // copy params + MeshDrawParamsD3D params(m_meshDrawParams); + + for (int i = 0; i < n; ++i) + { + params.objectTransform = (const float4x4&)xforms[i]; + m_meshRenderer->draw(mesh, ¶ms); + } + } +} + +void DemoContextD3D11::drawPoints(FluidRenderBuffers* buffersIn, int n, int offset, float radius, float screenWidth, float screenAspect, float fov, Vec3 lightPos, Vec3 lightTarget, Matrix44 lightTransform, ShadowMap* shadowTex, bool showDensity) +{ + FluidRenderBuffersD3D11& buffers = *reinterpret_cast<FluidRenderBuffersD3D11*>(buffersIn); + if (n == 0) + return; + + PointDrawParamsD3D params; + + params.renderMode = POINT_RENDER_SOLID; + params.cullMode = POINT_CULL_BACK; + params.model = (const XMMATRIX&)Matrix44::kIdentity; + params.view = (const XMMATRIX&)m_view; + params.projection = (const XMMATRIX&)m_proj; + + params.pointRadius = radius; + params.pointScale = screenWidth / screenAspect * (1.0f / (tanf(fov * 0.5f))); + params.spotMin = m_spotMin; + params.spotMax = m_spotMax; + + 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] = *((const float4*)&g_colors[i].r); + + // set shadow parameters + ShadowParamsD3D shadow; + RenderParamsUtilD3D::calcShadowParams(lightPos, lightTarget, lightTransform, m_shadowBias, &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_shadowMap; + + m_pointRenderer->draw(¶ms, buffers.m_positions.Get(), buffers.m_densities.Get(), buffers.m_indices.Get(), n, offset); +} + +void DemoContextD3D11::renderEllipsoids(FluidRenderer* rendererIn, FluidRenderBuffers* buffersIn, int n, int offset, float radius, float screenWidth, float screenAspect, float fov, Vec3 lightPos, Vec3 lightTarget, Matrix44 lightTransform, ShadowMap* shadowMap, Vec4 color, float blur, float ior, bool debug) +{ + FluidRenderBuffersD3D11& buffers = *reinterpret_cast<FluidRenderBuffersD3D11*>(buffersIn); + FluidRendererD3D11& renderer = *(FluidRendererD3D11*)rendererIn; + if (n == 0) + return; + + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + + FluidDrawParamsD3D params; + + params.renderMode = FLUID_RENDER_SOLID; + params.cullMode = FLUID_CULL_BACK; + params.model = (const XMMATRIX&)Matrix44::kIdentity; + params.view = (const 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 = float3(1.0f / screenWidth, screenAspect / screenWidth, 1.0f); + params.invProjection = float3(screenAspect * viewHeight, viewHeight, 1.0f); + + params.shadowMap = (ShadowMapD3D*)m_shadowMap; + + renderer.m_depthTexture.bindAndClear(m_appGraphCtxD3D11->m_deviceContext); + + // draw static shapes into depth buffer + //DrawShapes(); + + renderer.drawEllipsoids(¶ms, &buffers); + + + //--------------------------------------------------------------- + // build smooth depth + + renderer.m_depthSmoothTexture.bindAndClear(deviceContext); + + params.blurRadiusWorld = radius * 0.5f; + params.blurScale = screenWidth / screenAspect * (1.0f / (tanf(fov * 0.5f))); + params.invTexScale = float4(1.0f / screenAspect, 1.0f, 0.0f, 0.0f); + params.blurFalloff = blur; + params.debug = debug; + + renderer.drawBlurDepth(¶ms); + + //--------------------------------------------------------------- + // composite + + { + deviceContext->RSSetViewports(1, &m_appGraphCtxD3D11->m_viewport); + deviceContext->RSSetScissorRects(0, nullptr); + + deviceContext->OMSetRenderTargets(1, &m_appGraphCtxD3D11->m_rtv, m_appGraphCtxD3D11->m_dsv); + deviceContext->OMSetDepthStencilState(m_appGraphCtxD3D11->m_depthState, 0u); + + float blendFactor[4] = { 1.0, 1.0, 1.0, 1.0 }; + deviceContext->OMSetBlendState(m_compositeBlendState, blendFactor, 0xffff); + } + + params.invTexScale = (float4&)Vec2(1.0f / screenWidth, screenAspect / screenWidth); + params.clipPosToEye = (float4&)Vec2(tanf(fov*0.5f)*screenAspect, tanf(fov*0.5f)); + params.color = (float4&)color; + params.ior = ior; + params.spotMin = m_spotMin; + params.spotMax = m_spotMax; + params.debug = debug; + + params.lightPos = (const float3&)lightPos; + params.lightDir = (const float3&)-Normalize(lightTarget - lightPos); + params.lightTransform = (const XMMATRIX&)(ConvertToD3DProjection(lightTransform)); + + // Resolve MS back buffer/copy + if (m_msaaSamples > 1) + { + deviceContext->ResolveSubresource(m_fluidResolvedTarget, 0, m_appGraphCtxD3D11->m_backBuffer, 0, DXGI_FORMAT_R8G8B8A8_UNORM); + } + else + { + deviceContext->CopyResource(m_fluidResolvedTarget, m_appGraphCtxD3D11->m_backBuffer); + } + + renderer.drawComposite(¶ms, m_fluidResolvedTargetSRV); + + deviceContext->OMSetBlendState(nullptr, 0, 0xffff); +} + +DiffuseRenderBuffers* DemoContextD3D11::createDiffuseRenderBuffers(int numParticles, bool& enableInterop) +{ + ID3D11Device* device = m_appGraphCtxD3D11->m_device; + DiffuseRenderBuffersD3D11* buffers = new DiffuseRenderBuffersD3D11; + + buffers->m_numParticles = numParticles; + if (numParticles > 0) + { + { + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = numParticles * sizeof(Vec4); + bufDesc.Usage = D3D11_USAGE_DYNAMIC; + bufDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufDesc.MiscFlags = 0; + if (enableInterop) + { + bufDesc.CPUAccessFlags = 0; + bufDesc.Usage = D3D11_USAGE_DEFAULT; + bufDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + } + + device->CreateBuffer(&bufDesc, NULL, buffers->m_positions.ReleaseAndGetAddressOf()); + device->CreateBuffer(&bufDesc, NULL, buffers->m_velocities.ReleaseAndGetAddressOf()); + } + + if (enableInterop) + { + extern NvFlexLibrary* g_flexLib; + + buffers->m_positionsBuf = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_positions.Get(), numParticles, sizeof(Vec4)); + buffers->m_velocitiesBuf = NvFlexRegisterD3DBuffer(g_flexLib, buffers->m_velocities.Get(), numParticles, sizeof(Vec4)); + + if (buffers->m_positionsBuf == nullptr || + buffers->m_velocitiesBuf == nullptr) + enableInterop = false; + } + } + + return reinterpret_cast<DiffuseRenderBuffers*>(buffers); +} + +void DemoContextD3D11::destroyDiffuseRenderBuffers(DiffuseRenderBuffers* buffers) +{ + delete reinterpret_cast<DiffuseRenderBuffersD3D11*>(buffers); +} + +void DemoContextD3D11::updateDiffuseRenderBuffers(DiffuseRenderBuffers* buffersIn, NvFlexSolver* solver) +{ + DiffuseRenderBuffersD3D11* buffers = reinterpret_cast<DiffuseRenderBuffersD3D11*>(buffersIn); + // diffuse particles + if (buffers->m_numParticles) + { + NvFlexGetDiffuseParticles(solver, buffers->m_positionsBuf, buffers->m_velocitiesBuf, nullptr); + } +} + +void DemoContextD3D11::updateDiffuseRenderBuffers(DiffuseRenderBuffers* buffersIn, Vec4* diffusePositions, Vec4* diffuseVelocities, int numDiffuseParticles) +{ + DiffuseRenderBuffersD3D11& buffers = *reinterpret_cast<DiffuseRenderBuffersD3D11*>(buffersIn); + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + + D3D11_MAPPED_SUBRESOURCE res; + + // vertices + if (diffusePositions) + { + deviceContext->Map(buffers.m_positions.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + memcpy(res.pData, diffusePositions, sizeof(Vec4)*numDiffuseParticles); + deviceContext->Unmap(buffers.m_positions.Get(), 0); + } + + if (diffuseVelocities) + { + deviceContext->Map(buffers.m_velocities.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + memcpy(res.pData, diffuseVelocities, sizeof(Vec4)*numDiffuseParticles); + deviceContext->Unmap(buffers.m_velocities.Get(), 0); + } +} + +void DemoContextD3D11::drawDiffuse(FluidRenderer* renderIn, const DiffuseRenderBuffers* buffersIn, int n, float radius, float screenWidth, float screenAspect, float fov, Vec4 color, Vec3 lightPos, Vec3 lightTarget, Matrix44 lightTransform, ShadowMap* shadowMap, float motionBlur, float inscatter, float outscatter, bool shadowEnabled, bool front) +{ + FluidRendererD3D11* render = (FluidRendererD3D11*)renderIn; + const DiffuseRenderBuffersD3D11& buffers = *reinterpret_cast<const DiffuseRenderBuffersD3D11*>(buffersIn); + if (n == 0) + return; + + DiffuseDrawParamsD3D params; + + params.model = (const XMMATRIX&)Matrix44::kIdentity; + 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 = m_spotMin; + params.spotMax = m_spotMax; + params.color = float4(1.0f, 1.0f, 1.0f, 1.0f); + params.motionScale = motionBlur; + + // set shadow parameters + ShadowParamsD3D shadow; + RenderParamsUtilD3D::calcShadowParams(lightPos, lightTarget, lightTransform, m_shadowBias, &shadow); + params.lightTransform = shadow.lightTransform; + params.lightDir = shadow.lightDir; + params.lightPos = shadow.lightPos; + params.shadowMap = (ShadowMapD3D*)m_shadowMap; + + memcpy(params.shadowTaps, shadow.shadowTaps, sizeof(shadow.shadowTaps)); + + m_diffuseRenderer->draw(¶ms, buffers.m_positions.Get(), buffers.m_velocities.Get(), n); + + // reset depth stencil state + m_appGraphCtxD3D11->m_deviceContext->OMSetDepthStencilState(m_appGraphCtxD3D11->m_depthState, 0u); +} + +int DemoContextD3D11::getNumDiffuseRenderParticles(DiffuseRenderBuffers* buffers) +{ + return reinterpret_cast<DiffuseRenderBuffersD3D11*>(buffers)->m_numParticles; +} + +void DemoContextD3D11::beginLines() +{ +} + +void DemoContextD3D11::drawLine(const Vec3& p, const Vec3& q, const Vec4& color) +{ + m_debugLineRender->addLine(p, q, color); +} + +void DemoContextD3D11::endLines() +{ + // draw + Matrix44 projectionViewWorld = ((Matrix44&)(m_meshDrawParams.projection))*((Matrix44&)(m_meshDrawParams.view)); + + m_debugLineRender->flush(projectionViewWorld); +} + +void DemoContextD3D11::startGpuWork() {} +void DemoContextD3D11::endGpuWork() {} + +void DemoContextD3D11::flushGraphicsAndWait() +{ + ID3D11DeviceContext* deviceContext = m_appGraphCtxD3D11->m_deviceContext; + + deviceContext->End(m_renderCompletionFence); + while (S_OK != deviceContext->GetData(m_renderCompletionFence, 0, 0, 0)); +} + +void* DemoContextD3D11::getGraphicsCommandQueue() { return NULL; } + +void DemoContextD3D11::drawImguiGraph() +{ + imguiGraphDraw(); +} |