void TexWaves::BuildRootSignature() { CD3DX12_DESCRIPTOR_RANGE texTable; texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); CD3DX12_ROOT_PARAMETER slotRootParameter[4]; slotRootParameter[0].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_PIXEL); slotRootParameter[1].InitAsConstantBufferView(0); slotRootParameter[2].InitAsConstantBufferView(1); slotRootParameter[3].InitAsConstantBufferView(2); auto staticSamplers = FrameResource::GetStaticSamplers(); CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter, (UINT)staticSamplers.size(), staticSamplers.data(), D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ComPtr<ID3DBlob> serializedRootSig = nullptr; ComPtr<ID3DBlob> errorBlob = nullptr; HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf()); if (errorBlob != nullptr) OutputDebugStringA((char*)errorBlob->GetBufferPointer()); ThrowIfFailed(hr); ThrowIfFailed(_device->CreateRootSignature(0, serializedRootSig->GetBufferPointer(), serializedRootSig->GetBufferSize(), IID_PPV_ARGS(_rootSignature.GetAddressOf()))); }
void Box::BuildRootSignature() { CD3DX12_ROOT_PARAMETER slotRootParameter[1]; CD3DX12_DESCRIPTOR_RANGE cbvTable; cbvTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); slotRootParameter[0].InitAsDescriptorTable(1, &cbvTable); CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(1, slotRootParameter, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ComPtr<ID3DBlob> serializedRootSig = nullptr; ComPtr<ID3DBlob> errorBlob = nullptr; HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf()); if (errorBlob != nullptr) OutputDebugStringA((char*)errorBlob->GetBufferPointer()); ThrowIfFailed(hr); ThrowIfFailed(_device->CreateRootSignature(0, serializedRootSig->GetBufferPointer(), serializedRootSig->GetBufferSize(), IID_PPV_ARGS(&_rootSignature))); }
void WavesCSApp::BuildRootSignature() { CD3DX12_DESCRIPTOR_RANGE texTable; texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); CD3DX12_DESCRIPTOR_RANGE displacementMapTable; displacementMapTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1); // Root parameter can be a table, root descriptor or root constants. CD3DX12_ROOT_PARAMETER slotRootParameter[5]; // Perfomance TIP: Order from most frequent to least frequent. slotRootParameter[0].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_ALL); slotRootParameter[1].InitAsConstantBufferView(0); slotRootParameter[2].InitAsConstantBufferView(1); slotRootParameter[3].InitAsConstantBufferView(2); slotRootParameter[4].InitAsDescriptorTable(1, &displacementMapTable, D3D12_SHADER_VISIBILITY_ALL); auto staticSamplers = GetStaticSamplers(); // A root signature is an array of root parameters. CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(5, slotRootParameter, (UINT)staticSamplers.size(), staticSamplers.data(), D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer ComPtr<ID3DBlob> serializedRootSig = nullptr; ComPtr<ID3DBlob> errorBlob = nullptr; HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf()); if(errorBlob != nullptr) { ::OutputDebugStringA((char*)errorBlob->GetBufferPointer()); } ThrowIfFailed(hr); ThrowIfFailed(md3dDevice->CreateRootSignature( 0, serializedRootSig->GetBufferPointer(), serializedRootSig->GetBufferSize(), IID_PPV_ARGS(mRootSignature.GetAddressOf()))); }
void ShapeBuilder::BuildRootSignature() { // Shader programs typically require resources as input (constant buffers, // textures, samplers). The root signature defines the resources the shader // programs expect. If we think of the shader programs as a function, and // the input resources as function parameters, then the root signature can be // thought of as defining the function signature. // Root parameter can be a table, root descriptor or root constants. CD3DX12_ROOT_PARAMETER slotRootParameter[1]; // Create a single descriptor table of CBVs. CD3DX12_DESCRIPTOR_RANGE cbvTable; cbvTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); slotRootParameter[0].InitAsDescriptorTable(1, &cbvTable); // A root signature is an array of root parameters. CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(1, slotRootParameter, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer ComPtr<ID3DBlob> serializedRootSig = nullptr; ComPtr<ID3DBlob> errorBlob = nullptr; HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf()); if(errorBlob != nullptr) { ::OutputDebugStringA((char*)errorBlob->GetBufferPointer()); } ThrowIfFailed(hr); ThrowIfFailed(md3dDevice->CreateRootSignature( 0, serializedRootSig->GetBufferPointer(), serializedRootSig->GetBufferSize(), IID_PPV_ARGS(&mRootSignature))); }
void Sample3DSceneRenderer::CreateDeviceDependentResources() { auto d3dDevice = m_deviceResources->GetD3DDevice(); // Create a root signature with a single constant buffer slot. { CD3DX12_DESCRIPTOR_RANGE range; CD3DX12_ROOT_PARAMETER parameter; range.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); parameter.InitAsDescriptorTable(1, &range, D3D12_SHADER_VISIBILITY_VERTEX); D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer. D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS; CD3DX12_ROOT_SIGNATURE_DESC descRootSignature; descRootSignature.Init(1, ¶meter, 0, nullptr, rootSignatureFlags); ComPtr<ID3DBlob> pSignature; ComPtr<ID3DBlob> pError; DX::ThrowIfFailed(D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf())); DX::ThrowIfFailed(d3dDevice->CreateRootSignature(0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature))); NAME_D3D12_OBJECT(m_rootSignature); } // Load shaders asynchronously. auto createVSTask = DX::ReadDataAsync(L"SampleVertexShader.cso").then([this](std::vector<byte>& fileData) { m_vertexShader = fileData; }); auto createPSTask = DX::ReadDataAsync(L"SamplePixelShader.cso").then([this](std::vector<byte>& fileData) { m_pixelShader = fileData; }); // Create the pipeline state once the shaders are loaded. auto createPipelineStateTask = (createPSTask && createVSTask).then([this]() { static const D3D12_INPUT_ELEMENT_DESC inputLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, }; D3D12_GRAPHICS_PIPELINE_STATE_DESC state = {}; state.InputLayout = { inputLayout, _countof(inputLayout) }; state.pRootSignature = m_rootSignature.Get(); state.VS = CD3DX12_SHADER_BYTECODE(&m_vertexShader[0], m_vertexShader.size()); state.PS = CD3DX12_SHADER_BYTECODE(&m_pixelShader[0], m_pixelShader.size()); state.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); state.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); state.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); state.SampleMask = UINT_MAX; state.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; state.NumRenderTargets = 1; state.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); state.DSVFormat = m_deviceResources->GetDepthBufferFormat(); state.SampleDesc.Count = 1; DX::ThrowIfFailed(m_deviceResources->GetD3DDevice()->CreateGraphicsPipelineState(&state, IID_PPV_ARGS(&m_pipelineState))); // Shader data can be deleted once the pipeline state is created. m_vertexShader.clear(); m_pixelShader.clear(); }); // Create and upload cube geometry resources to the GPU. auto createAssetsTask = createPipelineStateTask.then([this]() { auto d3dDevice = m_deviceResources->GetD3DDevice(); // Create a command list. DX::ThrowIfFailed(d3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_deviceResources->GetCommandAllocator(), m_pipelineState.Get(), IID_PPV_ARGS(&m_commandList))); NAME_D3D12_OBJECT(m_commandList); // Cube vertices. Each vertex has a position and a color. VertexPositionColor cubeVertices[] = { { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f) }, { XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, { XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, { XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f) }, { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, { XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f) }, { XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f) }, { XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f) }, }; const UINT vertexBufferSize = sizeof(cubeVertices); // Create the vertex buffer resource in the GPU's default heap and copy vertex data into it using the upload heap. // The upload resource must not be released until after the GPU has finished using it. Microsoft::WRL::ComPtr<ID3D12Resource> vertexBufferUpload; CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT); CD3DX12_RESOURCE_DESC vertexBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize); DX::ThrowIfFailed(d3dDevice->CreateCommittedResource( &defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &vertexBufferDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_vertexBuffer))); CD3DX12_HEAP_PROPERTIES uploadHeapProperties(D3D12_HEAP_TYPE_UPLOAD); DX::ThrowIfFailed(d3dDevice->CreateCommittedResource( &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &vertexBufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&vertexBufferUpload))); NAME_D3D12_OBJECT(m_vertexBuffer); // Upload the vertex buffer to the GPU. { D3D12_SUBRESOURCE_DATA vertexData = {}; vertexData.pData = reinterpret_cast<BYTE*>(cubeVertices); vertexData.RowPitch = vertexBufferSize; vertexData.SlicePitch = vertexData.RowPitch; UpdateSubresources(m_commandList.Get(), m_vertexBuffer.Get(), vertexBufferUpload.Get(), 0, 0, 1, &vertexData); CD3DX12_RESOURCE_BARRIER vertexBufferResourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); m_commandList->ResourceBarrier(1, &vertexBufferResourceBarrier); } // Load mesh indices. Each trio of indices represents a triangle to be rendered on the screen. // For example: 0,2,1 means that the vertices with indexes 0, 2 and 1 from the vertex buffer compose the // first triangle of this mesh. unsigned short cubeIndices[] = { 0, 2, 1, // -x 1, 2, 3, 4, 5, 6, // +x 5, 7, 6, 0, 1, 5, // -y 0, 5, 4, 2, 6, 7, // +y 2, 7, 3, 0, 4, 6, // -z 0, 6, 2, 1, 3, 7, // +z 1, 7, 5, }; const UINT indexBufferSize = sizeof(cubeIndices); // Create the index buffer resource in the GPU's default heap and copy index data into it using the upload heap. // The upload resource must not be released until after the GPU has finished using it. Microsoft::WRL::ComPtr<ID3D12Resource> indexBufferUpload; CD3DX12_RESOURCE_DESC indexBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize); DX::ThrowIfFailed(d3dDevice->CreateCommittedResource( &defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &indexBufferDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_indexBuffer))); DX::ThrowIfFailed(d3dDevice->CreateCommittedResource( &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &indexBufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&indexBufferUpload))); NAME_D3D12_OBJECT(m_indexBuffer); // Upload the index buffer to the GPU. { D3D12_SUBRESOURCE_DATA indexData = {}; indexData.pData = reinterpret_cast<BYTE*>(cubeIndices); indexData.RowPitch = indexBufferSize; indexData.SlicePitch = indexData.RowPitch; UpdateSubresources(m_commandList.Get(), m_indexBuffer.Get(), indexBufferUpload.Get(), 0, 0, 1, &indexData); CD3DX12_RESOURCE_BARRIER indexBufferResourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER); m_commandList->ResourceBarrier(1, &indexBufferResourceBarrier); } // Create a descriptor heap for the constant buffers. { D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; heapDesc.NumDescriptors = DX::c_frameCount; heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; // This flag indicates that this descriptor heap can be bound to the pipeline and that descriptors contained in it can be referenced by a root table. heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; DX::ThrowIfFailed(d3dDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&m_cbvHeap))); NAME_D3D12_OBJECT(m_cbvHeap); } CD3DX12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(DX::c_frameCount * c_alignedConstantBufferSize); DX::ThrowIfFailed(d3dDevice->CreateCommittedResource( &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &constantBufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&m_constantBuffer))); NAME_D3D12_OBJECT(m_constantBuffer); // Create constant buffer views to access the upload buffer. D3D12_GPU_VIRTUAL_ADDRESS cbvGpuAddress = m_constantBuffer->GetGPUVirtualAddress(); CD3DX12_CPU_DESCRIPTOR_HANDLE cbvCpuHandle(m_cbvHeap->GetCPUDescriptorHandleForHeapStart()); m_cbvDescriptorSize = d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); for (int n = 0; n < DX::c_frameCount; n++) { D3D12_CONSTANT_BUFFER_VIEW_DESC desc; desc.BufferLocation = cbvGpuAddress; desc.SizeInBytes = c_alignedConstantBufferSize; d3dDevice->CreateConstantBufferView(&desc, cbvCpuHandle); cbvGpuAddress += desc.SizeInBytes; cbvCpuHandle.Offset(m_cbvDescriptorSize); } // Map the constant buffers. CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. DX::ThrowIfFailed(m_constantBuffer->Map(0, &readRange, reinterpret_cast<void**>(&m_mappedConstantBuffer))); ZeroMemory(m_mappedConstantBuffer, DX::c_frameCount * c_alignedConstantBufferSize); // We don't unmap this until the app closes. Keeping things mapped for the lifetime of the resource is okay. // Close the command list and execute it to begin the vertex/index buffer copy into the GPU's default heap. DX::ThrowIfFailed(m_commandList->Close()); ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() }; m_deviceResources->GetCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // Create vertex/index buffer views. m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(VertexPositionColor); m_vertexBufferView.SizeInBytes = sizeof(cubeVertices); m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress(); m_indexBufferView.SizeInBytes = sizeof(cubeIndices); m_indexBufferView.Format = DXGI_FORMAT_R16_UINT; // Wait for the command list to finish executing; the vertex/index buffers need to be uploaded to the GPU before the upload resources go out of scope. m_deviceResources->WaitForGpu(); }); createAssetsTask.then([this]() { m_loadingComplete = true; }); }
void SampleRenderer::Initialize() { m_RenderQueue = new ::Dispatch::WorkQueue("RenderQueue", ::Concurrency::ThreadPriority::High); m_RenderQueue->Loop(); isInitialized = false; float aspectRatio = 1900.f/700; float fovAngleY = 70.0f * XM_PI / 180.0f; if (aspectRatio < 1.0f) { fovAngleY *= 2.0f; } XMMATRIX perspectiveMatrix = XMMatrixPerspectiveFovRH(fovAngleY, aspectRatio, 0.01f, 100.0f); XMStoreFloat4x4(&m_MVP.projection, XMMatrixTranspose(perspectiveMatrix)); static const XMVECTORF32 eye = { 0.0f, 0.7f, 1.5f, 0.0f }; static const XMVECTORF32 at = { 0.0f, -0.1f, 0.0f, 0.0f }; static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0f }; XMStoreFloat4x4(&m_MVP.model, XMMatrixTranspose(XMMatrixRotationY(1.57))); XMStoreFloat4x4(&m_MVP.view, XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up))); auto d3dDevice = gD3DDevice->GetD3DDevice(); CD3DX12_ROOT_PARAMETER parameter[3]; CD3DX12_DESCRIPTOR_RANGE range; range.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); parameter[0].InitAsDescriptorTable(1, &range, D3D12_SHADER_VISIBILITY_VERTEX); CD3DX12_DESCRIPTOR_RANGE range2; range2.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); parameter[1].InitAsDescriptorTable(1, &range2, D3D12_SHADER_VISIBILITY_PIXEL); CD3DX12_DESCRIPTOR_RANGE range3; range3.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0); parameter[2].InitAsDescriptorTable(1, &range3, D3D12_SHADER_VISIBILITY_PIXEL); D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS; CD3DX12_ROOT_SIGNATURE_DESC descRootSignature; descRootSignature.Init(3, parameter, 0, nullptr, rootSignatureFlags); PtrBlob pSignature, pError; ThrowIfFailed(D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetInitReference(), pError.GetInitReference())); ThrowIfFailed(d3dDevice->CreateRootSignature(0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), IID_PPV_ARGS(m_RootSignature.GetInitReference()))); m_CopyQueue = new CopyQueue_tr(d3dDevice); m_CopyQueue->StartLoop(); m_RenderQueue->Queue(::Dispatch::Bind([this, d3dDevice]() { m_VS.Load("/Data/Test/Test.vso"); m_PS.Load("/Data/Test/Test.pso"); static const D3D12_INPUT_ELEMENT_DESC inputLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, }; D3D12_GRAPHICS_PIPELINE_STATE_DESC state = {}; state.InputLayout = { inputLayout, _countof(inputLayout) }; state.pRootSignature = m_RootSignature; state.VS = { m_VS.GetBlob()->GetBufferPointer(), m_VS.GetBlob()->GetBufferSize() }; state.PS = { m_PS.GetBlob()->GetBufferPointer(), m_PS.GetBlob()->GetBufferSize() }; state.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); state.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); state.DepthStencilState.DepthEnable = FALSE; state.DepthStencilState.StencilEnable = FALSE; state.SampleMask = UINT_MAX; state.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; state.NumRenderTargets = 1; state.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; state.SampleDesc.Count = 1; ThrowIfFailed(d3dDevice->CreateGraphicsPipelineState(&state, IID_PPV_ARGS(m_PipeLineState.GetInitReference()))); LogUtil::Out("Renderer", ::Concurrency::Thread::GetCurrentThreadName()); })); m_RenderQueue->Queue(::Dispatch::Bind([this, d3dDevice]() { ThrowIfFailed(d3dDevice->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, gD3DDevice->GetCommandAllocator(), m_PipeLineState, IID_PPV_ARGS(m_CmdList.GetInitReference()))); D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; heapDesc.NumDescriptors = DeviceManager::GetFrameCount(); heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(d3dDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(m_CBVHeap.GetInitReference()))); m_CBVHeap->SetName(L"Constant Buffer Heap"); m_samplerHeap.Create(d3dDevice, D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 1, true); D3D12_SAMPLER_DESC samplerDesc = {}; samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 1; samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; d3dDevice->CreateSampler(&samplerDesc, m_samplerHeap.hCPU(0)); m_CubeMesh = new CubeMesh(d3dDevice, m_CmdList); this->m_CopyQueue->SubmitTexture(L"\\Data\\Test\\seafloor2bc1.dds", m_CubeMesh); m_CBO = new UniformBuffer<ModelViewProjectionConstantBuffer>("ModeViewMatrix", d3dDevice, 1U); m_CBO->CreateOnHeap(m_CBVHeap, d3dDevice); m_ConstantBuffer = m_CBO->Map(); ZeroMemory(m_ConstantBuffer, DeviceManager::GetFrameCount() * m_CBO->sAlignedConstantBufferSize); ThrowIfFailed(m_CmdList->Close()); ID3D12CommandList* ppCommandLists[] = { m_CmdList }; gD3DDevice->GetCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); gD3DDevice->WaitForGPU(); isInitialized = true; })); }
// These are the resources that depend on the device. void Game::CreateDeviceDependentResources() { auto device = m_deviceResources->GetD3DDevice(); m_strideSRV = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); // Create descriptor heaps. { // Describe and create a shader resource view (SRV) heap for the texture. D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; srvHeapDesc.NumDescriptors = 2; srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; DX::ThrowIfFailed( device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(m_srvHeap.ReleaseAndGetAddressOf()))); } // Create a root signature with one sampler and one texture { CD3DX12_DESCRIPTOR_RANGE descRange = {}; descRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); CD3DX12_ROOT_PARAMETER rp = {}; rp.InitAsDescriptorTable(1, &descRange, D3D12_SHADER_VISIBILITY_PIXEL); // Use a static sampler that matches the defaults // https://msdn.microsoft.com/en-us/library/windows/desktop/dn913202(v=vs.85).aspx#static_sampler D3D12_STATIC_SAMPLER_DESC samplerDesc = {}; samplerDesc.Filter = D3D12_FILTER_ANISOTROPIC; samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; samplerDesc.MaxAnisotropy = 16; samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; rootSignatureDesc.Init(1, &rp, 1, &samplerDesc, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS); ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> error; HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error); if (FAILED(hr)) { if (error) { OutputDebugStringA(reinterpret_cast<const char*>(error->GetBufferPointer())); } throw DX::com_exception(hr); } DX::ThrowIfFailed( device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(m_rootSignature.ReleaseAndGetAddressOf()))); } // Create the pipeline state, which includes loading shaders. auto vertexShaderBlob = DX::ReadData(L"VertexShader.cso"); auto pixelShaderBlob = DX::ReadData(L"PixelShader.cso"); static const D3D12_INPUT_ELEMENT_DESC s_inputElementDesc[2] = { { "SV_Position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, }; // Describe and create the graphics pipeline state object (PSO). D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { s_inputElementDesc, _countof(s_inputElementDesc) }; psoDesc.pRootSignature = m_rootSignature.Get(); psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShaderBlob.data(), vertexShaderBlob.size()); psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShaderBlob.data(), pixelShaderBlob.size()); psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.StencilEnable = FALSE; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = m_deviceResources->GetBackBufferFormat(); psoDesc.SampleDesc.Count = 1; DX::ThrowIfFailed( device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(m_pipelineState.ReleaseAndGetAddressOf()))); // Create vertex buffer. { static const Vertex s_vertexData[] = { { { -1.0f, -0.5f, 0.5f, 1.0f },{ 0.f, 1.f } }, { { 0.0f, -0.5f, 0.5f, 1.0f },{ 1.f, 1.f } }, { { 0.0f, 0.5f, 0.5f, 1.0f },{ 1.f, 0.f } }, { { -1.0f, 0.5f, 0.5f, 1.0f },{ 0.f, 0.f } }, { { 0.f, -0.5f, 0.5f, 1.0f },{ 0.f, 1.f } }, { { 1.0f, -0.5f, 0.5f, 1.0f },{ 1.f, 1.f } }, { { 1.0f, 0.5f, 0.5f, 1.0f },{ 1.f, 0.f } }, { { 0.f, 0.5f, 0.5f, 1.0f },{ 0.f, 0.f } }, }; // Note: using upload heaps to transfer static data like vert buffers is not // recommended. Every time the GPU needs it, the upload heap will be marshalled // over. Please read up on Default Heap usage. An upload heap is used here for // code simplicity and because there are very few verts to actually transfer. DX::ThrowIfFailed( device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(sizeof(s_vertexData)), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(m_vertexBuffer.ReleaseAndGetAddressOf()))); // Copy the quad data to the vertex buffer. UINT8* pVertexDataBegin; CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. DX::ThrowIfFailed( m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin))); memcpy(pVertexDataBegin, s_vertexData, sizeof(s_vertexData)); m_vertexBuffer->Unmap(0, nullptr); // Initialize the vertex buffer view. m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(Vertex); m_vertexBufferView.SizeInBytes = sizeof(s_vertexData); } // Create index buffer. { static const uint16_t s_indexData[6] = { 3,1,0, 2,1,3, }; // See note above DX::ThrowIfFailed( device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(sizeof(s_indexData)), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(m_indexBuffer.ReleaseAndGetAddressOf()))); // Copy the data to the index buffer. UINT8* pVertexDataBegin; CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. DX::ThrowIfFailed( m_indexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin))); memcpy(pVertexDataBegin, s_indexData, sizeof(s_indexData)); m_indexBuffer->Unmap(0, nullptr); // Initialize the index buffer view. m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress(); m_indexBufferView.Format = DXGI_FORMAT_R16_UINT; m_indexBufferView.SizeInBytes = sizeof(s_indexData); } { auto commandList = m_deviceResources->GetCommandList(); commandList->Reset(m_deviceResources->GetCommandAllocator(), nullptr); // Test DDSTextureLoader ComPtr<ID3D12Resource> ddsUploadHeap; CD3DX12_CPU_DESCRIPTOR_HANDLE cpuHandle(m_srvHeap->GetCPUDescriptorHandleForHeapStart()); { std::unique_ptr<uint8_t[]> ddsData; std::vector<D3D12_SUBRESOURCE_DATA> subresources; DX::ThrowIfFailed(LoadDDSTextureFromFile(device, L"dx5_logo.dds", m_dx5logo.ReleaseAndGetAddressOf(), ddsData, subresources)); const UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_dx5logo.Get(), 0, static_cast<UINT>(subresources.size())); // Create the GPU upload buffer. DX::ThrowIfFailed( device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(ddsUploadHeap.GetAddressOf()))); UpdateSubresources(commandList, m_dx5logo.Get(), ddsUploadHeap.Get(), 0, 0, static_cast<UINT>(subresources.size()), subresources.data()); commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_dx5logo.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); auto desc = m_dx5logo->GetDesc(); D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Format = desc.Format; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = desc.MipLevels; device->CreateShaderResourceView(m_dx5logo.Get(), &srvDesc, cpuHandle.Offset(0, m_strideSRV)); } // Test WICTextureLoader ComPtr<ID3D12Resource> wicUploadHeap; { std::unique_ptr<uint8_t[]> decodedData; D3D12_SUBRESOURCE_DATA subresource; DX::ThrowIfFailed(LoadWICTextureFromFile(device, L"cup_small.jpg", m_cup.ReleaseAndGetAddressOf(), decodedData, subresource)); const UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_cup.Get(), 0, 1); // Create the GPU upload buffer. DX::ThrowIfFailed( device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(wicUploadHeap.GetAddressOf()))); UpdateSubresources(commandList, m_cup.Get(), wicUploadHeap.Get(), 0, 0, 1, &subresource); commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_cup.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); auto desc = m_cup->GetDesc(); D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Format = desc.Format; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = desc.MipLevels; device->CreateShaderResourceView(m_cup.Get(), &srvDesc, cpuHandle.Offset(1, m_strideSRV)); } DX::ThrowIfFailed(commandList->Close()); m_deviceResources->GetCommandQueue()->ExecuteCommandLists(1, CommandListCast(&commandList)); // Wait until assets have been uploaded to the GPU. m_deviceResources->WaitForGpu(); } }