#define NOMINMAX #include #include #include "pipelineUtilD3D12.h" #include "meshRenderer.h" #include "bufferD3D12.h" #include "meshRendererD3D12.h" #include "../d3d/shaderCommonD3D.h" // this #include "meshRenderPipelineD3D12.h" // Shaders #include "../d3d/shaders/meshVS.hlsl.h" #include "../d3d/shaders/meshPS.hlsl.h" #include "../d3d/shaders/meshShadowPS.hlsl.h" namespace FlexSample { // Make async compute benchmark shader have a unique name namespace AsyncComputeBench { #include "../d3d/shaders/meshAsyncComputeBenchPS.hlsl.h" } MeshRenderPipelineD3D12::MeshRenderPipelineD3D12(): Parent(PRIMITIVE_TRIANGLE), m_shadowMapLinearSamplerIndex(-1) { } /* static */MeshRenderPipelineD3D12::PipelineStateType MeshRenderPipelineD3D12::getPipelineStateType(MeshDrawStage stage, MeshRenderMode mode, MeshCullMode cull) { switch (stage) { case MESH_DRAW_NULL: case MESH_DRAW_REFLECTION: case MESH_DRAW_LIGHT: { if (mode == MESH_RENDER_WIREFRAME) { return PIPELINE_STATE_LIGHT_WIREFRAME; } switch (cull) { case MESH_CULL_BACK: return PIPELINE_STATE_LIGHT_SOLID_CULL_BACK; case MESH_CULL_FRONT: return PIPELINE_STATE_LIGHT_SOLID_CULL_FRONT; default: case MESH_CULL_NONE: return PIPELINE_STATE_LIGHT_SOLID_CULL_NONE; } } case MESH_DRAW_SHADOW: { switch (cull) { case MESH_CULL_BACK: return PIPELINE_STATE_SHADOW_CULL_BACK; default: case MESH_CULL_NONE: return PIPELINE_STATE_SHADOW_CULL_NONE; } } } printf("Unhandled option!"); return PIPELINE_STATE_LIGHT_SOLID_CULL_BACK; } static D3D12_FILL_MODE _getFillMode(MeshRenderPipelineD3D12::PipelineStateType type) { switch (type) { default: return D3D12_FILL_MODE_SOLID; case MeshRenderPipelineD3D12::PIPELINE_STATE_LIGHT_WIREFRAME: return D3D12_FILL_MODE_WIREFRAME; } } static D3D12_CULL_MODE _getCullMode(MeshRenderPipelineD3D12::PipelineStateType type) { switch (type) { case MeshRenderPipelineD3D12::PIPELINE_STATE_COUNT_OF: break; case MeshRenderPipelineD3D12::PIPELINE_STATE_SHADOW_CULL_BACK: return D3D12_CULL_MODE_BACK; case MeshRenderPipelineD3D12::PIPELINE_STATE_LIGHT_SOLID_CULL_FRONT: return D3D12_CULL_MODE_FRONT; case MeshRenderPipelineD3D12::PIPELINE_STATE_LIGHT_SOLID_CULL_BACK: return D3D12_CULL_MODE_BACK; case MeshRenderPipelineD3D12::PIPELINE_STATE_SHADOW_CULL_NONE: case MeshRenderPipelineD3D12::PIPELINE_STATE_LIGHT_WIREFRAME: case MeshRenderPipelineD3D12::PIPELINE_STATE_LIGHT_SOLID_CULL_NONE: return D3D12_CULL_MODE_NONE; } printf("Unhandled option!"); return D3D12_CULL_MODE_NONE; } static void _initRasterizerDesc(MeshRenderPipelineD3D12::PipelineStateType type, FrontWindingType winding, D3D12_RASTERIZER_DESC& desc) { PipelineUtilD3D::initRasterizerDesc(winding, desc); desc.FillMode = _getFillMode(type); desc.CullMode = _getCullMode(type); } static void _initPipelineStateDesc(MeshRenderPipelineD3D12::PipelineStateType type, NvCo::Dx12RenderTarget* shadowMap, AppGraphCtxD3D12* renderContext, D3D12_GRAPHICS_PIPELINE_STATE_DESC& psoDesc) { PipelineUtilD3D::initTargetFormat((shadowMap && MeshRenderPipelineD3D12::isShadow(type)) ? shadowMap : nullptr, renderContext, psoDesc); psoDesc.InputLayout.NumElements = _countof(MeshRendererD3D12::MeshInputElementDescs); psoDesc.InputLayout.pInputElementDescs = MeshRendererD3D12::MeshInputElementDescs; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; } int MeshRenderPipelineD3D12::initialize(const RenderStateD3D12& state, const std::wstring& shadersPath, FrontWindingType winding, int shadowMapLinearSamplerIndex, NvCo::Dx12RenderTarget* shadowMap, bool asyncComputeBenchmark) { using namespace NvCo; ID3D12Device* device = state.m_device; m_shadowMapLinearSamplerIndex = shadowMapLinearSamplerIndex; // create the pipeline state object { D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; PipelineUtilD3D::initSolidBlendDesc(psoDesc.BlendState); // create the root signature ComPtr signiture; { CD3DX12_DESCRIPTOR_RANGE ranges[2]; CD3DX12_ROOT_PARAMETER params[3]; UINT rootIndex = 0; { D3D12_ROOT_PARAMETER& param = params[rootIndex++]; param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; param.Descriptor.ShaderRegister = 0u; param.Descriptor.RegisterSpace = 0u; param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; } const int numSrvs = 1; if (numSrvs > 0) { ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, numSrvs, 0); params[rootIndex++].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL); } const int numSamplers = 1; if (numSamplers > 0) { ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, numSamplers, 0); params[rootIndex++].InitAsDescriptorTable(1, &ranges[1], D3D12_SHADER_VISIBILITY_PIXEL); } D3D12_ROOT_SIGNATURE_DESC desc; desc.NumParameters = rootIndex; desc.pParameters = params; desc.NumStaticSamplers = 0; desc.pStaticSamplers = nullptr; desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; ComPtr sigBlob; NV_RETURN_ON_FAIL(Dx12HelperUtil::serializeRootSigniture(desc, D3D_ROOT_SIGNATURE_VERSION_1, sigBlob)); NV_RETURN_ON_FAIL(device->CreateRootSignature(0u, sigBlob->GetBufferPointer(), sigBlob->GetBufferSize(), IID_PPV_ARGS(&signiture))); } { psoDesc.VS = Dx12Blob(g_meshVS); psoDesc.PS = asyncComputeBenchmark ? Dx12Blob(AsyncComputeBench::g_meshPS) : Dx12Blob(g_meshPS);; NV_RETURN_ON_FAIL(_initPipelineState(state, winding, shadowMap, PIPELINE_STATE_LIGHT_SOLID_CULL_FRONT, signiture.Get(), psoDesc)); NV_RETURN_ON_FAIL(_initPipelineState(state, winding, shadowMap, PIPELINE_STATE_LIGHT_SOLID_CULL_BACK, signiture.Get(), psoDesc)); NV_RETURN_ON_FAIL(_initPipelineState(state, winding, shadowMap, PIPELINE_STATE_LIGHT_SOLID_CULL_NONE, signiture.Get(), psoDesc)); NV_RETURN_ON_FAIL(_initPipelineState(state, winding, shadowMap, PIPELINE_STATE_LIGHT_WIREFRAME, signiture.Get(), psoDesc)); } // Shadow rendering { D3D12_ROOT_PARAMETER params[1]; params[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; params[0].Descriptor.ShaderRegister = 0u; params[0].Descriptor.RegisterSpace = 0u; params[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; D3D12_ROOT_SIGNATURE_DESC desc; desc.NumParameters = 1; desc.pParameters = params; desc.NumStaticSamplers = 0; desc.pStaticSamplers = nullptr; desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; ComPtr sigBlob; NV_RETURN_ON_FAIL(Dx12HelperUtil::serializeRootSigniture(desc, D3D_ROOT_SIGNATURE_VERSION_1, sigBlob)); NV_RETURN_ON_FAIL(device->CreateRootSignature(0u, sigBlob->GetBufferPointer(), sigBlob->GetBufferSize(), IID_PPV_ARGS(&signiture))); } { psoDesc.VS = Dx12Blob(g_meshVS); psoDesc.PS = Dx12Blob(g_meshPS_Shadow); NV_RETURN_ON_FAIL(_initPipelineState(state, winding, shadowMap, PIPELINE_STATE_SHADOW_CULL_BACK, signiture.Get(), psoDesc)); NV_RETURN_ON_FAIL(_initPipelineState(state, winding, shadowMap, PIPELINE_STATE_SHADOW_CULL_NONE, signiture.Get(), psoDesc)); } } return NV_OK; } int MeshRenderPipelineD3D12::_initPipelineState(const RenderStateD3D12& state, FrontWindingType winding, NvCo::Dx12RenderTarget* shadowMap, PipelineStateType pipeType, ID3D12RootSignature* signiture, D3D12_GRAPHICS_PIPELINE_STATE_DESC& psoDesc) { ID3D12Device* device = state.m_device; _initRasterizerDesc(pipeType, winding, psoDesc.RasterizerState); _initPipelineStateDesc(pipeType, shadowMap, state.m_renderContext, psoDesc); psoDesc.pRootSignature = signiture; PipelineStateD3D12& pipeState = m_states[pipeType]; pipeState.m_rootSignature = signiture; NV_RETURN_ON_FAIL(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipeState.m_pipelineState))); return NV_OK; } int MeshRenderPipelineD3D12::bind(const void* paramsIn, const void* platformState) { const RenderStateD3D12& state = *(RenderStateD3D12*)platformState; const MeshDrawParamsD3D& params = *(MeshDrawParamsD3D*)paramsIn; NvCo::Dx12CircularResourceHeap::Cursor cursor; { Hlsl::MeshShaderConst constBuf; RenderParamsUtilD3D::calcMeshConstantBuffer(params, constBuf); cursor = state.m_constantHeap->newConstantBuffer(constBuf); if (!cursor.isValid()) { return NV_FAIL; } } const PipelineStateType pipeType = getPipelineStateType(params.renderStage, params.renderMode, params.cullMode); PipelineStateD3D12& pipeState = m_states[pipeType]; if (!pipeState.isValid()) { return NV_FAIL; } ID3D12GraphicsCommandList* commandList = state.m_commandList; commandList->SetGraphicsRootSignature(pipeState.m_rootSignature.Get()); commandList->SetPipelineState(pipeState.m_pipelineState.Get()); D3D12_GPU_VIRTUAL_ADDRESS cbvHandle = state.m_constantHeap->getGpuHandle(cursor); commandList->SetGraphicsRootConstantBufferView(0, cbvHandle); if (isShadow(pipeType)) { ID3D12DescriptorHeap* heaps[] = { nullptr }; commandList->SetDescriptorHeaps(0, heaps); } else { NvCo::Dx12RenderTarget* shadowMap = (NvCo::Dx12RenderTarget*)params.shadowMap; ID3D12DescriptorHeap* heaps[] = { state.m_srvCbvUavDescriptorHeap->getHeap(), state.m_samplerDescriptorHeap->getHeap() }; commandList->SetDescriptorHeaps(_countof(heaps), heaps); // Bind the srvs commandList->SetGraphicsRootDescriptorTable(1, state.m_srvCbvUavDescriptorHeap->getGpuHandle(shadowMap->getSrvHeapIndex(shadowMap->getPrimaryBufferType()))); // Bind the samplers commandList->SetGraphicsRootDescriptorTable(2, state.m_samplerDescriptorHeap->getGpuHandle(m_shadowMapLinearSamplerIndex)); } return NV_OK; } int MeshRenderPipelineD3D12::draw(const RenderAllocation& allocIn, size_t sizeOfAlloc, const void* platformState) { return MeshRendererD3D12::defaultDraw(allocIn, sizeOfAlloc, platformState); } } // namespace FlexSample