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{
153 RenderTargetLayout layout;
154
155 if (HandleIsValid(renderTargetHandle)) {
156 const RenderTargetVK & renderTarget = renderTargets[renderTargetHandle];
157 layout.numColorTargets = static_cast<uint8_t>(renderTarget.textures.size());
158
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);
162 }
163
164 if (renderTarget.depthTexture) {
165 layout.depthStencilFormat = renderTarget.depthTexture->format;
166 }
167 } else {
168 const GraphicsDeviceSettings & settings = graphicsDevice->getSettings();
169 layout.numColorTargets = 1;
170 layout.colorFormats[0] = settings.colorFormat;
171 layout.samples = static_cast<uint8_t>(settings.numSamples);
172 layout.depthStencilFormat = settings.depthFormat;
173 }
174
175 if (HandleIsValid(depthStencilHandle)) {
176 const DepthStencilTargetVK & depthTarget = depthTargets[depthStencilHandle];
177 if (HandleIsValid(depthTarget.renderTarget)) {
178 const RenderTargetVK & renderTarget = renderTargets[depthTarget.renderTarget];
179 if (renderTarget.depthTexture) {
180 layout.depthStencilFormat = renderTarget.depthTexture->format;
181 }
182 }
183 }
184
185 return layout;
186}
187
189{
191
192 VkCompareOp ops[] = {
193 VK_COMPARE_OP_NEVER,
194 VK_COMPARE_OP_LESS,
195 VK_COMPARE_OP_LESS_OR_EQUAL,
196 VK_COMPARE_OP_EQUAL,
197 VK_COMPARE_OP_GREATER_OR_EQUAL,
198 VK_COMPARE_OP_GREATER,
199 VK_COMPARE_OP_NOT_EQUAL,
200 VK_COMPARE_OP_ALWAYS,
201 };
202
203 ds.state = {};
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];
208
209 ds.state.depthBoundsTestEnable = VK_FALSE;
210 ds.state.minDepthBounds = 0;
211 ds.state.maxDepthBounds = 1;
212
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;
218
219 return depthStencilStates.addResource(ds);
220}
221
223{
224}
225
227{
229
230 VkCullModeFlagBits cullModes[] = {
231 VK_CULL_MODE_FRONT_BIT,
232 VK_CULL_MODE_BACK_BIT,
233 VK_CULL_MODE_NONE,
234 };
235
236 rs.state = {};
237 rs.state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
238
239 rs.state.cullMode = cullModes[rasterizerState.cullMode];
240 rs.state.frontFace = rasterizerState.frontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
241
242 rs.state.polygonMode = rasterizerState.wireFrame ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
243 rs.state.lineWidth = 1.0f;
244
245 rs.state.depthBiasEnable = rasterizerState.depthBias != 0;
246 rs.state.depthBiasConstantFactor = rasterizerState.depthBias;
247 rs.state.depthBiasSlopeFactor = rasterizerState.slopeScaledDepthBias;
248
249 rs.state.depthClampEnable = rasterizerState.depthBiasClamp != 0;
250 rs.state.depthBiasClamp = rasterizerState.depthBiasClamp;
251
252 rs.state.rasterizerDiscardEnable = VK_FALSE;
253
254 return rasterizerStates.addResource(rs);
255}
256
258{
259}
260
261namespace Cogs
262{
263 namespace Vulkan
264 {
265 VkBlendFactor BlendOptions[] = {
266 VK_BLEND_FACTOR_ZERO,
267 VK_BLEND_FACTOR_ONE,
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,
279 };
280 static_assert(sizeof(BlendOptions)/sizeof(BlendOptions[0]) == (size_t)Cogs::BlendState::Blend::Count, "Blend size");
281 }
282}
283
285{
286 auto handle = blendStates.addResource(BlendStateVK{});
287
288 auto & bs = blendStates[handle];
289
290 bs.state = {};
291 bs.state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
292
293 bs.state.attachmentCount = 1;
294 bs.state.pAttachments = bs.attachmentStates;
295
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;
304
305 for (auto & a : bs.attachmentStates) {
306 a.colorWriteMask = 0xF;
307 }
308
309 return handle;
310}
311
313{
314}
315
317{
318}
319
321{
322 return RenderTargetHandle();
323}
324
326{
327 return DepthStencilHandle();
328}
Log implementation class.
Definition: LogManager.h:140
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
Definition: LogManager.h:181
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.
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.
Definition: Common.h:81
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.
Definition: Flags.h:122