static string GetExpandedShaderCode(const wchar* path, GrowableList<wstring>& filePaths) { for(uint64 i = 0; i < filePaths.Count(); ++i) if(filePaths[i] == path) return string(); filePaths.Add(path); string fileContents = ReadFileAsString(path); // Look for includes size_t lineStart = 0; while(true) { size_t lineEnd = fileContents.find('\n', lineStart); size_t lineLength = 0; if(lineEnd == string::npos) lineLength = string::npos; else lineLength = lineEnd - lineStart; string line = fileContents.substr(lineStart, lineLength); if(line.find("#include") == 0) { wstring fullIncludePath; size_t startQuote = line.find('\"'); if(startQuote != -1) { size_t endQuote = line.find('\"', startQuote + 1); string includePath = line.substr(startQuote + 1, endQuote - startQuote - 1); fullIncludePath = AnsiToWString(includePath.c_str()); } else { startQuote = line.find('<'); if(startQuote == -1) throw Exception(L"Malformed include statement: \"" + AnsiToWString(line.c_str()) + L"\" in file " + path); size_t endQuote = line.find('>', startQuote + 1); string includePath = line.substr(startQuote + 1, endQuote - startQuote - 1); fullIncludePath = SampleFrameworkDir() + L"Shaders\\" + AnsiToWString(includePath.c_str()); } if(FileExists(fullIncludePath.c_str()) == false) throw Exception(L"Couldn't find #included file \"" + fullIncludePath + L"\" in file " + path); string includeCode = GetExpandedShaderCode(fullIncludePath.c_str(), filePaths); fileContents.insert(lineEnd + 1, includeCode); lineEnd += includeCode.length(); } if(lineEnd == string::npos) break; lineStart = lineEnd + 1; } return fileContents; }
HRESULT Open(D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes) override { std::wstring filePath; if(IncludeType == D3D_INCLUDE_LOCAL) filePath = AnsiToWString(pFileName); else if(IncludeType == D3D_INCLUDE_SYSTEM) filePath = SampleFrameworkDir() + L"Shaders\\" + AnsiToWString(pFileName); else return E_FAIL; if(FileExists(filePath.c_str()) == false) return E_FAIL; File file(filePath.c_str(), FileOpenMode::Read); *pBytes = UINT(file.Size()); uint8* data = reinterpret_cast<uint8*>(std::malloc(*pBytes)); file.Read(*pBytes, data); *ppData = data; return S_OK; }
void PostProcessHelper::Initialize() { // Load the shaders std::wstring fullScreenTriPath = SampleFrameworkDir() + L"Shaders\\FullScreenTriangle.hlsl"; fullScreenTriVS = CompileFromFile(fullScreenTriPath.c_str(), "FullScreenTriangleVS", ShaderType::Vertex); { D3D12_ROOT_PARAMETER1 rootParameters[NumRootParams] = {}; rootParameters[RootParam_StandardDescriptors].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; rootParameters[RootParam_StandardDescriptors].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; rootParameters[RootParam_StandardDescriptors].DescriptorTable.pDescriptorRanges = DX12::StandardDescriptorRanges(); rootParameters[RootParam_StandardDescriptors].DescriptorTable.NumDescriptorRanges = DX12::NumStandardDescriptorRanges; rootParameters[RootParam_SRVIndices].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; rootParameters[RootParam_SRVIndices].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; rootParameters[RootParam_SRVIndices].Descriptor.RegisterSpace = 0; rootParameters[RootParam_SRVIndices].Descriptor.ShaderRegister = 0; rootParameters[RootParam_AppSettings].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; rootParameters[RootParam_AppSettings].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; rootParameters[RootParam_AppSettings].Descriptor.RegisterSpace = 0; rootParameters[RootParam_AppSettings].Descriptor.ShaderRegister = AppSettings::CBufferRegister; D3D12_STATIC_SAMPLER_DESC staticSamplers[4] = {}; staticSamplers[0] = DX12::GetStaticSamplerState(SamplerState::Point, 0); staticSamplers[1] = DX12::GetStaticSamplerState(SamplerState::LinearClamp, 1); staticSamplers[2] = DX12::GetStaticSamplerState(SamplerState::Linear, 2); staticSamplers[3] = DX12::GetStaticSamplerState(SamplerState::LinearBorder, 3); D3D12_ROOT_SIGNATURE_DESC1 rootSignatureDesc = {}; rootSignatureDesc.NumParameters = ArraySize_(rootParameters); rootSignatureDesc.pParameters = rootParameters; rootSignatureDesc.NumStaticSamplers = ArraySize_(staticSamplers); rootSignatureDesc.pStaticSamplers = staticSamplers; rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; DX12::CreateRootSignature(&rootSignature, rootSignatureDesc); rootSignature->SetName(L"PostProcessHelper"); } }
static void GetTextureData(ID3D11Device* device, ID3D11ShaderResourceView* textureSRV, DXGI_FORMAT outFormat, TextureData<T>& texData) { static ComputeShaderPtr decodeTextureCS; static ComputeShaderPtr decodeTextureArrayCS; static const uint32 TGSize = 16; if(decodeTextureCS.Valid() == false) { CompileOptions opts; opts.Add("TGSize_", TGSize); const std::wstring shaderPath = SampleFrameworkDir() + L"Shaders\\DecodeTextureCS.hlsl"; decodeTextureCS = CompileCSFromFile(device, shaderPath.c_str(), "DecodeTextureCS", "cs_5_0", opts); decodeTextureArrayCS = CompileCSFromFile(device, shaderPath.c_str(), "DecodeTextureArrayCS", "cs_5_0", opts); } ID3D11Texture2DPtr texture; textureSRV->GetResource(reinterpret_cast<ID3D11Resource**>(&texture)); D3D11_TEXTURE2D_DESC texDesc; texture->GetDesc(&texDesc); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; textureSRV->GetDesc(&srvDesc); ID3D11ShaderResourceViewPtr sourceSRV = textureSRV; uint32 arraySize = texDesc.ArraySize; if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBE || srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.ArraySize = arraySize; srvDesc.Texture2DArray.FirstArraySlice = 0; srvDesc.Texture2DArray.MostDetailedMip = 0; srvDesc.Texture2DArray.MipLevels = -1; DXCall(device->CreateShaderResourceView(texture, &srvDesc, &sourceSRV)); } D3D11_TEXTURE2D_DESC decodeTextureDesc; decodeTextureDesc.Width = texDesc.Width; decodeTextureDesc.Height = texDesc.Height; decodeTextureDesc.ArraySize = arraySize; decodeTextureDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; decodeTextureDesc.Format = outFormat; decodeTextureDesc.MipLevels = 1; decodeTextureDesc.MiscFlags = 0; decodeTextureDesc.SampleDesc.Count = 1; decodeTextureDesc.SampleDesc.Quality = 0; decodeTextureDesc.Usage = D3D11_USAGE_DEFAULT; decodeTextureDesc.CPUAccessFlags = 0; ID3D11Texture2DPtr decodeTexture; DXCall(device->CreateTexture2D(&decodeTextureDesc, nullptr, &decodeTexture)); ID3D11UnorderedAccessViewPtr decodeTextureUAV; DXCall(device->CreateUnorderedAccessView(decodeTexture, nullptr, &decodeTextureUAV)); ID3D11DeviceContextPtr context; device->GetImmediateContext(&context); SetCSInputs(context, sourceSRV); SetCSOutputs(context, decodeTextureUAV); SetCSShader(context, arraySize > 1 ? decodeTextureArrayCS : decodeTextureCS); context->Dispatch(DispatchSize(TGSize, texDesc.Width), DispatchSize(TGSize, texDesc.Height), arraySize); ClearCSInputs(context); ClearCSOutputs(context); StagingTexture2D stagingTexture; stagingTexture.Initialize(device, texDesc.Width, texDesc.Height, outFormat, 1, 1, 0, arraySize); context->CopyResource(stagingTexture.Texture, decodeTexture); texData.Init(texDesc.Width, texDesc.Height, arraySize); for(uint32 slice = 0; slice < arraySize; ++slice) { uint32 pitch = 0; const uint8* srcData = reinterpret_cast<const uint8*>(stagingTexture.Map(context, slice, pitch)); Assert_(pitch >= texDesc.Width * sizeof(T)); const uint32 sliceOffset = texDesc.Width * texDesc.Height * slice; for(uint32 y = 0; y < texDesc.Height; ++y) { const T* rowData = reinterpret_cast<const T*>(srcData); for(uint32 x = 0; x < texDesc.Width; ++x) texData.Texels[y * texDesc.Width + x + sliceOffset] = rowData[x]; srcData += pitch; } } }
void PostProcessorBase::Initialize(ID3D11Device* device) { this->device = device; // Create resources for the full-screen quad // Load the shaders std::wstring quadPath = SampleFrameworkDir() + L"Shaders\\Quad.hlsl"; quadVS = CompileVSFromFile(device, quadPath.c_str(), "QuadVS"); // Create the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; DXCall(device->CreateInputLayout(layout, 2, quadVS->ByteCode->GetBufferPointer(), quadVS->ByteCode->GetBufferSize(), &quadInputLayout)); // Create and initialize the vertex and index buffers QuadVertex verts[4] = { { XMFLOAT4(1, 1, 1, 1), XMFLOAT2(1, 0) }, { XMFLOAT4(1, -1, 1, 1), XMFLOAT2(1, 1) }, { XMFLOAT4(-1, -1, 1, 1), XMFLOAT2(0, 1) }, { XMFLOAT4(-1, 1, 1, 1), XMFLOAT2(0, 0) } }; D3D11_BUFFER_DESC desc; desc.Usage = D3D11_USAGE_IMMUTABLE; desc.ByteWidth = sizeof(verts); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = verts; initData.SysMemPitch = 0; initData.SysMemSlicePitch = 0; DXCall(device->CreateBuffer(&desc, &initData, &quadVB)); unsigned short indices[6] = { 0, 1, 2, 2, 3, 0 }; desc.Usage = D3D11_USAGE_IMMUTABLE; desc.ByteWidth = sizeof(indices); desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = 0; initData.pSysMem = indices; DXCall(device->CreateBuffer(&desc, &initData, &quadIB)); // Create the constant buffer desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = CBSize(sizeof(PSConstants)); desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; DXCall(device->CreateBuffer(&desc, nullptr, &psConstants)); // Create a depth-stencil state D3D11_DEPTH_STENCIL_DESC dsDesc; dsDesc.DepthEnable = false; dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; dsDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; dsDesc.StencilEnable = false; dsDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; dsDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; dsDesc.BackFace = dsDesc.FrontFace; DXCall(device->CreateDepthStencilState(&dsDesc, &dsState)); // Create a blend state D3D11_BLEND_DESC blendDesc; blendDesc.AlphaToCoverageEnable = false; blendDesc.IndependentBlendEnable = false; for (uint32 i = 0; i < 8; ++i) { blendDesc.RenderTarget[i].BlendEnable = false; blendDesc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; blendDesc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendDesc.RenderTarget[i].DestBlend = D3D11_BLEND_ONE; blendDesc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ONE; blendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blendDesc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE; blendDesc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE; } DXCall(device->CreateBlendState(&blendDesc, &blendState)); // Create a rasterizer state D3D11_RASTERIZER_DESC rastDesc; rastDesc.AntialiasedLineEnable = false; rastDesc.CullMode = D3D11_CULL_NONE; rastDesc.DepthBias = 0; rastDesc.DepthBiasClamp = 0.0f; rastDesc.DepthClipEnable = true; rastDesc.FillMode = D3D11_FILL_SOLID; rastDesc.FrontCounterClockwise = false; rastDesc.MultisampleEnable = true; rastDesc.ScissorEnable = false; rastDesc.SlopeScaledDepthBias = 0; DXCall(device->CreateRasterizerState(&rastDesc, &rastState)); // Create sampler states D3D11_SAMPLER_DESC sampDesc; sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.BorderColor[0] = 0; sampDesc.BorderColor[1] = 0; sampDesc.BorderColor[2] = 0; sampDesc.BorderColor[3] = 0; sampDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampDesc.MaxAnisotropy = 1; sampDesc.MaxLOD = D3D11_FLOAT32_MAX; sampDesc.MinLOD = 0; sampDesc.MipLODBias = 0; DXCall(device->CreateSamplerState(&sampDesc, &linearSamplerState)); sampDesc.AddressU = sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; DXCall(device->CreateSamplerState(&sampDesc, &linearWrapSamplerState)); sampDesc.AddressU = sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER; DXCall(device->CreateSamplerState(&sampDesc, &linearBorderSamplerState)); sampDesc.AddressU = sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; DXCall(device->CreateSamplerState(&sampDesc, &pointSamplerState)); sampDesc.AddressU = sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER; DXCall(device->CreateSamplerState(&sampDesc, &pointBorderSamplerState)); }
void Initialize_Upload() { for(uint64 i = 0; i < MaxUploadSubmissions; ++i) DXCall(Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(&UploadSubmissions[i].CmdAllocator))); DXCall(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, UploadSubmissions[0].CmdAllocator, nullptr, IID_PPV_ARGS(&UploadCmdList))); DXCall(UploadCmdList->Close()); D3D12_COMMAND_QUEUE_DESC queueDesc = { }; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COPY; DXCall(Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&UploadCmdQueue))); UploadFence.Init(0); D3D12_RESOURCE_DESC resourceDesc = { }; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; resourceDesc.Width = uint32(UploadBufferSize); resourceDesc.Height = 1; resourceDesc.DepthOrArraySize = 1; resourceDesc.MipLevels = 1; resourceDesc.Format = DXGI_FORMAT_UNKNOWN; resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; resourceDesc.SampleDesc.Count = 1; resourceDesc.SampleDesc.Quality = 0; resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; resourceDesc.Alignment = 0; DXCall(Device->CreateCommittedResource(DX12::GetUploadHeapProps(), D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&UploadBuffer))); D3D12_RANGE readRange = { }; DXCall(UploadBuffer->Map(0, &readRange, reinterpret_cast<void**>(&UploadBufferCPUAddr))); // Temporary buffer memory that swaps every frame resourceDesc.Width = uint32(TempBufferSize); for(uint64 i = 0; i < RenderLatency; ++i) { DXCall(Device->CreateCommittedResource(DX12::GetUploadHeapProps(), D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&TempFrameBuffers[i]))); DXCall(TempFrameBuffers[i]->Map(0, &readRange, reinterpret_cast<void**>(&TempFrameCPUMem[i]))); TempFrameGPUMem[i] = TempFrameBuffers[i]->GetGPUVirtualAddress(); } // Texture conversion resources DXCall(Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE, IID_PPV_ARGS(&convertCmdAllocator))); DXCall(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COMPUTE, convertCmdAllocator, nullptr, IID_PPV_ARGS(&convertCmdList))); DXCall(convertCmdList->Close()); DXCall(convertCmdList->Reset(convertCmdAllocator, nullptr)); D3D12_COMMAND_QUEUE_DESC convertQueueDesc = {}; convertQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; convertQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; DXCall(Device->CreateCommandQueue(&convertQueueDesc, IID_PPV_ARGS(&convertCmdQueue))); CompileOptions opts; opts.Add("TGSize_", convertTGSize); const std::wstring shaderPath = SampleFrameworkDir() + L"Shaders\\DecodeTextureCS.hlsl"; convertCS = CompileFromFile(shaderPath.c_str(), "DecodeTextureCS", ShaderType::Compute, ShaderProfile::SM51, opts); convertArrayCS = CompileFromFile(shaderPath.c_str(), "DecodeTextureArrayCS", ShaderType::Compute, ShaderProfile::SM51, opts); { D3D12_DESCRIPTOR_RANGE ranges[2] = {}; ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; ranges[0].NumDescriptors = 1; ranges[0].BaseShaderRegister = 0; ranges[0].RegisterSpace = 0; ranges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; ranges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; ranges[1].NumDescriptors = 1; ranges[1].BaseShaderRegister = 0; ranges[1].RegisterSpace = 0; ranges[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; D3D12_ROOT_PARAMETER rootParameters[1] = {}; rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; rootParameters[0].DescriptorTable.pDescriptorRanges = ranges; rootParameters[0].DescriptorTable.NumDescriptorRanges = ArraySize_(ranges); D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; rootSignatureDesc.NumParameters = ArraySize_(rootParameters); rootSignatureDesc.pParameters = rootParameters; rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; DX12::CreateRootSignature(&convertRootSignature, rootSignatureDesc); } { D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = { }; psoDesc.CS = convertCS.ByteCode(); psoDesc.pRootSignature = convertRootSignature; psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; Device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&convertPSO)); psoDesc.CS = convertArrayCS.ByteCode(); Device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&convertArrayPSO)); } convertFence.Init(0); // Readback resources DXCall(Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(&readbackCmdAllocator))); DXCall(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, readbackCmdAllocator, nullptr, IID_PPV_ARGS(&readbackCmdList))); DXCall(readbackCmdList->Close()); DXCall(readbackCmdList->Reset(readbackCmdAllocator, nullptr)); readbackFence.Init(0); }