1#include "RenderTargetsD3D11.h"
4#include "TexturesD3D11.h"
5#include "FormatsD3D11.h"
6#include "GraphicsDeviceD3D11.h"
8#include "Foundation/Logging/Logger.h"
14 D3D11_BLEND Blends[] = {
17 D3D11_BLEND_SRC_COLOR,
18 D3D11_BLEND_INV_SRC_COLOR,
19 D3D11_BLEND_SRC_ALPHA,
20 D3D11_BLEND_INV_SRC_ALPHA,
21 D3D11_BLEND_DEST_ALPHA,
22 D3D11_BLEND_INV_DEST_ALPHA,
23 D3D11_BLEND_DEST_COLOR,
24 D3D11_BLEND_INV_DEST_COLOR,
25 D3D11_BLEND_SRC_ALPHA_SAT,
26 D3D11_BLEND_BLEND_FACTOR,
27 D3D11_BLEND_INV_BLEND_FACTOR,
29 static_assert(
sizeof(Blends) ==
sizeof(Blends[0]) * size_t(Cogs::BlendState::Blend::Count));
31 D3D11_BLEND_OP BlendOperations[] = {
33 D3D11_BLEND_OP_SUBTRACT,
34 D3D11_BLEND_OP_REV_SUBTRACT,
38 static_assert(
sizeof(BlendOperations) ==
sizeof(BlendOperations[0]) * size_t(Cogs::BlendState::BlendOperation::Count));
45#ifdef COGSRENDERING_GFX_ANNOTATE
49 auto & rt = renderTargets[handle];
51 for (
size_t i = 0; i < rt.numViews; i++) {
55 m.append(std::to_string(i));
57 rt.views[i]->SetPrivateData(WKPDID_D3DDebugObjectName,
static_cast<UINT
>(m.length()), m.c_str());
68#ifdef COGSRENDERING_GFX_ANNOTATE
72 auto & rt = depthStencilViews[handle];
74 rt->SetPrivateData(WKPDID_D3DDebugObjectName,
static_cast<UINT
>(name.
length()), name.
data());
84 if (texture ==
nullptr) {
88 RenderTargetD3D11 renderTarget;
89 renderTarget.numViews = 1;
91 HRESULT hr = graphicsDevice->getDevice()->CreateRenderTargetView(texture, NULL, renderTarget.views[0].internalPointer());
93 LOG_ERROR(logger,
"Failed to create render target: %s", direct3D11ReturnCodeAsString(hr));
97 return renderTargets.addResource(std::move(renderTarget), persistent);
102 this->renderTargets.removeResource(handle);
108 renderTarget.numViews = numViews;
110 for (
size_t i = 0; i < numViews; ++i) {
111 auto & texture = textures->textures[renderTargetViews[i].
texture];
112 renderTarget.texture[i] = renderTargetViews[i].
texture;
114 D3D11_TEXTURE2D_DESC textureDesc;
115 texture.texture2D->GetDesc(&textureDesc);
117 D3D11_RENDER_TARGET_VIEW_DESC renderTargetDesc = {};
119 if (textureDesc.Format == DXGI_FORMAT_R8G8B8A8_TYPELESS) {
120 renderTargetDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
122 renderTargetDesc.Format = textureDesc.Format;
125 if (texture.desc.layers > 1) {
126 renderTargetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
127 renderTargetDesc.Texture2DArray.FirstArraySlice = renderTargetViews[i].
layerIndex;
128 renderTargetDesc.Texture2DArray.ArraySize = renderTargetViews[i].
numLayers;
129 renderTargetDesc.Texture2DArray.MipSlice = renderTargetViews[i].
levelIndex;
131 else if (textureDesc.SampleDesc.Count > 1) {
132 renderTargetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
135 renderTargetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
136 renderTargetDesc.Texture2D.MipSlice = renderTargetViews[i].
levelIndex;
139 HRESULT hr = graphicsDevice->getDevice()->CreateRenderTargetView(texture.resource(), &renderTargetDesc, renderTarget.views[i].internalPointer());
141 LOG_ERROR(logger,
"Failed to create render target: %s", direct3D11ReturnCodeAsString(hr));
146 return renderTargets.addResource(std::move(renderTarget));
151 auto & texture = textures->textures[textureView.
texture];
153 D3D11_TEXTURE2D_DESC textureDesc;
154 texture.texture2D->GetDesc(&textureDesc);
156 D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {};
158 depthStencilViewDesc.Format = textureDesc.Format;
160 if (textureDesc.Format == DXGI_FORMAT_R32_TYPELESS) {
161 depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT;
162 }
else if (textureDesc.Format == DXGI_FORMAT_R16_TYPELESS) {
163 depthStencilViewDesc.Format = DXGI_FORMAT_D16_UNORM;
166 if (texture.desc.faces == 6) {
167 depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
168 depthStencilViewDesc.Texture2DArray.FirstArraySlice = textureView.
layerIndex;
169 depthStencilViewDesc.Texture2DArray.ArraySize = textureView.
numLayers;
170 depthStencilViewDesc.Texture2DArray.MipSlice = textureView.
levelIndex;
172 if (texture.desc.layers > 1) {
173 depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
174 depthStencilViewDesc.Texture2DArray.FirstArraySlice = textureView.
layerIndex;
175 depthStencilViewDesc.Texture2DArray.ArraySize = textureView.
numLayers;
176 depthStencilViewDesc.Texture2DArray.MipSlice = textureView.
levelIndex;
178 depthStencilViewDesc.ViewDimension = textureDesc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
183 HRESULT hr = graphicsDevice->getDevice()->CreateDepthStencilView(texture.resource(), &depthStencilViewDesc, depthStencilView.internalPointer());
185 LOG_ERROR(logger,
"Failed to create depth stencil target: %s", direct3D11ReturnCodeAsString(hr));
189 return depthStencilViews.addResource(std::move(depthStencilView));
195 renderTargets[handle].views[0]->GetResource((ID3D11Resource **)&texture);
197 D3D11_TEXTURE2D_DESC textureDesc;
198 texture->GetDesc(&textureDesc);
203 graphicsDevice->getSettings().depthFormat,
204 textureDesc.SampleDesc.Count,
207 if (!HandleIsValid(textureHandle)) {
208 LOG_ERROR(logger,
"Failed to create depth stencil target: Illegal texture handle.");
212 D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {};
213 depthStencilViewDesc.Format =
Direct3D11::Formats[(int)graphicsDevice->getSettings().depthFormat];
214 depthStencilViewDesc.ViewDimension = textureDesc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
217 HRESULT hr = graphicsDevice->getDevice()->CreateDepthStencilView(textures->getTexture(textureHandle), &depthStencilViewDesc, depthStencilView.internalPointer());
219 LOG_ERROR(logger,
"Failed to create depth stencil target: %s", direct3D11ReturnCodeAsString(hr));
220 textures->releaseTexture(textureHandle);
224 textures->releaseTexture(textureHandle);
226 return depthStencilViews.addResource(std::move(depthStencilView));
231 auto & texture = this->textures->textures[textureHandle];
233 D3D11_TEXTURE2D_DESC textureDesc;
234 texture.texture2D->GetDesc(&textureDesc);
236 D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {};
237 depthStencilViewDesc.Format = textureDesc.Format;
239 if (textureDesc.Format == DXGI_FORMAT_R32_TYPELESS) {
240 depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT;
241 }
else if (textureDesc.Format == DXGI_FORMAT_R16_TYPELESS) {
242 depthStencilViewDesc.Format = DXGI_FORMAT_D16_UNORM;
245 depthStencilViewDesc.ViewDimension = textureDesc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
248 HRESULT hr = graphicsDevice->getDevice()->CreateDepthStencilView(texture.resource(), &depthStencilViewDesc, depthStencilView.internalPointer());
250 LOG_ERROR(logger,
"Failed to create depth stencil target: %s", direct3D11ReturnCodeAsString(hr));
254 return this->depthStencilViews.addResource(std::move(depthStencilView));
259 this->depthStencilViews.removeResource(handle);
266 D3D11_COMPARISON_FUNC DepthFunctions[] = {
267 D3D11_COMPARISON_NEVER,
268 D3D11_COMPARISON_LESS,
269 D3D11_COMPARISON_LESS_EQUAL,
270 D3D11_COMPARISON_EQUAL,
271 D3D11_COMPARISON_GREATER_EQUAL,
272 D3D11_COMPARISON_GREATER,
273 D3D11_COMPARISON_NOT_EQUAL,
274 D3D11_COMPARISON_ALWAYS
281 D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
284 depthStencilDesc.DepthEnable = depthStencilState.
depthEnabled;
285 depthStencilDesc.DepthWriteMask = depthStencilState.
writeEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
286 depthStencilDesc.DepthFunc = Direct3D11::DepthFunctions[depthStencilState.
depthFunction];
289 depthStencilDesc.StencilEnable =
false;
290 depthStencilDesc.StencilReadMask = 0xFF;
291 depthStencilDesc.StencilWriteMask = 0xFF;
294 depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
295 depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
296 depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
297 depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
300 depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
301 depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
302 depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
303 depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
307 HRESULT hr = graphicsDevice->getDevice()->CreateDepthStencilState(&depthStencilDesc, d3dDepthStencilState.internalPointer());
310 LOG_ERROR(logger,
"Failed to load depth stencil state: %s", direct3D11ReturnCodeAsString(hr));
314 return this->depthStencilStates.addResource(std::move(d3dDepthStencilState));
319 this->depthStencilStates.removeResource(handle);
326 const D3D11_CULL_MODE CullModes[] = {
336 D3D11_RASTERIZER_DESC rasterizerDesc = {};
338 rasterizerDesc.FillMode = rasterizerState.
wireFrame ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
339 rasterizerDesc.CullMode = Direct3D11::CullModes[rasterizerState.
cullMode];
341 rasterizerDesc.AntialiasedLineEnable =
true;
343 rasterizerDesc.MultisampleEnable = rasterizerState.
wireFrame ? rasterizerState.
multiSample :
false;
344 rasterizerDesc.DepthClipEnable = rasterizerState.
noDepthClip ==
false;
346 rasterizerDesc.DepthBias =
static_cast<INT
>(rasterizerState.
depthBias);
349 rasterizerDesc.ScissorEnable = rasterizerState.
scissor;
352 HRESULT hr = graphicsDevice->getDevice()->CreateRasterizerState(&rasterizerDesc, d3dRasterizerState.internalPointer());
355 LOG_ERROR(logger,
"Failed to load rasterizer state: %s", direct3D11ReturnCodeAsString(hr));
359 return this->rasterizerStates.addResource(std::move(d3dRasterizerState));
364 this->rasterizerStates.removeResource(handle);
369 return loadBlendState(&blendState, &blendState, 1, BlendFlags::None);
374 return loadBlendState(&blendStateColor, &blendStateAlpha, 1, BlendFlags::None);
379 return loadBlendState(&blendStateColor, &blendStateAlpha, 1, flags);
386 D3D11_BLEND_DESC blendDesc = {};
387 blendDesc.AlphaToCoverageEnable = (flags & BlendFlags::AlphaToCoverage) != 0 ? TRUE : FALSE;
388 blendDesc.IndependentBlendEnable = (flags & BlendFlags::IndependentBlend) != 0 ? TRUE : FALSE;
392 const uint32_t numStates = blendDesc.IndependentBlendEnable ? 8 : 1;
393 for (uint32_t i = 0; i < numStates; ++i) {
394 const Cogs::BlendState& blendStateColor = i < numBlendStates ? blendStatesColor[i] : defaultBlendState;
395 const Cogs::BlendState& blendStateAlpha = blendStatesAlpha ? (i < numBlendStates ? blendStatesAlpha[i] : defaultBlendState) : defaultBlendState;
397 blendDesc.RenderTarget[i].BlendEnable = blendStateColor.
enabled;
398 blendDesc.RenderTarget[i].SrcBlend = Blends[size_t(blendStateColor.
sourceBlend)];
399 blendDesc.RenderTarget[i].DestBlend = Blends[size_t(blendStateColor.
destinationBlend)];
400 blendDesc.RenderTarget[i].BlendOp = BlendOperations[size_t(blendStateColor.
operation)];
401 blendDesc.RenderTarget[i].SrcBlendAlpha = blendStateAlpha.
enabled ? Blends[size_t(blendStateAlpha.
sourceBlend)] : D3D11_BLEND_ZERO;
402 blendDesc.RenderTarget[i].DestBlendAlpha = blendStateAlpha.
enabled ? Blends[size_t(blendStateAlpha.
destinationBlend)] : D3D11_BLEND_ONE;
403 blendDesc.RenderTarget[i].BlendOpAlpha = blendStateAlpha.
enabled ? BlendOperations[size_t(blendStateAlpha.
operation)] : D3D11_BLEND_OP_ADD;
404 blendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
407 ResourcePointer<ID3D11BlendState> d3dBlendState;
408 HRESULT hr = graphicsDevice->getDevice()->CreateBlendState(&blendDesc, d3dBlendState.internalPointer());
411 LOG_ERROR(logger,
"Failed to load blend state: %s", direct3D11ReturnCodeAsString(hr));
415 return this->blendStates.addResource(std::move(d3dBlendState));
420 this->blendStates.removeResource(handle);
425 this->depthStencilStates.clear();
426 this->rasterizerStates.clear();
427 this->blendStates.clear();
429 this->depthStencilViews.clear();
430 this->renderTargets.clear();
Log implementation class.
Provides a weakly referenced view over the contents of a string.
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
constexpr size_t length() const noexcept
Get the length of the string.
constexpr bool empty() const noexcept
Check if the string is empty.
const DXGI_FORMAT Formats[]
Must match up to Format definition.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
@ Direct3D11
Graphics device using the Direct3D 11 API.
Encapsulates blend state for the graphics pipeline in a state object.
uint8_t enabled
If blending is enabled.
Blend destinationBlend
Blend option for the blend destination data.
static BlendState DefaultState()
Creates a blend state object initialized with the default settings.
BlendOperation operation
How the two blend values are combined.
Blend sourceBlend
Blend option for the blend source data.
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.
uint16_t numLayers
Number of available layers to write to.
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.
static const Handle_t InvalidHandle
Represents an invalid handle.
Encapsulates state for primitive rasterization in a state object.
bool multiSample
If multisample rasterization should be enabled. Default is true.
bool scissor
Enable scissor rect.
bool frontCounterClockwise
If counter clockwise polygon winding is used to specify front facing polygons. Default is false.
bool noDepthClip
Clamp depth value instead of clipping against near and depth planes.
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.
uint16_t numLayers
Number of available layers to render to.
TextureHandle texture
Texture handle.
uint8_t levelIndex
Index of the mipmap level to render to.
void releaseBlendState(BlendStateHandle handle) override
Release the blend state with the given handle.
void releaseRenderTarget(RenderTargetHandle handle)
Release the render target with the given renderTargetHandle.
RasterizerStateHandle loadRasterizerState(const RasterizerState &rasterizerState) override
Load a rasterizer state object.
void releaseDepthStencilState(DepthStencilStateHandle handle) override
Release the depth stencil state with the given handle.
void releaseRasterizerState(RasterizerStateHandle handle) override
Release the rasterizer state with the given handle.
DepthStencilHandle createDepthStencilTarget(const RenderTargetHandle handle, const DepthStencilViewDescription &depthStencilView)
Creates a depth stencil view using the given description.
DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState) override
Load a depth stencil state object.
void releaseResources() override
Release all allocated render target resources.
BlendStateHandle loadBlendState(const BlendState &blendState) override
Load a blend state object.
void annotate(RenderTargetHandle handle, const StringView &name) override
Associate a name with an object for use in graphics debugging.
void releaseDepthStencilTarget(DepthStencilHandle handle) override
Release the depth target with the given depthStencilHandle.
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.