refactor: 删除旧的RHI实现,添加D3D12测试用例和第二阶段计划
This commit is contained in:
@@ -43,6 +43,7 @@ add_subdirectory(containers)
|
||||
add_subdirectory(memory)
|
||||
add_subdirectory(threading)
|
||||
add_subdirectory(debug)
|
||||
add_subdirectory(D3D12)
|
||||
|
||||
# ============================================================
|
||||
# Test Summary
|
||||
|
||||
26
tests/D3D12/CMakeLists.txt
Normal file
26
tests/D3D12/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(D3D12)
|
||||
|
||||
add_executable(D3D12
|
||||
WIN32
|
||||
main.cpp
|
||||
stbi/stb_image.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(D3D12 PRIVATE
|
||||
UNICODE
|
||||
_UNICODE
|
||||
)
|
||||
|
||||
target_include_directories(D3D12 PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/tests/D3D12
|
||||
${CMAKE_SOURCE_DIR}/tests/D3D12/stbi
|
||||
)
|
||||
|
||||
target_link_libraries(D3D12 PRIVATE
|
||||
d3d12
|
||||
dxgi
|
||||
d3dcompiler
|
||||
winmm
|
||||
)
|
||||
319
tests/D3D12/RHI/Enums.h
Normal file
319
tests/D3D12/RHI/Enums.h
Normal file
@@ -0,0 +1,319 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
enum class ShaderType : uint8_t {
|
||||
Vertex,
|
||||
Hull,
|
||||
Domain,
|
||||
Geometry,
|
||||
Pixel,
|
||||
Compute,
|
||||
Amplification,
|
||||
Mesh,
|
||||
Library
|
||||
};
|
||||
|
||||
enum class CullMode : uint8_t {
|
||||
None = 1,
|
||||
Front = 2,
|
||||
Back = 3
|
||||
};
|
||||
|
||||
enum class FillMode : uint8_t {
|
||||
Wireframe = 2,
|
||||
Solid = 3
|
||||
};
|
||||
|
||||
enum class BlendOp : uint8_t {
|
||||
Add = 1,
|
||||
Subtract = 2,
|
||||
ReverseSubtract = 3,
|
||||
Min = 4,
|
||||
Max = 5,
|
||||
LogicalClear = 8,
|
||||
LogicalSet = 9,
|
||||
LogicalCopy = 10,
|
||||
LogicalCopyInverted = 11,
|
||||
LogicalNoop = 12,
|
||||
LogicalInvert = 13,
|
||||
LogicalAnd = 14,
|
||||
LogicalNand = 15,
|
||||
LogicalOr = 16,
|
||||
LogicalNor = 17,
|
||||
LogicalXor = 18,
|
||||
LogicalEquiv = 19,
|
||||
LogicalAndReverse = 20,
|
||||
LogicalAndInverted = 21,
|
||||
LogicalOrReverse = 22,
|
||||
LogicalOrInverted = 23
|
||||
};
|
||||
|
||||
enum class BlendFactor : uint8_t {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
SrcColor = 2,
|
||||
InvSrcColor = 3,
|
||||
SrcAlpha = 4,
|
||||
InvSrcAlpha = 5,
|
||||
DstAlpha = 6,
|
||||
InvDstAlpha = 7,
|
||||
DstColor = 8,
|
||||
InvDstColor = 9,
|
||||
SrcAlphaSat = 10,
|
||||
BlendFactor = 11,
|
||||
InvBlendFactor = 12,
|
||||
Src1Color = 13,
|
||||
InvSrc1Color = 14,
|
||||
Src1Alpha = 15,
|
||||
InvSrc1Alpha = 16
|
||||
};
|
||||
|
||||
enum class ComparisonFunc : uint8_t {
|
||||
Never = 1,
|
||||
Less = 2,
|
||||
Equal = 3,
|
||||
LessEqual = 4,
|
||||
Greater = 5,
|
||||
NotEqual = 6,
|
||||
GreaterEqual = 7,
|
||||
Always = 8
|
||||
};
|
||||
|
||||
enum class StencilOp : uint8_t {
|
||||
Keep = 1,
|
||||
Zero = 2,
|
||||
Replace = 3,
|
||||
IncrSat = 4,
|
||||
DecrSat = 5,
|
||||
Invert = 6,
|
||||
Incr = 7,
|
||||
Decr = 8
|
||||
};
|
||||
|
||||
enum class TextureType : uint8_t {
|
||||
Texture1D,
|
||||
Texture2D,
|
||||
Texture2DArray,
|
||||
Texture3D,
|
||||
TextureCube,
|
||||
TextureCubeArray
|
||||
};
|
||||
|
||||
enum class BufferType : uint8_t {
|
||||
Vertex,
|
||||
Index,
|
||||
Constant,
|
||||
ReadBack,
|
||||
Indirect,
|
||||
RaytracingAccelerationStructure,
|
||||
ShaderBindingTable
|
||||
};
|
||||
|
||||
enum class DescriptorType : uint8_t {
|
||||
CBV,
|
||||
SRV,
|
||||
UAV,
|
||||
Sampler,
|
||||
RTV,
|
||||
DSV
|
||||
};
|
||||
|
||||
enum class PipelineType : uint8_t {
|
||||
Graphics,
|
||||
Compute,
|
||||
Raytracing
|
||||
};
|
||||
|
||||
enum class CommandQueueType : uint8_t {
|
||||
Direct,
|
||||
Compute,
|
||||
Copy
|
||||
};
|
||||
|
||||
enum class LoadAction : uint8_t {
|
||||
Undefined = 0,
|
||||
Load = 1,
|
||||
Clear = 2
|
||||
};
|
||||
|
||||
enum class StoreAction : uint8_t {
|
||||
Undefined = 0,
|
||||
Store = 1,
|
||||
Resolve = 2,
|
||||
StoreAndResolve = 3,
|
||||
Discard = 4
|
||||
};
|
||||
|
||||
enum class PresentFlags : uint8_t {
|
||||
None = 0,
|
||||
AllowTearing = 1,
|
||||
StrictlyTimedFrame = 2,
|
||||
AllowDisplayLatencyWaitableObject = 4
|
||||
};
|
||||
|
||||
enum class IndirectDrawArguments : uint32_t {
|
||||
VertexCountPerInstance = 0,
|
||||
InstanceCount = 4,
|
||||
StartVertexLocation = 8,
|
||||
StartInstanceLocation = 12
|
||||
};
|
||||
|
||||
enum class IndirectDispatchArguments : uint32_t {
|
||||
ThreadGroupCountX = 0,
|
||||
ThreadGroupCountY = 4,
|
||||
ThreadGroupCountZ = 8
|
||||
};
|
||||
|
||||
enum class StencilOpDesc : uint8_t {
|
||||
StencilFailOp,
|
||||
StencilDepthFailOp,
|
||||
StencilPassOp,
|
||||
StencilFunc
|
||||
};
|
||||
|
||||
enum class BlendStateFlag : uint8_t {
|
||||
None = 0,
|
||||
IndependentBlendEnable = 1,
|
||||
IndependentBlendEnable_8Targets = 2
|
||||
};
|
||||
|
||||
enum class DepthStencilStateFlag : uint8_t {
|
||||
None = 0,
|
||||
DepthWrite = 1,
|
||||
StencilWrite = 2
|
||||
};
|
||||
|
||||
enum class TextureAddressMode : uint8_t {
|
||||
Wrap = 1,
|
||||
Mirror = 2,
|
||||
Clamp = 3,
|
||||
Border = 4,
|
||||
MirrorOnce = 5
|
||||
};
|
||||
|
||||
enum class FilterMode : uint8_t {
|
||||
Point = 0,
|
||||
Linear = 1,
|
||||
Anisotropic = 2,
|
||||
ComparisonPoint = 3,
|
||||
ComparisonLinear = 4,
|
||||
ComparisonAnisotropic = 5,
|
||||
MinimumPoint = 7,
|
||||
MinimumLinear = 8,
|
||||
MinimumAnisotropic = 9,
|
||||
MaximumPoint = 11,
|
||||
MaximumLinear = 12,
|
||||
MaximumAnisotropic = 13
|
||||
};
|
||||
|
||||
enum class BorderColor : uint8_t {
|
||||
TransparentBlack = 0,
|
||||
OpaqueBlack = 1,
|
||||
OpaqueWhite = 2
|
||||
};
|
||||
|
||||
enum class LogicOp : uint8_t {
|
||||
Clear = 0,
|
||||
Set = 1,
|
||||
Copy = 2,
|
||||
CopyInverted = 3,
|
||||
Noop = 4,
|
||||
Invert = 5,
|
||||
And = 6,
|
||||
Nand = 7,
|
||||
Or = 8,
|
||||
Nor = 9,
|
||||
Xor = 10,
|
||||
Equiv = 11,
|
||||
AndReverse = 12,
|
||||
AndInverted = 13,
|
||||
OrReverse = 14,
|
||||
OrInverted = 15
|
||||
};
|
||||
|
||||
enum class ColorWriteMask : uint8_t {
|
||||
Red = 1,
|
||||
Green = 2,
|
||||
Blue = 4,
|
||||
Alpha = 8,
|
||||
All = 15
|
||||
};
|
||||
|
||||
inline ColorWriteMask operator|(ColorWriteMask a, ColorWriteMask b) {
|
||||
return static_cast<ColorWriteMask>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
||||
}
|
||||
|
||||
enum class ResourceBarrierType : uint8_t {
|
||||
Transition,
|
||||
Aliasing,
|
||||
UAV
|
||||
};
|
||||
|
||||
enum class RootParameterType : uint8_t {
|
||||
DescriptorTable,
|
||||
Constants,
|
||||
CBV,
|
||||
SRV,
|
||||
UAV
|
||||
};
|
||||
|
||||
enum class ShaderRegisterType : uint8_t {
|
||||
CBV,
|
||||
SRV,
|
||||
UAV,
|
||||
Sampler
|
||||
};
|
||||
|
||||
enum class RootSignatureVersion : uint8_t {
|
||||
Version1,
|
||||
Version1_0 = Version1,
|
||||
Version1_1
|
||||
};
|
||||
|
||||
enum class ClearDepthStencilFlags : uint8_t {
|
||||
Depth = 1,
|
||||
Stencil = 2,
|
||||
DepthAndStencil = 3
|
||||
};
|
||||
|
||||
enum class QueryHeapFlags : uint8_t {
|
||||
None = 0,
|
||||
Precision = 1
|
||||
};
|
||||
|
||||
enum class PipelineStateFlags : uint8_t {
|
||||
None = 0,
|
||||
DebugName = 1
|
||||
};
|
||||
|
||||
enum class BufferUAVFlags : uint8_t {
|
||||
None = 0,
|
||||
Raw = 1,
|
||||
Append = 2,
|
||||
Counter = 4
|
||||
};
|
||||
|
||||
enum class TextureLayout : uint8_t {
|
||||
Unknown,
|
||||
RowMajor,
|
||||
_64KB_UNDEFINED_SWIZZLE,
|
||||
Standard64KB
|
||||
};
|
||||
|
||||
enum class CommandListFlags : uint8_t {
|
||||
None = 0,
|
||||
DisallowSetName = 1
|
||||
};
|
||||
|
||||
enum class FenceFlags : uint8_t {
|
||||
None = 0,
|
||||
Signal = 1,
|
||||
Wait = 2
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
BIN
tests/D3D12/Res/Image/earth_d.jpg
Normal file
BIN
tests/D3D12/Res/Image/earth_d.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
BIN
tests/D3D12/Res/Image/head.png
Normal file
BIN
tests/D3D12/Res/Image/head.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
tests/D3D12/Res/Model/Sphere.lhsm
Normal file
BIN
tests/D3D12/Res/Model/Sphere.lhsm
Normal file
Binary file not shown.
99
tests/D3D12/Res/Shader/gs.hlsl
Normal file
99
tests/D3D12/Res/Shader/gs.hlsl
Normal file
@@ -0,0 +1,99 @@
|
||||
struct VertexData{
|
||||
float4 position:POSITION;
|
||||
float4 texcoord:TEXCOORD0;
|
||||
float4 normal:NORMAL;
|
||||
float4 tangent:TANGENT;
|
||||
};
|
||||
|
||||
struct VSOut{
|
||||
float4 position:SV_POSITION;
|
||||
float4 normal:NORMAL;
|
||||
float4 texcoord:TEXCOORD0;
|
||||
};
|
||||
|
||||
static const float PI=3.141592;
|
||||
cbuffer globalConstants:register(b0){
|
||||
float4 misc;
|
||||
};
|
||||
|
||||
Texture2D T_DiffuseTexture:register(t0);
|
||||
SamplerState samplerState:register(s0);
|
||||
|
||||
struct MaterialData{
|
||||
float r;
|
||||
};
|
||||
StructuredBuffer<MaterialData> materialData:register(t0,space1);
|
||||
cbuffer DefaultVertexCB:register(b1){
|
||||
float4x4 ProjectionMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float4x4 ModelMatrix;
|
||||
float4x4 IT_ModelMatrix;
|
||||
float4x4 ReservedMemory[1020];
|
||||
};
|
||||
|
||||
VSOut MainVS(VertexData inVertexData){
|
||||
VSOut vo;
|
||||
vo.normal=mul(IT_ModelMatrix,inVertexData.normal);
|
||||
float4 positionWS=mul(ModelMatrix,inVertexData.position);
|
||||
float4 positionVS=mul(ViewMatrix,positionWS);
|
||||
vo.position=mul(ProjectionMatrix,positionVS);
|
||||
//vo.position=float4(positionWS.xyz+vo.normal.xyz*sin(misc.x)*0.2f,1.0f);
|
||||
vo.texcoord=inVertexData.texcoord;
|
||||
return vo;
|
||||
}
|
||||
|
||||
[maxvertexcount(4)]
|
||||
void MainGS(triangle VSOut inPoint[3],uint inPrimitiveID:SV_PrimitiveID,
|
||||
inout TriangleStream<VSOut> outTriangleStream){
|
||||
outTriangleStream.Append(inPoint[0]);
|
||||
outTriangleStream.Append(inPoint[1]);
|
||||
outTriangleStream.Append(inPoint[2]);
|
||||
/*VSOut vo;
|
||||
float3 positionWS=inPoint[0].position.xyz;
|
||||
float3 N=normalize(inPoint[0].normal.xyz);
|
||||
vo.normal=float4(N,0.0f);
|
||||
float3 helperVec=abs(N.y)>0.999?float3(0.0f,0.0f,1.0f):float3(0.0f,1.0f,0.0f);
|
||||
float3 tangent=normalize(cross(N,helperVec));//u
|
||||
float3 bitangent=normalize(cross(tangent,N));//v
|
||||
float scale=materialData[inPrimitiveID].r;
|
||||
|
||||
|
||||
float3 p0WS=positionWS-(bitangent*0.5f-tangent*0.5f)*scale;//left bottom
|
||||
float4 p0VS=mul(ViewMatrix,float4(p0WS,1.0f));
|
||||
vo.position=mul(ProjectionMatrix,p0VS);
|
||||
vo.texcoord=float4(0.0f,1.0f,0.0f,0.0f);
|
||||
outTriangleStream.Append(vo);
|
||||
|
||||
float3 p1WS=positionWS-(bitangent*0.5f+tangent*0.5f)*scale;//right bottom
|
||||
float4 p1VS=mul(ViewMatrix,float4(p1WS,1.0f));
|
||||
vo.position=mul(ProjectionMatrix,p1VS);
|
||||
vo.texcoord=float4(1.0f,1.0f,0.0f,0.0f);
|
||||
outTriangleStream.Append(vo);
|
||||
|
||||
float3 p2WS=positionWS+(bitangent*0.5f+tangent*0.5f)*scale;//left top
|
||||
float4 p2VS=mul(ViewMatrix,float4(p2WS,1.0f));
|
||||
vo.position=mul(ProjectionMatrix,p2VS);
|
||||
vo.texcoord=float4(0.0f,0.0f,0.0f,0.0f);
|
||||
outTriangleStream.Append(vo);
|
||||
|
||||
float3 p3WS=positionWS+(bitangent*0.5f-tangent*0.5f)*scale;//right top
|
||||
float4 p3VS=mul(ViewMatrix,float4(p3WS,1.0f));
|
||||
vo.position=mul(ProjectionMatrix,p3VS);
|
||||
vo.texcoord=float4(1.0f,0.0f,0.0f,0.0f);
|
||||
outTriangleStream.Append(vo);*/
|
||||
|
||||
}
|
||||
|
||||
float4 MainPS(VSOut inPSInput):SV_TARGET{
|
||||
float3 N=normalize(inPSInput.normal.xyz);
|
||||
float3 bottomColor=float3(0.1f,0.4f,0.6f);
|
||||
float3 topColor=float3(0.7f,0.7f,0.7f);
|
||||
float theta=asin(N.y);//-PI/2 ~ PI/2
|
||||
theta/=PI;//-0.5~0.5
|
||||
theta+=0.5f;//0.0~1.0
|
||||
float ambientColorIntensity=1.0;
|
||||
float3 ambientColor=lerp(bottomColor,topColor,theta)*ambientColorIntensity;
|
||||
float4 diffuseColor=T_DiffuseTexture.Sample(samplerState,inPSInput.texcoord.xy);
|
||||
float3 surfaceColor=diffuseColor.rgb;
|
||||
return float4(surfaceColor,1.0f);
|
||||
}
|
||||
65
tests/D3D12/Res/Shader/ndctriangle.hlsl
Normal file
65
tests/D3D12/Res/Shader/ndctriangle.hlsl
Normal file
@@ -0,0 +1,65 @@
|
||||
struct VertexData{
|
||||
float4 position:POSITION;
|
||||
float4 texcoord:TEXCOORD0;
|
||||
float4 normal:NORMAL;
|
||||
float4 tangent:TANGENT;
|
||||
};
|
||||
|
||||
struct VSOut{
|
||||
float4 position:SV_POSITION;
|
||||
float4 normal:NORMAL;
|
||||
float4 texcoord:TEXCOORD0;
|
||||
float4 positionWS:TEXCOORD1;
|
||||
};
|
||||
|
||||
static const float PI=3.141592;
|
||||
cbuffer globalConstants:register(b0){
|
||||
float4 misc;
|
||||
};
|
||||
|
||||
cbuffer DefaultVertexCB:register(b1){
|
||||
float4x4 ProjectionMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float4x4 ModelMatrix;
|
||||
float4x4 IT_ModelMatrix;
|
||||
float4x4 ReservedMemory[1020];
|
||||
};
|
||||
|
||||
VSOut MainVS(VertexData inVertexData){
|
||||
VSOut vo;
|
||||
vo.normal=mul(IT_ModelMatrix,inVertexData.normal);
|
||||
float3 positionMS=inVertexData.position.xyz+vo.normal*sin(misc.x);
|
||||
float4 positionWS=mul(ModelMatrix,float4(positionMS,1.0));
|
||||
float4 positionVS=mul(ViewMatrix,positionWS);
|
||||
vo.position=mul(ProjectionMatrix,positionVS);
|
||||
vo.positionWS=positionWS;
|
||||
vo.texcoord=inVertexData.texcoord;
|
||||
return vo;
|
||||
}
|
||||
|
||||
float4 MainPS(VSOut inPSInput):SV_TARGET{
|
||||
float3 N=normalize(inPSInput.normal.xyz);
|
||||
float3 bottomColor=float3(0.1f,0.4f,0.6f);
|
||||
float3 topColor=float3(0.7f,0.7f,0.7f);
|
||||
float theta=asin(N.y);//-PI/2 ~ PI/2
|
||||
theta/=PI;//-0.5~0.5
|
||||
theta+=0.5f;//0.0~1.0
|
||||
float ambientColorIntensity=0.2;
|
||||
float3 ambientColor=lerp(bottomColor,topColor,theta)*ambientColorIntensity;
|
||||
float3 L=normalize(float3(1.0f,1.0f,-1.0f));
|
||||
|
||||
float diffuseIntensity=max(0.0f,dot(N,L));
|
||||
float3 diffuseLightColor=float3(0.1f,0.4f,0.6f);
|
||||
float3 diffuseColor=diffuseLightColor*diffuseIntensity;
|
||||
|
||||
float3 specularColor=float3(0.0f,0.0f,0.0f);
|
||||
if(diffuseIntensity>0.0f){
|
||||
float3 cameraPositionWS=float3(0.0f,0.0f,0.0f);
|
||||
float3 V=normalize(cameraPositionWS.xyz-inPSInput.positionWS.xyz);
|
||||
float3 R=normalize(reflect(-L,N));
|
||||
float specularIntensity=pow(max(0.0f,dot(V,R)),128.0f);
|
||||
specularColor=float3(1.0f,1.0f,1.0f)*specularIntensity;
|
||||
}
|
||||
float3 surfaceColor=ambientColor+diffuseColor+specularColor;
|
||||
return float4(surfaceColor,1.0f);
|
||||
}
|
||||
940
tests/D3D12/main.cpp
Normal file
940
tests/D3D12/main.cpp
Normal file
@@ -0,0 +1,940 @@
|
||||
#include <windows.h>
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <DirectXMath.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "stbi/stb_image.h"
|
||||
|
||||
#pragma comment(lib,"d3d12.lib")
|
||||
#pragma comment(lib,"dxgi.lib")
|
||||
#pragma comment(lib,"d3dcompiler.lib")
|
||||
#pragma comment(lib,"winmm.lib")
|
||||
|
||||
//=================================================================================
|
||||
// D3D12 核心全局对象 (最小渲染所需)
|
||||
//=================================================================================
|
||||
ID3D12Device* gD3D12Device = nullptr;
|
||||
ID3D12CommandQueue* gCommandQueue = nullptr;
|
||||
IDXGISwapChain3* gSwapChain = nullptr;
|
||||
|
||||
// 渲染目标 (SwapChain的后台Buffer)
|
||||
ID3D12Resource* gDSRT = nullptr; // 深度模板缓冲
|
||||
ID3D12Resource* gColorRTs[2]; // 颜色缓冲 (双缓冲)
|
||||
int gCurrentRTIndex = 0;
|
||||
|
||||
// 描述符堆
|
||||
ID3D12DescriptorHeap* gSwapChainRTVHeap = nullptr; // RTV堆
|
||||
ID3D12DescriptorHeap* gSwapChainDSVHeap = nullptr; // DSV堆
|
||||
UINT gRTVDescriptorSize = 0;
|
||||
UINT gDSVDescriptorSize = 0;
|
||||
|
||||
// 命令相关
|
||||
ID3D12CommandAllocator* gCommandAllocator = nullptr;
|
||||
ID3D12GraphicsCommandList* gCommandList = nullptr;
|
||||
|
||||
// 同步对象
|
||||
ID3D12Fence* gFence = nullptr;
|
||||
HANDLE gFenceEvent = nullptr;
|
||||
UINT64 gFenceValue = 0;
|
||||
|
||||
//=================================================================================
|
||||
// 工具函数前向声明
|
||||
//=================================================================================
|
||||
D3D12_RESOURCE_BARRIER InitResourceBarrier(
|
||||
ID3D12Resource* inResource, D3D12_RESOURCE_STATES inPrevState,
|
||||
D3D12_RESOURCE_STATES inNextState);
|
||||
|
||||
ID3D12Resource* CreateBufferObject(ID3D12GraphicsCommandList* inCommandList,
|
||||
void* inData, int inDataLen, D3D12_RESOURCE_STATES inFinalResourceState);
|
||||
|
||||
//=================================================================================
|
||||
// 工具函数
|
||||
//=================================================================================
|
||||
float srandom() {
|
||||
float number = float(rand()) / float(RAND_MAX);
|
||||
number *= 2.0f;
|
||||
number -= 1.0f;
|
||||
return number;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 数据结构定义
|
||||
//=================================================================================
|
||||
struct StaticMeshComponentVertexData {
|
||||
float mPosition[4];
|
||||
float mTexcoord[4];
|
||||
float mNormal[4];
|
||||
float mTangent[4];
|
||||
};
|
||||
|
||||
struct SubMesh {
|
||||
ID3D12Resource* mIBO;
|
||||
D3D12_INDEX_BUFFER_VIEW mIBView;
|
||||
int mIndexCount;
|
||||
};
|
||||
|
||||
//=================================================================================
|
||||
// 网格组件类 (StaticMeshComponent)
|
||||
// 封装顶点缓冲(VBO)、索引缓冲(IBO)和渲染逻辑
|
||||
//=================================================================================
|
||||
class StaticMeshComponent {
|
||||
public:
|
||||
ID3D12Resource* mVBO;
|
||||
D3D12_VERTEX_BUFFER_VIEW mVBOView;
|
||||
StaticMeshComponentVertexData* mVertexData;
|
||||
int mVertexCount;
|
||||
std::unordered_map<std::string, SubMesh*> mSubMeshes;
|
||||
|
||||
void SetVertexCount(int inVertexCount) {
|
||||
mVertexCount = inVertexCount;
|
||||
mVertexData = new StaticMeshComponentVertexData[inVertexCount];
|
||||
memset(mVertexData, 0, sizeof(StaticMeshComponentVertexData) * inVertexCount);
|
||||
}
|
||||
void SetVertexPosition(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||
mVertexData[inIndex].mPosition[0] = inX;
|
||||
mVertexData[inIndex].mPosition[1] = inY;
|
||||
mVertexData[inIndex].mPosition[2] = inZ;
|
||||
mVertexData[inIndex].mPosition[3] = inW;
|
||||
}
|
||||
void SetVertexTexcoord(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||
mVertexData[inIndex].mTexcoord[0] = inX;
|
||||
mVertexData[inIndex].mTexcoord[1] = inY;
|
||||
mVertexData[inIndex].mTexcoord[2] = inZ;
|
||||
mVertexData[inIndex].mTexcoord[3] = inW;
|
||||
}
|
||||
void SetVertexNormal(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||
mVertexData[inIndex].mNormal[0] = inX;
|
||||
mVertexData[inIndex].mNormal[1] = inY;
|
||||
mVertexData[inIndex].mNormal[2] = inZ;
|
||||
mVertexData[inIndex].mNormal[3] = inW;
|
||||
}
|
||||
void SetVertexTangent(int inIndex, float inX, float inY, float inZ, float inW = 1.0f) {
|
||||
mVertexData[inIndex].mTangent[0] = inX;
|
||||
mVertexData[inIndex].mTangent[1] = inY;
|
||||
mVertexData[inIndex].mTangent[2] = inZ;
|
||||
mVertexData[inIndex].mTangent[3] = inW;
|
||||
}
|
||||
void InitFromFile(ID3D12GraphicsCommandList* inCommandList, const char* inFilePath) {
|
||||
FILE* pFile = nullptr;
|
||||
errno_t err = fopen_s(&pFile, inFilePath, "rb");
|
||||
if (err == 0) {
|
||||
int temp = 0;
|
||||
fread(&temp, 4, 1, pFile);
|
||||
mVertexCount = temp;
|
||||
mVertexData = new StaticMeshComponentVertexData[mVertexCount];
|
||||
fread(mVertexData, 1, sizeof(StaticMeshComponentVertexData) * mVertexCount, pFile);
|
||||
mVBO = CreateBufferObject(inCommandList, mVertexData,
|
||||
sizeof(StaticMeshComponentVertexData) * mVertexCount,
|
||||
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
|
||||
mVBOView.BufferLocation = mVBO->GetGPUVirtualAddress();
|
||||
mVBOView.SizeInBytes = sizeof(StaticMeshComponentVertexData) * mVertexCount;
|
||||
mVBOView.StrideInBytes = sizeof(StaticMeshComponentVertexData);
|
||||
|
||||
while (!feof(pFile)) {
|
||||
fread(&temp, 4, 1, pFile);
|
||||
if (feof(pFile)) {
|
||||
break;
|
||||
}
|
||||
char name[256] = { 0 };
|
||||
fread(name, 1, temp, pFile);
|
||||
fread(&temp, 4, 1, pFile);
|
||||
SubMesh* submesh = new SubMesh;
|
||||
submesh->mIndexCount = temp;
|
||||
unsigned int* indexes = new unsigned int[temp];
|
||||
fread(indexes, 1, sizeof(unsigned int) * temp, pFile);
|
||||
submesh->mIBO = CreateBufferObject(inCommandList, indexes,
|
||||
sizeof(unsigned int) * temp,
|
||||
D3D12_RESOURCE_STATE_INDEX_BUFFER);
|
||||
|
||||
submesh->mIBView.BufferLocation = submesh->mIBO->GetGPUVirtualAddress();
|
||||
submesh->mIBView.SizeInBytes = sizeof(unsigned int) * temp;
|
||||
submesh->mIBView.Format = DXGI_FORMAT_R32_UINT;
|
||||
mSubMeshes.insert(std::pair<std::string, SubMesh*>(name, submesh));
|
||||
delete[] indexes;
|
||||
}
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
void Render(ID3D12GraphicsCommandList* inCommandList) {
|
||||
D3D12_VERTEX_BUFFER_VIEW vbos[] = {
|
||||
mVBOView
|
||||
};
|
||||
inCommandList->IASetVertexBuffers(0, 1, vbos);
|
||||
if (mSubMeshes.empty()) {
|
||||
inCommandList->DrawInstanced(mVertexCount, 1, 0, 0);
|
||||
}
|
||||
else {
|
||||
for (auto iter = mSubMeshes.begin();
|
||||
iter != mSubMeshes.end(); iter++) {
|
||||
inCommandList->IASetIndexBuffer(&iter->second->mIBView);
|
||||
inCommandList->DrawIndexedInstanced(iter->second->mIndexCount, 1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=================================================================================
|
||||
// ResourceBarrier 工具函数
|
||||
// 用于资源状态转换 (例如: PRESENT → RENDER_TARGET)
|
||||
//=================================================================================
|
||||
D3D12_RESOURCE_BARRIER InitResourceBarrier(
|
||||
ID3D12Resource* inResource, D3D12_RESOURCE_STATES inPrevState,
|
||||
D3D12_RESOURCE_STATES inNextState) {
|
||||
D3D12_RESOURCE_BARRIER d3d12ResourceBarrier;
|
||||
memset(&d3d12ResourceBarrier, 0, sizeof(d3d12ResourceBarrier));
|
||||
d3d12ResourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
d3d12ResourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
d3d12ResourceBarrier.Transition.pResource = inResource;
|
||||
d3d12ResourceBarrier.Transition.StateBefore = inPrevState;
|
||||
d3d12ResourceBarrier.Transition.StateAfter = inNextState;
|
||||
d3d12ResourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
return d3d12ResourceBarrier;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 根签名初始化 (RootSignature)
|
||||
// 定义GPU资源绑定规则: CBV(常量缓冲) / SRV(着色器资源) / DescriptorTable
|
||||
//=================================================================================
|
||||
ID3D12RootSignature* InitRootSignature() {
|
||||
D3D12_ROOT_PARAMETER rootParameters[4];
|
||||
rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
||||
rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||
rootParameters[1].Constants.RegisterSpace = 0;
|
||||
rootParameters[1].Constants.ShaderRegister = 0;
|
||||
rootParameters[1].Constants.Num32BitValues = 4;
|
||||
|
||||
rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
rootParameters[0].Descriptor.RegisterSpace = 0;
|
||||
rootParameters[0].Descriptor.ShaderRegister = 1;
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE descriptorRange[1];
|
||||
descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
descriptorRange[0].RegisterSpace = 0;
|
||||
descriptorRange[0].BaseShaderRegister = 0;
|
||||
descriptorRange[0].NumDescriptors = 1;
|
||||
descriptorRange[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
|
||||
rootParameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
rootParameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
rootParameters[2].DescriptorTable.pDescriptorRanges = descriptorRange;
|
||||
rootParameters[2].DescriptorTable.NumDescriptorRanges = _countof(descriptorRange);
|
||||
|
||||
rootParameters[3].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
||||
rootParameters[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
rootParameters[3].Descriptor.RegisterSpace = 1;
|
||||
rootParameters[3].Descriptor.ShaderRegister = 0;
|
||||
|
||||
D3D12_STATIC_SAMPLER_DESC samplerDesc[1];
|
||||
memset(samplerDesc, 0, sizeof(D3D12_STATIC_SAMPLER_DESC) * _countof(samplerDesc));
|
||||
samplerDesc[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
samplerDesc[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
samplerDesc[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
samplerDesc[0].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
||||
samplerDesc[0].MaxLOD = D3D12_FLOAT32_MAX;
|
||||
samplerDesc[0].RegisterSpace = 0;
|
||||
samplerDesc[0].ShaderRegister = 0;
|
||||
samplerDesc[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
||||
rootSignatureDesc.NumParameters = _countof(rootParameters);
|
||||
rootSignatureDesc.pParameters = rootParameters;
|
||||
rootSignatureDesc.NumStaticSamplers = _countof(samplerDesc);
|
||||
rootSignatureDesc.pStaticSamplers = samplerDesc;
|
||||
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||
|
||||
ID3DBlob* signature;
|
||||
HRESULT hResult = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr);
|
||||
ID3D12RootSignature* d3d12RootSignature;
|
||||
gD3D12Device->CreateRootSignature(
|
||||
0, signature->GetBufferPointer(), signature->GetBufferSize(),
|
||||
IID_PPV_ARGS(&d3d12RootSignature));
|
||||
|
||||
return d3d12RootSignature;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 着色器加载函数
|
||||
// 从.hlsl文件编译着色器 (VS/GS/PS)
|
||||
//=================================================================================
|
||||
void CreateShaderFromFile(
|
||||
LPCTSTR inShaderFilePath,
|
||||
const char* inMainFunctionName,
|
||||
const char* inTarget,
|
||||
D3D12_SHADER_BYTECODE* inShader) {
|
||||
ID3DBlob* shaderBuffer = nullptr;
|
||||
ID3DBlob* errorBuffer = nullptr;
|
||||
HRESULT hResult = D3DCompileFromFile(inShaderFilePath, nullptr, nullptr,
|
||||
inMainFunctionName, inTarget, D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
|
||||
0, &shaderBuffer, &errorBuffer);
|
||||
if (FAILED(hResult)) {
|
||||
char szLog[1024] = { 0 };
|
||||
strcpy_s(szLog, (char*)errorBuffer->GetBufferPointer());
|
||||
printf("CreateShaderFromFile error : [%s][%s]:[%s]\n", inMainFunctionName, inTarget, szLog);
|
||||
errorBuffer->Release();
|
||||
return;
|
||||
}
|
||||
inShader->pShaderBytecode = shaderBuffer->GetBufferPointer();
|
||||
inShader->BytecodeLength = shaderBuffer->GetBufferSize();
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 常量缓冲 (Constant Buffer) 创建与更新
|
||||
// UPLOAD堆: CPU可写, GPU可读
|
||||
//=================================================================================
|
||||
ID3D12Resource* CreateConstantBufferObject(int inDataLen) {
|
||||
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||
d3dHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
d3d12ResourceDesc.Alignment = 0;
|
||||
d3d12ResourceDesc.Width = inDataLen;
|
||||
d3d12ResourceDesc.Height = 1;
|
||||
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||
d3d12ResourceDesc.MipLevels = 1;
|
||||
d3d12ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
ID3D12Resource* bufferObject = nullptr;
|
||||
gD3D12Device->CreateCommittedResource(
|
||||
&d3dHeapProperties,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&d3d12ResourceDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&bufferObject)
|
||||
);
|
||||
return bufferObject;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 更新常量缓冲数据
|
||||
//=================================================================================
|
||||
void UpdateConstantBuffer(ID3D12Resource* inCB, void* inData, int inDataLen) {
|
||||
D3D12_RANGE d3d12Range = { 0 };
|
||||
unsigned char* pBuffer = nullptr;
|
||||
inCB->Map(0, &d3d12Range, (void**)&pBuffer);
|
||||
memcpy(pBuffer, inData, inDataLen);
|
||||
inCB->Unmap(0, nullptr);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// GPU Buffer创建 (顶点/索引缓冲)
|
||||
// DEFAULT堆 → 通过Upload堆中转数据 → 状态转换
|
||||
//=================================================================================
|
||||
ID3D12Resource* CreateBufferObject(ID3D12GraphicsCommandList* inCommandList,
|
||||
void* inData, int inDataLen, D3D12_RESOURCE_STATES inFinalResourceState) {
|
||||
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||
d3dHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
d3d12ResourceDesc.Alignment = 0;
|
||||
d3d12ResourceDesc.Width = inDataLen;
|
||||
d3d12ResourceDesc.Height = 1;
|
||||
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||
d3d12ResourceDesc.MipLevels = 1;
|
||||
d3d12ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
ID3D12Resource* bufferObject = nullptr;
|
||||
gD3D12Device->CreateCommittedResource(
|
||||
&d3dHeapProperties,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&d3d12ResourceDesc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&bufferObject)
|
||||
);
|
||||
d3d12ResourceDesc = bufferObject->GetDesc();
|
||||
UINT64 memorySizeUsed = 0;
|
||||
UINT64 rowSizeInBytes = 0;
|
||||
UINT rowUsed = 0;
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT subresourceFootprint;
|
||||
gD3D12Device->GetCopyableFootprints(&d3d12ResourceDesc, 0, 1, 0,
|
||||
&subresourceFootprint, &rowUsed, &rowSizeInBytes, &memorySizeUsed);
|
||||
|
||||
ID3D12Resource* tempBufferObject = nullptr;
|
||||
d3dHeapProperties = {};
|
||||
d3dHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
gD3D12Device->CreateCommittedResource(
|
||||
&d3dHeapProperties,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&d3d12ResourceDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&tempBufferObject)
|
||||
);
|
||||
|
||||
BYTE* pData;
|
||||
tempBufferObject->Map(0, nullptr, reinterpret_cast<void**>(&pData));
|
||||
BYTE* pDstTempBuffer = reinterpret_cast<BYTE*>(pData + subresourceFootprint.Offset);
|
||||
const BYTE* pSrcData = reinterpret_cast<BYTE*>(inData);
|
||||
for (UINT i = 0; i < rowUsed; i++) {
|
||||
memcpy(pDstTempBuffer + subresourceFootprint.Footprint.RowPitch * i, pSrcData + rowSizeInBytes * i, rowSizeInBytes);
|
||||
}
|
||||
tempBufferObject->Unmap(0, nullptr);
|
||||
inCommandList->CopyBufferRegion(bufferObject, 0, tempBufferObject, 0, subresourceFootprint.Footprint.Width);
|
||||
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(bufferObject, D3D12_RESOURCE_STATE_COPY_DEST, inFinalResourceState);
|
||||
inCommandList->ResourceBarrier(1, &barrier);
|
||||
return bufferObject;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 2D纹理创建
|
||||
// DEFAULT堆 → 通过Upload堆中转数据 → CopyTextureRegion → 状态转换
|
||||
//=================================================================================
|
||||
ID3D12Resource* CreateTexture2D(ID3D12GraphicsCommandList* inCommandList,
|
||||
const void* inPixelData, int inDataSizeInBytes, int inWidth, int inHeight,
|
||||
DXGI_FORMAT inFormat) {
|
||||
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||
d3dHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
|
||||
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
d3d12ResourceDesc.Alignment = 0;
|
||||
d3d12ResourceDesc.Width = inWidth;
|
||||
d3d12ResourceDesc.Height = inHeight;
|
||||
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||
d3d12ResourceDesc.MipLevels = 1;
|
||||
d3d12ResourceDesc.Format = inFormat;
|
||||
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
ID3D12Resource* texture = nullptr;
|
||||
gD3D12Device->CreateCommittedResource(&d3dHeapProperties,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&d3d12ResourceDesc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&texture)
|
||||
);
|
||||
d3d12ResourceDesc = texture->GetDesc();
|
||||
UINT64 memorySizeUsed = 0;
|
||||
UINT64 rowSizeInBytes = 0;
|
||||
UINT rowUsed = 0;
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT subresourceFootprint;
|
||||
gD3D12Device->GetCopyableFootprints(&d3d12ResourceDesc, 0, 1, 0,
|
||||
&subresourceFootprint, &rowUsed, &rowSizeInBytes, &memorySizeUsed);
|
||||
|
||||
ID3D12Resource* tempBufferObject = nullptr;
|
||||
D3D12_HEAP_PROPERTIES d3dTempHeapProperties = {};
|
||||
d3dTempHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
|
||||
D3D12_RESOURCE_DESC d3d12TempResourceDesc = {};
|
||||
d3d12TempResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
d3d12TempResourceDesc.Alignment = 0;
|
||||
d3d12TempResourceDesc.Width = memorySizeUsed;
|
||||
d3d12TempResourceDesc.Height = 1;
|
||||
d3d12TempResourceDesc.DepthOrArraySize = 1;
|
||||
d3d12TempResourceDesc.MipLevels = 1;
|
||||
d3d12TempResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
d3d12TempResourceDesc.SampleDesc.Count = 1;
|
||||
d3d12TempResourceDesc.SampleDesc.Quality = 0;
|
||||
d3d12TempResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
d3d12TempResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
gD3D12Device->CreateCommittedResource(
|
||||
&d3dTempHeapProperties,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&d3d12TempResourceDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&tempBufferObject)
|
||||
);
|
||||
BYTE* pData;
|
||||
tempBufferObject->Map(0, nullptr, reinterpret_cast<void**>(&pData));
|
||||
BYTE* pDstTempBuffer = reinterpret_cast<BYTE*>(pData + subresourceFootprint.Offset);
|
||||
const BYTE* pSrcData = reinterpret_cast<const BYTE*>(inPixelData);
|
||||
for (UINT i = 0; i < rowUsed; i++) {
|
||||
memcpy(pDstTempBuffer + subresourceFootprint.Footprint.RowPitch * i, pSrcData + rowSizeInBytes * i, rowSizeInBytes);
|
||||
}
|
||||
tempBufferObject->Unmap(0, nullptr);
|
||||
D3D12_TEXTURE_COPY_LOCATION dst = {};
|
||||
dst.pResource = texture;
|
||||
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dst.SubresourceIndex = 0;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION src = {};
|
||||
src.pResource = tempBufferObject;
|
||||
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
src.PlacedFootprint = subresourceFootprint;
|
||||
inCommandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(texture,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
inCommandList->ResourceBarrier(1, &barrier);
|
||||
return texture;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 渲染管线状态对象 (PSO)
|
||||
// 包含: InputLayout / VS/GS/PS / Rasterizer / DepthStencil / Blend
|
||||
//=================================================================================
|
||||
ID3D12PipelineState* CreatePSO(ID3D12RootSignature* inID3D12RootSignature,
|
||||
D3D12_SHADER_BYTECODE inVertexShader, D3D12_SHADER_BYTECODE inPixelShader,
|
||||
D3D12_SHADER_BYTECODE inGSShader) {
|
||||
D3D12_INPUT_ELEMENT_DESC vertexDataElementDesc[] = {
|
||||
{"POSITION",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,0,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
|
||||
{"TEXCOORD",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,sizeof(float) * 4,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
|
||||
{"NORMAL",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,sizeof(float) * 8,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
|
||||
{"TANGENT",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,sizeof(float) * 12,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0}
|
||||
};
|
||||
D3D12_INPUT_LAYOUT_DESC vertexDataLayoutDesc = {};
|
||||
vertexDataLayoutDesc.NumElements = 4;
|
||||
vertexDataLayoutDesc.pInputElementDescs = vertexDataElementDesc;
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
||||
psoDesc.pRootSignature = inID3D12RootSignature;
|
||||
psoDesc.VS = inVertexShader;
|
||||
psoDesc.GS = inGSShader;
|
||||
psoDesc.PS = inPixelShader;
|
||||
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
psoDesc.SampleDesc.Count = 1;
|
||||
psoDesc.SampleDesc.Quality = 0;
|
||||
psoDesc.SampleMask = 0xffffffff;
|
||||
psoDesc.InputLayout = vertexDataLayoutDesc;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
|
||||
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
|
||||
psoDesc.RasterizerState.DepthClipEnable = TRUE;
|
||||
|
||||
psoDesc.DepthStencilState.DepthEnable = true;
|
||||
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
||||
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
|
||||
psoDesc.BlendState = { 0 };
|
||||
D3D12_RENDER_TARGET_BLEND_DESC rtBlendDesc = {
|
||||
FALSE,FALSE,
|
||||
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
||||
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
||||
D3D12_LOGIC_OP_NOOP,
|
||||
D3D12_COLOR_WRITE_ENABLE_ALL,
|
||||
};
|
||||
for (int i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
|
||||
psoDesc.BlendState.RenderTarget[i] = rtBlendDesc;
|
||||
psoDesc.NumRenderTargets = 1;
|
||||
ID3D12PipelineState* d3d12PSO = nullptr;
|
||||
|
||||
HRESULT hResult = gD3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&d3d12PSO));
|
||||
if (FAILED(hResult)) {
|
||||
return nullptr;
|
||||
}
|
||||
return d3d12PSO;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// D3D12 初始化核心函数 (InitD3D12)
|
||||
// 最小渲染系统初始化流程:
|
||||
// 1. 启用Debug层 (可选, _DEBUG)
|
||||
// 2. 创建IDXGIFactory4
|
||||
// 3. 枚举Adapter, 创建ID3D12Device
|
||||
// 4. 创建CommandQueue (命令队列)
|
||||
// 5. 创建SwapChain (交换链)
|
||||
// 6. 创建DepthStencilBuffer (深度缓冲)
|
||||
// 7. 创建RTV/DSV描述符堆
|
||||
// 8. 创建RenderTargetView / DepthStencilView
|
||||
// 9. 创建CommandAllocator / CommandList
|
||||
// 10. 创建Fence (同步)
|
||||
//=================================================================================
|
||||
bool InitD3D12(HWND inHWND, int inWidth, int inHeight) {
|
||||
HRESULT hResult;
|
||||
UINT dxgiFactoryFlags = 0;
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
ID3D12Debug* debugController = nullptr;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||
debugController->EnableDebugLayer();
|
||||
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
IDXGIFactory4* dxgiFactory;
|
||||
hResult = CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&dxgiFactory));
|
||||
if (FAILED(hResult)) {
|
||||
return false;
|
||||
}
|
||||
IDXGIAdapter1* adapter;
|
||||
int adapterIndex = 0;
|
||||
bool adapterFound = false;
|
||||
while (dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
adapter->GetDesc1(&desc);
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||
continue;
|
||||
}
|
||||
hResult = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr);
|
||||
if (SUCCEEDED(hResult)) {
|
||||
adapterFound = true;
|
||||
break;
|
||||
}
|
||||
adapterIndex++;
|
||||
}
|
||||
if (false == adapterFound) {
|
||||
return false;
|
||||
}
|
||||
hResult = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&gD3D12Device));
|
||||
if (FAILED(hResult)) {
|
||||
return false;
|
||||
}
|
||||
D3D12_COMMAND_QUEUE_DESC d3d12CommandQueueDesc = {};
|
||||
hResult = gD3D12Device->CreateCommandQueue(&d3d12CommandQueueDesc, IID_PPV_ARGS(&gCommandQueue));
|
||||
if (FAILED(hResult)) {
|
||||
return false;
|
||||
}
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
||||
swapChainDesc.BufferCount = 2;
|
||||
swapChainDesc.BufferDesc = {};
|
||||
swapChainDesc.BufferDesc.Width = inWidth;
|
||||
swapChainDesc.BufferDesc.Height = inHeight;
|
||||
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.OutputWindow = inHWND;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.Windowed = true;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
|
||||
IDXGISwapChain* swapChain = nullptr;
|
||||
dxgiFactory->CreateSwapChain(gCommandQueue, &swapChainDesc, &swapChain);
|
||||
gSwapChain = static_cast<IDXGISwapChain3*>(swapChain);
|
||||
|
||||
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
||||
d3dHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
|
||||
D3D12_RESOURCE_DESC d3d12ResourceDesc = {};
|
||||
d3d12ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
d3d12ResourceDesc.Alignment = 0;
|
||||
d3d12ResourceDesc.Width = inWidth;
|
||||
d3d12ResourceDesc.Height = inHeight;
|
||||
d3d12ResourceDesc.DepthOrArraySize = 1;
|
||||
d3d12ResourceDesc.MipLevels = 1;
|
||||
d3d12ResourceDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
d3d12ResourceDesc.SampleDesc.Count = 1;
|
||||
d3d12ResourceDesc.SampleDesc.Quality = 0;
|
||||
d3d12ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
d3d12ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
|
||||
D3D12_CLEAR_VALUE dsClearValue = {};
|
||||
dsClearValue.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
dsClearValue.DepthStencil.Depth = 1.0f;
|
||||
dsClearValue.DepthStencil.Stencil = 0;
|
||||
|
||||
gD3D12Device->CreateCommittedResource(&d3dHeapProperties,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&d3d12ResourceDesc,
|
||||
D3D12_RESOURCE_STATE_DEPTH_WRITE,
|
||||
&dsClearValue,
|
||||
IID_PPV_ARGS(&gDSRT)
|
||||
);
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC d3dDescriptorHeapDescRTV = {};
|
||||
d3dDescriptorHeapDescRTV.NumDescriptors = 2;
|
||||
d3dDescriptorHeapDescRTV.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
gD3D12Device->CreateDescriptorHeap(&d3dDescriptorHeapDescRTV, IID_PPV_ARGS(&gSwapChainRTVHeap));
|
||||
gRTVDescriptorSize = gD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC d3dDescriptorHeapDescDSV = {};
|
||||
d3dDescriptorHeapDescDSV.NumDescriptors = 1;
|
||||
d3dDescriptorHeapDescDSV.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
|
||||
gD3D12Device->CreateDescriptorHeap(&d3dDescriptorHeapDescDSV, IID_PPV_ARGS(&gSwapChainDSVHeap));
|
||||
gDSVDescriptorSize = gD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHeapStart = gSwapChainRTVHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
gSwapChain->GetBuffer(i, IID_PPV_ARGS(&gColorRTs[i]));
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvPointer;
|
||||
rtvPointer.ptr = rtvHeapStart.ptr + i * gRTVDescriptorSize;
|
||||
gD3D12Device->CreateRenderTargetView(gColorRTs[i], nullptr, rtvPointer);
|
||||
}
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC d3dDSViewDesc = {};
|
||||
d3dDSViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
d3dDSViewDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||
|
||||
gD3D12Device->CreateDepthStencilView(gDSRT, &d3dDSViewDesc, gSwapChainDSVHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
gD3D12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&gCommandAllocator));
|
||||
gD3D12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, gCommandAllocator, nullptr, IID_PPV_ARGS(&gCommandList));
|
||||
|
||||
gD3D12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&gFence));
|
||||
gFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 命令相关辅助函数
|
||||
//=================================================================================
|
||||
ID3D12CommandAllocator* GetCommandAllocator() {
|
||||
return gCommandAllocator;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList* GetCommandList() {
|
||||
return gCommandList;
|
||||
}
|
||||
|
||||
void WaitForCompletionOfCommandList() {
|
||||
if (gFence->GetCompletedValue() < gFenceValue) {
|
||||
gFence->SetEventOnCompletion(gFenceValue, gFenceEvent);
|
||||
WaitForSingleObject(gFenceEvent, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 命令列表结束提交
|
||||
// 关闭CommandList → ExecuteCommandLists → Signal Fence
|
||||
//=================================================================================
|
||||
void EndCommandList() {
|
||||
gCommandList->Close();
|
||||
ID3D12CommandList* ppCommandLists[] = { gCommandList };
|
||||
gCommandQueue->ExecuteCommandLists(1, ppCommandLists);
|
||||
gFenceValue += 1;
|
||||
gCommandQueue->Signal(gFence, gFenceValue);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 开始渲染到SwapChain
|
||||
// 1. 获取当前BackBuffer索引
|
||||
// 2. 状态转换: PRESENT → RENDER_TARGET
|
||||
// 3. 设置RenderTargets (Color + Depth)
|
||||
// 4. 设置Viewport/Scissor
|
||||
// 5. Clear Color/Depth
|
||||
//=================================================================================
|
||||
void BeginRenderToSwapChain(ID3D12GraphicsCommandList* inCommandList) {
|
||||
gCurrentRTIndex = gSwapChain->GetCurrentBackBufferIndex();
|
||||
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(gColorRTs[gCurrentRTIndex], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
inCommandList->ResourceBarrier(1, &barrier);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE colorRT, dsv;
|
||||
dsv.ptr = gSwapChainDSVHeap->GetCPUDescriptorHandleForHeapStart().ptr;
|
||||
colorRT.ptr = gSwapChainRTVHeap->GetCPUDescriptorHandleForHeapStart().ptr + gCurrentRTIndex * gRTVDescriptorSize;
|
||||
inCommandList->OMSetRenderTargets(1, &colorRT, FALSE, &dsv);
|
||||
D3D12_VIEWPORT viewport = { 0.0f,0.0f,1280.0f,720.0f };
|
||||
D3D12_RECT scissorRect = { 0,0,1280,720 };
|
||||
inCommandList->RSSetViewports(1, &viewport);
|
||||
inCommandList->RSSetScissorRects(1, &scissorRect);
|
||||
const float clearColor[] = { 0.0f,0.0f,0.0f,1.0f };
|
||||
inCommandList->ClearRenderTargetView(colorRT, clearColor, 0, nullptr);
|
||||
inCommandList->ClearDepthStencilView(dsv, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 结束渲染到SwapChain
|
||||
// 状态转换: RENDER_TARGET → PRESENT
|
||||
//=================================================================================
|
||||
void EndRenderToSwapChain(ID3D12GraphicsCommandList* inCommandList) {
|
||||
D3D12_RESOURCE_BARRIER barrier = InitResourceBarrier(gColorRTs[gCurrentRTIndex], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
|
||||
inCommandList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 交换缓冲区 (显示渲染结果)
|
||||
//=================================================================================
|
||||
void SwapD3D12Buffers() {
|
||||
gSwapChain->Present(0, 0);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 获取D3D12设备
|
||||
//=================================================================================
|
||||
ID3D12Device* GetD3DDevice() {
|
||||
return gD3D12Device;
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// Win32 窗口相关
|
||||
//=================================================================================
|
||||
LPCTSTR gWindowClassName = L"BattleFire";
|
||||
|
||||
//=================================================================================
|
||||
// 窗口消息回调函数
|
||||
//=================================================================================
|
||||
LRESULT CALLBACK WindowProc(HWND inHWND, UINT inMSG, WPARAM inWParam, LPARAM inLParam) {
|
||||
switch (inMSG) {
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
return DefWindowProc(inHWND, inMSG, inWParam, inLParam);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// 主入口函数 WinMain
|
||||
// 程序入口点
|
||||
//=================================================================================
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int inShowCmd) {
|
||||
WNDCLASSEX wndClassEx;
|
||||
wndClassEx.cbSize = sizeof(WNDCLASSEX);
|
||||
wndClassEx.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndClassEx.cbClsExtra = NULL;
|
||||
wndClassEx.cbWndExtra = NULL;
|
||||
wndClassEx.hInstance = hInstance;
|
||||
wndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wndClassEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wndClassEx.hbrBackground = NULL;
|
||||
wndClassEx.lpszMenuName = NULL;
|
||||
wndClassEx.lpszClassName = gWindowClassName;
|
||||
wndClassEx.lpfnWndProc = WindowProc;
|
||||
if (!RegisterClassEx(&wndClassEx)) {
|
||||
MessageBox(NULL, L"Register Class Failed!", L"Error", MB_OK | MB_ICONERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int viewportWidth = 1280;
|
||||
int viewportHeight = 720;
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = viewportWidth;
|
||||
rect.bottom = viewportHeight;
|
||||
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
int windowWidth = rect.right - rect.left;
|
||||
int windowHeight = rect.bottom - rect.top;
|
||||
HWND hwnd = CreateWindowEx(NULL,
|
||||
gWindowClassName,
|
||||
L"My Render Window",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
windowWidth, windowHeight,
|
||||
NULL,
|
||||
NULL,
|
||||
hInstance,
|
||||
NULL);
|
||||
if (!hwnd) {
|
||||
MessageBox(NULL, L"Create Window Failed!", L"Error", MB_OK | MB_ICONERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
InitD3D12(hwnd, 1280, 720);
|
||||
ID3D12GraphicsCommandList* commandList = GetCommandList();
|
||||
ID3D12CommandAllocator* commandAllocator = GetCommandAllocator();
|
||||
StaticMeshComponent staticMeshComponent;
|
||||
staticMeshComponent.InitFromFile(commandList, "Res/Model/Sphere.lhsm");
|
||||
|
||||
ID3D12RootSignature* rootSignature = InitRootSignature();
|
||||
D3D12_SHADER_BYTECODE vs, gs, ps;
|
||||
CreateShaderFromFile(L"Res/Shader/gs.hlsl", "MainVS", "vs_5_1", &vs);
|
||||
CreateShaderFromFile(L"Res/Shader/gs.hlsl", "MainGS", "gs_5_1", &gs);
|
||||
CreateShaderFromFile(L"Res/Shader/gs.hlsl", "MainPS", "ps_5_1", &ps);
|
||||
ID3D12PipelineState* pso = CreatePSO(rootSignature, vs, ps, gs);
|
||||
|
||||
ID3D12Resource* cb = CreateConstantBufferObject(65536);
|
||||
DirectX::XMMATRIX projectionMatrix = DirectX::XMMatrixPerspectiveFovLH(
|
||||
(45.0f * 3.141592f) / 180.0f, 1280.0f / 720.0f, 0.1f, 1000.0f);
|
||||
DirectX::XMMATRIX viewMatrix = DirectX::XMMatrixIdentity();
|
||||
DirectX::XMMATRIX modelMatrix = DirectX::XMMatrixTranslation(0.0f, 0.0f, 5.0f);
|
||||
DirectX::XMFLOAT4X4 tempMatrix;
|
||||
float matrices[64];
|
||||
|
||||
DirectX::XMStoreFloat4x4(&tempMatrix, projectionMatrix);
|
||||
memcpy(matrices, &tempMatrix, sizeof(float) * 16);
|
||||
DirectX::XMStoreFloat4x4(&tempMatrix, viewMatrix);
|
||||
memcpy(matrices + 16, &tempMatrix, sizeof(float) * 16);
|
||||
DirectX::XMStoreFloat4x4(&tempMatrix, modelMatrix);
|
||||
memcpy(matrices + 32, &tempMatrix, sizeof(float) * 16);
|
||||
DirectX::XMVECTOR determinant;
|
||||
DirectX::XMMATRIX inverseModelMatrix = DirectX::XMMatrixInverse(&determinant, modelMatrix);
|
||||
if (DirectX::XMVectorGetX(determinant) != 0.0f) {
|
||||
DirectX::XMMATRIX normalMatrix = DirectX::XMMatrixTranspose(inverseModelMatrix);
|
||||
DirectX::XMStoreFloat4x4(&tempMatrix, modelMatrix);
|
||||
memcpy(matrices + 48, &tempMatrix, sizeof(float) * 16);
|
||||
}
|
||||
UpdateConstantBuffer(cb, matrices, sizeof(float) * 64);
|
||||
|
||||
ID3D12Resource* sb = CreateConstantBufferObject(65536);
|
||||
struct MaterialData {
|
||||
float r;
|
||||
};
|
||||
MaterialData* materialDatas = new MaterialData[3000];
|
||||
for (int i = 0; i < 3000; i++) {
|
||||
materialDatas[i].r = srandom() * 0.1f + 0.1f;
|
||||
}
|
||||
UpdateConstantBuffer(sb, materialDatas, sizeof(MaterialData) * 3000);
|
||||
|
||||
int imageWidth, imageHeight, imageChannel;
|
||||
stbi_uc* pixels = stbi_load("Res/Image/earth_d.jpg", &imageWidth, &imageHeight, &imageChannel, 4);
|
||||
ID3D12Resource* texture = CreateTexture2D(commandList, pixels,
|
||||
imageWidth * imageHeight * imageChannel, imageWidth, imageHeight, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
delete[] pixels;
|
||||
ID3D12Device* d3dDevice = GetD3DDevice();
|
||||
|
||||
ID3D12DescriptorHeap* srvHeap = nullptr;
|
||||
D3D12_DESCRIPTOR_HEAP_DESC d3dDescriptorHeapDescSRV = {};
|
||||
d3dDescriptorHeapDescSRV.NumDescriptors = 3;
|
||||
d3dDescriptorHeapDescSRV.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
d3dDescriptorHeapDescSRV.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3dDevice->CreateDescriptorHeap(&d3dDescriptorHeapDescSRV, IID_PPV_ARGS(&srvHeap));
|
||||
|
||||
ID3D12DescriptorHeap* descriptorHeaps[] = { srvHeap };
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = 1;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srvHeapPtr = srvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
d3dDevice->CreateShaderResourceView(texture, &srvDesc, srvHeapPtr);
|
||||
srvHeapPtr.ptr += d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
|
||||
EndCommandList();
|
||||
WaitForCompletionOfCommandList();
|
||||
|
||||
ShowWindow(hwnd, inShowCmd);
|
||||
UpdateWindow(hwnd);
|
||||
float color[] = { 0.5f,0.5f,0.5f,1.0f };
|
||||
MSG msg;
|
||||
DWORD last_time = timeGetTime();
|
||||
DWORD appStartTime = last_time;
|
||||
while (true) {
|
||||
ZeroMemory(&msg, sizeof(MSG));
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
} else {
|
||||
WaitForCompletionOfCommandList();
|
||||
DWORD current_time = timeGetTime();
|
||||
DWORD frameTime = current_time - last_time;
|
||||
DWORD timeSinceAppStartInMS = current_time - appStartTime;
|
||||
last_time = current_time;
|
||||
float frameTimeInSecond = float(frameTime) / 1000.0f;
|
||||
float timeSinceAppStartInSecond = float(timeSinceAppStartInMS) / 1000.0f;
|
||||
color[0] = timeSinceAppStartInSecond;
|
||||
commandAllocator->Reset();
|
||||
commandList->Reset(commandAllocator, nullptr);
|
||||
BeginRenderToSwapChain(commandList);
|
||||
commandList->SetPipelineState(pso);
|
||||
commandList->SetGraphicsRootSignature(rootSignature);
|
||||
commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
|
||||
commandList->SetGraphicsRootConstantBufferView(0, cb->GetGPUVirtualAddress());
|
||||
commandList->SetGraphicsRoot32BitConstants(1, 4, color, 0);
|
||||
commandList->SetGraphicsRootDescriptorTable(2, srvHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
commandList->SetGraphicsRootShaderResourceView(3, sb->GetGPUVirtualAddress());
|
||||
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
staticMeshComponent.Render(commandList);
|
||||
EndRenderToSwapChain(commandList);
|
||||
EndCommandList();
|
||||
SwapD3D12Buffers();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
2
tests/D3D12/stbi/stb_image.cpp
Normal file
2
tests/D3D12/stbi/stb_image.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
7194
tests/D3D12/stbi/stb_image.h
Normal file
7194
tests/D3D12/stbi/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user