図0002a
#include "INCStructs.hlsli"
cbuffer ConstantBuffer : register(b0)
{
row_major float4x4 MatrixTransform : packoffset(c0);
float4 Emissive : packoffset(c4);
};
PSPCInput main(VSPCInput input)
{
PSPCInput result;
result.position = mul(input.position, MatrixTransform);
result.color = input.color;
return result;
}
#include "INCStructs.hlsli"
cbuffer ConstantBuffer : register(b0)
{
row_major float4x4 MatrixTransform : packoffset(c0);
float4 Emissive : packoffset(c4);
};
float4 main(PSPCInput input) : SV_TARGET
{
return saturate(Emissive + input.color);
}
void TriangleSprite::OnCreate() {
//頂点を作成するための配列
vector<VertexPositionColor> vertices = {
{ VertexPositionColor(Vec3(0.0f, 0.5f, 0.0f), Col4(1.0f,0.0f,0.0f,1.0f)) },
{ VertexPositionColor(Vec3(0.5f, -0.5f, 0.0f), Col4(0.0f, 1.0f, 0.0f, 1.0f)) },
{ VertexPositionColor(Vec3(-0.5f, -0.5f, 0.0f), Col4(0.0f, 0.0f, 1.0f, 1.0f)) },
};
m_TriangleMesh = MeshResource::CreateMeshResource(vertices, false);
///ルートシグネチャ作成
CreateRootSignature();
///デスクプリタヒープ作成
CreateDescriptorHeap();
///コンスタントバッファ作成
CreateConstantBuffer();
///パイプラインステート作成
CreatePipelineState();
///コマンドリスト作成
CreateCommandList();
//コンスタントバッファの更新
UpdateConstantBuffer();
}
///ルートシグネチャ作成
void TriangleSprite::CreateRootSignature() {
//コンスタントバッファ付ルートシグネチャ
m_RootSignature = RootSignature::CreateCbv();
}
//コンスタントバッファのみ
static inline ComPtr<ID3D12RootSignature> CreateCbv() {
auto Dev = App::GetApp()->GetDeviceResources();
ComPtr<ID3D12RootSignature> Ret = Dev->GetRootSignature(L"Cbv");
if (Ret != nullptr) {
return Ret;
}
CD3DX12_DESCRIPTOR_RANGE ranges[1];
ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
CD3DX12_ROOT_PARAMETER rootParameters[1];
rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_ALL);
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr,
rootSignatureFlags);
Ret = CreateDirect(rootSignatureDesc);
Dev->SetRootSignature(L"Cbv", Ret);
return Ret;
}
///デスクプリタヒープ作成
void TriangleSprite::CreateDescriptorHeap() {
auto Dev = App::GetApp()->GetDeviceResources();
m_CbvSrvDescriptorHandleIncrementSize
= Dev->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
//CbvSrvデスクプリタヒープ(コンスタントバッファのみ)
m_CbvSrvUavDescriptorHeap = DescriptorHeap::CreateCbvSrvUavHeap(1);
//GPU側デスクプリタヒープのハンドルの配列の作成
m_GPUDescriptorHandleVec.clear();
CD3DX12_GPU_DESCRIPTOR_HANDLE CbvHandle(
m_CbvSrvUavDescriptorHeap->GetGPUDescriptorHandleForHeapStart(),
0,
0
);
m_GPUDescriptorHandleVec.push_back(CbvHandle);
}
static inline ComPtr<ID3D12DescriptorHeap> CreateCbvSrvUavHeap(UINT NumDescriptorHeap) {
//CbvSrvデスクプリタヒープ
D3D12_DESCRIPTOR_HEAP_DESC CbvSrvHeapDesc = {};
CbvSrvHeapDesc.NumDescriptors = NumDescriptorHeap;
CbvSrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
CbvSrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
return CreateDirect(CbvSrvHeapDesc);
}
class TriangleSprite : public ObjectInterface, public ShapeInterface {
//中略
///コンスタントバッファ
struct SpriteConstantBuffer
{
Mat4x4 World;
Col4 Emissive;
SpriteConstantBuffer() {
memset(this, 0, sizeof(SpriteConstantBuffer));
};
};
///コンスタントバッファデータ
SpriteConstantBuffer m_SpriteConstantBuffer;
///コンスタントバッファアップロードヒープ
ComPtr<ID3D12Resource> m_ConstantBufferUploadHeap;
///コンスタントバッファのGPU側変数
void* m_pConstantBuffer{ nullptr };
//中略
};
///コンスタントバッファ作成
void TriangleSprite::CreateConstantBuffer() {
auto Dev = App::GetApp()->GetDeviceResources();
ThrowIfFailed(Dev->GetDevice()->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer((sizeof(SpriteConstantBuffer) + 255) & ~255),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_ConstantBufferUploadHeap)),
L"コンスタントバッファ用のアップロードヒープ作成に失敗しました",
L"Dev->GetDevice()->CreateCommittedResource()",
L"TriangleSprite::CreateConstantBuffer()"
);
//コンスタントバッファのビューを作成
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
cbvDesc.BufferLocation = m_ConstantBufferUploadHeap->GetGPUVirtualAddress();
//コンスタントバッファは256バイトにアラインメント
cbvDesc.SizeInBytes = (sizeof(SpriteConstantBuffer) + 255) & ~255;
//コンスタントバッファビューを作成すべきデスクプリタヒープ上のハンドルを取得
//シェーダリソースがある場合コンスタントバッファはシェーダリソースビューのあとに設置する
CD3DX12_CPU_DESCRIPTOR_HANDLE cbvSrvHandle(
m_CbvSrvUavDescriptorHeap->GetCPUDescriptorHandleForHeapStart(),
0,
0
);
Dev->GetDevice()->CreateConstantBufferView(&cbvDesc, cbvSrvHandle);
//コンスタントバッファのアップロードヒープのマップ
CD3DX12_RANGE readRange(0, 0);
ThrowIfFailed(m_ConstantBufferUploadHeap->Map(0,
&readRange, reinterpret_cast<void**>(&m_pConstantBuffer)),
L"コンスタントバッファのマップに失敗しました",
L"pImpl->m_ConstantBufferUploadHeap->Map()",
L"TriangleSprite::CreateConstantBuffer()"
);
}
1、コンスタントバッファのためにDx12によって確保される領域はアップロードヒープである。 2、アップロードヒープとデスクプリタヒープのCPU側ハンドルを使って、コンスタントバッファビューを作成する。 3、アップロードヒープにデータをアップするために、メンバ変数のポインタをマップさせる
void TriangleSprite::UpdateConstantBuffer() {
//コンスタントバッファの準備
m_SpriteConstantBuffer.Emissive = Col4(0.0f, 0.0f, 0, 1.0f);
Matrix4X4 mat;
mat.TranslationFromVector(m_Pos);
m_SpriteConstantBuffer.World = mat;
//更新
memcpy(m_pConstantBuffer, reinterpret_cast<void**>(&m_SpriteConstantBuffer),
sizeof(m_SpriteConstantBuffer));
}
void TriangleSprite::CreatePipelineState() {
D3D12_GRAPHICS_PIPELINE_STATE_DESC PineLineDesc;
m_PipelineState
= PipelineState::CreateDefault2D<VertexPositionColor,
VSPCSprite, PSPCSprite>(m_RootSignature, PineLineDesc);
}
DECLARE_DX12SHADER(VSPCSprite)
#define DECLARE_DX12SHADER(ShaderName) class ShaderName : \
public Dx12Shader<ShaderName>{ \
public: \
ShaderName(); \
};
IMPLEMENT_DX12SHADER(VSPCSprite, App::GetApp()->m_wstrRelativeShadersPath + L"VSPCSprite.cso")
#define IMPLEMENT_DX12SHADER(ShaderName,CsoFilename) unique_ptr<ShaderName, ShaderName::Deleter> ShaderName::m_Ptr; \
ShaderName::ShaderName() : \
Dx12Shader(CsoFilename){}
void TriangleSprite::CreateCommandList() {
m_CommandList = CommandList::CreateDefault(m_PipelineState);
CommandList::Close(m_CommandList);
}
void TriangleSprite::DrawObject() {
auto Dev = App::GetApp()->GetDeviceResources();
//コマンドリストのリセット
CommandList::Reset(m_PipelineState, m_CommandList);
//メッシュが更新されていればリソース更新
m_TriangleMesh->UpdateResources<VertexPositionColor>(m_CommandList);
//ルートシグネチャのセット
m_CommandList->SetGraphicsRootSignature(m_RootSignature.Get());
//デスクプリタヒープのセット
ID3D12DescriptorHeap* ppHeaps[] = { m_CbvSrvUavDescriptorHeap.Get() };
m_CommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
//GPUデスクプリタヒープハンドルのセット
for (size_t i = 0; i < m_GPUDescriptorHandleVec.size(); i++) {
m_CommandList->SetGraphicsRootDescriptorTable(i, m_GPUDescriptorHandleVec[i]);
}
m_CommandList->RSSetViewports(1, &Dev->GetViewport());
m_CommandList->RSSetScissorRects(1, &Dev->GetScissorRect());
//レンダーターゲットビューのハンドルを取得
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle = Dev->GetRtvHandle();
//デプスステンシルビューのハンドルを取得
CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle = Dev->GetDsvHandle();
//取得したハンドルをセット
m_CommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
m_CommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_CommandList->IASetVertexBuffers(0, 1, &m_TriangleMesh->GetVertexBufferView());
m_CommandList->DrawInstanced(m_TriangleMesh->GetNumVertices(), 1, 0, 0);
//コマンドリストのクローズ
CommandList::Close(m_CommandList);
//デバイスにコマンドリストを送る
Dev->InsertDrawCommandLists(m_CommandList.Get());
}