12DirectX12Texture::DirectX12Texture(ID3D12Device* device,
13 ID3D12CommandQueue* commandQueue,
14 ID3D12GraphicsCommandList* commandList)
15 : m_device(device), m_commandQueue(commandQueue),
16 m_commandList(commandList) {}
18DirectX12Texture::~DirectX12Texture() {
19 m_uploadBuffer.Reset();
24bool DirectX12Texture::LoadFromMemory(
const void* data, uint32_t
width,
26 TextureFormat format) {
27 if (!data || !m_device ||
width == 0 ||
height == 0)
return false;
33 DXGI_FORMAT dxgiFormat = GetDXGIFormat(format);
35 if (!CreateTextureResource(
width,
height, dxgiFormat))
return false;
36 if (!UploadTextureData(data,
width,
height))
return false;
37 if (!CreateSRV(dxgiFormat))
return false;
42bool DirectX12Texture::LoadFromFile(
const std::string& filePath) {
44 unsigned char* pixels =
45 stbi_load(filePath.c_str(), &w, &h, &channels, 4);
47 SLEAK_ERROR(
"DirectX12Texture: Failed to load image: {}",
52 bool result = LoadFromMemory(pixels,
static_cast<uint32_t
>(w),
53 static_cast<uint32_t
>(h),
54 TextureFormat::RGBA8);
55 stbi_image_free(pixels);
59void DirectX12Texture::Bind(uint32_t slot)
const {
60 if (m_commandList && m_srvHeap) {
61 BindToCommandList(m_commandList, 2);
65void DirectX12Texture::Unbind()
const {
69void DirectX12Texture::SetFilter(TextureFilter filter) {
75void DirectX12Texture::SetWrapMode(TextureWrapMode wrapMode) {
76 m_wrapMode = wrapMode;
79void DirectX12Texture::BindToCommandList(
80 ID3D12GraphicsCommandList* cmdList, UINT rootParameterIndex)
const {
83 if (m_usesSharedHeap) {
85 cmdList->SetGraphicsRootDescriptorTable(rootParameterIndex, m_srvGpuHandle);
86 }
else if (m_srvHeap) {
88 ID3D12DescriptorHeap* heaps[] = {m_srvHeap.Get()};
89 cmdList->SetDescriptorHeaps(1, heaps);
90 cmdList->SetGraphicsRootDescriptorTable(
92 m_srvHeap->GetGPUDescriptorHandleForHeapStart());
96bool DirectX12Texture::CreateTextureResource(uint32_t
width,
99 D3D12_RESOURCE_DESC texDesc{};
100 texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
101 texDesc.Alignment = 0;
102 texDesc.Width =
width;
104 texDesc.DepthOrArraySize = 1;
105 texDesc.MipLevels = 1;
106 texDesc.Format = format;
107 texDesc.SampleDesc.Count = 1;
108 texDesc.SampleDesc.Quality = 0;
109 texDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
110 texDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
112 D3D12_HEAP_PROPERTIES heapProps{};
113 heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
114 heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
115 heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
116 heapProps.CreationNodeMask = 1;
117 heapProps.VisibleNodeMask = 1;
119 HRESULT hr = m_device->CreateCommittedResource(
120 &heapProps, D3D12_HEAP_FLAG_NONE, &texDesc,
121 D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
122 IID_PPV_ARGS(&m_texture));
126 "DirectX12Texture: Failed to create texture resource "
128 static_cast<unsigned int>(hr));
135bool DirectX12Texture::UploadTextureData(
const void* data,
139 D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
141 UINT64 rowSizeInBytes;
143 D3D12_RESOURCE_DESC texDesc = m_texture->GetDesc();
144 m_device->GetCopyableFootprints(&texDesc, 0, 1, 0, &footprint,
145 &numRows, &rowSizeInBytes,
149 D3D12_HEAP_PROPERTIES uploadHeapProps{};
150 uploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
151 uploadHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
152 uploadHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
153 uploadHeapProps.CreationNodeMask = 1;
154 uploadHeapProps.VisibleNodeMask = 1;
156 D3D12_RESOURCE_DESC uploadDesc{};
157 uploadDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
158 uploadDesc.Alignment = 0;
159 uploadDesc.Width = totalBytes;
160 uploadDesc.Height = 1;
161 uploadDesc.DepthOrArraySize = 1;
162 uploadDesc.MipLevels = 1;
163 uploadDesc.Format = DXGI_FORMAT_UNKNOWN;
164 uploadDesc.SampleDesc.Count = 1;
165 uploadDesc.SampleDesc.Quality = 0;
166 uploadDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
167 uploadDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
169 HRESULT hr = m_device->CreateCommittedResource(
170 &uploadHeapProps, D3D12_HEAP_FLAG_NONE, &uploadDesc,
171 D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
172 IID_PPV_ARGS(&m_uploadBuffer));
176 "DirectX12Texture: Failed to create upload buffer");
181 BYTE* mapped =
nullptr;
182 hr = m_uploadBuffer->Map(0,
nullptr,
183 reinterpret_cast<void**
>(&mapped));
185 SLEAK_ERROR(
"DirectX12Texture: Failed to map upload buffer");
189 const BYTE* srcData =
static_cast<const BYTE*
>(data);
190 UINT srcRowPitch =
width * 4;
191 BYTE* destRow = mapped + footprint.Offset;
193 for (UINT row = 0; row < numRows; row++) {
194 memcpy(destRow + row * footprint.Footprint.RowPitch,
195 srcData + row * srcRowPitch,
199 m_uploadBuffer->Unmap(0,
nullptr);
202 Microsoft::WRL::ComPtr<ID3D12CommandAllocator> cmdAllocator;
203 Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> cmdList;
205 hr = m_device->CreateCommandAllocator(
206 D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAllocator));
207 if (FAILED(hr))
return false;
209 hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
210 cmdAllocator.Get(),
nullptr,
211 IID_PPV_ARGS(&cmdList));
212 if (FAILED(hr))
return false;
215 D3D12_TEXTURE_COPY_LOCATION dst{};
216 dst.pResource = m_texture.Get();
217 dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
218 dst.SubresourceIndex = 0;
220 D3D12_TEXTURE_COPY_LOCATION src{};
221 src.pResource = m_uploadBuffer.Get();
222 src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
223 src.PlacedFootprint = footprint;
225 cmdList->CopyTextureRegion(&dst, 0, 0, 0, &src,
nullptr);
228 D3D12_RESOURCE_BARRIER barrier{};
229 barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
230 barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
231 barrier.Transition.pResource = m_texture.Get();
232 barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
233 barrier.Transition.StateAfter =
234 D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
235 barrier.Transition.Subresource =
236 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
237 cmdList->ResourceBarrier(1, &barrier);
242 ID3D12CommandList* ppCmdLists[] = {cmdList.Get()};
243 m_commandQueue->ExecuteCommandLists(1, ppCmdLists);
249bool DirectX12Texture::CreateSRV(DXGI_FORMAT format) {
251 D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc{};
252 srvHeapDesc.NumDescriptors = 1;
253 srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
254 srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
256 HRESULT hr = m_device->CreateDescriptorHeap(
257 &srvHeapDesc, IID_PPV_ARGS(&m_srvHeap));
260 "DirectX12Texture: Failed to create SRV descriptor heap");
265 D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc{};
266 srvDesc.Shader4ComponentMapping =
267 D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
268 srvDesc.Format = format;
269 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
270 srvDesc.Texture2D.MipLevels = 1;
272 m_device->CreateShaderResourceView(
273 m_texture.Get(), &srvDesc,
274 m_srvHeap->GetCPUDescriptorHandleForHeapStart());
279bool DirectX12Texture::CreateSRVIntoHandle(DXGI_FORMAT format,
280 D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle) {
281 D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc{};
282 srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
283 srvDesc.Format = format;
284 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
285 srvDesc.Texture2D.MipLevels = 1;
286 m_device->CreateShaderResourceView(m_texture.Get(), &srvDesc, cpuHandle);
290DXGI_FORMAT DirectX12Texture::GetDXGIFormat(TextureFormat format)
const {
292 case TextureFormat::RGBA8:
293 return DXGI_FORMAT_R8G8B8A8_UNORM;
294 case TextureFormat::BGRA8:
295 return DXGI_FORMAT_B8G8R8A8_UNORM;
296 case TextureFormat::RGB8:
297 return DXGI_FORMAT_R8G8B8A8_UNORM;
299 return DXGI_FORMAT_R8G8B8A8_UNORM;
303void DirectX12Texture::WaitForUpload() {
304 Microsoft::WRL::ComPtr<ID3D12Fence> fence;
305 HRESULT hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE,
306 IID_PPV_ARGS(&fence));
307 if (FAILED(hr))
return;
309 HANDLE
event = CreateEvent(
nullptr, FALSE, FALSE,
nullptr);
312 m_commandQueue->Signal(fence.Get(), 1);
313 if (fence->GetCompletedValue() < 1) {
314 fence->SetEventOnCompletion(1, event);
315 WaitForSingleObject(event, INFINITE);
Backend-facing rendering layer shared by the four graphics backends.
Root namespace for everything the engine exposes.