D3D(int width, int height, HWND hWnd) : mBufferWidth(width), mBufferHeight(height), mDev(nullptr) { { #if _DEBUG CHK(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(mDxgiFactory.ReleaseAndGetAddressOf()))); #else CHK(CreateDXGIFactory2(0, IID_PPV_ARGS(mDxgiFactory.ReleaseAndGetAddressOf()))); #endif /* _DEBUG */ } #if _DEBUG ID3D12Debug* debug = nullptr; D3D12GetDebugInterface(IID_PPV_ARGS(&debug)); if (debug) { debug->EnableDebugLayer(); debug->Release(); debug = nullptr; } #endif /* _DEBUG */ ID3D12Device* dev; CHK(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev))); mDev = dev; CHK(mDev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(mCmdAlloc.ReleaseAndGetAddressOf()))); D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; CHK(mDev->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(mCmdQueue.ReleaseAndGetAddressOf()))); DXGI_SWAP_CHAIN_DESC1 scDesc = {}; scDesc.Width = width; scDesc.Height = height; scDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scDesc.SampleDesc.Count = 1; scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scDesc.BufferCount = BUFFER_COUNT; scDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; CHK(mDxgiFactory->CreateSwapChainForHwnd(mCmdQueue.Get(), hWnd, &scDesc, nullptr, nullptr, mSwapChain.ReleaseAndGetAddressOf())); CHK(mDev->CreateCommandList( 0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCmdAlloc.Get(), nullptr, IID_PPV_ARGS(mCmdList.ReleaseAndGetAddressOf()))); CHK(mDev->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(mFence.ReleaseAndGetAddressOf()))); mFenceEveneHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); for (int i = 0; i < BUFFER_COUNT; i++) { CHK(mSwapChain->GetBuffer(i, IID_PPV_ARGS(mD3DBuffer[i].ReleaseAndGetAddressOf()))); mD3DBuffer[i]->SetName(L"SwapChain_Buffer"); } { D3D12_DESCRIPTOR_HEAP_DESC desc = {}; desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; desc.NumDescriptors = 10; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapRtv.ReleaseAndGetAddressOf()))); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; desc.NumDescriptors = 100; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapCbvSrvUav.ReleaseAndGetAddressOf()))); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; desc.NumDescriptors = 10; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapSampler.ReleaseAndGetAddressOf()))); } auto rtvStep = mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); for (auto i = 0u; i < BUFFER_COUNT; i++) { auto d = mDescHeapRtv->GetCPUDescriptorHandleForHeapStart(); d.ptr += i * rtvStep; mDev->CreateRenderTargetView(mD3DBuffer[i].Get(), nullptr, d); } { CD3DX12_DESCRIPTOR_RANGE descRange1[2], descRange2[1]; descRange1[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0, 4294967295U); descRange1[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, 0, -1); descRange2[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0, 0, 4294967295U); CD3DX12_ROOT_PARAMETER rootParam[2]; rootParam[0].InitAsDescriptorTable(ARRAYSIZE(descRange1), descRange1); rootParam[1].InitAsDescriptorTable(ARRAYSIZE(descRange2), descRange2); ID3D10Blob *sig, *info; auto rootSigDesc = D3D12_ROOT_SIGNATURE_DESC(); rootSigDesc.NumParameters = 2; rootSigDesc.NumStaticSamplers = 0; rootSigDesc.pParameters = rootParam; rootSigDesc.pStaticSamplers = nullptr; CHK(D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &sig, &info)); mDev->CreateRootSignature( 0, sig->GetBufferPointer(), sig->GetBufferSize(), IID_PPV_ARGS(mRootSignature.ReleaseAndGetAddressOf())); sig->Release(); } ID3D10Blob *vs, *ps; { ID3D10Blob *info; UINT flag = 0; #if _DEBUG flag |= D3DCOMPILE_DEBUG; #endif /* _DEBUG */ CHK(D3DCompileFromFile(L"ConstantBuffer.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", flag, 0, &vs, &info)); CHK(D3DCompileFromFile(L"ConstantBuffer.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", flag, 0, &ps, &info)); } D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.InputLayout.NumElements = 0; psoDesc.pRootSignature = mRootSignature.Get(); psoDesc.VS.pShaderBytecode = vs->GetBufferPointer(); psoDesc.VS.BytecodeLength = vs->GetBufferSize(); psoDesc.PS.pShaderBytecode = ps->GetBufferPointer(); psoDesc.PS.BytecodeLength = ps->GetBufferSize(); psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(CCCD3DX12_DEFAULT()); psoDesc.BlendState = CD3DX12_BLEND_DESC(CCCD3DX12_DEFAULT()); psoDesc.DepthStencilState.DepthEnable = false; psoDesc.DepthStencilState.StencilEnable = false; psoDesc.SampleMask = UINT_MAX; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.SampleDesc.Count = 1; CHK(mDev->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(mPso.ReleaseAndGetAddressOf()))); vs->Release(); ps->Release(); { // Read DDS file vector<char> texData(4 * 256 * 256); ifstream ifs("d3d12.dds", ios::binary); if (!ifs) throw runtime_error("Texture not found."); ifs.seekg(128, ios::beg); // Skip DDS header ifs.read(texData.data(), texData.size()); D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( DXGI_FORMAT_B8G8R8A8_UNORM, 256, 256, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_NONE, D3D12_TEXTURE_LAYOUT_UNKNOWN, 0); CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, //&CD3D12_RESOURCE_DESC::Buffer(texData.size()), &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(mTex.ReleaseAndGetAddressOf()))); mTex->SetName(L"Texure"); D3D12_BOX box = {}; box.right = 256; box.bottom = 256; box.back = 1; CHK(mTex->WriteToSubresource(0, &box, texData.data(), 4 * 256, 4 * 256 * 256)); } D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Texture2D.MipLevels = 1; srvDesc.Texture2D.MostDetailedMip = 0; // No MIP srvDesc.Texture2D.PlaneSlice = 0; srvDesc.Texture2D.ResourceMinLODClamp = 0.0f; mDev->CreateShaderResourceView(mTex.Get(), &srvDesc, mDescHeapCbvSrvUav->GetCPUDescriptorHandleForHeapStart()); D3D12_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; samplerDesc.MinLOD = -FLT_MAX; samplerDesc.MaxLOD = FLT_MAX; samplerDesc.MipLODBias = 0; samplerDesc.MaxAnisotropy = 0; samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; mDev->CreateSampler(&samplerDesc, mDescHeapSampler->GetCPUDescriptorHandleForHeapStart()); CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(mCB.ReleaseAndGetAddressOf()))); mCB->SetName(L"ConstantBuffer"); D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; cbvDesc.BufferLocation = mCB->GetGPUVirtualAddress(); cbvDesc.SizeInBytes = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; // must be a multiple of 256 auto cbvSrvUavDescHandle = mDescHeapCbvSrvUav->GetCPUDescriptorHandleForHeapStart(); auto cbvSrvUavStep = mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); cbvSrvUavDescHandle.ptr += cbvSrvUavStep; mDev->CreateConstantBufferView( &cbvDesc, cbvSrvUavDescHandle); CHK(mCB->Map(0, nullptr, reinterpret_cast<void**>(&mCBUploadPtr))); }
D3D(int width, int height, HWND hWnd) : mBufferWidth(width), mBufferHeight(height), mDev(nullptr) { { #if _DEBUG CHK(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(mDxgiFactory.ReleaseAndGetAddressOf()))); #else CHK(CreateDXGIFactory2(0, IID_PPV_ARGS(mDxgiFactory.ReleaseAndGetAddressOf()))); #endif /* _DEBUG */ } #if _DEBUG ID3D12Debug* debug = nullptr; D3D12GetDebugInterface(IID_PPV_ARGS(&debug)); if (debug) { debug->EnableDebugLayer(); debug->Release(); debug = nullptr; } #endif /* _DEBUG */ ID3D12Device* dev; CHK(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev))); mDev = dev; for (auto& a : mCmdAlloc) { CHK(mDev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(a.ReleaseAndGetAddressOf()))); } D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; CHK(mDev->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(mCmdQueue.ReleaseAndGetAddressOf()))); DXGI_SWAP_CHAIN_DESC1 scDesc = {}; scDesc.Width = width; scDesc.Height = height; scDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scDesc.SampleDesc.Count = 1; scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scDesc.BufferCount = BUFFER_COUNT; scDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; CHK(mDxgiFactory->CreateSwapChainForHwnd(mCmdQueue.Get(), hWnd, &scDesc, nullptr, nullptr, mSwapChain.ReleaseAndGetAddressOf())); CHK(mDev->CreateCommandList( 0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCmdAlloc[0].Get(), nullptr, IID_PPV_ARGS(mCmdList.ReleaseAndGetAddressOf()))); mCmdList->Close(); CHK(mDev->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(mFence.ReleaseAndGetAddressOf()))); mFenceEveneHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); for (int i = 0; i < BUFFER_COUNT; i++) { CHK(mSwapChain->GetBuffer(i, IID_PPV_ARGS(mD3DBuffer[i].ReleaseAndGetAddressOf()))); mD3DBuffer[i]->SetName(L"SwapChain_Buffer"); } { D3D12_DESCRIPTOR_HEAP_DESC desc = {}; desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; desc.NumDescriptors = 10; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapRtv.ReleaseAndGetAddressOf()))); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; desc.NumDescriptors = 10; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapDsv.ReleaseAndGetAddressOf()))); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; desc.NumDescriptors = 100; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; desc.NodeMask = 0; for (auto& c : mDescHeapCbvSrvUav) { CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(c.ReleaseAndGetAddressOf()))); } } auto rtvStep = mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); for (auto i = 0u; i < BUFFER_COUNT; i++) { auto d = mDescHeapRtv->GetCPUDescriptorHandleForHeapStart(); d.ptr += i * rtvStep; mDev->CreateRenderTargetView(mD3DBuffer[i].Get(), nullptr, d); } { CD3DX12_DESCRIPTOR_RANGE descRange1[1]; descRange1[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); CD3DX12_ROOT_PARAMETER rootParam[1]; rootParam[0].InitAsDescriptorTable(ARRAYSIZE(descRange1), descRange1); ID3D10Blob *sig, *info; auto rootSigDesc = D3D12_ROOT_SIGNATURE_DESC(); rootSigDesc.NumParameters = 1; rootSigDesc.NumStaticSamplers = 0; rootSigDesc.pParameters = rootParam; rootSigDesc.pStaticSamplers = nullptr; rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; CHK(D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &sig, &info)); mDev->CreateRootSignature( 0, sig->GetBufferPointer(), sig->GetBufferSize(), IID_PPV_ARGS(mRootSignature.ReleaseAndGetAddressOf())); sig->Release(); } ID3D10Blob *vs, *ps; { ID3D10Blob *info; UINT flag = 0; #if _DEBUG flag |= D3DCOMPILE_DEBUG; #endif /* _DEBUG */ CHK(D3DCompileFromFile(L"../Mesh/Mesh.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", flag, 0, &vs, &info)); CHK(D3DCompileFromFile(L"../Mesh/Mesh.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", flag, 0, &ps, &info)); } D3D12_INPUT_ELEMENT_DESC inputLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, }; D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.InputLayout.NumElements = 3; psoDesc.InputLayout.pInputElementDescs = inputLayout; psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; psoDesc.pRootSignature = mRootSignature.Get(); psoDesc.VS.pShaderBytecode = vs->GetBufferPointer(); psoDesc.VS.BytecodeLength = vs->GetBufferSize(); psoDesc.PS.pShaderBytecode = ps->GetBufferPointer(); psoDesc.PS.BytecodeLength = ps->GetBufferSize(); psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3DX12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3DX12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = true; psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; psoDesc.DepthStencilState.StencilEnable = false; psoDesc.SampleMask = UINT_MAX; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; psoDesc.SampleDesc.Count = 1; CHK(mDev->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(mPso.ReleaseAndGetAddressOf()))); vs->Release(); ps->Release(); WaveFrontReader<uint16_t> mesh; CHK(mesh.Load(L"../Mesh/teapot.obj")); mIndexCount = static_cast<UINT>(mesh.indices.size()); mVBIndexOffset = static_cast<UINT>(sizeof(mesh.vertices[0]) * mesh.vertices.size()); UINT IBSize = static_cast<UINT>(sizeof(mesh.indices[0]) * mIndexCount); void* vbData = mesh.vertices.data(); void* ibData = mesh.indices.data(); CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(mVBIndexOffset + IBSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(mVB.ReleaseAndGetAddressOf()))); mVB->SetName(L"VertexBuffer"); char* vbUploadPtr = nullptr; CHK(mVB->Map(0, nullptr, reinterpret_cast<void**>(&vbUploadPtr))); memcpy_s(vbUploadPtr, mVBIndexOffset, vbData, mVBIndexOffset); memcpy_s(vbUploadPtr + mVBIndexOffset, IBSize, ibData, IBSize); mVB->Unmap(0, nullptr); mVBView.BufferLocation = mVB->GetGPUVirtualAddress(); mVBView.StrideInBytes = sizeof(mesh.vertices[0]); mVBView.SizeInBytes = mVBIndexOffset; mIBView.BufferLocation = mVB->GetGPUVirtualAddress() + mVBIndexOffset; mIBView.Format = DXGI_FORMAT_R16_UINT; mIBView.SizeInBytes = IBSize; auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( DXGI_FORMAT_R32_TYPELESS, mBufferWidth, mBufferHeight, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN, 0); D3D12_CLEAR_VALUE dsvClearValue; dsvClearValue.Format = DXGI_FORMAT_D32_FLOAT; dsvClearValue.DepthStencil.Depth = 1.0f; dsvClearValue.DepthStencil.Stencil = 0; CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), // No need to read/write by CPU D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &dsvClearValue, IID_PPV_ARGS(mDB.ReleaseAndGetAddressOf()))); mDB->SetName(L"DepthTexture"); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; dsvDesc.Format = DXGI_FORMAT_D32_FLOAT; dsvDesc.Texture2D.MipSlice = 0; dsvDesc.Flags = D3D12_DSV_FLAG_NONE; mDev->CreateDepthStencilView(mDB.Get(), &dsvDesc, mDescHeapDsv->GetCPUDescriptorHandleForHeapStart()); #define CB_SIZE 256 UINT cbSize = CB_SIZE; assert((cbSize % D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT) == 0); CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(cbSize * MaxFrameLatency), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(mCB.ReleaseAndGetAddressOf()))); mCB->SetName(L"ConstantBuffer"); for (auto i = 0u; i < MaxFrameLatency; ++i) { D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; cbvDesc.BufferLocation = mCB->GetGPUVirtualAddress() + i * cbSize; cbvDesc.SizeInBytes = cbSize; mDev->CreateConstantBufferView( &cbvDesc, mDescHeapCbvSrvUav[i]->GetCPUDescriptorHandleForHeapStart()); } CHK(mCB->Map(0, nullptr, reinterpret_cast<void**>(&mCBUploadPtr))); // Create D3D11 UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; auto featureLevel = D3D_FEATURE_LEVEL_11_0; auto cmdQueue = static_cast<IUnknown*>(mCmdQueue.Get()); #if _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif /* _DEBUG */ CHK(D3D11On12CreateDevice( static_cast<IUnknown*>(mDev), flags, &featureLevel, 1, &cmdQueue, 1, 0, mDev11.ReleaseAndGetAddressOf(), mDevCont11.ReleaseAndGetAddressOf(), nullptr)); CHK(mDev11.As(&mDev11on12)); D3D11_RESOURCE_FLAGS backBuffer11Flags = {}; backBuffer11Flags.BindFlags = D3D11_BIND_RENDER_TARGET; for (int i = 0; i < BUFFER_COUNT; i++) { CHK(mDev11on12->CreateWrappedResource( mD3DBuffer[i].Get(), &backBuffer11Flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET, IID_PPV_ARGS(&mBackBuffer11Tex[i]))); D3D11_TEXTURE2D_DESC texDesc; mBackBuffer11Tex[i]->GetDesc(&texDesc); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; rtvDesc.Format = texDesc.Format; rtvDesc.Texture2D.MipSlice = 0; CHK(mDev11->CreateRenderTargetView( mBackBuffer11Tex[i].Get(), &rtvDesc, mBackBuffer11Rtv[i].ReleaseAndGetAddressOf())); } }
D3D(int width, int height, HWND hWnd) : mBufferWidth(width), mBufferHeight(height), mDev(nullptr) { { #if _DEBUG CHK(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(mDxgiFactory.ReleaseAndGetAddressOf()))); #else CHK(CreateDXGIFactory2(0, IID_PPV_ARGS(mDxgiFactory.ReleaseAndGetAddressOf()))); #endif /* _DEBUG */ } #if _DEBUG ID3D12Debug* debug = nullptr; D3D12GetDebugInterface(IID_PPV_ARGS(&debug)); if (debug) { debug->EnableDebugLayer(); debug->Release(); debug = nullptr; } #endif /* _DEBUG */ ID3D12Device* dev; CHK(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dev))); mDev = dev; CHK(mDev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(mCmdAlloc.ReleaseAndGetAddressOf()))); D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; CHK(mDev->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(mCmdQueue.ReleaseAndGetAddressOf()))); DXGI_SWAP_CHAIN_DESC1 scDesc = {}; scDesc.Width = width; scDesc.Height = height; scDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scDesc.SampleDesc.Count = 1; scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scDesc.BufferCount = BUFFER_COUNT; scDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; CHK(mDxgiFactory->CreateSwapChainForHwnd(mCmdQueue.Get(), hWnd, &scDesc, nullptr, nullptr, mSwapChain.ReleaseAndGetAddressOf())); CHK(mDev->CreateCommandList( 0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCmdAlloc.Get(), nullptr, IID_PPV_ARGS(mCmdList.ReleaseAndGetAddressOf()))); CHK(mDev->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(mFence.ReleaseAndGetAddressOf()))); mFenceEveneHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); for (int i = 0; i < BUFFER_COUNT; i++) { CHK(mSwapChain->GetBuffer(i, IID_PPV_ARGS(mD3DBuffer[i].ReleaseAndGetAddressOf()))); mD3DBuffer[i]->SetName(L"SwapChain_Buffer"); } { D3D12_DESCRIPTOR_HEAP_DESC desc = {}; desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; desc.NumDescriptors = 10; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapRtv.ReleaseAndGetAddressOf()))); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; desc.NumDescriptors = 10; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapDsv.ReleaseAndGetAddressOf()))); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; desc.NumDescriptors = 100; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapCbvSrvUav.ReleaseAndGetAddressOf()))); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; desc.NumDescriptors = 100; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; desc.NodeMask = 0; CHK(mDev->CreateDescriptorHeap(&desc, IID_PPV_ARGS(mDescHeapSampler.ReleaseAndGetAddressOf()))); } auto rtvStep = mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); for (auto i = 0u; i < BUFFER_COUNT; i++) { auto d = mDescHeapRtv->GetCPUDescriptorHandleForHeapStart(); d.ptr += i * rtvStep; mDev->CreateRenderTargetView(mD3DBuffer[i].Get(), nullptr, d); } { CD3DX12_DESCRIPTOR_RANGE descRange1[2]; descRange1[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); descRange1[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); CD3DX12_DESCRIPTOR_RANGE descRange2[1]; descRange2[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0); CD3DX12_ROOT_PARAMETER rootParam[2]; rootParam[0].InitAsDescriptorTable(ARRAYSIZE(descRange1), descRange1); rootParam[1].InitAsDescriptorTable(ARRAYSIZE(descRange2), descRange2, D3D12_SHADER_VISIBILITY_PIXEL); ID3D10Blob *sig, *info; auto rootSigDesc = D3D12_ROOT_SIGNATURE_DESC(); rootSigDesc.NumParameters = ARRAYSIZE(rootParam); rootSigDesc.NumStaticSamplers = 0; rootSigDesc.pParameters = rootParam; rootSigDesc.pStaticSamplers = nullptr; rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; CHK(D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &sig, &info)); mDev->CreateRootSignature( 0, sig->GetBufferPointer(), sig->GetBufferSize(), IID_PPV_ARGS(mRootSignature.ReleaseAndGetAddressOf())); sig->Release(); } ID3D10Blob *vs, *ps; { ID3D10Blob *info; UINT flag = 0; #if _DEBUG flag |= D3DCOMPILE_DEBUG; #endif /* _DEBUG */ CHK(D3DCompileFromFile(L"MeshTex.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", flag, 0, &vs, &info)); CHK(D3DCompileFromFile(L"MeshTex.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", flag, 0, &ps, &info)); } D3D12_INPUT_ELEMENT_DESC inputLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, }; D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.InputLayout.NumElements = 3; psoDesc.InputLayout.pInputElementDescs = inputLayout; psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; psoDesc.pRootSignature = mRootSignature.Get(); psoDesc.VS.pShaderBytecode = vs->GetBufferPointer(); psoDesc.VS.BytecodeLength = vs->GetBufferSize(); psoDesc.PS.pShaderBytecode = ps->GetBufferPointer(); psoDesc.PS.BytecodeLength = ps->GetBufferSize(); psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3DX12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3DX12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = true; psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; psoDesc.DepthStencilState.StencilEnable = false; psoDesc.SampleMask = UINT_MAX; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; psoDesc.SampleDesc.Count = 1; CHK(mDev->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(mPso.ReleaseAndGetAddressOf()))); vs->Release(); ps->Release(); WaveFrontReader<uint16_t> mesh; CHK(mesh.Load(L"teapot_tex2.obj")); mIndexCount = static_cast<UINT>(mesh.indices.size()); mVBIndexOffset = static_cast<UINT>(sizeof(mesh.vertices[0]) * mesh.vertices.size()); UINT IBSize = static_cast<UINT>(sizeof(mesh.indices[0]) * mIndexCount); void* vbData = mesh.vertices.data(); void* ibData = mesh.indices.data(); CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(mVBIndexOffset + IBSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(mVB.ReleaseAndGetAddressOf()))); mVB->SetName(L"VertexBuffer"); char* vbUploadPtr = nullptr; CHK(mVB->Map(0, nullptr, reinterpret_cast<void**>(&vbUploadPtr))); memcpy_s(vbUploadPtr, mVBIndexOffset, vbData, mVBIndexOffset); memcpy_s(vbUploadPtr + mVBIndexOffset, IBSize, ibData, IBSize); mVB->Unmap(0, nullptr); mVBView.BufferLocation = mVB->GetGPUVirtualAddress(); mVBView.StrideInBytes = sizeof(mesh.vertices[0]); mVBView.SizeInBytes = mVBIndexOffset; mIBView.BufferLocation = mVB->GetGPUVirtualAddress() + mVBIndexOffset; mIBView.Format = DXGI_FORMAT_R16_UINT; mIBView.SizeInBytes = IBSize; auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( DXGI_FORMAT_R32_TYPELESS, mBufferWidth, mBufferHeight, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN, 0); D3D12_CLEAR_VALUE dsvClearValue; dsvClearValue.Format = DXGI_FORMAT_D32_FLOAT; dsvClearValue.DepthStencil.Depth = 1.0f; dsvClearValue.DepthStencil.Stencil = 0; CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), // No need to read/write by CPU D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &dsvClearValue, IID_PPV_ARGS(mDB.ReleaseAndGetAddressOf()))); mDB->SetName(L"DepthTexture"); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; dsvDesc.Format = DXGI_FORMAT_D32_FLOAT; dsvDesc.Texture2D.MipSlice = 0; dsvDesc.Flags = D3D12_DSV_FLAG_NONE; mDev->CreateDepthStencilView(mDB.Get(), &dsvDesc, mDescHeapDsv->GetCPUDescriptorHandleForHeapStart()); CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(mCB.ReleaseAndGetAddressOf()))); mCB->SetName(L"ConstantBuffer"); D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; cbvDesc.BufferLocation = mCB->GetGPUVirtualAddress(); cbvDesc.SizeInBytes = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; // must be a multiple of 256 mDev->CreateConstantBufferView( &cbvDesc, mDescHeapCbvSrvUav->GetCPUDescriptorHandleForHeapStart()); CHK(mCB->Map(0, nullptr, reinterpret_cast<void**>(&mCBUploadPtr))); { // Read DDS file vector<char> texData(4 * 256 * 256); ifstream ifs("cat.dds", ios::binary); if (!ifs) throw runtime_error("Texture not found."); ifs.seekg(128, ios::beg); // Skip DDS header ifs.read(texData.data(), texData.size()); resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( DXGI_FORMAT_B8G8R8A8_UNORM, 256, 256, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_NONE, D3D12_TEXTURE_LAYOUT_UNKNOWN, 0); CHK(mDev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(mTex.ReleaseAndGetAddressOf()))); mTex->SetName(L"Texure"); D3D12_BOX box = {}; box.right = 256; box.bottom = 256; box.back = 1; CHK(mTex->WriteToSubresource(0, &box, texData.data(), 4 * 256, 4 * 256 * 256)); } D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Texture2D.MipLevels = 1; srvDesc.Texture2D.MostDetailedMip = 0; // No MIP srvDesc.Texture2D.PlaneSlice = 0; srvDesc.Texture2D.ResourceMinLODClamp = 0.0f; auto cbvSrcUavDescHandle = mDescHeapCbvSrvUav->GetCPUDescriptorHandleForHeapStart(); auto cbvSrvUavDescStep = mDev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); cbvSrcUavDescHandle.ptr += cbvSrvUavDescStep; mDev->CreateShaderResourceView(mTex.Get(), &srvDesc, cbvSrcUavDescHandle); D3D12_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; samplerDesc.MinLOD = -FLT_MAX; samplerDesc.MaxLOD = FLT_MAX; samplerDesc.MipLODBias = 0; samplerDesc.MaxAnisotropy = 0; samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; mDev->CreateSampler(&samplerDesc, mDescHeapSampler->GetCPUDescriptorHandleForHeapStart()); }