674 lines
28 KiB
C++
674 lines
28 KiB
C++
#include "BattleFireDirect.h"
|
|
ID3D12Device* gD3D12Device = nullptr;
|
|
ID3D12CommandQueue* gCommandQueue = nullptr;
|
|
IDXGISwapChain3* gSwapChain = nullptr;
|
|
ID3D12Resource* gDSRT = nullptr, * gColorRTs[2];
|
|
int gCurrentRTIndex = 0;
|
|
ID3D12DescriptorHeap* gSwapChainRTVHeap = nullptr;
|
|
ID3D12DescriptorHeap* gSwapChainDSVHeap = nullptr;
|
|
UINT gRTVDescriptorSize = 0;
|
|
UINT gDSVDescriptorSize = 0;
|
|
ID3D12CommandAllocator* gCommandAllocator = nullptr;
|
|
ID3D12GraphicsCommandList* gCommandList = nullptr;
|
|
ID3D12Fence* gFence = nullptr;
|
|
HANDLE gFenceEvent = nullptr;
|
|
UINT64 gFenceValue = 0;
|
|
|
|
ID3D12RootSignature* InitRootSignature() {
|
|
//1110001110101111111111111111111111
|
|
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;//cbv
|
|
|
|
D3D12_DESCRIPTOR_RANGE descriptorRange[1];
|
|
descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
descriptorRange[0].RegisterSpace = 0;
|
|
descriptorRange[0].BaseShaderRegister = 0;//t0
|
|
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);//cbv
|
|
|
|
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;//srv
|
|
|
|
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;//s0
|
|
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;
|
|
|
|
//64 DWORD -> float 128 WORD -> 16bit
|
|
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;
|
|
}
|
|
|
|
ID3D12RootSignature* InitVolumeRootSignature() {
|
|
D3D12_ROOT_PARAMETER rootParameters[2];
|
|
|
|
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;
|
|
|
|
rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
rootParameters[1].Descriptor.RegisterSpace = 0;
|
|
rootParameters[1].Descriptor.ShaderRegister = 1;
|
|
|
|
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
|
rootSignatureDesc.NumParameters = _countof(rootParameters);
|
|
rootSignatureDesc.pParameters = rootParameters;
|
|
rootSignatureDesc.NumStaticSamplers = 0;
|
|
rootSignatureDesc.pStaticSamplers = nullptr;
|
|
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;
|
|
}
|
|
|
|
void CreateShaderFromFile(
|
|
LPCTSTR inShaderFilePath,
|
|
const char* inMainFunctionName,
|
|
const char* inTarget,//"vs_5_0","ps_5_0","vs_4_0"
|
|
D3D12_SHADER_BYTECODE* inShader) {
|
|
ID3DBlob* shaderBuffer = nullptr;
|
|
ID3DBlob* errorBuffer = nullptr;
|
|
HRESULT hResult = D3DCompileFromFile(inShaderFilePath, nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
|
inMainFunctionName, inTarget, D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
|
|
0, &shaderBuffer, &errorBuffer);
|
|
if (FAILED(hResult)) {
|
|
char szLog[1024] = {0};
|
|
if (errorBuffer) {
|
|
strcpy(szLog, (char*)errorBuffer->GetBufferPointer());
|
|
} else {
|
|
strcpy(szLog, "Unknown error");
|
|
}
|
|
printf("CreateShaderFromFile error : [%s][%s]:[%s]\n", inMainFunctionName, inTarget, szLog);
|
|
errorBuffer->Release();
|
|
return;
|
|
}
|
|
inShader->pShaderBytecode = shaderBuffer->GetBufferPointer();
|
|
inShader->BytecodeLength = shaderBuffer->GetBufferSize();
|
|
}
|
|
ID3D12Resource* CreateConstantBufferObject(int inDataLen) {
|
|
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;//cpu,gpu
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
ID3D12PipelineState* CreateVolumePSO(ID3D12RootSignature* inID3D12RootSignature,
|
|
D3D12_SHADER_BYTECODE inVertexShader, D3D12_SHADER_BYTECODE inPixelShader) {
|
|
D3D12_INPUT_ELEMENT_DESC vertexDataElementDesc[] = {
|
|
{"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0}
|
|
};
|
|
D3D12_INPUT_LAYOUT_DESC vertexDataLayoutDesc = {};
|
|
vertexDataLayoutDesc.NumElements = 1;
|
|
vertexDataLayoutDesc.pInputElementDescs = vertexDataElementDesc;
|
|
|
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
|
psoDesc.pRootSignature = inID3D12RootSignature;
|
|
psoDesc.VS = inVertexShader;
|
|
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_LINE;
|
|
|
|
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_WIREFRAME;
|
|
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
|
psoDesc.RasterizerState.FrontCounterClockwise = FALSE;
|
|
psoDesc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
|
|
psoDesc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
|
|
psoDesc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
|
psoDesc.RasterizerState.DepthClipEnable = TRUE;
|
|
psoDesc.RasterizerState.MultisampleEnable = FALSE;
|
|
psoDesc.RasterizerState.AntialiasedLineEnable = FALSE;
|
|
psoDesc.RasterizerState.ForcedSampleCount = 0;
|
|
psoDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
|
|
|
psoDesc.DepthStencilState.DepthEnable = TRUE;
|
|
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
|
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
|
|
psoDesc.DepthStencilState.StencilEnable = FALSE;
|
|
|
|
psoDesc.BlendState.AlphaToCoverageEnable = FALSE;
|
|
psoDesc.BlendState.IndependentBlendEnable = FALSE;
|
|
for (int i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
|
|
psoDesc.BlendState.RenderTarget[i].BlendEnable = FALSE;
|
|
psoDesc.BlendState.RenderTarget[i].LogicOpEnable = FALSE;
|
|
psoDesc.BlendState.RenderTarget[i].SrcBlend = D3D12_BLEND_ONE;
|
|
psoDesc.BlendState.RenderTarget[i].DestBlend = D3D12_BLEND_ZERO;
|
|
psoDesc.BlendState.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD;
|
|
psoDesc.BlendState.RenderTarget[i].SrcBlendAlpha = D3D12_BLEND_ONE;
|
|
psoDesc.BlendState.RenderTarget[i].DestBlendAlpha = D3D12_BLEND_ZERO;
|
|
psoDesc.BlendState.RenderTarget[i].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
|
psoDesc.BlendState.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP;
|
|
psoDesc.BlendState.RenderTarget[i].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
|
}
|
|
psoDesc.NumRenderTargets = 1;
|
|
ID3D12PipelineState* d3d12PSO = nullptr;
|
|
|
|
HRESULT hResult = gD3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&d3d12PSO));
|
|
if (FAILED(hResult)) {
|
|
printf("CreateVolumePSO failed: 0x%08X\n", hResult);
|
|
return nullptr;
|
|
}
|
|
return d3d12PSO;
|
|
}
|
|
|
|
ID3D12PipelineState* CreateQuadPSO(ID3D12RootSignature* inID3D12RootSignature,
|
|
D3D12_SHADER_BYTECODE inVertexShader, D3D12_SHADER_BYTECODE inPixelShader) {
|
|
D3D12_INPUT_ELEMENT_DESC vertexDataElementDesc[] = {
|
|
{"POSITION",0,DXGI_FORMAT_R32G32_FLOAT,0,0,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
|
|
{"TEXCOORD",0,DXGI_FORMAT_R32G32_FLOAT,0,8,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0}
|
|
};
|
|
D3D12_INPUT_LAYOUT_DESC vertexDataLayoutDesc = {};
|
|
vertexDataLayoutDesc.NumElements = 2;
|
|
vertexDataLayoutDesc.pInputElementDescs = vertexDataElementDesc;
|
|
|
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
|
psoDesc.pRootSignature = inID3D12RootSignature;
|
|
psoDesc.VS = inVertexShader;
|
|
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_NONE;
|
|
psoDesc.RasterizerState.FrontCounterClockwise = FALSE;
|
|
psoDesc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
|
|
psoDesc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
|
|
psoDesc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
|
psoDesc.RasterizerState.DepthClipEnable = TRUE;
|
|
psoDesc.RasterizerState.MultisampleEnable = FALSE;
|
|
psoDesc.RasterizerState.AntialiasedLineEnable = FALSE;
|
|
psoDesc.RasterizerState.ForcedSampleCount = 0;
|
|
psoDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
|
|
|
psoDesc.DepthStencilState.DepthEnable = TRUE;
|
|
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
|
|
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
|
|
psoDesc.DepthStencilState.StencilEnable = FALSE;
|
|
|
|
psoDesc.BlendState.AlphaToCoverageEnable = FALSE;
|
|
psoDesc.BlendState.IndependentBlendEnable = FALSE;
|
|
for (int i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
|
|
psoDesc.BlendState.RenderTarget[i].BlendEnable = TRUE;
|
|
psoDesc.BlendState.RenderTarget[i].LogicOpEnable = FALSE;
|
|
psoDesc.BlendState.RenderTarget[i].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
|
psoDesc.BlendState.RenderTarget[i].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
|
psoDesc.BlendState.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD;
|
|
psoDesc.BlendState.RenderTarget[i].SrcBlendAlpha = D3D12_BLEND_ONE;
|
|
psoDesc.BlendState.RenderTarget[i].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
|
psoDesc.BlendState.RenderTarget[i].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
|
psoDesc.BlendState.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP;
|
|
psoDesc.BlendState.RenderTarget[i].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
|
}
|
|
psoDesc.NumRenderTargets = 1;
|
|
ID3D12PipelineState* d3d12PSO = nullptr;
|
|
|
|
HRESULT hResult = gD3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&d3d12PSO));
|
|
if (FAILED(hResult)) {
|
|
printf("CreateQuadPSO failed: 0x%08X\n", hResult);
|
|
return nullptr;
|
|
}
|
|
return d3d12PSO;
|
|
}
|
|
|
|
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)
|
|
);
|
|
//RTV,DSV,alloc
|
|
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);
|
|
}
|
|
}
|
|
void EndCommandList() {
|
|
gCommandList->Close();//
|
|
ID3D12CommandList* ppCommandLists[] = { gCommandList };
|
|
gCommandQueue->ExecuteCommandLists(1, ppCommandLists);
|
|
//CommandList
|
|
gFenceValue += 1;
|
|
gCommandQueue->Signal(gFence, gFenceValue);//
|
|
}
|
|
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);
|
|
}
|
|
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);
|
|
}
|
|
ID3D12Resource* CreateBufferObject(ID3D12GraphicsCommandList* inCommandList,
|
|
void* inData, int inDataLen, D3D12_RESOURCE_STATES inFinalResourceState) {
|
|
D3D12_HEAP_PROPERTIES d3dHeapProperties = {};
|
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;//gpu
|
|
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);
|
|
// 3 x 4 x 4 = 48bytes,32bytes,24bytes + 24bytes
|
|
ID3D12Resource* tempBufferObject = nullptr;
|
|
d3dHeapProperties = {};
|
|
d3dHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;//cpu,gpu
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
|
|
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);
|
|
// 3 x 4 x 4 = 48bytes,32bytes,24bytes + 24bytes
|
|
ID3D12Resource* tempBufferObject = nullptr;
|
|
D3D12_HEAP_PROPERTIES d3dTempHeapProperties = {};
|
|
d3dTempHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;//cpu,gpu
|
|
|
|
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;
|
|
}
|
|
ID3D12Device* GetD3DDevice() {
|
|
return gD3D12Device;
|
|
}
|