Cogs.Core
TexturesD3D12.cpp
1#include "TexturesD3D12.h"
2
3#include "Foundation/Logging/Logger.h"
4
5#include <algorithm>
6
7#include "FormatsD3D12.h"
8
9namespace
10{
11 Cogs::Logging::Log logger = Cogs::Logging::getLogger("TexturesD3D12");
12}
13
15{
16 textures.removeResource(textureHandle);
17}
18
20{
21 SamplerD3D12 sampler = {};
22 sampler.samplerDesc.AddressU = Direct3D12::AddressModes[state.addressModeS];
23 sampler.samplerDesc.AddressV = Direct3D12::AddressModes[state.addressModeT];
24 sampler.samplerDesc.AddressW = Direct3D12::AddressModes[state.addressModeW];
25 sampler.samplerDesc.Filter = Direct3D12::FilterModes[state.filter];
26 sampler.samplerDesc.MaxAnisotropy = state.maxAnisotropy;
27 sampler.samplerDesc.ComparisonFunc = Direct3D12::ComparisonFunctions[state.comparisonFunction];
28 sampler.samplerDesc.MinLOD = 0;
29 sampler.samplerDesc.MaxLOD = 16;
30 sampler.samplerDesc.BorderColor[0] = state.borderColor[0];
31 sampler.samplerDesc.BorderColor[1] = state.borderColor[1];
32 sampler.samplerDesc.BorderColor[2] = state.borderColor[2];
33 sampler.samplerDesc.BorderColor[3] = state.borderColor[3];
34
35 return samplerStates.addResource(sampler);
36}
37
39{
40 samplerStates.removeResource(handle);
41}
42
44{
45
46}
47
49{
50 samplerStates.clear();
51
52 textures.clear();
53}
54
56{
57 TextureViewD3D12 view = {};
58
59 view.texture = viewDescription.texture;
60
61 createShaderResourceView(view.srvDesc, textures[view.texture], viewDescription, textures[view.texture].desc.flags);
62
63 return textureViews.addResource(view);
64}
65
67{
68 textureViews.removeResource(handle);
69}
70
72{
73 auto & texture = textures[textureHandle];
74
75 return &*texture.resource;
76}
77
79{
80 TextureD3D12 texture;
81 texture.desc = desc;
82 texture.dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
83 texture.width = desc.width;
84 texture.height = desc.height;
85 texture.format = desc.format;
86 texture.numSamples = desc.samples;
87
88 D3D12_RESOURCE_FLAGS resourceFlags = D3D12_RESOURCE_FLAG_NONE;
89
90 resourceFlags |= (desc.flags & TextureFlags::DepthBuffer) != 0 ? D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL : D3D12_RESOURCE_FLAG_NONE;
91 resourceFlags |= (desc.flags & TextureFlags::RenderTarget) != 0 ? D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET : D3D12_RESOURCE_FLAG_NONE;
92
93 D3D12_RESOURCE_DESC textureDesc;
94 textureDesc.Dimension = texture.dimension;
95 textureDesc.DepthOrArraySize = static_cast<UINT16>(desc.layers * desc.faces);
96 textureDesc.Alignment = 0;
97 textureDesc.Width = desc.width;
98 textureDesc.Height = desc.height;
99 textureDesc.Format = Direct3D12::Formats[(int)desc.format];
100 textureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
101 textureDesc.Flags = resourceFlags;
102 textureDesc.MipLevels = static_cast<UINT16>(desc.levels);
103 textureDesc.SampleDesc.Count = desc.samples;
104 textureDesc.SampleDesc.Quality = 0;
105
106 D3D12_CLEAR_VALUE clearValue;
107 HRESULT hr;
108
109 if ((desc.flags & TextureFlags::DepthBuffer) != 0) {
110 clearValue.Format = textureDesc.Format == DXGI_FORMAT_R32_TYPELESS ? DXGI_FORMAT_D32_FLOAT : textureDesc.Format;
111 clearValue.DepthStencil.Depth = 1.0f;
112 clearValue.DepthStencil.Stencil = 0;
113
114 hr = device->CreateCommittedResource(
115 &defaultHeapProperties,
116 D3D12_HEAP_FLAG_NONE,
117 &textureDesc,
118 D3D12_RESOURCE_STATE_COMMON,
119 &clearValue,
120 IID_PPV_ARGS(texture.resource.internalPointer()));
121
122 if ((desc.flags & TextureFlags::Texture) != 0) {
123 TextureViewDescription viewDesc = {};
124 viewDesc.numLayers = 1;
125 viewDesc.numLevels = desc.levels;
126 createShaderResourceView(texture.srvDesc, texture, viewDesc, desc.flags);
127 }
128 } else {
129 clearValue.Format = textureDesc.Format;
130 clearValue.Color[0] = 1;
131 clearValue.Color[1] = 1;
132 clearValue.Color[2] = 1;
133 clearValue.Color[3] = 1;
134
135 hr = device->CreateCommittedResource(
136 &defaultHeapProperties,
137 D3D12_HEAP_FLAG_NONE,
138 &textureDesc,
139 D3D12_RESOURCE_STATE_COMMON,
140 (desc.flags & TextureFlags::RenderTarget) ? &clearValue : nullptr,
141 IID_PPV_ARGS(texture.resource.internalPointer()));
142
143 texture.numSubResources = textureDesc.DepthOrArraySize * textureDesc.MipLevels;
144
145 if (data) {
146 const int maxSubresources = 16;
147 UINT64 uploadBufferSize = 0;
148 D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[maxSubresources];
149 UINT numRows[maxSubresources];
150 UINT64 rowSizesInBytes[maxSubresources];
151
152 auto resourceDesc = texture.resource->GetDesc();
153 device->GetCopyableFootprints(&resourceDesc, 0, texture.numSubResources, 0, layouts, numRows, rowSizesInBytes, &uploadBufferSize);
154
155 CD3DX12_RESOURCE_DESC uploadBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize);
156
157 device->CreateCommittedResource(
158 &uploadHeapProperties,
159 D3D12_HEAP_FLAG_NONE,
160 &uploadBufferDesc,
161 D3D12_RESOURCE_STATE_GENERIC_READ,
162 nullptr,
163 IID_PPV_ARGS(texture.uploadResource.internalPointer()));
164
165 UINT8 * resourceData;
166 texture.uploadResource->Map(0, nullptr, reinterpret_cast<void**>(&resourceData));
167
168 size_t subResourceIndex = 0;
169 for (size_t i = 0; i < desc.layers; ++i) {
170 for (size_t j = 0; j < desc.faces; ++j) {
171 for (size_t k = 0; k < desc.levels; ++k) {
172 D3D12_SUBRESOURCE_DATA srcData;
173
174 srcData.pData = data->getData(i, j, k);
175 srcData.RowPitch = static_cast<uint32_t>(data->getPitch(k));
176 srcData.SlicePitch = data->getLayerSize(0, desc.faces - 1, 0, desc.levels - 1);
177
178 auto & layout = layouts[subResourceIndex];
179 auto & rows = numRows[subResourceIndex];
180
181 D3D12_MEMCPY_DEST destData = { resourceData + layout.Offset, layout.Footprint.RowPitch, layout.Footprint.RowPitch * rows };
182 MemcpySubresource(&destData, &srcData, rowSizesInBytes[subResourceIndex], rows, layout.Footprint.Depth);
183
184 ++subResourceIndex;
185 }
186 }
187 }
188
189 texture.uploadResource->Unmap(0, nullptr);
190 texture.needsUpload = true;
191 }
192
193 TextureViewDescription viewDesc = {};
194 viewDesc.numLayers = 1;
195 viewDesc.numLevels = desc.levels;
196 createShaderResourceView(texture.srvDesc, texture, viewDesc, desc.flags);
197 }
198
199 if (FAILED(hr)) {
200 LOG_ERROR(logger, "Error creating committed resource for texture.");
202 }
203
204 return textures.addResource(texture);
205}
206
207bool Cogs::TexturesD3D12::createShaderResourceView(D3D12_SHADER_RESOURCE_VIEW_DESC & srvDesc, TextureD3D12 & texture, const TextureViewDescription & viewDesc, TextureFlags::ETextureFlags flags)
208{
209 const bool cubeMap = (flags & TextureFlags::CubeMap) != 0;
210
211 if (cubeMap && texture.desc.faces != 6) {
212 LOG_ERROR(logger, "Cannot create cube map with %d faces.", texture.desc.faces);
213 return false;
214 }
215
216 srvDesc = {};
217 srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
218 srvDesc.Format = Direct3D12::Formats[(int)texture.desc.format];
219
220 if (srvDesc.Format == DXGI_FORMAT_R32_TYPELESS) {
221 srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
222 } else if (srvDesc.Format == DXGI_FORMAT_R16_TYPELESS) {
223 srvDesc.Format = DXGI_FORMAT_R16_FLOAT;
224 } else if (srvDesc.Format == DXGI_FORMAT_R8G8B8A8_TYPELESS) {
225 srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
226 }
227
228 const uint32_t mostDetailedMip = std::min(viewDesc.levelIndex, std::max(1u, texture.desc.levels) - 1u);
229
230 if (texture.desc.layers == 1) {
231 if (cubeMap) {
232 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
233 srvDesc.TextureCube.MipLevels = texture.desc.levels;
234 srvDesc.TextureCube.MostDetailedMip = mostDetailedMip;
235 } else {
236 srvDesc.ViewDimension = texture.desc.samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMS : D3D12_SRV_DIMENSION_TEXTURE2D;
237 srvDesc.Texture2D.MipLevels = texture.desc.levels;
238 srvDesc.Texture2D.MostDetailedMip = mostDetailedMip;
239 }
240 } else {
241 if (cubeMap) {
242 srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
243 srvDesc.TextureCubeArray.MipLevels = texture.desc.levels;
244 srvDesc.TextureCubeArray.NumCubes = texture.desc.layers;
245 srvDesc.TextureCubeArray.MostDetailedMip = mostDetailedMip;
246 } else {
247 srvDesc.ViewDimension = texture.desc.samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
248 srvDesc.Texture2DArray.MipLevels = texture.desc.levels;
249 srvDesc.Texture2DArray.ArraySize = static_cast<uint32_t>(texture.desc.layers);
250 srvDesc.Texture2DArray.MostDetailedMip = mostDetailedMip;
251 }
252 }
253
254 return true;
255}
Log implementation class.
Definition: LogManager.h:139
const DXGI_FORMAT Formats[]
Must match up to Format definition.
Definition: FormatsD3D12.cpp:9
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
static const Handle_t InvalidHandle
Represents an invalid handle.
Definition: Common.h:80
Encapsulates state for texture sampling in a state object.
Definition: SamplerState.h:12
ComparisonFunction comparisonFunction
Specifies the comparison function to use when applying a comparison sampler.
Definition: SamplerState.h:73
unsigned int maxAnisotropy
Specifies the maximum number of anisotropic samples to use when sampling a texture.
Definition: SamplerState.h:76
AddressMode addressModeW
Specifies the addressing mode along the W axis in texture coordinate space.
Definition: SamplerState.h:67
AddressMode addressModeS
Specifies the addressing mode along the S axis in texture coordinate space.
Definition: SamplerState.h:63
float borderColor[4]
Definition: SamplerState.h:80
FilterMode filter
Specifies the filter to use for texture sampling.
Definition: SamplerState.h:70
AddressMode addressModeT
Specifies the addressing mode along the T axis in texture coordinate space.
Definition: SamplerState.h:65
ETextureFlags
Texture flags enumeration.
Definition: Flags.h:114
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122
@ RenderTarget
The texture can be used as a render target and drawn into.
Definition: Flags.h:120
@ Texture
Texture usage, see Default.
Definition: Flags.h:118
@ CubeMap
The texture can be used as a cube map.
Definition: Flags.h:126
Describes how to fetch data from a texture in shaders.
Definition: ITextures.h:13
uint32_t numLayers
Number of array layers available.
Definition: ITextures.h:19
uint32_t numLevels
Number of mipmap levels available.
Definition: ITextures.h:23
uint32_t levelIndex
First mipmap level to fetch data from.
Definition: ITextures.h:21
TextureHandle texture
Texture.
Definition: ITextures.h:15
void * getNativeHandle(TextureHandle textureHandle) override
Get the device-specific handle (D3D texture pointer, OpenGL texture ID etc) associated with the given...
void releaseSamplerState(SamplerStateHandle handle) override
Release the sampler state with the given handle.
TextureViewHandle createTextureView(TextureViewDescription &viewDescription) override
Create a texture view used to bind a limited view of the texture data to the rendering pipeline.
SamplerStateHandle loadSamplerState(const SamplerState &state) override
Load a sampler state object.
void releaseResources() override
Release all allocated texture resources.
void releaseTexture(TextureHandle textureHandle) override
Release the texture with the given textureHandle.
void releaseTextureView(const TextureViewHandle &handle) override
Release the given texture view.
TextureHandle loadTexture(const TextureDescription &desc, const TextureData *data) override
Load a texture from the given description.
void generateMipmaps(TextureHandle texureHandle) override
Use the graphics device to generate mipmaps for the texture with the given texture handle.