1#include "RenderTargetsVK.h"
3#include "GraphicsDeviceVK.h"
11void Cogs::RenderTargetsVK::initialize(GraphicsDeviceVK * device)
13 graphicsDevice = device;
22 assert(HandleIsValid(handle) &&
"Invalid render target handle.");
24 auto & renderTarget = renderTargets[handle];
26 auto & texture = *renderTarget.textures.front();
28 auto depthTextureHandle = graphicsDevice->textures.loadTexture(
nullptr, texture.width, texture.height, TextureFormat::D32_FLOAT, texture.samples,
TextureFlags::DepthBuffer);
30 return createDepthStencilTarget(handle, depthTextureHandle);
35 assert(HandleIsValid(handle) &&
"Invalid render target handle.");
36 assert(HandleIsValid(depthTexturehandle) &&
"Invalid depth texture handle.");
40 auto & renderTarget = renderTargets[handle];
41 renderTarget.depthTexture = &graphicsDevice->textures.textures[depthTexturehandle];
43 std::vector<VkImageView> attachmentViews;
44 std::vector<VkAttachmentDescription> attachments;
45 std::vector<VkAttachmentReference> references;
50 for (
auto & texture : renderTarget.textures) {
51 attachmentViews.push_back(texture->imageView);
54 width = texture->width;
55 height = texture->height;
58 VkAttachmentDescription desc = {};
59 desc.format = texture->vkFormat;
60 desc.samples = (VkSampleCountFlagBits)texture->samples;
61 desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
62 desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
63 desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
64 desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
65 desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
66 desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
68 attachments.push_back(desc);
70 references.push_back(VkAttachmentReference{
static_cast<uint32_t
>(references.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
73 if (renderTarget.depthTexture) {
74 auto & texture = *renderTarget.depthTexture;
77 width = texture.width;
78 height = texture.height;
81 attachmentViews.push_back(texture.imageView);
83 VkAttachmentDescription desc = {};
84 desc.format = texture.vkFormat;
85 desc.samples = (VkSampleCountFlagBits)texture.samples;
86 desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
87 desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
88 desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
89 desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
90 desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
91 desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
93 attachments.push_back(desc);
96 const VkAttachmentReference depthReference = {
97 static_cast<uint32_t
>(attachments.size()) - 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
100 VkSubpassDescription subpass = {};
101 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
103 subpass.inputAttachmentCount = 0;
104 subpass.pInputAttachments =
nullptr;
105 subpass.colorAttachmentCount =
static_cast<uint32_t
>(references.size());
106 subpass.pColorAttachments = references.data();
107 subpass.pResolveAttachments =
nullptr;
108 subpass.pDepthStencilAttachment = &depthReference;
109 subpass.preserveAttachmentCount = 0;
110 subpass.pPreserveAttachments =
nullptr;
112 VkRenderPassCreateInfo renderPassInfo = {};
113 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
114 renderPassInfo.attachmentCount =
static_cast<uint32_t
>(attachments.size());
115 renderPassInfo.pAttachments = attachments.data();
116 renderPassInfo.subpassCount = 1;
117 renderPassInfo.pSubpasses = &subpass;
118 renderPassInfo.dependencyCount = 0;
119 renderPassInfo.pDependencies =
nullptr;
121 auto result = vkCreateRenderPass(graphicsDevice->device, &renderPassInfo,
nullptr, &renderTarget.renderPass);
123 if (VK_FAILED(result)) {
124 VK_LOG_ERROR(result,
"Error creating render pass.");
128 VkFramebufferCreateInfo framebufferInfo = {};
129 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
130 framebufferInfo.pNext =
nullptr;
131 framebufferInfo.renderPass = renderTarget.renderPass;
132 framebufferInfo.attachmentCount =
static_cast<uint32_t
>(attachmentViews.size());
133 framebufferInfo.pAttachments = attachmentViews.data();
134 framebufferInfo.width = width;
135 framebufferInfo.height = height;
136 framebufferInfo.layers = 1;
138 result = vkCreateFramebuffer(graphicsDevice->device, &framebufferInfo,
nullptr, &renderTarget.framebuffer);
140 if (VK_FAILED(result)) {
155 if (HandleIsValid(renderTargetHandle)) {
156 const RenderTargetVK & renderTarget = renderTargets[renderTargetHandle];
157 layout.
numColorTargets =
static_cast<uint8_t
>(renderTarget.textures.size());
159 for (
size_t i = 0; i < renderTarget.textures.size(); ++i) {
160 layout.
colorFormats[i] = renderTarget.textures[i]->format;
161 layout.
samples =
static_cast<uint8_t
>(renderTarget.textures[i]->samples);
164 if (renderTarget.depthTexture) {
175 if (HandleIsValid(depthStencilHandle)) {
177 if (HandleIsValid(depthTarget.renderTarget)) {
178 const RenderTargetVK & renderTarget = renderTargets[depthTarget.renderTarget];
179 if (renderTarget.depthTexture) {
192 VkCompareOp ops[] = {
195 VK_COMPARE_OP_LESS_OR_EQUAL,
197 VK_COMPARE_OP_GREATER_OR_EQUAL,
198 VK_COMPARE_OP_GREATER,
199 VK_COMPARE_OP_NOT_EQUAL,
200 VK_COMPARE_OP_ALWAYS,
204 ds.state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
205 ds.state.depthTestEnable = depthStencilState.
depthEnabled;
206 ds.state.depthWriteEnable = depthStencilState.
writeEnabled;
207 ds.state.depthCompareOp = ops[depthStencilState.
depthFunction];
209 ds.state.depthBoundsTestEnable = VK_FALSE;
210 ds.state.minDepthBounds = 0;
211 ds.state.maxDepthBounds = 1;
213 ds.state.back.failOp = VK_STENCIL_OP_KEEP;
214 ds.state.back.passOp = VK_STENCIL_OP_KEEP;
215 ds.state.back.compareOp = VK_COMPARE_OP_ALWAYS;
216 ds.state.stencilTestEnable = VK_FALSE;
217 ds.state.front = ds.state.back;
219 return depthStencilStates.addResource(ds);
230 VkCullModeFlagBits cullModes[] = {
231 VK_CULL_MODE_FRONT_BIT,
232 VK_CULL_MODE_BACK_BIT,
237 rs.state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
239 rs.state.cullMode = cullModes[rasterizerState.
cullMode];
240 rs.state.frontFace = rasterizerState.
frontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
242 rs.state.polygonMode = rasterizerState.
wireFrame ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
243 rs.state.lineWidth = 1.0f;
245 rs.state.depthBiasEnable = rasterizerState.
depthBias != 0;
246 rs.state.depthBiasConstantFactor = rasterizerState.
depthBias;
252 rs.state.rasterizerDiscardEnable = VK_FALSE;
254 return rasterizerStates.addResource(rs);
265 VkBlendFactor BlendOptions[] = {
266 VK_BLEND_FACTOR_ZERO,
268 VK_BLEND_FACTOR_SRC_COLOR,
269 VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
270 VK_BLEND_FACTOR_SRC_ALPHA,
271 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
272 VK_BLEND_FACTOR_DST_ALPHA,
273 VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
274 VK_BLEND_FACTOR_DST_COLOR,
275 VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
276 VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
277 VK_BLEND_FACTOR_CONSTANT_COLOR,
278 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
280 static_assert(
sizeof(BlendOptions)/
sizeof(BlendOptions[0]) == (size_t)Cogs::BlendState::Blend::Count,
"Blend size");
288 auto & bs = blendStates[handle];
291 bs.state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
293 bs.state.attachmentCount = 1;
294 bs.state.pAttachments = bs.attachmentStates;
296 bs.attachmentStates[0].blendEnable = blendState.
enabled;
297 bs.attachmentStates[0].srcColorBlendFactor = Vulkan::BlendOptions[(size_t)blendState.
sourceBlend];
298 bs.attachmentStates[0].dstColorBlendFactor = Vulkan::BlendOptions[(
size_t)blendState.
destinationBlend];
299 bs.attachmentStates[0].colorBlendOp = VK_BLEND_OP_ADD;
300 bs.attachmentStates[0].srcAlphaBlendFactor = Vulkan::BlendOptions[(size_t)blendState.
sourceBlend];
301 bs.attachmentStates[0].dstAlphaBlendFactor = Vulkan::BlendOptions[(
size_t)blendState.
destinationBlend];
302 bs.attachmentStates[0].alphaBlendOp = VK_BLEND_OP_ADD;
303 bs.attachmentStates[0].colorWriteMask = 0xF;
305 for (
auto & a : bs.attachmentStates) {
306 a.colorWriteMask = 0xF;
Log implementation class.
void releaseBlendState(BlendStateHandle handle) override
Release the blend state with the given handle.
void releaseRenderTarget(RenderTargetHandle renderTargetHandle) override
Release the render target with the given renderTargetHandle.
DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState) override
Load a depth stencil state object.
BlendStateHandle loadBlendState(const BlendState &blendState) override
Load a blend state object.
void releaseResources() override
Release all allocated render target resources.
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.
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 releaseDepthStencilTarget(DepthStencilHandle depthStencilHandle) override
Release the depth target with the given depthStencilHandle.
RenderTargetHandle createRenderTarget(const RenderTargetViewDescription *renderTargetViews, const size_t numViews) override
Create a render target using the given view descriptions.
DepthStencilHandle createDepthStencilTarget(const RenderTargetHandle handle) override
Creates a depth/stencil target to back the render target with the given handle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
@ Vulkan
Graphics device using the Vulkan 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.
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.
Settings for graphics device initialization.
TextureFormat depthFormat
Depth buffer format.
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 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 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.
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.