Unverified Commit 6c0205ce authored by Yuting Jiang's avatar Yuting Jiang Committed by GitHub
Browse files

Benchmarks: micro benchmarks - add source code for DirectXRenderPerf (#549)



**Description**
add source code for DirectXRenderPerf.

---------
Co-authored-by: default avataryukirora <yuting.jiang@microsoft.com>
parent 67f2aa72
...@@ -65,7 +65,7 @@ jobs: ...@@ -65,7 +65,7 @@ jobs:
sudo docker rmi $(sudo docker images --format "{{.Repository}}:{{.Tag}}" --filter=reference="node" --filter=reference="buildpack-deps") sudo docker rmi $(sudo docker images --format "{{.Repository}}:{{.Tag}}" --filter=reference="node" --filter=reference="buildpack-deps")
df -h df -h
- name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧 - name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧
uses: jlumbroso/free-disk-space@main uses: hirnidrin/free-disk-space@main
with: with:
# This might remove tools that are actually needed, if set to "true" but frees about 6 GB # This might remove tools that are actually needed, if set to "true" but frees about 6 GB
tool-cache: false tool-cache: false
......
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <algorithm>
#include <codecvt>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "../directx_utils/Options.h"
using namespace std;
// enum class for pass type
enum class PassType { GeometryPass, ShadowMapPass, LightingPass };
class BenchmarkOptions : public Options {
public:
int m_textureSize = 0;
int m_textureNum = 10;
int m_vertexNum = 3000;
int m_indexNum = 3000;
int m_width = 1080;
int m_height = 720;
int m_warmup = 500;
int m_num_object = 1;
string m_outfile = "outfile.txt";
PassType m_pass_type = PassType::ShadowMapPass;
int m_num_frames = 3000;
int m_num_light = 1;
bool m_quiet = true;
BenchmarkOptions(int argc, char *argv[]) : Options(argc, argv) {}
virtual void get_option_usage() {
cout << "Usage: " << endl;
cout << " --width <int> set the width of the window" << endl;
cout << " --height <int> set the height of the window" << endl;
cout << " --warmup <int> set the warmup frames" << endl;
cout << " --vertex <int> set the number of vertices" << endl;
cout << " --index <int> set the number of indices" << endl;
cout << " --texture_size <int> set the size of textures <x,x>" << endl;
cout << " --outfile <string> set the output file name" << endl;
cout << " --pass <string> set the pass type" << endl;
cout << " --object <int> set the number of objects" << endl;
cout << " --frame <int> set the number of frames" << endl;
cout << " --light <int> set the number of lights" << endl;
cout << " --quiet disable window" << endl;
}
virtual void parse_arguments() {
m_width = get_cmd_line_argument_int("--width", 1080);
m_height = get_cmd_line_argument_int("--height", 720);
m_warmup = get_cmd_line_argument_int("--warmup", 500);
m_vertexNum = get_cmd_line_argument_int("--vertex", m_vertexNum);
m_indexNum = get_cmd_line_argument_int("--index", m_indexNum);
m_textureSize = get_cmd_line_argument_int("--texture", 3);
m_textureNum = get_cmd_line_argument_int("--texture_num", 3);
m_outfile = get_cmd_line_argument_string("--outfile");
auto pass = get_cmd_line_argument_string("--pass");
std::transform(pass.begin(), pass.end(), pass.begin(), [](unsigned char c) { return std::tolower(c); });
if (pass == "geometry") {
m_pass_type = PassType::GeometryPass;
} else if (pass == "shadow") {
m_pass_type = PassType::ShadowMapPass;
} else if (pass == "lighting") {
m_pass_type = PassType::LightingPass;
} else {
cout << "Error: Invalid pass type: " << pass << endl;
exit(1);
}
m_num_object = get_cmd_line_argument_int("--object", m_num_object);
m_num_frames = get_cmd_line_argument_int("--frame", m_num_frames);
m_num_light = get_cmd_line_argument_int("--light", m_num_light);
m_quiet = get_cmd_line_argument_bool("--quiet");
};
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "BufferHelper.h"
// Function to calculate the byte size of the constant buffer,
// which must be a multiple of 256 bytes.
UINT CalcConstantBufferByteSize(UINT byteSize) {
// Calculate the aligned size.
return (byteSize + 255) & ~255;
}
/*
* @brief: Create a default buffer.
* @param: device the device of GPU object.
* @param: cmdList the command list of GPU object.
* @param: initData the data to be copied to the default buffer.
* @param: byteSize the size of data.
* @return: the default buffer.
*/
Microsoft::WRL::ComPtr<ID3D12Resource> CreateDefaultBuffer(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList,
const void *initData, UINT64 byteSize,
Microsoft::WRL::ComPtr<ID3D12Resource> &uploadBuffer) {
ComPtr<ID3D12Resource> defaultBuffer;
// Create the actual default buffer resource.
ThrowIfFailed(device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(byteSize),
D3D12_RESOURCE_STATE_COMMON, nullptr,
IID_PPV_ARGS(defaultBuffer.GetAddressOf())));
// In order to copy CPU memory data into our default buffer, we need to create
// an intermediate upload heap.
ThrowIfFailed(device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(byteSize),
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
IID_PPV_ARGS(uploadBuffer.GetAddressOf())));
// Describe the data we want to copy into the default buffer.
D3D12_SUBRESOURCE_DATA subResourceData = {};
subResourceData.pData = initData;
subResourceData.RowPitch = byteSize;
subResourceData.SlicePitch = subResourceData.RowPitch;
// Schedule to copy the data to the default buffer resource. At a high level, the helper function
// UpdateSubresources will copy the CPU memory into the intermediate upload heap. Then, using
// ID3D12CommandList::CopySubresourceRegion, the intermediate upload heap data will be copied to mBuffer.
cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(defaultBuffer.Get(), D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_COPY_DEST));
UpdateSubresources<1>(cmdList, defaultBuffer.Get(), uploadBuffer.Get(), 0, 0, 1, &subResourceData);
cmdList->ResourceBarrier(1,
&CD3DX12_RESOURCE_BARRIER::Transition(defaultBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_GENERIC_READ));
// Note: uploadBuffer has to be kept alive after the above function calls because
// the command list has not been executed yet that performs the actual copy.
// The caller can Release the uploadBuffer after it knows the copy has been executed.
return defaultBuffer;
}
std::vector<UINT8> CreateRandomTexture(const UINT width, const UINT height, const UINT texturePixelSize) {
// Create a buffer to store the texture data
std::vector<unsigned char> textureData(width * height * texturePixelSize);
// Initialize the random number generator
std::random_device rd;
std::mt19937 generator(rd());
std::uniform_int_distribution<int> distribution(0, 255);
// Generate random data for the texture
for (UINT i = 0; i < width * height * texturePixelSize; ++i) {
textureData[i] = static_cast<unsigned char>(distribution(generator));
}
return textureData;
}
void UploadTexture(ID3D12Device *device, ID3D12GraphicsCommandList *pCmdList, const std::vector<UINT8> &textureData,
Microsoft::WRL::ComPtr<ID3D12Resource> &texture, const UINT width, const UINT height,
const UINT texturePixelSize) {
// Create the GPU upload buffer.
const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture.Get(), 0, 1);
ID3D12Resource *textureUploadHeap;
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(&textureUploadHeap)));
// Copy data to the intermediate upload heap and then schedule a copy
// from the upload heap to the Texture2D.
D3D12_SUBRESOURCE_DATA textureDataDesc = {};
textureDataDesc.pData = textureData.data();
textureDataDesc.RowPitch = width * texturePixelSize;
textureDataDesc.SlicePitch = textureDataDesc.RowPitch * height;
UpdateSubresources(pCmdList, texture.Get(), textureUploadHeap, 0, 0, 1, &textureDataDesc);
pCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
}
void CreateTextureResource(ID3D12Device *device, UINT width, UINT height, DXGI_FORMAT format,
Microsoft::WRL::ComPtr<ID3D12Resource> &textureResource, UINT16 arraySize) {
D3D12_RESOURCE_DESC textureDesc = {};
textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.DepthOrArraySize = arraySize;
textureDesc.MipLevels = 1;
textureDesc.Format = format;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
ThrowIfFailed(device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE, &textureDesc, D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, IID_PPV_ARGS(&textureResource)));
}
void Texture2D(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList,
Microsoft::WRL::ComPtr<ID3D12Resource> &textureResource, int width, int height, DXGI_FORMAT format) {
CreateTextureResource(device, width, height, format, textureResource, 1);
auto textureData = CreateRandomTexture(width, height);
UploadTexture(device, cmdList, textureData, textureResource, width, height);
}
void TextureCube(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList,
Microsoft::WRL::ComPtr<ID3D12Resource> &textureResource, int width, int height, DXGI_FORMAT format) {
CreateTextureResource(device, width, height, format, textureResource, 6);
std::vector<UINT8> textureCubeData;
for (int i = 0; i < 6; ++i) {
auto textureData = CreateRandomTexture(width, height);
textureCubeData.insert(textureCubeData.end(), textureData.begin(), textureData.end());
}
UploadTexture(device, cmdList, textureCubeData, textureResource, width, height);
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <random>
#include "../directx_third_party/DXSampleHelper.h"
#include "../directx_third_party/d3dx12.h"
// Helper class for creating and uploading resources to the GPU.
template <typename T> class UploadBuffer {
public:
UploadBuffer(ID3D12Device *device, UINT elementCount, bool isConstantBuffer)
: m_isConstantBuffer(isConstantBuffer) {
m_elementByteSize = sizeof(T);
if (isConstantBuffer)
m_elementByteSize = CalcConstantBufferByteSize(sizeof(T));
ThrowIfFailed(
device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(m_elementByteSize * elementCount),
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&m_uploadBuffer)));
}
UploadBuffer(const UploadBuffer &rhs) = delete;
UploadBuffer &operator=(const UploadBuffer &rhs) = delete;
~UploadBuffer() {
if (m_uploadBuffer != nullptr)
m_uploadBuffer->Unmap(0, nullptr);
m_mappedData = nullptr;
}
ID3D12Resource *Resource() const { return m_uploadBuffer.Get(); }
void CopyData(int elementIndex, const T &data) {
ThrowIfFailed(m_uploadBuffer->Map(0, nullptr, reinterpret_cast<void **>(&m_mappedData)));
memcpy(&m_mappedData[elementIndex * m_elementByteSize], &data, sizeof(T));
m_uploadBuffer->Unmap(0, nullptr);
}
private:
Microsoft::WRL::ComPtr<ID3D12Resource> m_uploadBuffer;
BYTE *m_mappedData = nullptr;
UINT m_elementByteSize = 0;
bool m_isConstantBuffer = false;
};
/*
* @brief: Create a default buffer.
* @param: device the device of GPU object.
* @param: cmdList the command list of GPU object.
* @param: initData the data to be copied to the default buffer.
* @param: byteSize the size of data.
* @return: the default buffer.
*/
Microsoft::WRL::ComPtr<ID3D12Resource> CreateDefaultBuffer(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList,
const void *initData, UINT64 byteSize,
Microsoft::WRL::ComPtr<ID3D12Resource> &uploadBuffer);
/*
* @brief: Calculate the size of constant buffer.
*/
UINT CalcConstantBufferByteSize(UINT byteSize);
/*
* @brief: Create a random texture.
* @param: width the width of texture.
* @param: height the height of texture.
* @param: texturePixelSize the size of texture pixel.
* @return: the random texture data.
*/
std::vector<UINT8> CreateRandomTexture(const UINT width, const UINT height, const UINT texturePixelSize = 4);
/*
* @brief: Upload the texture to GPU.
* @param: device the device of GPU object.
* @param: pCmdList the command list of GPU object.
* @param: textureData the texture data to be uploaded.
* @param: texture the texture resource.
* @param: width the width of texture.
* @param: height the height of texture.
* @param: texturePixelSize the size of texture pixel.
*/
void UploadTexture(ID3D12Device *device, ID3D12GraphicsCommandList *pCmdList, const std::vector<UINT8> &textureData,
Microsoft::WRL::ComPtr<ID3D12Resource> &texture, const UINT width, const UINT height,
const UINT texturePixelSize = 4);
/*
* @brief: Create a texture resource.
* @param: device the device of GPU object.
* @param: width the width of texture.
* @param: height the height of texture.
* @param: format the format of texture.
* @param: textureResource the texture resource.
* @param: arraySize the size of texture array.
*/
void CreateTextureResource(ID3D12Device *device, UINT width, UINT height, DXGI_FORMAT format,
Microsoft::WRL::ComPtr<ID3D12Resource> &textureResource, UINT16 arraySize);
/*
* @brief: Create a random texture resource and upload it to GPU.
* @param: device the device of GPU object.
* @param: cmdList the command list of GPU object.
* @param: textureResource the texture resource.
* @param: width the width of texture.
* @param: height the height of texture.
* @param: format the format of texture.
*/
void Texture2D(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList,
Microsoft::WRL::ComPtr<ID3D12Resource> &textureResource, int width, int height, DXGI_FORMAT format);
/*
* @brief: Create a random texture cube resource and upload it to GPU.
* @param: device the device of GPU object.
* @param: cmdList the command list of GPU object.
* @param: textureResource the texture resource.
* @param: width the width of texture.
* @param: height the height of texture.
* @param: format the format of texture.
*/
void TextureCube(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList,
Microsoft::WRL::ComPtr<ID3D12Resource> &textureResource, int width, int height, DXGI_FORMAT format);
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{627418c9-578a-47a9-8579-45c0e08fe528}</ProjectGuid>
<RootNamespace>DirectXRenderPerformance</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<ConformanceMode>false</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<FxCompile>
<ShaderModel>5.1</ShaderModel>
</FxCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>false</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="BufferHelper.cpp" />
<ClCompile Include="..\directx_third_party\DeviceResources.cpp" />
<ClCompile Include="..\directx_utils\D3D12Timer.cpp" />
<ClCompile Include="GeometryHelper.cpp" />
<ClCompile Include="RenderApp.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="RenderGeometryPass.cpp" />
<ClCompile Include="RenderLightingPass.cpp" />
<ClCompile Include="RenderShadowMapPass.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\directx_third_party\d3dx12.h" />
<ClInclude Include="..\directx_third_party\DeviceResources.h" />
<ClInclude Include="..\directx_third_party\DXSampleHelper.h" />
<ClInclude Include="..\directx_third_party\pch.h" />
<ClInclude Include="..\directx_utils\D3D12Timer.h" />
<ClInclude Include="..\directx_utils\Options.h" />
<ClInclude Include="BufferHelper.h" />
<ClInclude Include="GeometryHelper.h" />
<ClInclude Include="RenderApp.h" />
<ClInclude Include="BenchmarkOptions.h" />
<ClInclude Include="RenderGeometryPass.h" />
<ClInclude Include="RenderLightingPass.h" />
<ClInclude Include="RenderShadowMapPass.h" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="Shaders\Base.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.0</ShaderModel>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy %(Identity) "$(OutDir)\Shaders" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)\%(Identity)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy %(Identity) "$(OutDir)\Shaders" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)\%(Identity)</Outputs>
</CustomBuild>
<CustomBuild Include="Shaders\ShadowMap.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.0</ShaderModel>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy %(Identity) "$(OutDir)\Shaders" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)\%(Identity)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy %(Identity) "$(OutDir)\Shaders" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)\%(Identity)</Outputs>
</CustomBuild>
<CustomBuild Include="Shaders\DefferredLightingPixel.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.0</ShaderModel>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy %(Identity) "$(OutDir\Shaders)" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)\%(Identity)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy %(Identity) "$(OutDir)\Shaders" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)\%(Identity)</Outputs>
</CustomBuild>
<CustomBuild Include="Shaders\DefferredLightingVertex.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4.0</ShaderModel>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4.0</ShaderModel>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy %(Identity) "$(OutDir)\Shaders" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)\%(Identity)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy %(Identity) "$(OutDir)\Shaders" &gt; NUL</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)\%(Identity)</Outputs>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="packages\directxtex_uwp.2023.3.30.1\build\native\directxtex_uwp.targets" Condition="Exists('packages\directxtex_uwp.2023.3.30.1\build\native\directxtex_uwp.targets')" />
</ImportGroup>
</Project>
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "GeometryHelper.h"
namespace MathHelper {
DirectX::XMFLOAT4X4 Identity4x4() {
DirectX::XMFLOAT4X4 identity;
DirectX::XMStoreFloat4x4(&identity, DirectX::XMMatrixIdentity());
return identity;
}
float genRand2N_f(int n) {
srand((unsigned int)time(NULL));
// Seed
std::random_device rd;
// Random number generator
std::default_random_engine generator(rd());
std::uniform_real_distribution<float> distribution(0, n);
return distribution(generator);
}
uint16_t genRand2N_large(int n) {
srand((unsigned int)time(NULL));
// Seed
std::random_device rd;
// Random number generator
std::default_random_engine generator(rd());
// Use std::uniform_int_distribution<uint16_t> with the desired range
std::uniform_int_distribution<uint16_t> distribution(0, static_cast<uint16_t>(n));
return distribution(generator);
};
} // namespace MathHelper
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <d3d12.h>
#include <dxgi1_4.h>
#include <random>
#include <wrl.h>
#include <DirectXMath.h>
#include "../directx_third_party/DXSampleHelper.h"
#include "../directx_third_party/pch.h"
#include "BufferHelper.h"
using Microsoft::WRL::ComPtr;
namespace MathHelper {
const float Infinity = FLT_MAX;
const float Pi = 3.1415926535f;
// Create identity4*4 matrix
DirectX::XMFLOAT4X4 Identity4x4();
// Returns random float in [0, n).
float genRand2N_f(int n);
// Returns random uint16_t in [0, n).
uint16_t genRand2N_large(int n);
} // namespace MathHelper
// Simple struct to represent a vertex.
class Vertex {
public:
Vertex() {
x = MathHelper::genRand2N_f(2) - 1;
y = MathHelper::genRand2N_f(2) - 1;
z = MathHelper::genRand2N_f(2) - 1;
}
Vertex(float x, float y, float z) : x(x), y(y), z(z) {}
Vertex(const Vertex &v) : x(v.x), y(v.y), z(v.z) {}
float x, y, z; // Position
// You can add other attributes such as color, normal, texture coordinates etc.
};
// Simple struct to represent a Geometry object.
struct Geometry {
std::unique_ptr<Vertex[]> vertexData = nullptr;
std::vector<uint16_t> indexData;
UINT vertexNum;
UINT indexNum;
UINT vertexByteSize;
UINT indexByteSize;
UINT vertexByteStride;
};
// Create a random geometry data buffer.
template <class T> std::unique_ptr<Geometry> CreateRandomGeometry(const UINT vertexNum, const UINT indexNum) {
static_assert(std::is_base_of<Vertex, T>::value, "T must be a Vertex or derived from Vertex");
std::unique_ptr<Geometry> geo = make_unique<Geometry>();
// Create the vertices.
// Allocate memory and reinterpret_cast it to Vertex array
geo->vertexData.reset(reinterpret_cast<Vertex *>(new T[vertexNum]));
// Fill in the random vertex data.
for (UINT i = 0; i < vertexNum; i++) {
// Here you need to reinterpret_cast it back to T for accessing/modifying
T &v = reinterpret_cast<T &>(geo->vertexData[i]);
v = T();
}
// Create the indices.
// Fill in the random index data.
for (UINT i = 0; i < indexNum; i++) {
geo->indexData.push_back(MathHelper::genRand2N_large(vertexNum));
}
geo->vertexNum = vertexNum;
geo->indexNum = indexNum;
geo->vertexByteStride = sizeof(T);
geo->vertexByteSize = sizeof(T) * vertexNum;
geo->indexByteSize = sizeof(std::uint16_t) * indexNum;
return geo;
}
// Helpter class to manage geometry data buffer on GPU.
struct GeometryResource {
ComPtr<ID3DBlob> VertexBufferCPU = nullptr;
ComPtr<ID3DBlob> IndexBufferCPU = nullptr;
ComPtr<ID3D12Resource> VertexBufferGPU = nullptr;
ComPtr<ID3D12Resource> IndexBufferGPU = nullptr;
ComPtr<ID3D12Resource> VertexBufferUploader = nullptr;
ComPtr<ID3D12Resource> IndexBufferUploader = nullptr;
// Data about the buffers.
UINT VertexByteStride = 0;
UINT VertexBufferByteSize = 0;
DXGI_FORMAT IndexFormat = DXGI_FORMAT_R16_UINT;
UINT IndexBufferByteSize = 0;
D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
UINT IndexCount = 0;
UINT StartIndexLocation = 0;
INT BaseVertexLocation = 0;
/*
* @brief Get the vertex buffer view.
*/
D3D12_VERTEX_BUFFER_VIEW VertexBufferView() const {
D3D12_VERTEX_BUFFER_VIEW vbv;
vbv.BufferLocation = VertexBufferGPU->GetGPUVirtualAddress();
vbv.StrideInBytes = VertexByteStride;
vbv.SizeInBytes = VertexBufferByteSize;
return vbv;
}
/*
* @brief Get the index buffer view.
*/
D3D12_INDEX_BUFFER_VIEW IndexBufferView() const {
D3D12_INDEX_BUFFER_VIEW ibv;
ibv.BufferLocation = IndexBufferGPU->GetGPUVirtualAddress();
ibv.Format = IndexFormat;
ibv.SizeInBytes = IndexBufferByteSize;
return ibv;
}
/*
* @brief Upload geometry data and set necessary information about the geometry.
*/
void Create(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, std::unique_ptr<Geometry> &geoData) {
if (device == nullptr) {
throw std::runtime_error("device is nullptr");
}
if (cmdList == nullptr) {
throw std::runtime_error("cmdList is nullptr");
}
if (geoData == nullptr) {
throw std::runtime_error("geoData is nullptr");
}
auto geometry = geoData.get();
ThrowIfFailed(D3DCreateBlob(geometry->vertexByteSize, &this->VertexBufferCPU));
CopyMemory(this->VertexBufferCPU->GetBufferPointer(), geometry->vertexData.get(), geometry->vertexByteSize);
ThrowIfFailed(D3DCreateBlob(geometry->indexByteSize, &this->IndexBufferCPU));
CopyMemory(this->IndexBufferCPU->GetBufferPointer(), geometry->indexData.data(), geometry->indexByteSize);
this->VertexBufferGPU = CreateDefaultBuffer(device, cmdList, geometry->vertexData.get(),
geometry->vertexByteSize, this->VertexBufferUploader);
this->IndexBufferGPU = CreateDefaultBuffer(device, cmdList, geometry->indexData.data(), geometry->indexByteSize,
this->IndexBufferUploader);
this->VertexByteStride = geometry->vertexByteStride;
this->VertexBufferByteSize = geometry->vertexByteSize;
this->IndexBufferByteSize = geometry->indexByteSize;
this->IndexCount = geometry->indexNum;
}
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "RenderGeometryPass.h"
#include "RenderLightingPass.h"
#include "RenderShadowMapPass.h"
#include <codecvt>
#include <cstdio>
#include <iostream>
#include <locale>
#include <string>
#include <tuple>
#include <windows.h>
/*
* @brief: Main message handler for the sample.
*/
LRESULT WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
// Handle window event.
switch (message) {
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
/*
* @brief: Main window procedure.
*/
static LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
// Forward hwnd on because we can get messages (e.g., WM_CREATE)
// before CreateWindow returns, and thus before mhMainWnd is valid.
return WindowProc(hwnd, msg, wParam, lParam);
}
/*
* @brief: Register a window app.
*/
bool InitMainWindow(HINSTANCE hInstance, int width, int height, HWND &hMainWnd, const std::wstring &winTitle,
bool quiet_mode) {
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"MainWnd";
if (!RegisterClass(&wc)) {
return false;
}
// Compute window rectangle dimensions based on requested client area dimensions.
RECT R = {0, 0, width, height};
AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
width = R.right - R.left;
height = R.bottom - R.top;
hMainWnd = CreateWindow(wc.lpszClassName, winTitle.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
width, height, 0, 0, hInstance, 0);
if (!hMainWnd) {
return false;
}
if (!quiet_mode) {
ShowWindow(hMainWnd, SW_SHOW);
UpdateWindow(hMainWnd);
}
return true;
}
/*
* @brief: Load the render microbenchmark according to the pass type.
*/
std::unique_ptr<RenderApp> get_render_pointer(BenchmarkOptions &args, HINSTANCE hInstance, HWND hMainWnd,
std::wstring &winTitle) {
if (args.m_pass_type == PassType::GeometryPass) {
return std::make_unique<RenderGeometryPass>(&args, hInstance, hMainWnd, winTitle);
} else if (args.m_pass_type == PassType::ShadowMapPass) {
return std::make_unique<RenderShadowMapPass>(&args, hInstance, hMainWnd, winTitle);
} else if (args.m_pass_type == PassType::LightingPass) {
return std::make_unique<RenderLightingPass>(&args, hInstance, hMainWnd, winTitle);
} else
throw "invalid pass name";
}
/*
* @brief: Main entry point for a Windows application.
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// Enable console attach and redirect stdout/stderr to console.
if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()) {
FILE *stream;
if (freopen_s(&stream, "CONOUT$", "w", stdout) == 0) {
printf("Hello, Console!\n");
}
if (freopen_s(&stream, "CONOUT$", "w", stderr) == 0) {
fprintf(stderr, "Hello, Error Console!\n");
}
// Or use std::cout
std::cout << "Hello from std::cout" << std::endl;
}
MSG msg = {0};
try {
// Parse command line arguments.
BenchmarkOptions args(__argc, __argv);
args.init();
// Create the main window.
HWND hMainWnd;
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
std::wstring winTitle = converter.from_bytes("");
if (!InitMainWindow(hInstance, args.m_width, args.m_height, hMainWnd, winTitle, args.m_quiet))
return -1;
// Create the render microbenchmark.
auto app_sample = get_render_pointer(args, hInstance, hMainWnd, winTitle);
app_sample->Initialize();
app_sample->LoadAssets();
while (msg.message != WM_QUIT) {
// If there are Window messages then process them.
// We need to handle message here otherwise it is no response.
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
// Update and render per frame.
app_sample->Tick();
}
}
} catch (const std::exception &e) {
std::cerr << e.what() << '\n';
}
return (int)msg.wParam;
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "RenderApp.h"
#include "../directx_third_party/d3dx12.h"
RenderApp::RenderApp(BenchmarkOptions *args) {
if (args == nullptr) {
throw std::runtime_error("BenchmarkOptions is nullptr");
}
m_opts = args;
m_width = args->m_width;
m_height = args->m_height;
m_deviceResources = std::make_unique<DX::DeviceResources>(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_D32_FLOAT,
m_swapChainBufferCount, D3D_FEATURE_LEVEL_11_0,
DX::DeviceResources::c_AllowTearing);
}
RenderApp::RenderApp(BenchmarkOptions *args, HINSTANCE hInstance, HWND hMainWnd, std::wstring &winTitle)
: RenderApp(args) {
m_hinstance = hInstance;
m_hMainWnd = hMainWnd;
m_winTitle = winTitle;
}
RenderApp::~RenderApp() {
if (m_outfile.is_open()) {
m_outfile.close();
}
if (m_deviceResources) {
m_deviceResources->WaitForGpu();
}
}
void RenderApp::Initialize() {
if (m_deviceResources == nullptr) {
throw std::runtime_error("DeviceResources is nullptr");
}
m_deviceResources->SetWindow(m_hMainWnd, m_width, m_height);
m_deviceResources->CreateDeviceResources();
CreateDeviceDependentResources();
m_deviceResources->CreateWindowSizeDependentResources();
CreateWindowSizeDependentResources();
// Wait until initialization is complete.
// Execute the initialization commands.
m_deviceResources->WaitForGpu();
auto device = m_deviceResources->GetD3DDevice();
auto commandQueue = m_deviceResources->GetCommandQueue();
m_gpuTimer.init(device, commandQueue, m_maxTimerNum, D3D12::QueueType::compute);
m_outfile.open(m_opts->m_outfile, std::ios_base::out);
}
void RenderApp::CreateDeviceDependentResources() {
auto device = m_deviceResources->GetD3DDevice();
if (device == nullptr) {
throw std::runtime_error("D3D12Device is nullptr");
}
// Create a fence for synchronizing between different frames
ThrowIfFailed(device->CreateFence(m_deviceResources->GetCurrentFrameIndex(), D3D12_FENCE_FLAG_NONE,
IID_PPV_ARGS(m_fence.ReleaseAndGetAddressOf())));
// Start off the fence with the current frame index
uint64_t currentIdx = m_deviceResources->GetCurrentFrameIndex();
m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), currentIdx);
CreateRootSignatures(device);
BuildPipelineStates(device);
}
void RenderApp::CreateWindowSizeDependentResources() {
auto device = m_deviceResources->GetD3DDevice();
auto rtvHeap = m_deviceResources->m_rtvDescriptorHeap.Get();
auto pCmdList = m_deviceResources->GetCommandList();
auto cmdListAlloc = m_deviceResources->GetCommandAllocator();
auto cmdQueue = m_deviceResources->GetCommandQueue();
if (device == nullptr) {
throw std::runtime_error("D3D12Device is nullptr");
}
if (rtvHeap == nullptr) {
throw std::runtime_error("RTVDescriptorHeap is nullptr");
}
if (pCmdList == nullptr) {
throw std::runtime_error("CommandList is nullptr");
}
if (cmdListAlloc == nullptr) {
throw std::runtime_error("CommandAllocator is nullptr");
}
if (cmdQueue == nullptr) {
throw std::runtime_error("CommandQueue is nullptr");
}
ThrowIfFailed(cmdListAlloc->Reset());
ThrowIfFailed(pCmdList->Reset(cmdListAlloc, nullptr));
// Prepare and init GPU resources.
if (m_numPassRenderTargets > 0)
m_renderTargets.resize(m_numPassRenderTargets);
if (m_numShaderResource > 0)
m_shaderResources.resize(m_numShaderResource);
CreateRenderTargetView(device, m_width, m_height, rtvHeap);
CreateShaderResourceView(device, pCmdList, m_width, m_height);
// Send the command list off to the GPU for processing.
ThrowIfFailed(pCmdList->Close());
ID3D12CommandList *commandLists[] = {pCmdList};
cmdQueue->ExecuteCommandLists(1, commandLists);
}
void RenderApp::CreateRootSignatures(ID3D12Device *device) {
std::vector<CD3DX12_ROOT_PARAMETER> rootParameters;
int numRootParameters = DefineRootParameters(rootParameters);
CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
rootSignatureDesc.NumParameters = numRootParameters;
rootSignatureDesc.pParameters = rootParameters.data();
std::vector<CD3DX12_STATIC_SAMPLER_DESC> samplers;
auto numSamplers = DefineStaticSamplers(samplers);
rootSignatureDesc.NumStaticSamplers = (UINT)numSamplers;
rootSignatureDesc.pStaticSamplers = samplers.data();
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
ID3DBlob *serializedRootSignature = nullptr;
ID3DBlob *errorBlob = nullptr;
auto hr = (D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, &serializedRootSignature,
&errorBlob));
if (hr != S_OK || errorBlob != nullptr) {
std::cout << ((char *)errorBlob->GetBufferPointer()) << std::endl;
}
ThrowIfFailed(device->CreateRootSignature(0, serializedRootSignature->GetBufferPointer(),
serializedRootSignature->GetBufferSize(),
IID_PPV_ARGS(&m_rootSignature)));
}
void RenderApp::CreateRenderTargetResource(ID3D12Device *device, UINT width, UINT height, DXGI_FORMAT format,
D3D12_RESOURCE_FLAGS flags,
Microsoft::WRL::ComPtr<ID3D12Resource> &renderTarget) {
// Create the render target resources:
D3D12_CLEAR_VALUE m_clearValue = {}; // Specify a clear value for the render target (optional)
m_clearValue.Format = format;
m_clearValue.Color[0] = 0.0f; // Red component
m_clearValue.Color[1] = 0.0f; // Green component
m_clearValue.Color[2] = 0.0f; // Blue component
m_clearValue.Color[3] = 1.0f; // Alpha component
D3D12_HEAP_PROPERTIES heapProperties = {}; // Specify heap properties for the render target (optional)
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
D3D12_RESOURCE_DESC resourceDesc = {}; // Specify resource properties for the render target
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
resourceDesc.Alignment = 0;
resourceDesc.Width = width;
resourceDesc.Height = height;
resourceDesc.DepthOrArraySize = 1;
resourceDesc.MipLevels = 1;
resourceDesc.Format = format;
resourceDesc.SampleDesc.Count = 1;
resourceDesc.SampleDesc.Quality = 0;
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resourceDesc.Flags = flags;
// Create the render target resource
ThrowIfFailed(device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc,
D3D12_RESOURCE_STATE_COMMON, &m_clearValue,
IID_PPV_ARGS(&renderTarget)));
}
CD3DX12_CPU_DESCRIPTOR_HANDLE RenderApp::GetRenderTargetView(ID3D12Device *device) {
const CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
return rtvDescriptor;
}
void RenderApp::CreateRenderTargetView(ID3D12Device *device, UINT width, UINT height, ID3D12DescriptorHeap *rtvHeap) {
D3D12_DESCRIPTOR_HEAP_DESC rtvDescriptorHeapDesc = {};
rtvDescriptorHeapDesc.NumDescriptors = m_numPassRenderTargets;
rtvDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
ThrowIfFailed(device->CreateDescriptorHeap(&rtvDescriptorHeapDesc,
IID_PPV_ARGS(m_rtvDescriptorHeap.ReleaseAndGetAddressOf())));
m_rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
// Define the render target properties
DXGI_FORMAT format = m_renderTargetFormat; // Pixel format of the render target
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; // Specify the resource flags
// Create the render target resources.
for (int i = 0; i < m_numPassRenderTargets; ++i) {
CreateRenderTargetResource(device, width, height, format, flags, m_renderTargets[i]);
}
auto rtvHandle = GetRenderTargetView(device);
// Create a RTV for each custom render target.
for (UINT i = 0; i < m_numPassRenderTargets; ++i) {
// Create the RTV descriptor
device->CreateRenderTargetView(m_renderTargets[i].Get(), nullptr, rtvHandle);
// Increment the handle to the next descriptor
rtvHandle.Offset(1, m_rtvDescriptorSize);
}
}
D3D12_GRAPHICS_PIPELINE_STATE_DESC RenderApp::DefinePSODesc(const std::vector<D3D12_INPUT_ELEMENT_DESC> &inputLayout,
ComPtr<ID3DBlob> vertexShader,
ComPtr<ID3DBlob> pixelShader) {
// Describe and create the graphics pipeline state object (PSO).
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
ZeroMemory(&psoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
psoDesc.InputLayout = {inputLayout.data(), (UINT)inputLayout.size()};
psoDesc.pRootSignature = m_rootSignature.Get();
psoDesc.VS = {reinterpret_cast<UINT8 *>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize()};
psoDesc.PS = {reinterpret_cast<UINT8 *>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize()};
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
psoDesc.SampleMask = UINT_MAX;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN; // No depth-stencil
psoDesc.NumRenderTargets = m_numPassRenderTargets;
for (int i = 0; i < m_numPassRenderTargets; i++) {
psoDesc.RTVFormats[i] = m_renderTargetFormat;
}
psoDesc.SampleDesc.Count = 1;
psoDesc.SampleDesc.Quality = 0;
return psoDesc;
}
void RenderApp::LoadAssets() {
auto device = m_deviceResources->GetD3DDevice();
auto pCmdList = m_deviceResources->GetCommandList();
auto cmdListAlloc = m_deviceResources->GetCommandAllocator();
auto cmdQueue = m_deviceResources->GetCommandQueue();
ThrowIfFailed(cmdListAlloc->Reset());
ThrowIfFailed(pCmdList->Reset(cmdListAlloc, nullptr));
CreateConstantBufferResources(device);
UpdateConstantBufferData();
BuildShapeGeometry(device, pCmdList);
ThrowIfFailed(pCmdList->Close());
ID3D12CommandList *commandLists[] = {pCmdList};
cmdQueue->ExecuteCommandLists(1, commandLists);
this->m_deviceResources->WaitForGpu();
}
void RenderApp::Tick() {
auto device = m_deviceResources->GetD3DDevice();
auto pCmdList = m_deviceResources->GetCommandList();
auto cmdListAlloc = m_deviceResources->GetCommandAllocator();
auto cmdQueue = m_deviceResources->GetCommandQueue();
Update();
Render();
this->m_deviceResources->WaitForGpu();
CalculateFrameStats();
}
void RenderApp::Update() {
// Check to see if the GPU is keeping up
auto const frameIdx = m_frameIndex;
auto const numBackBuffers = m_deviceResources->GetBackBufferCount();
uint64_t completedValue = m_fence->GetCompletedValue();
if ((frameIdx >
completedValue) // if frame index is reset to zero it may temporarily be smaller than the last GPU signal
&& (frameIdx - completedValue > numBackBuffers)) {
// GPU not caught up, wait for at least one available frame
ThrowIfFailed(m_fence->SetEventOnCompletion(frameIdx - numBackBuffers, m_fenceEvent.Get()));
WaitForSingleObjectEx(m_fenceEvent.Get(), INFINITE, FALSE);
}
}
void RenderApp::CalculateFrameStats() {
auto timeInMs = m_gpuTimer.getElapsedMsByTimestampPair(m_gpuTimerIdx);
m_frameTimeList.push_back(timeInMs);
m_gpuTimerIdx++;
if (m_gpuTimerIdx == m_maxTimerNum) {
m_gpuTimerIdx = 0;
}
m_frameIndex++;
if (m_frameIndex < m_opts->m_warmup) {
m_frameTimeList.clear();
} else {
cout << m_frameTimeList.back() << endl;
m_outfile << m_frameTimeList.back() << endl;
}
if (m_frameIndex == m_opts->m_warmup + m_opts->m_num_frames) {
// Calculate the median
double median = 0;
std::sort(m_frameTimeList.begin(), m_frameTimeList.end());
int size = m_frameTimeList.size();
if (m_frameTimeList.size() % 2 == 0) {
median = (m_frameTimeList[size / 2 - 1] + m_frameTimeList[size / 2]) / 2;
} else {
median = m_frameTimeList[size / 2];
}
m_outfile << "Mean: " << median << std::endl;
std::cout << "Mean: " << median << std::endl;
PostMessage(m_hMainWnd, WM_CLOSE, 0, 0);
}
}
void RenderApp::ClearRenderTargetView() {
auto commandList = m_deviceResources->GetCommandList();
auto device = m_deviceResources->GetD3DDevice();
// Clear the views.
auto rtvDescriptor = GetRenderTargetView(device);
auto const dsvDescriptor = m_deviceResources->GetDepthStencilView();
float clearColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
std::vector<CD3DX12_CPU_DESCRIPTOR_HANDLE> rtvHandles(m_numPassRenderTargets);
for (int i = 0; i < m_numPassRenderTargets; i++) {
commandList->ClearRenderTargetView(rtvDescriptor, clearColor, 0, nullptr);
rtvHandles[i] = rtvDescriptor;
rtvDescriptor.Offset(1, m_rtvDescriptorSize);
}
rtvDescriptor = GetRenderTargetView(device);
commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
// Indicate that the back buffer will be used as a render target.
commandList->OMSetRenderTargets(m_numPassRenderTargets, rtvHandles.data(), FALSE, nullptr);
// Set the viewport and scissor rect.
auto const viewport = m_deviceResources->GetScreenViewport();
auto const scissorRect = m_deviceResources->GetScissorRect();
commandList->RSSetViewports(1, &viewport);
commandList->RSSetScissorRects(1, &scissorRect);
}
void RenderApp::PrepareRenderTarget(ID3D12GraphicsCommandList *pCommandList) {
for (int i = 0; i < m_numPassRenderTargets; i++) {
// Transition from COMMON to RENDER_TARGET
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = m_renderTargets[i].Get();
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
pCommandList->ResourceBarrier(1, &barrier);
}
}
void RenderApp::RestoreRenderTarget(ID3D12GraphicsCommandList *pCommandList) {
for (int i = 0; i < m_numPassRenderTargets; i++) {
// Indicate that the back buffer will now be used to present.
pCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[i].Get(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_COMMON));
}
}
void RenderApp::Render() {
auto device = m_deviceResources->GetD3DDevice();
auto cmdList = m_deviceResources->GetCommandList();
auto cmdQueue = m_deviceResources->GetCommandQueue();
m_deviceResources->Prepare();
PrepareRenderTarget(cmdList);
ClearRenderTargetView();
SetStatesBeforeDraw(cmdList);
eventStart(cmdList);
Draw(cmdList);
eventEnd(cmdList);
RestoreRenderTarget(cmdList);
m_deviceResources->Present();
// GPU will signal an increasing value each frame
m_deviceResources->GetCommandQueue()->Signal(m_fence.Get(), m_frameIndex);
}
void RenderApp::DrawRenderItems(ID3D12GraphicsCommandList *pCmdList, int drawNum) {
auto ri = m_geometry.get();
for (int i = 0; i < drawNum; ++i) {
pCmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
}
}
void RenderApp::BuildShapeGeometry(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList) {
// Create random geometry.
std::unique_ptr<Geometry> geoData = CreateRandomGeometry<Vertex>(m_opts->m_vertexNum, m_opts->m_indexNum);
m_geometry = std::make_unique<GeometryResource>();
m_geometry->Create(device, cmdList, geoData);
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <fstream>
#include <iostream>
#include <system_error>
#include <tuple>
#include <unordered_map>
#include <windows.h>
#include "../directx_third_party/DeviceResources.h"
#include "../directx_utils/D3D12Timer.h"
#include "BenchmarkOptions.h"
#include "GeometryHelper.h"
using Microsoft::WRL::ComPtr;
using namespace DirectX;
using namespace std;
class RenderApp {
public:
RenderApp(BenchmarkOptions *args);
RenderApp(BenchmarkOptions *args, HINSTANCE hInstance, HWND hMainWnd, std::wstring &winTitle);
RenderApp(const RenderApp &rhs) = delete;
RenderApp &operator=(const RenderApp &rhs) = delete;
~RenderApp();
/*
* @brief: Execute the update and render per frame.
*/
void Tick();
/*
* @brief: Initialize the application.
*/
virtual void Initialize();
/*
* @brief: Prepare the data assets needed for render.
*/
virtual void LoadAssets();
/*
* @brief: Calculate the frame stats.
*/
void CalculateFrameStats();
/*
* @brief: Update to run next frame.
*/
void Update();
/*
* @brief: Executes basic render loop .
*/
void Render();
protected:
/*
* @brief: Define the root parameters.
* @param: rootParameters The root parameters to be defined.
* @return: The number of root parameters.
*/
virtual int DefineRootParameters(std::vector<CD3DX12_ROOT_PARAMETER> &rootParameters) = 0;
/*
* @brief: Define the static samplers.
* @param: samplers The static samplers to be defined.
* @return: The number of static samplers.
*/
virtual int DefineStaticSamplers(std::vector<CD3DX12_STATIC_SAMPLER_DESC> &samplers) = 0;
/*
* @brief: Build the pipeline states.
* @param: device The device to build the pipeline states.
*/
virtual void BuildPipelineStates(ID3D12Device *device) = 0;
/*
* @brief: Create the shader resource view.
* @param: device The device to create the shader resource view.
* @param: cmdList The command list to create the shader resource view.
* @param: width The width of the shader resource view.
* @param: height The height of the shader resource view.
*/
virtual void CreateShaderResourceView(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, int width,
int height) = 0;
/*
* @brief: Create the constant buffer resources.
* @param: device The device to create the constant buffer resources.
*/
virtual void CreateConstantBufferResources(ID3D12Device *device) = 0;
/*
* @brief: Update the constant buffer data.
*/
virtual void UpdateConstantBufferData() = 0;
/*
* @brief: Render and draw defined by pass.
* @param: cmdList The command list to draw the render items.
*/
virtual void Draw(ID3D12GraphicsCommandList *cmdList) = 0;
/*
* @brief: Set the states before draw.
* @param: cmdList The command list to set the states before draw.
*/
virtual void SetStatesBeforeDraw(ID3D12GraphicsCommandList *cmdList) = 0;
/*
* @brief: Create the device dependent resources.
*/
virtual void CreateDeviceDependentResources();
/*
* @brief: Create the window size dependent resources.
*/
virtual void CreateWindowSizeDependentResources();
/*
* @brief: Create the root signature.
* @param: device The device to create the root signature.
*/
virtual void CreateRootSignatures(ID3D12Device *device);
/*
* @brief: Build the geometry.
*/
virtual void BuildShapeGeometry(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList);
/*
* @brief: Draw the render items.
* @param: pCmdList The command list to draw the render item.
* @param: drawTimes The times to draw the render item.
*/
virtual void DrawRenderItems(ID3D12GraphicsCommandList *pCmdList, int drawTimes);
/*
* @brief: Create the render target view.
* @param: device The device to create the render target view.
* @param: width The width of the render target view.
* @param: height The height of the render target view.
* @param: rtvHeap The descriptor heap to create the render target view.
*/
virtual void CreateRenderTargetView(ID3D12Device *device, UINT width, UINT height, ID3D12DescriptorHeap *rtvHeap);
/*
* @brief: Create the Render target resource.
* @param: device The device to create the render target resource.
* @param: width The width of the render target resource.
* @param: height The height of the render target resource.
* @param: format The format of the render target resource.
* @param: flags The flags of the render target resource.
* @param: renderTarget The render target resource to be created.
*/
virtual void CreateRenderTargetResource(ID3D12Device *device, UINT width, UINT height, DXGI_FORMAT format,
D3D12_RESOURCE_FLAGS flags,
Microsoft::WRL::ComPtr<ID3D12Resource> &renderTarget);
/*
* @brief: Define the pipeline state description.
* @param: inputLayout The input layout of the pipeline state description.
* @param: vertexShader The vertex shader of the pipeline state description.
* @param: pixelShader The pixel shader of the pipeline state description.
* @return: The pipeline state description.
*/
D3D12_GRAPHICS_PIPELINE_STATE_DESC DefinePSODesc(const std::vector<D3D12_INPUT_ELEMENT_DESC> &inputLayout,
ComPtr<ID3DBlob> vertexShader, ComPtr<ID3DBlob> pixelShader);
/*
* @brief: Prepare the render target state to draw.
*/
void PrepareRenderTarget(ID3D12GraphicsCommandList *pCommandList);
/*
* @brief: restore render target state.
*/
void RestoreRenderTarget(ID3D12GraphicsCommandList *pCommandList);
/*
* @brief: Clear, bind the render target view and set the viewport and scissor rect.
*/
void ClearRenderTargetView();
/*
* @brief: Get the first render target view of the pass.
*/
CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView(ID3D12Device *device);
// Window info.
std::wstring m_winTitle;
int m_width = 1280;
int m_height = 720;
HINSTANCE m_hinstance = nullptr;
HWND m_hMainWnd = nullptr;
int m_swapChainBufferCount = 2;
// Device resources.
std::unique_ptr<DX::DeviceResources> m_deviceResources;
D3D_DRIVER_TYPE m_d3dDriverType = D3D_DRIVER_TYPE_HARDWARE;
// Root signature.
ComPtr<ID3D12RootSignature> m_rootSignature = nullptr;
// Render target view.
ComPtr<ID3D12DescriptorHeap> m_rtvDescriptorHeap = nullptr;
DXGI_FORMAT m_renderTargetFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
DXGI_FORMAT m_colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
UINT m_numPassRenderTargets = 1; // Number of render targets
std::vector<Microsoft::WRL::ComPtr<ID3D12Resource>> m_renderTargets; // Array of render target resources
UINT m_rtvDescriptorSize = 0;
// Shader resource view.
UINT m_numShaderResource = 0; // Number of ShaderResources
std::vector<Microsoft::WRL::ComPtr<ID3D12Resource>> m_shaderResources;
UINT m_cbvSrvDescriptorSize = 0;
ComPtr<ID3D12DescriptorHeap> m_srvDescriptorHeap = nullptr;
// PSO objects.
std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> m_PSOs;
std::unique_ptr<GeometryResource> m_geometry;
// A synchronization fence and an event. These members will be used
// to synchronize the CPU with the GPU so that there will be no
// contention for the constant buffers.
Microsoft::WRL::ComPtr<ID3D12Fence> m_fence;
Microsoft::WRL::Wrappers::Event m_fenceEvent;
// Frame
UINT64 m_frameIndex = 0;
vector<double> m_frameTimeList;
// Benchmark options.
BenchmarkOptions *m_opts;
ofstream m_outfile;
// GPU timer
D3D12::D3D12Timer m_gpuTimer;
int m_maxTimerNum = 500;
int m_gpuTimerIdx = 0;
void eventStart(ID3D12GraphicsCommandList *pCommandList) { m_gpuTimer.start(pCommandList, m_gpuTimerIdx); }
void eventEnd(ID3D12GraphicsCommandList *pCommandList) {
m_gpuTimer.stop(pCommandList, m_gpuTimerIdx);
m_gpuTimer.resolveQueryToCPU(pCommandList, m_gpuTimerIdx);
}
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "RenderGeometryPass.h"
int RenderGeometryPass::DefineRootParameters(std::vector<CD3DX12_ROOT_PARAMETER> &rootParameters) {
int numRootParams = 5;
rootParameters.resize(numRootParams);
std::unique_ptr<CD3DX12_DESCRIPTOR_RANGE> texTable0 = std::make_unique<CD3DX12_DESCRIPTOR_RANGE>();
texTable0->Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0);
std::unique_ptr<CD3DX12_DESCRIPTOR_RANGE> texTable1 = std::make_unique<CD3DX12_DESCRIPTOR_RANGE>();
texTable1->Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, m_numShaderResource - 1, 1, 0);
rootParameters[0].InitAsConstantBufferView(0); // obj cb
rootParameters[1].InitAsConstantBufferView(1); // pass cb
rootParameters[2].InitAsConstantBufferView(2); // material cb
rootParameters[3].InitAsDescriptorTable(1, texTable0.release(), D3D12_SHADER_VISIBILITY_PIXEL); // cube texture
rootParameters[4].InitAsDescriptorTable(1, texTable1.release(), D3D12_SHADER_VISIBILITY_PIXEL); // texture array
return numRootParams;
}
int RenderGeometryPass::DefineStaticSamplers(std::vector<CD3DX12_STATIC_SAMPLER_DESC> &samplers) {
int samplersCount = 1;
samplers.resize(samplersCount);
CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(0, // shaderRegister
D3D12_FILTER_ANISOTROPIC, // filter
D3D12_TEXTURE_ADDRESS_MODE_WRAP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_WRAP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_WRAP, // addressW
0.0f, // mipLODBias
8); // maxAnisotropy
samplers[0] = anisotropicWrap;
return samplersCount;
}
void RenderGeometryPass::CreateShaderResourceView(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, int width,
int height) {
// Create a descriptor heap that will store the SRV:
D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
srvHeapDesc.NumDescriptors = m_numShaderResource;
srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvDescriptorHeap)));
CD3DX12_CPU_DESCRIPTOR_HANDLE cpuHandle(m_srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
m_cbvSrvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
// Whole screen texture.
TextureCube(device, cmdList, m_shaderResources[0], m_width, m_height, m_colorFormat);
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = m_shaderResources[0]->GetDesc().Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
srvDesc.Texture2D.MipLevels = m_shaderResources[0]->GetDesc().MipLevels;
device->CreateShaderResourceView(m_shaderResources[0].Get(), &srvDesc, cpuHandle);
cpuHandle.Offset(m_cbvSrvDescriptorSize);
// Small texture.
for (int i = 1; i < m_numShaderResource; i++) {
Texture2D(device, cmdList, m_shaderResources[i], width, height, m_colorFormat);
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = m_shaderResources[i]->GetDesc().Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = m_shaderResources[i]->GetDesc().MipLevels;
device->CreateShaderResourceView(m_shaderResources[i].Get(), &srvDesc, cpuHandle);
cpuHandle.Offset(m_cbvSrvDescriptorSize);
}
}
void RenderGeometryPass::CreateConstantBufferResources(ID3D12Device *device) {
m_viewCB = std::make_unique<UploadBuffer<BaseViewConstantBuffer>>(device, 1, true);
m_objectCB = std::make_unique<UploadBuffer<ObjectConstantBuffer>>(device, 1, true);
m_materialCB = std::make_unique<UploadBuffer<MaterialConstantBuffer>>(device, 1, true);
}
void RenderGeometryPass::UpdateConstantBufferData() {
BaseViewConstantBuffer viewCBData;
ObjectConstantBuffer objectCBData;
MaterialConstantBuffer materialCBData;
m_viewCB->CopyData(0, viewCBData);
m_objectCB->CopyData(0, objectCBData);
m_materialCB->CopyData(0, materialCBData);
}
void RenderGeometryPass::BuildShapeGeometry(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList) {
// Create random geometry.
std::unique_ptr<Geometry> geoData = CreateRandomGeometry<GeometryVertex>(m_opts->m_vertexNum, m_opts->m_indexNum);
m_geometry = std::make_unique<GeometryResource>();
m_geometry->Create(device, cmdList, geoData);
}
void RenderGeometryPass::BuildPipelineStates(ID3D12Device *device) {
std::string textureCount_str = std::to_string(m_numShaderResource - 1);
LPCSTR textureCount = textureCount_str.c_str();
D3D_SHADER_MACRO defines[] = {
{"TEXTURECOUNT", textureCount},
{nullptr, nullptr}}; // The last entry must be nullptr to indicate the end of the array
ComPtr<ID3DBlob> vertexShader = CompileShader(L"Shaders/Base.hlsl", defines, "VS", "vs_5_1");
ComPtr<ID3DBlob> pixelShader = CompileShader(L"Shaders/Base.hlsl", defines, "PS", "ps_5_1");
// Define shader input layout.
std::vector<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},
{"TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
};
auto psoDesc = DefinePSODesc(inputLayout, vertexShader, pixelShader);
ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PSOs["deferredBase"])));
}
void RenderGeometryPass::Draw(ID3D12GraphicsCommandList *cmdList) { DrawRenderItems(cmdList, m_opts->m_num_object); }
void RenderGeometryPass::SetStatesBeforeDraw(ID3D12GraphicsCommandList *cmdList) {
cmdList->SetPipelineState(m_PSOs["deferredBase"].Get());
cmdList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap *heaps[] = {m_srvDescriptorHeap.Get()};
cmdList->SetDescriptorHeaps(_countof(heaps), heaps);
cmdList->SetGraphicsRootConstantBufferView(0, m_objectCB.get()->Resource()->GetGPUVirtualAddress());
cmdList->SetGraphicsRootConstantBufferView(1, m_viewCB.get()->Resource()->GetGPUVirtualAddress());
cmdList->SetGraphicsRootConstantBufferView(2, m_materialCB.get()->Resource()->GetGPUVirtualAddress());
CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle(m_srvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
cmdList->SetGraphicsRootDescriptorTable(3, srvHandle);
srvHandle.Offset(1, m_cbvSrvDescriptorSize);
cmdList->SetGraphicsRootDescriptorTable(4, m_srvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
auto ri = m_geometry.get();
// Set vertex and index buffers
cmdList->IASetVertexBuffers(0, 1, &ri->VertexBufferView());
cmdList->IASetIndexBuffer(&ri->IndexBufferView());
cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "RenderApp.h"
class GeometryVertex : Vertex {
public:
GeometryVertex() : Vertex() {
float tx = MathHelper::genRand2N_f(2) - 1;
float ty = MathHelper::genRand2N_f(2) - 1;
float tz = MathHelper::genRand2N_f(2) - 1;
float nx = MathHelper::genRand2N_f(2) - 1;
float ny = MathHelper::genRand2N_f(2) - 1;
float nz = MathHelper::genRand2N_f(2) - 1;
float u = MathHelper::genRand2N_f(1);
float v = MathHelper::genRand2N_f(1);
Normal = {tx, ty, tz};
TangentU = {nx, ny, nz};
TexC = {u, v};
}
GeometryVertex(const DirectX::XMFLOAT3 &p, const DirectX::XMFLOAT3 &n, const DirectX::XMFLOAT2 &uv,
const DirectX::XMFLOAT3 &t)
: Vertex(p.x, p.y, p.z), Normal(n), TangentU(t), TexC(uv) {}
GeometryVertex(float px, float py, float pz, float nx, float ny, float nz, float tx, float ty, float tz, float u,
float v)
: Vertex(px, py, pz), Normal(nx, ny, nz), TangentU(tx, ty, tz), TexC(u, v) {}
GeometryVertex(const GeometryVertex &rhs) {
Normal = rhs.Normal;
TangentU = rhs.TangentU;
TexC = rhs.TexC;
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
DirectX::XMFLOAT3 Normal;
DirectX::XMFLOAT2 TexC;
DirectX::XMFLOAT3 TangentU;
};
struct ObjectConstantBuffer {
DirectX::XMFLOAT4X4 World = MathHelper::Identity4x4();
DirectX::XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
UINT MaterialIndex;
};
struct BaseViewConstantBuffer {
DirectX::XMFLOAT4X4 View = MathHelper::Identity4x4();
DirectX::XMFLOAT4X4 ViewProj = MathHelper::Identity4x4();
DirectX::XMFLOAT3 EyePosW = {0.0f, 0.0f, 0.0f};
};
struct MaterialConstantBuffer {
DirectX::XMFLOAT4 DiffuseAlbedo = {1.0f, 1.0f, 1.0f, 1.0f};
DirectX::XMFLOAT3 FresnelR0 = {0.01f, 0.01f, 0.01f};
float Roughness = 0.5f;
// Used in texture mapping.
DirectX::XMFLOAT4X4 MatTransform = MathHelper::Identity4x4();
UINT DiffuseMapIndex = 0;
UINT NormalMapIndex = 1;
};
class RenderGeometryPass : public RenderApp {
public:
RenderGeometryPass(BenchmarkOptions *args) : RenderApp(args) {
// screen + texture size
m_numShaderResource = args->m_textureNum + 1;
m_numPassRenderTargets = 3;
}
RenderGeometryPass(BenchmarkOptions *args, HINSTANCE hInstance, HWND hMainWnd, std::wstring &winTitle)
: RenderApp(args, hInstance, hMainWnd, winTitle) {
m_numShaderResource = args->m_textureNum + 1;
m_numPassRenderTargets = 3;
}
RenderGeometryPass(const RenderGeometryPass &rhs) = delete;
RenderGeometryPass &operator=(const RenderGeometryPass &rhs) = delete;
~RenderGeometryPass() = default;
protected:
virtual int DefineRootParameters(std::vector<CD3DX12_ROOT_PARAMETER> &rootParameters) override;
virtual int DefineStaticSamplers(std::vector<CD3DX12_STATIC_SAMPLER_DESC> &samplers) override;
virtual void CreateShaderResourceView(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, int width,
int height) override;
virtual void CreateConstantBufferResources(ID3D12Device *device) override;
virtual void UpdateConstantBufferData() override;
virtual void BuildPipelineStates(ID3D12Device *device) override;
virtual void Draw(ID3D12GraphicsCommandList *cmdList) override;
virtual void SetStatesBeforeDraw(ID3D12GraphicsCommandList *cmdList) override;
virtual void BuildShapeGeometry(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList) override;
std::unique_ptr<UploadBuffer<ObjectConstantBuffer>> m_objectCB = nullptr;
std::unique_ptr<UploadBuffer<BaseViewConstantBuffer>> m_viewCB = nullptr;
std::unique_ptr<UploadBuffer<MaterialConstantBuffer>> m_materialCB = nullptr;
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "RenderLightingPass.h"
void RenderLightingPass::CreateConstantBufferResources(ID3D12Device *device) {
m_stencilingCB = std::make_unique<UploadBuffer<StencilingConstantBuffer>>(device, 1, true);
m_viewCB = std::make_unique<UploadBuffer<ViewConstantBuffer>>(device, 1, true);
m_lightingCB = std::make_unique<UploadBuffer<DeferredLightUniformsConstantBuffer>>(device, 1, true);
m_shadowProjectionCB = std::make_unique<UploadBuffer<ShadowProjectionConstantBuffer>>(device, 1, true);
}
void RenderLightingPass::UpdateConstantBufferData() {
StencilingConstantBuffer stencilCBData;
ViewConstantBuffer viewDBData;
DeferredLightUniformsConstantBuffer lightingCBData;
ShadowProjectionConstantBuffer shadowProjectionCBData;
m_stencilingCB.get()->CopyData(0, stencilCBData);
m_viewCB.get()->CopyData(0, viewDBData);
m_lightingCB.get()->CopyData(0, lightingCBData);
m_shadowProjectionCB.get()->CopyData(0, shadowProjectionCBData);
}
void RenderLightingPass::CreateShaderResourceView(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, int width,
int height) {
// Create a descriptor heap that will store the SRV:
D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
srvHeapDesc.NumDescriptors = m_numShaderResource;
srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvDescriptorHeap)));
CD3DX12_CPU_DESCRIPTOR_HANDLE cpuHandle(m_srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
m_cbvSrvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
// Fill out the heap with actual descriptors.
for (int i = 0; i < m_numShaderResource; i++) {
Texture2D(device, cmdList, m_shaderResources[i], width, height, m_colorFormat);
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = m_shaderResources[i]->GetDesc().Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = m_shaderResources[i]->GetDesc().MipLevels;
device->CreateShaderResourceView(m_shaderResources[i].Get(), &srvDesc, cpuHandle);
cpuHandle.Offset(m_cbvSrvDescriptorSize);
}
}
int RenderLightingPass::DefineRootParameters(std::vector<CD3DX12_ROOT_PARAMETER> &rootParameters) {
const int numRootParameters = 5;
rootParameters.resize(numRootParameters);
// Root signature defines what resources are bound to the graphics pipeline.
int rootParametersIndex = 0;
// Create root signatures consisting of 3 constant buffers.
rootParameters[rootParametersIndex].InitAsConstantBufferView(rootParametersIndex, 0,
D3D12_SHADER_VISIBILITY_VERTEX);
rootParametersIndex++;
rootParameters[rootParametersIndex].InitAsConstantBufferView(rootParametersIndex, 0, D3D12_SHADER_VISIBILITY_ALL);
rootParametersIndex++;
rootParameters[rootParametersIndex].InitAsConstantBufferView(rootParametersIndex, 0, D3D12_SHADER_VISIBILITY_PIXEL);
rootParametersIndex++;
rootParameters[rootParametersIndex].InitAsConstantBufferView(rootParametersIndex, 0, D3D12_SHADER_VISIBILITY_PIXEL);
rootParametersIndex++;
// SRV root parameter
std::unique_ptr<CD3DX12_DESCRIPTOR_RANGE[]> descriptorRange = std::make_unique<CD3DX12_DESCRIPTOR_RANGE[]>(1);
descriptorRange[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, m_numShaderResource, 0,
0); // Using valid D3D12_DESCRIPTOR_RANGE_TYPE_SRV
rootParameters[rootParametersIndex].InitAsDescriptorTable(1, descriptorRange.release(),
D3D12_SHADER_VISIBILITY_PIXEL);
rootParametersIndex++;
return numRootParameters;
}
void RenderLightingPass::BuildPipelineStates(ID3D12Device *device) {
// Define shader input layout.
std::vector<D3D12_INPUT_ELEMENT_DESC> inputLayout = {D3D12_INPUT_ELEMENT_DESC{
"POSITION", // SemanticName
0, // SemanticIndex
DXGI_FORMAT_R32G32B32_FLOAT, // Format
0, // InputSlot
D3D12_APPEND_ALIGNED_ELEMENT, // AlignedByteOffset
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, // InputSlotClass
0 // InstanceDataStepRate
}};
// Create the pipeline state, which includes compiling and loading shaders.
ComPtr<ID3DBlob> vertexShader =
CompileShader(L"Shaders/DefferredLightingVertex.hlsl", nullptr, "RadialVertexMain", "vs_5_1");
ComPtr<ID3DBlob> pixelShader =
CompileShader(L"Shaders/DefferredLightingPixel.hlsl", nullptr, "DeferredLightPixelMain", "ps_5_1");
auto psoDesc = DefinePSODesc(inputLayout, vertexShader, pixelShader);
ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PSOs["deferredLighting"])));
vertexShader = CompileShader(L"Shaders/DefferredLightingVertex.hlsl", nullptr, "RadialVertexMain", "vs_5_1");
pixelShader =
CompileShader(L"Shaders/DefferredLightingPixel.hlsl", nullptr, "MainOnePassPointLightShadowPS", "ps_5_1");
psoDesc = DefinePSODesc(inputLayout, vertexShader, pixelShader);
ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PSOs["ShadowProjection"])));
}
void RenderLightingPass::SetStatesBeforeDraw(ID3D12GraphicsCommandList *cmdList) {
ID3D12DescriptorHeap *ppHeaps[] = {m_srvDescriptorHeap.Get()};
cmdList->SetDescriptorHeaps(ARRAYSIZE(ppHeaps), ppHeaps);
cmdList->SetGraphicsRootSignature(m_rootSignature.Get());
cmdList->SetGraphicsRootConstantBufferView(0, m_stencilingCB.get()->Resource()->GetGPUVirtualAddress());
cmdList->SetGraphicsRootConstantBufferView(1, m_viewCB.get()->Resource()->GetGPUVirtualAddress());
cmdList->SetGraphicsRootConstantBufferView(2, m_lightingCB.get()->Resource()->GetGPUVirtualAddress());
cmdList->SetGraphicsRootConstantBufferView(3, m_shadowProjectionCB.get()->Resource()->GetGPUVirtualAddress());
cmdList->SetGraphicsRootDescriptorTable(4, m_srvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
auto ri = m_geometry.get();
// Set vertex and index buffers
cmdList->IASetVertexBuffers(0, 1, &ri->VertexBufferView());
cmdList->IASetIndexBuffer(&ri->IndexBufferView());
cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
}
void RenderLightingPass::Draw(ID3D12GraphicsCommandList *cmdList) {
DrawShadowProjection(cmdList);
DrawLighting(cmdList);
}
void RenderLightingPass::DrawShadowProjection(ID3D12GraphicsCommandList *cmdList) {
cmdList->SetPipelineState(m_PSOs["ShadowProjection"].Get());
DrawRenderItems(cmdList, m_opts->m_num_light);
}
void RenderLightingPass::DrawLighting(ID3D12GraphicsCommandList *cmdList) {
cmdList->SetPipelineState(m_PSOs["deferredLighting"].Get());
DrawRenderItems(cmdList, m_opts->m_num_light);
}
/*
* @brief: Get the samplers.
* @return: The static samplers.
*/
int RenderLightingPass::DefineStaticSamplers(std::vector<CD3DX12_STATIC_SAMPLER_DESC> &samplerData)
{
int samplersCount = 10;
samplerData.resize(samplersCount);
int samplerIndex = 0;
CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_SceneDepthTextureSampler(
samplerIndex, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_SceneDepthTextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_GBufferATextureSampler(
samplerIndex, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_GBufferATextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_GBufferBTextureSampler(
samplerIndex, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_GBufferBTextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_GBufferCTextureSampler(
samplerIndex, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_GBufferCTextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_GBufferDTextureSampler(
samplerIndex, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_GBufferDTextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_GBufferETextureSampler(
samplerIndex, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_GBufferETextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_ScreenSpaceAOTextureSampler(
samplerIndex, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_ScreenSpaceAOTextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC LightAttenuationTextureSampler(
samplerIndex, D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_WRAP, D3D12_TEXTURE_ADDRESS_MODE_WRAP,
D3D12_TEXTURE_ADDRESS_MODE_WRAP);
samplerData[samplerIndex++] = LightAttenuationTextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC SceneTexturesStruct_CustomDepthTextureSampler(
8, // shaderRegister
D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = SceneTexturesStruct_CustomDepthTextureSampler;
const CD3DX12_STATIC_SAMPLER_DESC ShadowDepthCubeTextureSampler(9, // shaderRegister
D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, // filter
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressU
D3D12_TEXTURE_ADDRESS_MODE_CLAMP, // addressV
D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
samplerData[samplerIndex++] = ShadowDepthCubeTextureSampler;
return samplersCount;
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "RenderApp.h"
struct DeferredLightUniformsConstantBuffer {
XMFLOAT4 DeferredLightUniforms_ShadowMapChannelMask = {0.00, 0.00, 0.00, 0.00};
XMFLOAT2 DeferredLightUniforms_DistanceFadeMAD = {0.00, 0.00};
float DeferredLightUniforms_ContactShadowLength = 0.00;
float DeferredLightUniforms_VolumetricScatteringIntensity = 1.00;
UINT DeferredLightUniforms_ShadowedBits = 3;
UINT DeferredLightUniforms_LightingChannelMask = 1;
float PrePadding_DeferredLightUniforms_40 = 0.00;
float PrePadding_DeferredLightUniforms_44 = 0.00;
XMFLOAT3 DeferredLightUniforms_Position = {722.74805, 2515.36084, 94.87169};
float DeferredLightUniforms_InvRadius = 0.00195;
XMFLOAT3 DeferredLightUniforms_Color = {8.64818, 6.97867, 4.4531};
float DeferredLightUniforms_FalloffExponent = 8.00;
XMFLOAT3 DeferredLightUniforms_Direction = {1.00, 0.00, 0.00};
float DeferredLightUniforms_SpecularScale = 1.00;
XMFLOAT3 DeferredLightUniforms_Tangent = {0.00, 0.00, 1.00};
float DeferredLightUniforms_SourceRadius = 0.00;
XMFLOAT2 DeferredLightUniforms_SpotAngles = {2.00, 1.00};
float DeferredLightUniforms_SoftSourceRadius = 0.00;
float DeferredLightUniforms_SourceLength = 0.00;
float DeferredLightUniforms_RectLightBarnCosAngle = 2652.84375;
float DeferredLightUniforms_RectLightBarnLength = 5.89947E-43;
};
struct ViewConstantBuffer {
XMFLOAT4 View_InvDeviceZToWorldZTransform = {0.00, 0.00, 0.10, -1.00000E-08};
XMFLOAT4 View_TemporalAAParams = {0.00, 1.00, 0.00, 0.00};
XMFLOAT4 View_BufferSizeAndInvSize = {1384.00, 676.00, 0.00072, 0.00148};
XMFLOAT4 View_DiffuseOverrideParameter = {0.00, 0.00, 0.00, 1.00};
XMFLOAT4 View_SpecularOverrideParameter = {0.00, 0.00, 0.00, 1.00};
XMFLOAT4X4 View_ClipToView = {0.00, 0.48821, 0.00, 0.00, 0.00, 0.00, 0.00, 0.10,
0.00, 0.00, 1.00, 0.00, 0, 0, 0, 0};
XMFLOAT4X4 View_ViewToClip = {
1.00, 0.00, 0.00, 0.00, 0.00, 2.04831, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00, 0.00, 0.00, 10.00, 0.00,
};
XMFLOAT4X4 View_ScreenToWorld = {-0.04472, 0.00587, 0.48612, 0.00, -0.98725, 0.12963, -0.09239, 0.00,
-7.70195, 2584.20215, 184.65012, 1.00, 0, 0, 0, 0};
XMFLOAT3 View_WorldCameraOrigin = {-7.70195, 2584.20215, 184.65012};
float padding0 = 0;
XMFLOAT3 View_PreViewTranslation = {7.70195, -2584.20215, -184.65012};
float padding1 = 0;
XMFLOAT4 View_ScreenPositionScaleBias = {0.49928, -0.49926, 0.49926, 0.49928};
XMFLOAT4X4 View_TranslatedWorldToClip = {
1.00, 0.00, 0.00, 0.00, 0.00, 2.04831, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00, 0.00, 0.00, 10.00, 0.00,
};
UINT View_StateFrameIndexMod8View_StateFrameIndexMod8 = 1;
XMFLOAT3 Padding = {0, 0, 0}; // Add padding to maintain 16-byte alignment
};
struct StencilingConstantBuffer {
XMFLOAT4 StencilingGeometryPosAndScale = {715.04608, -68.84131, -89.77843, 530.0614};
XMFLOAT4 StencilingConeParameters = {0.00, 0.00, 0.00, 0.00};
XMFLOAT4X4 StencilingConeTransform = {0.00, 0.00, -0.005, 0.00, -1.00, 1.00, 0.50, 1.00,
1.00, 0.00, -1.00143, -1.00, 0.00, -1.00, 0.00, 0.00};
XMFLOAT3 StencilingPreViewTranslation = {1.00, 0.00, 0.00};
};
struct ShadowProjectionConstantBuffer {
XMFLOAT4 LightPositionAndInvRadius = {722.74805, 2515.36084, 94.87169, 0.00195};
XMFLOAT4 PointLightDepthBiasAndProjParameters = {0.025, 0.00, -0.99805, -1.00};
XMFLOAT4X4 ShadowViewProjectionMatrices[6] = {{0.00, 0.00, -1.00196, -1.00, 0.00, -1.00, 0.00, 0.00, 1.00, 0.00,
0.00, 0.00, -94.87168, 2515.3606, -725.16437, -722.74805},
{0.00, 0.00, 1.00196, 1.00, 0.00, -1.00, 0.00, 0.00, -1.00, 0.00,
0.00, 0.00, 94.87168, 2515.3606, 723.16046, 722.74805},
{-1.00, 0.00, 0.00, 0.00, 0.00, 0.00, -1.00196, -1.00, 0.00, 1.00,
0.00, 0.00, -722.74799, -94.87168, 2519.28125, 2515.36084},
{-1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00196, 1.00, 0.00, -1.00,
0.00, 0.00, -722.74799, 94.87168, -2521.28516, -2515.36084},
{-1.00, 0.00, 0.00, 0.00, 0.00, -1.00, 0.00, 0.00, 0.00, 0.00,
-1.00196, -1.00, -722.74799, 2515.3606, 94.05539, 94.87169},
{1.00, 0.00, 0.00, 0.00, 0.00, -1.00, 0.00, 0.00, 0.00, 0.00, 1.00196,
1.00, 722.74799, 2515.3606, -96.05931, -94.87169}};
float ShadowSharpen = 1;
float ShadowFadeFraction = 1;
float InvShadowmapResolution = 0.00098;
};
class RenderLightingPass : public RenderApp {
public:
RenderLightingPass(BenchmarkOptions *opts) : RenderApp(opts) {
m_numShaderResource = 10;
m_numPassRenderTargets = 1;
}
RenderLightingPass(BenchmarkOptions *args, HINSTANCE hInstance, HWND hMainWnd, std::wstring &winTitle)
: RenderApp(args, hInstance, hMainWnd, winTitle) {}
RenderLightingPass(const RenderLightingPass &rhs) = delete;
RenderLightingPass &operator=(const RenderLightingPass &rhs) = delete;
~RenderLightingPass() = default;
void DrawShadowProjection(ID3D12GraphicsCommandList *cmdList);
void DrawLighting(ID3D12GraphicsCommandList *cmdList);
protected:
virtual int DefineRootParameters(std::vector<CD3DX12_ROOT_PARAMETER> &rootParameters) override;
virtual int DefineStaticSamplers(std::vector<CD3DX12_STATIC_SAMPLER_DESC> &samplers) override;
virtual void CreateShaderResourceView(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, int width,
int height) override;
virtual void CreateConstantBufferResources(ID3D12Device *device) override;
virtual void UpdateConstantBufferData() override;
virtual void BuildPipelineStates(ID3D12Device *device) override;
virtual void Draw(ID3D12GraphicsCommandList *cmdList) override;
virtual void SetStatesBeforeDraw(ID3D12GraphicsCommandList *cmdList) override;
std::unique_ptr<UploadBuffer<StencilingConstantBuffer>> m_stencilingCB = nullptr;
std::unique_ptr<UploadBuffer<ViewConstantBuffer>> m_viewCB = nullptr;
std::unique_ptr<UploadBuffer<DeferredLightUniformsConstantBuffer>> m_lightingCB = nullptr;
std::unique_ptr<UploadBuffer<ShadowProjectionConstantBuffer>> m_shadowProjectionCB = nullptr;
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "RenderShadowMapPass.h"
int RenderShadowMapPass::DefineRootParameters(std::vector<CD3DX12_ROOT_PARAMETER> &rootParameters) {
const int numRootParameters = 1;
rootParameters.resize(numRootParameters);
rootParameters[0].InitAsConstantBufferView(0); // obj cb
return numRootParameters;
}
int RenderShadowMapPass::DefineStaticSamplers(std::vector<CD3DX12_STATIC_SAMPLER_DESC> &samplers) { return 0; }
void RenderShadowMapPass::CreateShaderResourceView(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, int width,
int height) {
return;
}
void RenderShadowMapPass::CreateConstantBufferResources(ID3D12Device *device) {
m_viewCB = std::make_unique<UploadBuffer<ShadowViewConstantBuffer>>(device, 1, true);
}
void RenderShadowMapPass::UpdateConstantBufferData() {
ShadowViewConstantBuffer viewDBData;
viewDBData.world = MathHelper::Identity4x4();
viewDBData.projection = MathHelper::Identity4x4();
m_viewCB.get()->CopyData(0, viewDBData);
}
void RenderShadowMapPass::BuildPipelineStates(ID3D12Device *device) {
// Define shader input layout.
std::vector<D3D12_INPUT_ELEMENT_DESC> inputLayout = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}
};
// Create the pipeline state, which includes compiling and loading shaders.
ComPtr<ID3DBlob> vertexShader = CompileShader(L"Shaders/ShadowMap.hlsl", nullptr, "VS", "vs_5_1");
ComPtr<ID3DBlob> pixelShader = CompileShader(L"Shaders/ShadowMap.hlsl", nullptr, "PS", "ps_5_1");
CD3DX12_DEPTH_STENCIL_DESC depthStencilDesc(D3D12_DEFAULT);
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
depthStencilDesc.StencilEnable = false;
auto psoDesc = DefinePSODesc(inputLayout, vertexShader, pixelShader);
psoDesc.DSVFormat = m_deviceResources->m_depthBufferFormat;
psoDesc.RasterizerState.DepthBias = 100000;
psoDesc.RasterizerState.DepthBiasClamp = 0.0f;
psoDesc.RasterizerState.SlopeScaledDepthBias = 1.0f;
psoDesc.DepthStencilState = depthStencilDesc;
ThrowIfFailed(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PSOs["ShadowMap"])));
}
void RenderShadowMapPass::SetStatesBeforeDraw(ID3D12GraphicsCommandList *cmdList) {
// Set necessary state.
cmdList->SetPipelineState(m_PSOs["ShadowMap"].Get());
cmdList->SetGraphicsRootSignature(m_rootSignature.Get());
auto dsv = m_deviceResources->GetDepthStencilView();
cmdList->ClearDepthStencilView(dsv, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
auto device = m_deviceResources->GetD3DDevice();
cmdList->OMSetRenderTargets(1, &GetRenderTargetView(device), true, &dsv);
// Set root arguments.
cmdList->SetGraphicsRootConstantBufferView(0, m_viewCB->Resource()->GetGPUVirtualAddress());
auto ri = m_geometry.get();
// Set vertex and index buffers
cmdList->IASetVertexBuffers(0, 1, &ri->VertexBufferView());
cmdList->IASetIndexBuffer(&ri->IndexBufferView());
cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
}
void RenderShadowMapPass::Draw(ID3D12GraphicsCommandList *cmdList) { DrawRenderItems(cmdList, m_opts->m_num_object); }
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "RenderApp.h"
struct ShadowViewConstantBuffer {
XMFLOAT4X4 world;
XMFLOAT4X4 projection;
};
class RenderShadowMapPass : public RenderApp {
public:
RenderShadowMapPass(BenchmarkOptions *opts) : RenderApp(opts) {}
RenderShadowMapPass(BenchmarkOptions *args, HINSTANCE hInstance, HWND hMainWnd, std::wstring &winTitle)
: RenderApp(args, hInstance, hMainWnd, winTitle) {}
RenderShadowMapPass(const RenderShadowMapPass &rhs) = delete;
RenderShadowMapPass &operator=(const RenderShadowMapPass &rhs) = delete;
~RenderShadowMapPass() = default;
protected:
virtual int DefineRootParameters(std::vector<CD3DX12_ROOT_PARAMETER> &rootParameters) override;
virtual int DefineStaticSamplers(std::vector<CD3DX12_STATIC_SAMPLER_DESC> &samplers) override;
virtual void CreateShaderResourceView(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, int width,
int height) override;
virtual void CreateConstantBufferResources(ID3D12Device *device) override;
virtual void UpdateConstantBufferData() override;
virtual void BuildPipelineStates(ID3D12Device *device) override;
virtual void Draw(ID3D12GraphicsCommandList *cmdList) override;
virtual void SetStatesBeforeDraw(ID3D12GraphicsCommandList *cmdList) override;
std::unique_ptr<UploadBuffer<ShadowViewConstantBuffer>> m_viewCB = nullptr;
};
// Scene cube.
TextureCube gCubeMap : register(t0);
// An array of textures, which is only supported in shader model 5.1+. Unlike Texture2DArray, the textures
// in this array can be different sizes and formats, making it more flexible than texture arrays.
Texture2D gTextureMaps[TEXTURECOUNT] : register(t1);
SamplerState gsamAnisotropicWrap : register(s0);
// Constant data that varies per frame.
cbuffer D3DObjectConstantBuffer : register(b0)
{
float4x4 gWorld;
float4x4 gTexTransform;
uint gMaterialIndex;
};
// Constant data that varies per material.
cbuffer PassConstantBuffer : register(b1)
{
float4x4 gView;
float4x4 gViewProj;
float3 gEyePosW;
};
cbuffer MaterialDataConstantBuffer : register(b2)
{
float4 DiffuseAlbedo;
float3 FresnelR0;
float Roughness;
float4x4 MatTransform;
uint DiffuseMapIndex;
uint NormalMapIndex;
};
//---------------------------------------------------------------------------------------
// Transforms a normal map sample to world space.
//---------------------------------------------------------------------------------------
float3 NormalSampleToWorldSpace(float3 normalMapSample, float3 unitNormalW, float3 tangentW)
{
// Transform from [0,1] to [-1,1].
float3 normalT = 2.0f * normalMapSample - 1.0f;
float3 N = unitNormalW;
float3 T = normalize(tangentW - dot(tangentW, N) * N);
float3 B = cross(N, T);
float3x3 TBN = float3x3(T, B, N);
// Trans to world space.
float3 bumpedNormalW = mul(normalT, TBN);
return bumpedNormalW;
}
struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 TexC : TEXCOORD;
float3 TangentU : TANGENT;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float3 TangentW : TANGENT;
float2 TexC : TEXCOORD;
};
struct PixelOut
{
float4 position : SV_Target0;
float4 normal : SV_Target1;
float4 color : SV_Target2;
};
float3 SchlickFresnel(float3 R0, float3 normal, float3 lightVec)
{
float cosIncidentAngle = saturate(dot(normal, lightVec));
float f0 = 1.0f - cosIncidentAngle;
float3 reflectPercent = R0 + (1.0f - R0) * (f0 * f0 * f0 * f0 * f0);
return reflectPercent;
}
VertexOut VS(VertexIn vin)
{
VertexOut vout = (VertexOut)0.0f;
float4 posW = mul(float4(vin.PosL, 1.0f), gWorld);
vout.PosW = posW.xyz;
vout.PosH = mul(posW, gViewProj);
vout.NormalW = mul(vin.NormalL, (float3x3) gWorld);
vout.TangentW = mul(vin.TangentU, (float3x3) gWorld);
float4 texC = mul(float4(vin.TexC, 0.0f, 1.0f), gTexTransform);
vout.TexC = mul(texC, MatTransform).xy;
return vout;
}
PixelOut PS(VertexOut pin)
{
// Normalize normap map.
pin.NormalW = normalize(pin.NormalW);
float4 normalSample = gTextureMaps[NormalMapIndex].Sample(gsamAnisotropicWrap, pin.TexC);
float3 bumpedNormalW = NormalSampleToWorldSpace(normalSample.xyz, pin.NormalW, pin.TangentW);
float4 diffuseAlbedo = DiffuseAlbedo *
gTextureMaps[DiffuseMapIndex].Sample(gsamAnisotropicWrap, pin.TexC);
const float shininess = (1.0f - Roughness) * normalSample.a;
PixelOut pout;
pout.position = float4(pin.PosW, FresnelR0.x);
pout.normal = float4(bumpedNormalW, shininess);
float3 toEyeW = normalize(gEyePosW - pin.PosW);
float3 ref = reflect(-toEyeW, bumpedNormalW);
float4 reflectColor = gCubeMap.Sample(gsamAnisotropicWrap, ref);
float3 fresnelFactor = SchlickFresnel(FresnelR0, bumpedNormalW, ref);
pout.color = float4(diffuseAlbedo.xyz + shininess * fresnelFactor * reflectColor.xyz, 1.0f);
return pout;
}
cbuffer StencilingParametersConstantBuffer : register(b0)
{
float4 StencilingGeometryPosAndScale;
float4 StencilingConeParameters;
float4x4 StencilingConeTransform;
float3 StencilingPreViewTranslation;
float padding;
};
cbuffer ViewConstantBuffer : register(b1)
{
float4 View_InvDeviceZToWorldZTransform;
float4 View_TemporalAAParams;
float4 View_BufferSizeAndInvSize;
float4 View_DiffuseOverrideParameter;
float4 View_SpecularOverrideParameter;
float4x4 View_ClipToView;
float4x4 View_ViewToClip;
float4x4 View_ScreenToWorld;
float3 View_WorldCameraOrigin;
float Padding0;
float3 View_PreViewTranslation;
float Padding1;
float4 View_ScreenPositionScaleBias;
float4x4 View_TranslatedWorldToClip;
uint View_StateFrameIndexMod8;
float3 Padding; // Add padding to maintain 16-byte alignment
};
struct VertexInput
{
float3 InPosition : POSITION;
};
struct VertexOutput
{
float4 OutScreenPosition : TEXCOORD0;
float4 OutPosition : SV_POSITION;
};
const static float PI = 3.1415926535897932f;
const static float MaxHalfFloat = 65504.0f;
VertexOutput RadialVertexMain1(VertexInput input, uint InVertexId : SV_VertexID)
{
//printf ("RadialVertexMain\n");
VertexOutput output;
float3 WorldPosition;
uint NumSides = StencilingConeParameters.x;
if (NumSides != 0)
{
float SphereRadius = StencilingConeParameters.w;
float ConeAngle = StencilingConeParameters.z;
const float InvCosRadiansPerSide = 1.0f / cos(PI / (float)NumSides);
const float ZRadius = SphereRadius * cos(ConeAngle);
const float TanConeAngle = tan(ConeAngle);
uint NumSlices = StencilingConeParameters.y;
uint CapIndexStart = NumSides * NumSlices;
if (InVertexId < CapIndexStart)
{
uint SliceIndex = InVertexId / NumSides;
uint SideIndex = InVertexId % NumSides;
const float CurrentAngle = SideIndex * 2 * PI / (float)NumSides;
const float DistanceDownConeDirection =
ZRadius * SliceIndex / (float)(NumSlices - 1);
const float SliceRadius =
DistanceDownConeDirection * TanConeAngle * InvCosRadiansPerSide;
const float3 LocalPosition = float3(
ZRadius * SliceIndex / (float)(NumSlices - 1),
SliceRadius * sin(CurrentAngle), SliceRadius * cos(CurrentAngle));
WorldPosition =
mul(float4(LocalPosition, 1), StencilingConeTransform).xyz +
StencilingPreViewTranslation;
}
else
{
const float CapRadius = ZRadius * tan(ConeAngle);
uint VertexId = InVertexId - CapIndexStart;
uint SliceIndex = VertexId / NumSides;
uint SideIndex = VertexId % NumSides;
const float UnadjustedSliceRadius =
CapRadius * SliceIndex / (float)(NumSlices - 1);
const float SliceRadius = UnadjustedSliceRadius * InvCosRadiansPerSide;
const float ZDistance =
sqrt(SphereRadius * SphereRadius -
UnadjustedSliceRadius * UnadjustedSliceRadius);
const float CurrentAngle = SideIndex * 2 * PI / (float)NumSides;
const float3 LocalPosition =
float3(ZDistance, SliceRadius * sin(CurrentAngle),
SliceRadius * cos(CurrentAngle));
WorldPosition =
mul(float4(LocalPosition, 1), StencilingConeTransform).xyz +
StencilingPreViewTranslation;
}
}
else
{
WorldPosition = input.InPosition * StencilingGeometryPosAndScale.w +
StencilingGeometryPosAndScale.xyz;
}
output.OutScreenPosition = output.OutPosition =
mul(float4(WorldPosition, 1), View_TranslatedWorldToClip);
return output;
}
VertexOutput RadialVertexMain(VertexInput input, uint InVertexId : SV_VertexID)
{
VertexOutput output;
float3 WorldPosition = {0,0, 0};
uint NumSides = StencilingConeParameters.x;
if (NumSides != 0)
{
float SphereRadius = StencilingConeParameters.w;
float ConeAngle = StencilingConeParameters.z;
const float InvCosRadiansPerSide = 1.0f / cos(PI / (float)NumSides);
const float ZRadius = SphereRadius * cos(ConeAngle);
const float TanConeAngle = tan(ConeAngle);
uint NumSlices = StencilingConeParameters.y;
uint CapIndexStart = NumSides * NumSlices;
if (InVertexId < CapIndexStart)
{
uint SliceIndex = InVertexId / NumSides;
uint SideIndex = InVertexId % NumSides;
const float CurrentAngle = SideIndex * 2 * PI / (float)NumSides;
const float DistanceDownConeDirection =
ZRadius * SliceIndex / (float)(NumSlices - 1);
const float SliceRadius =
DistanceDownConeDirection * TanConeAngle * InvCosRadiansPerSide;
const float3 LocalPosition = float3(
ZRadius * SliceIndex / (float)(NumSlices - 1),
SliceRadius * sin(CurrentAngle), SliceRadius * cos(CurrentAngle));
float4 position = mul(float4(LocalPosition, 1), StencilingConeTransform);
WorldPosition = position.xyz + StencilingPreViewTranslation;
}
else
{
const float CapRadius = ZRadius * tan(ConeAngle);
uint VertexId = InVertexId - CapIndexStart;
uint SliceIndex = VertexId / NumSides;
uint SideIndex = VertexId % NumSides;
const float UnadjustedSliceRadius =
CapRadius * SliceIndex / (float)(NumSlices - 1);
const float SliceRadius = UnadjustedSliceRadius * InvCosRadiansPerSide;
const float ZDistance =
sqrt(SphereRadius * SphereRadius -
UnadjustedSliceRadius * UnadjustedSliceRadius);
const float CurrentAngle = SideIndex * 2 * PI / (float)NumSides;
const float3 LocalPosition =
float3(ZDistance, SliceRadius * sin(CurrentAngle),
SliceRadius * cos(CurrentAngle));
float4 position = mul(float4(LocalPosition, 1), StencilingConeTransform);
WorldPosition = position.xyz + StencilingPreViewTranslation;
}
}
else
{
WorldPosition = input.InPosition * StencilingGeometryPosAndScale.w +
StencilingGeometryPosAndScale.xyz;
}
output.OutScreenPosition = output.OutPosition =
mul(float4(WorldPosition, 1), View_TranslatedWorldToClip);
return output;
}
cbuffer ObjectConstantBuffer : register(b0)
{
float4x4 gWorld;
float4x4 gViewProj;
};
struct VertexIn
{
float3 PosL : POSITION;
float2 TexC : TEXCOORD0;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
};
void SetShadowDepthOutputs(float4 WorldPosition, float4x4 gViewProj, out float4 OutPosition, out float ShadowDepth)
{
// Transform the vertex position from world to view
OutPosition = mul(WorldPosition, gViewProj);
float DepthBias = 0.01;
float InvMaxSubjectDepth = 0.001;
// Output linear, normalized depth
ShadowDepth = OutPosition.z * InvMaxSubjectDepth + DepthBias;
OutPosition.z = ShadowDepth * OutPosition.w;
}
// Generate depth info from the view of light.
VertexOut VS(VertexIn vin)
{
VertexOut vout;
// Transform the vertex position from object / local space to world space
float4 WorldPos = mul(float4(vin.PosL, 1.0), gWorld);
float dummy; // Corrected the variable name
SetShadowDepthOutputs(
WorldPos,
gViewProj,
vout.PosH,
dummy
);
return vout;
}
void PS(VertexOut pin)
{
// Pixel shader implementation goes here
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment