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);
264 Cogs::TextureFormat depthFormatFromDXGI(DXGI_FORMAT format)
267 case DXGI_FORMAT_D16_UNORM:
return Cogs::TextureFormat::D16_UNORM;
268 case DXGI_FORMAT_D24_UNORM_S8_UINT:
return Cogs::TextureFormat::D24S8_UNORM;
269 case DXGI_FORMAT_D32_FLOAT:
return Cogs::TextureFormat::D32_FLOAT;
270 default:
return Cogs::TextureFormat::Unknown;
279 if (HandleIsValid(renderTargetHandle)) {
283 for (
size_t i = 0; i < renderTarget.numViews; ++i) {
284 layout.
colorFormats[i] = textures->textures[renderTarget.texture[i]].format;
287 if (renderTarget.numViews) {
288 D3D11_TEXTURE2D_DESC textureDesc;
289 textures->textures[renderTarget.texture[0]].texture2D->GetDesc(&textureDesc);
290 layout.
samples =
static_cast<uint8_t
>(textureDesc.SampleDesc.Count);
299 if (HandleIsValid(depthStencilHandle)) {
300 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
301 ID3D11DepthStencilView * view = depthStencilViews[depthStencilHandle];
302 view->GetDesc(&dsvDesc);
305 }
else if (!HandleIsValid(renderTargetHandle)) {
316 D3D11_COMPARISON_FUNC DepthFunctions[] = {
317 D3D11_COMPARISON_NEVER,
318 D3D11_COMPARISON_LESS,
319 D3D11_COMPARISON_LESS_EQUAL,
320 D3D11_COMPARISON_EQUAL,
321 D3D11_COMPARISON_GREATER_EQUAL,
322 D3D11_COMPARISON_GREATER,
323 D3D11_COMPARISON_NOT_EQUAL,
324 D3D11_COMPARISON_ALWAYS
331 D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
334 depthStencilDesc.DepthEnable = depthStencilState.
depthEnabled;
335 depthStencilDesc.DepthWriteMask = depthStencilState.
writeEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
336 depthStencilDesc.DepthFunc = Direct3D11::DepthFunctions[depthStencilState.
depthFunction];
339 depthStencilDesc.StencilEnable =
false;
340 depthStencilDesc.StencilReadMask = 0xFF;
341 depthStencilDesc.StencilWriteMask = 0xFF;
344 depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
345 depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
346 depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
347 depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
350 depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
351 depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
352 depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
353 depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
357 HRESULT hr = graphicsDevice->getDevice()->CreateDepthStencilState(&depthStencilDesc, d3dDepthStencilState.internalPointer());
360 LOG_ERROR(logger,
"Failed to load depth stencil state: %s", direct3D11ReturnCodeAsString(hr));
364 return this->depthStencilStates.addResource(std::move(d3dDepthStencilState));
369 this->depthStencilStates.removeResource(handle);
376 const D3D11_CULL_MODE CullModes[] = {
386 D3D11_RASTERIZER_DESC rasterizerDesc = {};
388 rasterizerDesc.FillMode = rasterizerState.
wireFrame ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
389 rasterizerDesc.CullMode = Direct3D11::CullModes[rasterizerState.
cullMode];
391 rasterizerDesc.AntialiasedLineEnable =
true;
393 rasterizerDesc.MultisampleEnable = rasterizerState.
wireFrame ? rasterizerState.
multiSample :
false;
394 rasterizerDesc.DepthClipEnable = rasterizerState.
noDepthClip ==
false;
396 rasterizerDesc.DepthBias =
static_cast<INT
>(rasterizerState.
depthBias);
399 rasterizerDesc.ScissorEnable = rasterizerState.
scissor;
402 HRESULT hr = graphicsDevice->getDevice()->CreateRasterizerState(&rasterizerDesc, d3dRasterizerState.internalPointer());
405 LOG_ERROR(logger,
"Failed to load rasterizer state: %s", direct3D11ReturnCodeAsString(hr));
409 return this->rasterizerStates.addResource(std::move(d3dRasterizerState));
414 this->rasterizerStates.removeResource(handle);
419 return loadBlendState(&blendState, &blendState, 1, BlendFlags::None);
424 return loadBlendState(&blendStateColor, &blendStateAlpha, 1, BlendFlags::None);
429 return loadBlendState(&blendStateColor, &blendStateAlpha, 1, flags);
436 D3D11_BLEND_DESC blendDesc = {};
437 blendDesc.AlphaToCoverageEnable = ((flags & BlendFlags::AlphaToCoverage) != BlendFlags::None) ? TRUE : FALSE;
438 blendDesc.IndependentBlendEnable = ((flags & BlendFlags::IndependentBlend) != BlendFlags::None) ? TRUE : FALSE;
442 const uint32_t numStates = blendDesc.IndependentBlendEnable ? 8 : 1;
443 for (uint32_t i = 0; i < numStates; ++i) {
444 const Cogs::BlendState& blendStateColor = i < numBlendStates ? blendStatesColor[i] : defaultBlendState;
445 const Cogs::BlendState& blendStateAlpha = blendStatesAlpha ? (i < numBlendStates ? blendStatesAlpha[i] : defaultBlendState) : defaultBlendState;
447 blendDesc.RenderTarget[i].BlendEnable = blendStateColor.
enabled;
448 blendDesc.RenderTarget[i].SrcBlend = Blends[size_t(blendStateColor.
sourceBlend)];
449 blendDesc.RenderTarget[i].DestBlend = Blends[size_t(blendStateColor.
destinationBlend)];
450 blendDesc.RenderTarget[i].BlendOp = BlendOperations[size_t(blendStateColor.
operation)];
451 blendDesc.RenderTarget[i].SrcBlendAlpha = blendStateAlpha.
enabled ? Blends[size_t(blendStateAlpha.
sourceBlend)] : D3D11_BLEND_ZERO;
452 blendDesc.RenderTarget[i].DestBlendAlpha = blendStateAlpha.
enabled ? Blends[size_t(blendStateAlpha.
destinationBlend)] : D3D11_BLEND_ONE;
453 blendDesc.RenderTarget[i].BlendOpAlpha = blendStateAlpha.
enabled ? BlendOperations[size_t(blendStateAlpha.
operation)] : D3D11_BLEND_OP_ADD;
454 blendDesc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
457 ResourcePointer<ID3D11BlendState> d3dBlendState;
458 HRESULT hr = graphicsDevice->getDevice()->CreateBlendState(&blendDesc, d3dBlendState.internalPointer());
461 LOG_ERROR(logger,
"Failed to load blend state: %s", direct3D11ReturnCodeAsString(hr));
465 return this->blendStates.addResource(std::move(d3dBlendState));
470 this->blendStates.removeResource(handle);
475 this->depthStencilStates.clear();
476 this->rasterizerStates.clear();
477 this->blendStates.clear();
479 this->depthStencilViews.clear();
480 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.
Settings for graphics device initialization.
int numSamples
Number of samples to use for back buffer MSAA.
TextureFormat colorFormat
Back buffer format.
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 the formats and sample count of a render target's attachments.
TextureFormat colorFormats[8]
Formats of the color targets, only the first numColorTargets entries are valid.
TextureFormat depthStencilFormat
Format of the depth stencil target, TextureFormat::Unknown if there is none.
uint8_t samples
Number of samples, 1 implies no multisampling.
uint8_t numColorTargets
Number of valid entries in colorFormats.
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.
RenderTargetLayout getLayout(const RenderTargetHandle renderTargetHandle, const DepthStencilHandle depthStencilHandle) override
Get the view layout for the given render target / depth stencil target pair.
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.