Cogs.Core
RenderTargetsD3D12.cpp
1#include "RenderTargetsD3D12.h"
2
3#include "TexturesD3D12.h"
4#include "FormatsD3D12.h"
5#include "GraphicsDeviceD3D12.h"
6
7namespace {
8
9 D3D12_BLEND Blends[] = {
10 D3D12_BLEND_ZERO,
11 D3D12_BLEND_ONE,
12 D3D12_BLEND_SRC_COLOR,
13 D3D12_BLEND_INV_SRC_COLOR,
14 D3D12_BLEND_SRC_ALPHA,
15 D3D12_BLEND_INV_SRC_ALPHA,
16 D3D12_BLEND_DEST_ALPHA,
17 D3D12_BLEND_INV_DEST_ALPHA,
18 D3D12_BLEND_DEST_COLOR,
19 D3D12_BLEND_INV_DEST_COLOR,
20 D3D12_BLEND_SRC_ALPHA_SAT,
21 D3D12_BLEND_BLEND_FACTOR,
22 D3D12_BLEND_INV_BLEND_FACTOR,
23 };
24 static_assert(sizeof(Blends) == sizeof(Blends[0]) * size_t(Cogs::BlendState::Blend::Count));
25
26 D3D12_BLEND_OP BlendOperations[] = {
27 D3D12_BLEND_OP_ADD,
28 D3D12_BLEND_OP_SUBTRACT,
29 D3D12_BLEND_OP_REV_SUBTRACT,
30 D3D12_BLEND_OP_MIN,
31 D3D12_BLEND_OP_MAX
32 };
33 static_assert(sizeof(BlendOperations) == sizeof(BlendOperations[0]) * size_t(Cogs::BlendState::BlendOperation::Count));
34
35
36 D3D12_BLEND BlendOptions[] = {
37 D3D12_BLEND_ZERO,
38 D3D12_BLEND_ONE,
39 D3D12_BLEND_SRC_COLOR,
40 D3D12_BLEND_INV_SRC_COLOR,
41 D3D12_BLEND_SRC_ALPHA,
42 D3D12_BLEND_INV_SRC_ALPHA,
43 D3D12_BLEND_DEST_ALPHA,
44 D3D12_BLEND_INV_DEST_ALPHA,
45 };
46}
47
48
49HRESULT Cogs::RenderTargetsD3D12::initialize(struct GraphicsDeviceD3D12 * graphicsDevice)
50{
51 this->graphicsDevice = graphicsDevice;
52 device = graphicsDevice->device;
53 textures = &graphicsDevice->textures;
54
55 rtvPool.initialize(device, 256, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
56 dsvPool.initialize(device, 256, D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
57
58 return S_OK;
59}
60
61Cogs::RenderTargetHandle Cogs::RenderTargetsD3D12::createRenderTarget(ID3D12Resource * texture)
62{
63 auto textureDesc = texture->GetDesc();
64
65 RenderTargetD3D12 renderTarget{};
66 renderTarget.descriptor[0] = rtvPool.allocate();
67 renderTarget.descriptorHandle[0] = renderTarget.descriptor[0]->handle;
68 renderTarget.numViews = 1;
69 renderTarget.numSamples = textureDesc.SampleDesc.Count;
70
71 renderTarget.viewDesc[0].Format = textureDesc.Format;
72 renderTarget.viewDesc[0].ViewDimension = textureDesc.SampleDesc.Count > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS : D3D12_RTV_DIMENSION_TEXTURE2D;
73
74 device->CreateRenderTargetView(texture, renderTarget.viewDesc, renderTarget.descriptorHandle[0]);
75
76 renderTarget.resource = texture;
77
78 return renderTargets.addResource(renderTarget);
79}
80
81Cogs::RenderTargetHandle Cogs::RenderTargetsD3D12::createRenderTarget(const RenderTargetViewDescription * renderTargetViews, const size_t numViews)
82{
83 RenderTargetD3D12 renderTarget{};
84 renderTarget.numViews = static_cast<uint8_t>(numViews);
85
86 for (size_t i = 0; i < numViews; ++i) {
87 renderTarget.descriptor[i] = rtvPool.allocate();
88 renderTarget.descriptorHandle[i] = renderTarget.descriptor[i]->handle;
89
90 const auto & texture = textures->textures[renderTargetViews[i].texture];
91
92 renderTarget.textures[i] = renderTargetViews[i].texture;
93
94 renderTarget.viewDesc[i].Format = Direct3D12::Formats[(int)texture.format];
95 renderTarget.viewDesc[i].ViewDimension = texture.numSamples > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS : D3D12_RTV_DIMENSION_TEXTURE2D;
96
97 if (texture.desc.layers == 1) {
98 renderTarget.viewDesc[i].ViewDimension = texture.numSamples > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS : D3D12_RTV_DIMENSION_TEXTURE2D;
99 renderTarget.viewDesc[i].Texture2D.MipSlice = 0;
100 } else {
101 renderTarget.viewDesc[i].ViewDimension = texture.numSamples > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
102 renderTarget.viewDesc[i].Texture2DArray.ArraySize = 1;
103 renderTarget.viewDesc[i].Texture2DArray.FirstArraySlice = renderTargetViews[i].layerIndex;
104 renderTarget.viewDesc[i].Texture2DArray.MipSlice = renderTargetViews[i].levelIndex;
105 }
106
107 device->CreateRenderTargetView(texture.resource, &renderTarget.viewDesc[i], renderTarget.descriptorHandle[i]);
108 }
109
110 return renderTargets.addResource(renderTarget);
111}
112
114{
115 auto & renderTarget = renderTargets[handle];
116
117 for (size_t i = 0; i < renderTarget.numViews; ++i) {
118 graphicsDevice->context.currentFrameResources->orphanedRTVs.push_back(OrphanRTVDescriptor{ renderTarget.descriptor[i] });
119 }
120
121 renderTargets.removeResource(handle);
122}
123
125{
126 auto & renderTarget = renderTargets[handle];
127 auto & renderTexture = textures->textures[renderTarget.textures[0]];
128
129 auto depthTextureHandle = textures->loadTexture(nullptr, renderTexture.width, renderTexture.height, TextureFormat::R32_TYPELESS, renderTexture.numSamples, TextureFlags::DepthBuffer);
130
131 return createDepthStencilTarget(handle, depthTextureHandle);
132}
133
135{
137 desc.texture = textureHandle;
138 desc.numLayers = 1;
139
140 return createDepthStencilTarget(handle, desc);
141}
142
144{
145 auto & texture = textures->textures[depthStencilView.texture];
146
147 auto textureDesc = texture.resource->GetDesc();
148
149 DepthStencilTargetD3D12 dsTarget{};
150 dsTarget.descriptor = dsvPool.allocate();
151 dsTarget.descriptorHandle = dsTarget.descriptor->handle;
152
153 dsTarget.viewDesc.Format = textureDesc.Format == DXGI_FORMAT_R32_TYPELESS ? DXGI_FORMAT_D32_FLOAT : textureDesc.Format;
154 if (texture.desc.layers == 1) {
155 dsTarget.viewDesc.ViewDimension = textureDesc.SampleDesc.Count > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS : D3D12_DSV_DIMENSION_TEXTURE2D;
156 dsTarget.viewDesc.Texture2D.MipSlice = 0;
157 } else {
158 dsTarget.viewDesc.ViewDimension = textureDesc.SampleDesc.Count > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY : D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
159 dsTarget.viewDesc.Texture2DArray.ArraySize = 1;
160 dsTarget.viewDesc.Texture2DArray.FirstArraySlice = depthStencilView.layerIndex;
161 dsTarget.viewDesc.Texture2DArray.MipSlice = depthStencilView.levelIndex;
162 }
163
164 dsTarget.texture = depthStencilView.texture;
165
166 device->CreateDepthStencilView(texture.resource, &dsTarget.viewDesc, dsTarget.descriptorHandle);
167
168 return depthStencilTargets.addResource(dsTarget);
169}
170
172{
173 dsvPool.deallocate(depthStencilTargets[handle].descriptor);
174
175 depthStencilTargets.removeResource(handle);
176}
177
178namespace Cogs
179{
180 namespace Direct3D12
181 {
182 D3D12_COMPARISON_FUNC DepthFunctions[] = {
183 D3D12_COMPARISON_FUNC_NEVER,
184 D3D12_COMPARISON_FUNC_LESS,
185 D3D12_COMPARISON_FUNC_LESS_EQUAL,
186 D3D12_COMPARISON_FUNC_EQUAL,
187 D3D12_COMPARISON_FUNC_GREATER_EQUAL,
188 D3D12_COMPARISON_FUNC_GREATER,
189 D3D12_COMPARISON_FUNC_NOT_EQUAL,
190 D3D12_COMPARISON_FUNC_ALWAYS
191 };
192 }
193}
194
196{
197 DepthStencilStateD3D12 depthStencilStateD3d12;
198
199 // Depth test parameters
200 depthStencilStateD3d12.depthStencilDesc.DepthEnable = depthStencilState.depthEnabled;
201 depthStencilStateD3d12.depthStencilDesc.DepthWriteMask = depthStencilState.writeEnabled ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
202 depthStencilStateD3d12.depthStencilDesc.DepthFunc = Direct3D12::DepthFunctions[depthStencilState.depthFunction];
203
204 // Stencil test parameters
205 depthStencilStateD3d12.depthStencilDesc.StencilEnable = false;
206 depthStencilStateD3d12.depthStencilDesc.StencilReadMask = 0xFF;
207 depthStencilStateD3d12.depthStencilDesc.StencilWriteMask = 0xFF;
208
209 // Stencil operations if pixel is front-facing
210 depthStencilStateD3d12.depthStencilDesc.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
211 depthStencilStateD3d12.depthStencilDesc.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_INCR;
212 depthStencilStateD3d12.depthStencilDesc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP;
213 depthStencilStateD3d12.depthStencilDesc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
214
215 // Stencil operations if pixel is back-facing
216 depthStencilStateD3d12.depthStencilDesc.BackFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
217 depthStencilStateD3d12.depthStencilDesc.BackFace.StencilDepthFailOp = D3D12_STENCIL_OP_DECR;
218 depthStencilStateD3d12.depthStencilDesc.BackFace.StencilPassOp = D3D12_STENCIL_OP_KEEP;
219 depthStencilStateD3d12.depthStencilDesc.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
220
221 return depthStencilStates.addResource(depthStencilStateD3d12);
222}
223
225{
226 depthStencilStates.removeResource(handle);
227}
228
229namespace Cogs
230{
231 namespace Direct3D11
232 {
233 const D3D12_CULL_MODE CullModes[] = {
234 D3D12_CULL_MODE_FRONT,
235 D3D12_CULL_MODE_BACK,
236 D3D12_CULL_MODE_NONE
237 };
238 }
239}
240
242{
243 RasterizerStateD3D12 rasterizerStateD3d12;
244 rasterizerStateD3d12.rasterizerDesc = {};
245
246 rasterizerStateD3d12.rasterizerDesc.FillMode = rasterizerState.wireFrame ? D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;
247 rasterizerStateD3d12.rasterizerDesc.CullMode = Direct3D11::CullModes[rasterizerState.cullMode];
248
249 rasterizerStateD3d12.rasterizerDesc.AntialiasedLineEnable = true;
250 rasterizerStateD3d12.rasterizerDesc.FrontCounterClockwise = rasterizerState.frontCounterClockwise;
251 rasterizerStateD3d12.rasterizerDesc.MultisampleEnable = rasterizerState.multiSample;
252 rasterizerStateD3d12.rasterizerDesc.DepthClipEnable = true;
253
254 rasterizerStateD3d12.rasterizerDesc.DepthBias = static_cast<INT>(rasterizerState.depthBias);
255 rasterizerStateD3d12.rasterizerDesc.SlopeScaledDepthBias = rasterizerState.slopeScaledDepthBias;
256 rasterizerStateD3d12.rasterizerDesc.DepthBiasClamp = rasterizerState.depthBiasClamp;
257
258 return rasterizerStates.addResource(rasterizerStateD3d12);
259}
260
262{
263 rasterizerStates.removeResource(handle);
264}
265
266
268{
269 return loadBlendState(&blendState, &blendState, 1, BlendFlags::None);
270}
271
273{
274 return loadBlendState(&blendStateColor, &blendStateAlpha, 1, BlendFlags::None);
275}
276
277Cogs::BlendStateHandle Cogs::RenderTargetsD3D12::loadBlendState(const BlendState& blendStateColor, const BlendState& blendStateAlpha, const uint32_t flags)
278{
279 return loadBlendState(&blendStateColor, &blendStateAlpha, 1, flags);
280}
281
282Cogs::BlendStateHandle Cogs::RenderTargetsD3D12::loadBlendState(const BlendState* blendStatesColor, const BlendState* blendStatesAlpha, const uint32_t numBlendStates, const uint32_t flags)
283{
284 if (!blendStatesColor || !numBlendStates) return BlendStateHandle::InvalidHandle;
285
286 BlendStateD3D12 blendStateD3d12 = {};
287 blendStateD3d12.blendDesc = {};
288
289 blendStateD3d12.blendDesc.AlphaToCoverageEnable = (flags & BlendFlags::AlphaToCoverage) != 0 ? TRUE : FALSE;
290 blendStateD3d12.blendDesc.IndependentBlendEnable = (flags & BlendFlags::IndependentBlend) != 0 ? TRUE : FALSE;
291
292 const BlendState defaultBlendState = BlendState::DefaultState();
293
294 const uint32_t numStates = blendStateD3d12.blendDesc.IndependentBlendEnable ? 8 : 1;
295 for (uint32_t i = 0; i < numStates; ++i) {
296 const Cogs::BlendState& blendStateColor = i < numBlendStates ? blendStatesColor[i] : defaultBlendState;
297 const Cogs::BlendState& blendStateAlpha = blendStatesAlpha ? (i < numBlendStates ? blendStatesAlpha[i] : defaultBlendState) : defaultBlendState;
298
299 blendStateD3d12.blendDesc.RenderTarget[i].BlendEnable = blendStateColor.enabled;
300 blendStateD3d12.blendDesc.RenderTarget[i].SrcBlend = Blends[size_t(blendStateColor.sourceBlend)];
301 blendStateD3d12.blendDesc.RenderTarget[i].DestBlend = Blends[size_t(blendStateColor.destinationBlend)];
302 blendStateD3d12.blendDesc.RenderTarget[i].BlendOp = BlendOperations[size_t(blendStateColor.operation)];
303 blendStateD3d12.blendDesc.RenderTarget[i].SrcBlendAlpha = blendStateAlpha.enabled ? Blends[size_t(blendStateAlpha.sourceBlend)] : D3D12_BLEND_ZERO;
304 blendStateD3d12.blendDesc.RenderTarget[i].DestBlendAlpha = blendStateAlpha.enabled ? Blends[size_t(blendStateAlpha.destinationBlend)] : D3D12_BLEND_ONE;
305 blendStateD3d12.blendDesc.RenderTarget[i].BlendOpAlpha = blendStateAlpha.enabled ? BlendOperations[size_t(blendStateAlpha.operation)] : D3D12_BLEND_OP_ADD;
306 blendStateD3d12.blendDesc.RenderTarget[i].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
307 }
308 return blendStates.addResource(blendStateD3d12);
309}
310
312{
313 blendStates.removeResource(handle);
314}
315
317{
318 // Noop
319}
const DXGI_FORMAT Formats[]
Must match up to Format definition.
Definition: FormatsD3D12.cpp:9
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ Direct3D12
Graphics device using the Direct3D 12 API.
@ Direct3D11
Graphics device using the Direct3D 11 API.
Encapsulates blend state for the graphics pipeline in a state object.
Definition: BlendState.h:9
uint8_t enabled
If blending is enabled.
Definition: BlendState.h:41
Blend destinationBlend
Blend option for the blend destination data.
Definition: BlendState.h:47
static BlendState DefaultState()
Creates a blend state object initialized with the default settings.
Definition: BlendState.h:55
BlendOperation operation
How the two blend values are combined.
Definition: BlendState.h:50
Blend sourceBlend
Blend option for the blend source data.
Definition: BlendState.h:44
Encapsulates state for depth buffer usage and stencil buffer usage in a state object.
bool depthEnabled
If depth testing is enabled/disabled. Default is true.
DepthFunction depthFunction
The depth function to use for depth testing.
bool writeEnabled
If writes to the depth buffer are enabled/disabled. Default is true.
Describes a single depth stencil view and which resources to use from the underlying texture.
TextureHandle texture
Texture handle.
uint8_t levelIndex
Index of the mipmap level to render to.
uint16_t layerIndex
Index of the first layer (if array) to write depth to.
handle_type handle
Internal resource handle.
Definition: Common.h:74
static const Handle_t InvalidHandle
Represents an invalid handle.
Definition: Common.h:80
Encapsulates state for primitive rasterization in a state object.
bool multiSample
If multisample rasterization should be enabled. Default is true.
bool frontCounterClockwise
If counter clockwise polygon winding is used to specify front facing polygons. Default is false.
CullMode cullMode
Which face culling mode to apply to primitives before rasterization.
float depthBias
Depth bias to apply to depth values after initial rasterization before depth values are written.
float depthBiasClamp
Value to clamp the depth bias to so that it may not go outside desired values even when applying slop...
float slopeScaledDepthBias
Slope scaled depth bias value controlling the depth bias value based on the area of the polygon on sc...
bool wireFrame
If only wire frames should be rasterized. Default is false.
Describes a single render target view and which resources to use from the underlying texture.
uint16_t layerIndex
Index of the first layer (if array) to render to.
TextureHandle texture
Texture handle.
uint8_t levelIndex
Index of the mipmap level to render to.
void releaseRenderTarget(RenderTargetHandle handle)
Release the render target with the given renderTargetHandle.
RasterizerStateHandle loadRasterizerState(const RasterizerState &rasterizerState)
Load a rasterizer state object.
BlendStateHandle loadBlendState(const BlendState &blendState)
Load a blend state object.
void releaseBlendState(BlendStateHandle handle)
Release the blend state with the given handle.
void releaseDepthStencilTarget(DepthStencilHandle handle)
Release the depth target with the given depthStencilHandle.
DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState)
Load a depth stencil state object.
void releaseDepthStencilState(DepthStencilStateHandle handle)
Release the depth stencil state with the given handle.
void releaseRasterizerState(RasterizerStateHandle handle)
Release the rasterizer state with the given handle.
void releaseResources()
Release all allocated render target resources.
DepthStencilHandle createDepthStencilTarget(const RenderTargetHandle handle)
Creates a depth/stencil target to back the render target with the given handle.
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122