Cogs.Core
RenderTargetsVK.cpp
1#include "RenderTargetsVK.h"
2
3#include "GraphicsDeviceVK.h"
4#include "TexturesVK.h"
5
6namespace
7{
8 Cogs::Logging::Log logger = Cogs::Logging::getLogger("RenderTargetsVK");
9}
10
11void Cogs::RenderTargetsVK::initialize(GraphicsDeviceVK * device)
12{
13 graphicsDevice = device;
14}
15
17{
18}
19
21{
22 assert(HandleIsValid(handle) && "Invalid render target handle.");
23
24 auto & renderTarget = renderTargets[handle];
25
26 auto & texture = *renderTarget.textures.front();
27
28 auto depthTextureHandle = graphicsDevice->textures.loadTexture(nullptr, texture.width, texture.height, TextureFormat::D32_FLOAT, texture.samples, TextureFlags::DepthBuffer);
29
30 return createDepthStencilTarget(handle, depthTextureHandle);
31}
32
34{
35 assert(HandleIsValid(handle) && "Invalid render target handle.");
36 assert(HandleIsValid(depthTexturehandle) && "Invalid depth texture handle.");
37
38 //TODO: Validate compatibility.
39
40 auto & renderTarget = renderTargets[handle];
41 renderTarget.depthTexture = &graphicsDevice->textures.textures[depthTexturehandle];
42
43 std::vector<VkImageView> attachmentViews;
44 std::vector<VkAttachmentDescription> attachments;
45 std::vector<VkAttachmentReference> references;
46
47 uint32_t width = 0;
48 uint32_t height = 0;
49
50 for (auto & texture : renderTarget.textures) {
51 attachmentViews.push_back(texture->imageView);
52
53 if (!width) {
54 width = texture->width;
55 height = texture->height;
56 }
57
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;
67
68 attachments.push_back(desc);
69
70 references.push_back(VkAttachmentReference{ static_cast<uint32_t>(references.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
71 }
72
73 if (renderTarget.depthTexture) {
74 auto & texture = *renderTarget.depthTexture;
75
76 if (!width) {
77 width = texture.width;
78 height = texture.height;
79 }
80
81 attachmentViews.push_back(texture.imageView);
82
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;
92
93 attachments.push_back(desc);
94 }
95
96 const VkAttachmentReference depthReference = {
97 static_cast<uint32_t>(attachments.size()) - 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
98 };
99
100 VkSubpassDescription subpass = {};
101 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
102 subpass.flags = 0;
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;
111
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;
120
121 auto result = vkCreateRenderPass(graphicsDevice->device, &renderPassInfo, nullptr, &renderTarget.renderPass);
122
123 if (VK_FAILED(result)) {
124 VK_LOG_ERROR(result, "Error creating render pass.");
126 }
127
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;
137
138 result = vkCreateFramebuffer(graphicsDevice->device, &framebufferInfo, nullptr, &renderTarget.framebuffer);
139
140 if (VK_FAILED(result)) {
142 }
143
144 return depthTargets.addResource(DepthStencilTargetVK{});
145}
146
148{
149}
150
152{
154
155 VkCompareOp ops[] = {
156 VK_COMPARE_OP_NEVER,
157 VK_COMPARE_OP_LESS,
158 VK_COMPARE_OP_LESS_OR_EQUAL,
159 VK_COMPARE_OP_EQUAL,
160 VK_COMPARE_OP_GREATER_OR_EQUAL,
161 VK_COMPARE_OP_GREATER,
162 VK_COMPARE_OP_NOT_EQUAL,
163 VK_COMPARE_OP_ALWAYS,
164 };
165
166 ds.state = {};
167 ds.state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
168 ds.state.depthTestEnable = depthStencilState.depthEnabled;
169 ds.state.depthWriteEnable = depthStencilState.writeEnabled;
170 ds.state.depthCompareOp = ops[depthStencilState.depthFunction];
171
172 ds.state.depthBoundsTestEnable = VK_FALSE;
173 ds.state.minDepthBounds = 0;
174 ds.state.maxDepthBounds = 1;
175
176 ds.state.back.failOp = VK_STENCIL_OP_KEEP;
177 ds.state.back.passOp = VK_STENCIL_OP_KEEP;
178 ds.state.back.compareOp = VK_COMPARE_OP_ALWAYS;
179 ds.state.stencilTestEnable = VK_FALSE;
180 ds.state.front = ds.state.back;
181
182 return depthStencilStates.addResource(ds);
183}
184
186{
187}
188
190{
192
193 VkCullModeFlagBits cullModes[] = {
194 VK_CULL_MODE_FRONT_BIT,
195 VK_CULL_MODE_BACK_BIT,
196 VK_CULL_MODE_NONE,
197 };
198
199 rs.state = {};
200 rs.state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
201
202 rs.state.cullMode = cullModes[rasterizerState.cullMode];
203 rs.state.frontFace = rasterizerState.frontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
204
205 rs.state.polygonMode = rasterizerState.wireFrame ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
206 rs.state.lineWidth = 1.0f;
207
208 rs.state.depthBiasEnable = rasterizerState.depthBias != 0;
209 rs.state.depthBiasConstantFactor = rasterizerState.depthBias;
210 rs.state.depthBiasSlopeFactor = rasterizerState.slopeScaledDepthBias;
211
212 rs.state.depthClampEnable = rasterizerState.depthBiasClamp != 0;
213 rs.state.depthBiasClamp = rasterizerState.depthBiasClamp;
214
215 rs.state.rasterizerDiscardEnable = VK_FALSE;
216
217 return rasterizerStates.addResource(rs);
218}
219
221{
222}
223
224namespace Cogs
225{
226 namespace Vulkan
227 {
228 VkBlendFactor BlendOptions[] = {
229 VK_BLEND_FACTOR_ZERO,
230 VK_BLEND_FACTOR_ONE,
231 VK_BLEND_FACTOR_SRC_COLOR,
232 VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
233 VK_BLEND_FACTOR_SRC_ALPHA,
234 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
235 VK_BLEND_FACTOR_DST_ALPHA,
236 VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
237 VK_BLEND_FACTOR_DST_COLOR,
238 VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
239 VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
240 VK_BLEND_FACTOR_CONSTANT_COLOR,
241 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
242 };
243 static_assert(sizeof(BlendOptions)/sizeof(BlendOptions[0]) == (size_t)Cogs::BlendState::Blend::Count, "Blend size");
244 }
245}
246
248{
249 auto handle = blendStates.addResource(BlendStateVK{});
250
251 auto & bs = blendStates[handle];
252
253 bs.state = {};
254 bs.state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
255
256 bs.state.attachmentCount = 1;
257 bs.state.pAttachments = bs.attachmentStates;
258
259 bs.attachmentStates[0].blendEnable = blendState.enabled;
260 bs.attachmentStates[0].srcColorBlendFactor = Vulkan::BlendOptions[(size_t)blendState.sourceBlend];
261 bs.attachmentStates[0].dstColorBlendFactor = Vulkan::BlendOptions[(size_t)blendState.destinationBlend];
262 bs.attachmentStates[0].colorBlendOp = VK_BLEND_OP_ADD;
263 bs.attachmentStates[0].srcAlphaBlendFactor = Vulkan::BlendOptions[(size_t)blendState.sourceBlend];
264 bs.attachmentStates[0].dstAlphaBlendFactor = Vulkan::BlendOptions[(size_t)blendState.destinationBlend];
265 bs.attachmentStates[0].alphaBlendOp = VK_BLEND_OP_ADD;
266 bs.attachmentStates[0].colorWriteMask = 0xF;
267
268 for (auto & a : bs.attachmentStates) {
269 a.colorWriteMask = 0xF;
270 }
271
272 return handle;
273}
274
276{
277}
278
280{
281}
282
284{
285 return RenderTargetHandle();
286}
287
289{
290 return DepthStencilHandle();
291}
Log implementation class.
Definition: LogManager.h:139
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.
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
Definition: LogManager.h:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ Vulkan
Graphics device using the Vulkan 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
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.
static const Handle_t InvalidHandle
Represents an invalid handle.
Definition: Common.h:80
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 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.
Definition: Flags.h:122