Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
vkRenderTarget.cpp
Go to the documentation of this file.
1
2
4
7
9
10namespace Divide
11{
13 : RenderTarget( context, descriptor )
14 {
15 _renderingInfo = {};
16 _renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
17
18 for ( auto& info : _colourAttachmentInfo )
19 {
20 info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
21 info.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
22 }
23
24 auto& info = _depthAttachmentInfo;
25 info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
26 info.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
27 }
28
30 {
32 {
33 _renderingInfo.renderArea.offset.x = 0;
34 _renderingInfo.renderArea.offset.y = 0;
35 _renderingInfo.renderArea.extent.width = getWidth();
36 _renderingInfo.renderArea.extent.height = getHeight();
37 _renderingInfo.layerCount = 1u;
38 return true;
39 }
40
41 return false;
42 }
43
44 void vkRenderTarget::blitFrom( VkCommandBuffer cmdBuffer, vkRenderTarget* source, const RTBlitParams& params ) noexcept
45 {
47
48 if ( source == nullptr || !IsValid(params) )
49 {
50 return;
51 }
52
53 VK_API::PushDebugMessage(cmdBuffer, "vkRrenderTarget::blitFrom");
54
55 vkRenderTarget* output = this;
56 [[maybe_unused]] const vec2<U16> outputDim = output->_descriptor._resolution;
57
58 vkRenderTarget* input = source;
59 [[maybe_unused]] const vec2<U16> inputDim = input->_descriptor._resolution;
60
61 VkDependencyInfo dependencyInfo = vk::dependencyInfo();
62 for ( const RTBlitEntry entry : params )
63 {
64 if ( entry._input._index == INVALID_INDEX ||
65 entry._output._index == INVALID_INDEX ||
66 !input->_attachmentsUsed[entry._input._index] ||
67 !output->_attachmentsUsed[entry._output._index] )
68 {
69 continue;
70 }
71
72 PROFILE_SCOPE( "Blit Entry Loop", Profiler::Category::Graphics );
73
74 std::array<VkImageMemoryBarrier2, 2> imageBarriers{};
75 U8 imageBarrierCount = 0u;
76
77 const RTAttachment_uptr& inAtt = input->_attachments[entry._input._index];
78 const RTAttachment_uptr& outAtt = output->_attachments[entry._output._index];
79
80 vkTexture* vkTexIn = static_cast<vkTexture*>(Get(inAtt->texture()));
81 vkTexture* vkTexOut = static_cast<vkTexture*>(Get(outAtt->texture()));
82
83 const bool isDepthTextureIn = IsDepthTexture( vkTexIn->descriptor()._packing );
84 const bool isDepthTextureOut = IsDepthTexture( vkTexOut->descriptor()._packing );
85
86 U16 layerCount = entry._layerCount;
87 DIVIDE_ASSERT(layerCount != U16_MAX && entry._mipCount != U16_MAX );
88 if ( IsCubeTexture( vkTexIn->descriptor()._texType ) )
89 {
90 layerCount *= 6u;
91 }
92
93 const VkImageSubresourceRange subResourceIn = {
94 .aspectMask = vkTexture::GetAspectFlags( vkTexIn->descriptor() ),
95 .baseMipLevel = entry._input._mipOffset,
96 .levelCount = entry._mipCount,
97 .baseArrayLayer = entry._input._layerOffset,
98 .layerCount = layerCount
99 };
100 const VkImageSubresourceRange subResourceOut = {
101 .aspectMask = vkTexture::GetAspectFlags( vkTexOut->descriptor() ),
102 .baseMipLevel = entry._output._mipOffset,
103 .levelCount = entry._mipCount,
104 .baseArrayLayer = entry._output._layerOffset,
105 .layerCount = layerCount
106 };
107 {
110
111 vkTexture::TransitionTexture( sourceTransition, subResourceIn, vkTexIn->image()->_image, imageBarriers[imageBarrierCount++] );
112 vkTexture::TransitionTexture( targetTransition, subResourceOut, vkTexOut->image()->_image, imageBarriers[imageBarrierCount++] );
113 }
114
115 const U16 srcDepth = vkTexIn->descriptor()._texType == TextureType::TEXTURE_3D ? vkTexIn->depth() : 1u;
116 const U16 dstDepth = vkTexOut->descriptor()._texType == TextureType::TEXTURE_3D ? vkTexIn->depth() : 1u;
117
118 if ( imageBarrierCount > 0u )
119 {
120 dependencyInfo.imageMemoryBarrierCount = imageBarrierCount;
121 dependencyInfo.pImageMemoryBarriers = imageBarriers.data();
122
123 VK_PROFILE( vkCmdPipelineBarrier2, cmdBuffer, &dependencyInfo );
124 imageBarrierCount = 0u;
125 }
126
127 VkImageBlit2 blitRegions[MAX_BLIT_ENTRIES] = {};
128 U8 blitRegionCount = 0u;
129
130
131 for ( U8 mip = 0u; mip < entry._mipCount; ++mip )
132 {
133 const VkImageSubresourceLayers srcSubResource = {
134 .aspectMask = VkImageAspectFlags( entry._input._index == RT_DEPTH_ATTACHMENT_IDX ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT ),
135 .mipLevel = to_U32( entry._input._mipOffset + mip ),
136 .baseArrayLayer = entry._input._layerOffset,
137 .layerCount = layerCount,
138 };
139
140 const VkImageSubresourceLayers dstSubResource = {
141 .aspectMask = VkImageAspectFlags( entry._output._index == RT_DEPTH_ATTACHMENT_IDX ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT ),
142 .mipLevel = to_U32( entry._output._mipOffset + mip ),
143 .baseArrayLayer = entry._output._layerOffset,
144 .layerCount = layerCount,
145 };
146
147 VkImageBlit2& blitRegion = blitRegions[blitRegionCount++];
148
149 blitRegion = {
150 .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
151 .srcSubresource = srcSubResource,
152 .dstSubresource = dstSubResource,
153 };
154
155 blitRegion.srcOffsets[0] = blitRegion.dstOffsets[0] = {
156 .x = 0,
157 .y = 0,
158 .z = 0
159 };
160
161 blitRegion.srcOffsets[1] = {
162 .x = vkTexIn->width(),
163 .y = vkTexIn->height(),
164 .z = srcDepth
165 };
166
167 blitRegion.dstOffsets[1] = {
168 .x = vkTexOut->width(),
169 .y = vkTexOut->height(),
170 .z = dstDepth
171 };
172 }
173
174 if ( blitRegionCount > 0u )
175 {
176 const VkBlitImageInfo2 blitInfo = {
177 .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
178 .srcImage = vkTexIn->image()->_image,
179 .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
180 .dstImage = vkTexOut->image()->_image,
181 .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
182 .regionCount = blitRegionCount,
183 .pRegions = blitRegions,
184 .filter = VK_FILTER_NEAREST,
185 };
186
187 VK_PROFILE( vkCmdBlitImage2, cmdBuffer, &blitInfo );
188 }
189
190 {
193
194 vkTexture::TransitionTexture( sourceTransition, subResourceIn, vkTexIn->image()->_image, imageBarriers[imageBarrierCount++] );
195 vkTexture::TransitionTexture( targetTransition, subResourceOut, vkTexOut->image()->_image, imageBarriers[imageBarrierCount++] );
196 }
197
198 if ( imageBarrierCount > 0u )
199 {
200 dependencyInfo.imageMemoryBarrierCount = imageBarrierCount;
201 dependencyInfo.pImageMemoryBarriers = imageBarriers.data();
202
203 VK_PROFILE( vkCmdPipelineBarrier2, cmdBuffer, &dependencyInfo );
204 imageBarrierCount = 0u;
205 }
206 }
207
208 VK_API::PopDebugMessage( cmdBuffer );
209 }
210
211 void vkRenderTarget::transitionAttachments( VkCommandBuffer cmdBuffer, const RTDrawDescriptor& descriptor, const RTTransitionMask& transitionMask, const bool toWrite )
212 {
214
216
217 // Double the number of barriers needed in case we have an MSAA RenderTarget (we need to transition the resolve targets as well)
218 thread_local std::array<VkImageMemoryBarrier2, RT_MAX_ATTACHMENT_COUNT * 2> memBarriers{};
219 U8 memBarrierCount = 0u;
220 thread_local VkDependencyInfo dependencyInfo = vk::dependencyInfo();
221
222 const DrawLayerEntry& srcDepthLayer = descriptor._writeLayers[RT_DEPTH_ATTACHMENT_IDX];
223 DrawLayerEntry targetDepthLayer{};
224
225 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
226 {
227 if ( !_attachmentsUsed[i] )
228 {
229 continue;
230 }
231
232 if ( descriptor._writeLayers[i]._layer != INVALID_INDEX && (descriptor._writeLayers[i]._layer > 0u || descriptor._writeLayers[i]._cubeFace > 0u) )
233 {
234 targetDepthLayer = descriptor._writeLayers[i];
235 break;
236 }
237 }
238
239 {
240 PROFILE_SCOPE( "Colour Attachments", Profiler::Category::Graphics);
241 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
242 {
243 if ( _attachmentsUsed[i] && descriptor._drawMask[i] )
244 {
245 const auto& att = _attachments[i];
246 RTAttachment::Layout usage = att->_attachmentUsage;
247 if ( (toWrite && usage == RTAttachment::Layout::ATTACHMENT) ||
248 (!toWrite && usage == RTAttachment::Layout::SHADER_READ) )
249 {
250 continue;
251 }
252
253 vkTexture* vkTexRender = static_cast<vkTexture*>(Get(att->renderTexture()));
254
255 ImageView targetView = vkTexRender->getView();
256
257 const DrawLayerEntry targetColourLayer = descriptor._writeLayers[i]._layer == INVALID_INDEX ? targetDepthLayer : descriptor._writeLayers[i];
258
259 if ( IsCubeTexture( vkTexRender->descriptor()._texType ) )
260 {
261 targetView._subRange._layerRange = { to_U16(targetColourLayer._cubeFace + (targetColourLayer._layer * 6u)), descriptor._layeredRendering ? U16_MAX : U16_ONE };
262 }
263 else
264 {
265 assert( targetColourLayer._cubeFace == 0u );
266 targetView._subRange._layerRange = { targetColourLayer._layer, descriptor._layeredRendering ? U16_MAX : U16_ONE };
267 }
268
269 if ( descriptor._mipWriteLevel > 0u )
270 {
271 targetView._subRange._mipLevels = { descriptor._mipWriteLevel, 1u };
272 }
273
274 const bool resolveMSAA = descriptor._autoResolveMSAA && _attachmentsAutoResolve[i];
276
277 if (toWrite )
278 {
279 _subresourceRange[i].aspectMask = vkTexture::GetAspectFlags( vkTexRender->descriptor() );
280
281 if ( usage == RTAttachment::Layout::UNDEFINED )
282 {
284
285 _subresourceRange[i].baseMipLevel = 0u;
286 _subresourceRange[i].levelCount = VK_REMAINING_MIP_LEVELS;
287 _subresourceRange[i].baseArrayLayer = 0u;
288 _subresourceRange[i].layerCount = VK_REMAINING_ARRAY_LAYERS;
289 }
290 else
291 {
292 _subresourceRange[i].baseMipLevel = targetView._subRange._mipLevels._offset;
293 _subresourceRange[i].levelCount = targetView._subRange._mipLevels._count == U16_MAX ? VK_REMAINING_MIP_LEVELS : targetView._subRange._mipLevels._count;
294 _subresourceRange[i].baseArrayLayer = targetView._subRange._layerRange._offset;
295 _subresourceRange[i].layerCount = targetView._subRange._layerRange._count == U16_MAX ? VK_REMAINING_ARRAY_LAYERS : targetView._subRange._layerRange._count;
296 }
298 }
299 else
300 {
302 }
303
304 if ( transitionMask[i] )
305 {
306 att->_attachmentUsage = usage;
307
308 if ( !resolveMSAA || descriptor._keepMSAADataAfterResolve )
309 {
310 vkTexture::TransitionTexture( targetTransition, _subresourceRange[i], vkTexRender->image()->_image, memBarriers[memBarrierCount++]);
311 }
312
313 if ( resolveMSAA )
314 {
315 vkTexture* vkTexResolve = static_cast<vkTexture*>(Get(_attachments[i]->resolvedTexture()));
316 DIVIDE_ASSERT( vkTexRender->sampleFlagBits() != VK_SAMPLE_COUNT_1_BIT && vkTexResolve->sampleFlagBits() == VK_SAMPLE_COUNT_1_BIT );
317
318 PROFILE_SCOPE( "Colour Resolve", Profiler::Category::Graphics );
319 vkTexture::TransitionTexture( targetTransition, _subresourceRange[i], vkTexResolve->image()->_image, memBarriers[memBarrierCount++] );
320 }
321
322 if ( att->_descriptor._externalAttachment != nullptr)
323 {
324 att->_descriptor._externalAttachment->_attachmentUsage = usage;
325 }
326 }
327 }
328 }
329 }
330
332 {
333 PROFILE_SCOPE( "Depth Attachment", Profiler::Category::Graphics );
334
335 const auto& att = _attachments[RT_DEPTH_ATTACHMENT_IDX];
336
337 RTAttachment::Layout usage = att->_attachmentUsage;
338 if ( (toWrite && usage != RTAttachment::Layout::ATTACHMENT) ||
339 (!toWrite && usage != RTAttachment::Layout::SHADER_READ) )
340 {
341 vkTexture* vkTexRender = static_cast<vkTexture*>(Get(att->renderTexture()));
342
343 ImageView targetView = vkTexRender->getView();
344 const DrawLayerEntry depthEntry = srcDepthLayer._layer == INVALID_INDEX ? targetDepthLayer : srcDepthLayer;
345 if ( IsCubeTexture( vkTexRender->descriptor()._texType ) )
346 {
347 targetView._subRange._layerRange = { to_U16(depthEntry._cubeFace + (depthEntry._layer * 6u)), descriptor._layeredRendering ? U16_MAX : U16_ONE };
348 }
349 else
350 {
351 targetView._subRange._layerRange = { depthEntry._layer, descriptor._layeredRendering ? U16_MAX : U16_ONE };
352 }
353
354 if ( descriptor._mipWriteLevel > 0u )
355 {
356 targetView._subRange._mipLevels = { descriptor._mipWriteLevel, 1u };
357 }
358
359 const bool hasStencil = att->_descriptor._type == RTAttachmentType::DEPTH_STENCIL;
360 vkTexture::TransitionType targetTransition = toWrite
363
364 if ( toWrite )
365 {
366 _subresourceRange[RT_DEPTH_ATTACHMENT_IDX].aspectMask = vkTexture::GetAspectFlags( vkTexRender->descriptor() );
367 if ( usage == RTAttachment::Layout::UNDEFINED )
368 {
370
372 _subresourceRange[RT_DEPTH_ATTACHMENT_IDX].levelCount = VK_REMAINING_MIP_LEVELS;
373 _subresourceRange[RT_DEPTH_ATTACHMENT_IDX].baseArrayLayer = 0u;
374 _subresourceRange[RT_DEPTH_ATTACHMENT_IDX].layerCount = VK_REMAINING_ARRAY_LAYERS;
375 }
376 else
377 {
379 _subresourceRange[RT_DEPTH_ATTACHMENT_IDX].levelCount = targetView._subRange._mipLevels._count == U16_MAX ? VK_REMAINING_MIP_LEVELS : targetView._subRange._mipLevels._count;
381 _subresourceRange[RT_DEPTH_ATTACHMENT_IDX].layerCount = targetView._subRange._layerRange._count == U16_MAX ? VK_REMAINING_ARRAY_LAYERS : targetView._subRange._layerRange._count;
382 }
384 }
385 else
386 {
388 }
389
390 if ( transitionMask[RT_DEPTH_ATTACHMENT_IDX] )
391 {
392 att->_attachmentUsage = usage;
393
394 const bool resolveMSAA = descriptor._autoResolveMSAA && _attachmentsAutoResolve[RT_DEPTH_ATTACHMENT_IDX];
395 if ( !resolveMSAA || descriptor._keepMSAADataAfterResolve )
396 {
397 vkTexture::TransitionTexture( targetTransition, _subresourceRange[RT_DEPTH_ATTACHMENT_IDX], vkTexRender->image()->_image, memBarriers[memBarrierCount++] );
398 }
399
400 if ( resolveMSAA )
401 {
402 vkTexture* vkTexResolve = static_cast<vkTexture*>(Get(att->resolvedTexture()));
403 DIVIDE_ASSERT(vkTexRender->sampleFlagBits() != VK_SAMPLE_COUNT_1_BIT && vkTexResolve->sampleFlagBits() == VK_SAMPLE_COUNT_1_BIT );
404
406 vkTexture::TransitionTexture( targetTransition, _subresourceRange[RT_DEPTH_ATTACHMENT_IDX], vkTexResolve->image()->_image, memBarriers[memBarrierCount++] );
407 }
408
409 if ( att->_descriptor._externalAttachment != nullptr )
410 {
411 att->_descriptor._externalAttachment->_attachmentUsage = usage;
412 }
413 }
414 }
415 }
416
417 if ( memBarrierCount > 0u )
418 {
419 dependencyInfo.imageMemoryBarrierCount = memBarrierCount;
420 dependencyInfo.pImageMemoryBarriers = memBarriers.data();
421
422 VK_PROFILE( vkCmdPipelineBarrier2, cmdBuffer, &dependencyInfo );
423 }
424 }
425
426
427 void vkRenderTarget::begin( VkCommandBuffer cmdBuffer, const RTDrawDescriptor& descriptor, const RTClearDescriptor& clearPolicy, VkPipelineRenderingCreateInfo& pipelineRenderingCreateInfoOut )
428 {
430
431 static RTTransitionMask s_defaultTransitionMask = {true, true, true, true, true };
432
433 _previousPolicy = descriptor;
434
435 assert(pipelineRenderingCreateInfoOut.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
436
437 const bool needLayeredColour = descriptor._writeLayers[RT_DEPTH_ATTACHMENT_IDX]._layer != INVALID_INDEX && (descriptor._writeLayers[RT_DEPTH_ATTACHMENT_IDX]._layer > 0u || descriptor._writeLayers[RT_DEPTH_ATTACHMENT_IDX]._cubeFace > 0u);
438 DrawLayerEntry targetColourLayer{};
439
440 bool needLayeredDepth = false;
441 DrawLayerEntry targetDepthLayer{};
442
443 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
444 {
445 if ( !_attachmentsUsed[i] )
446 {
447 continue;
448 }
449
450 if ( descriptor._writeLayers[i]._layer != INVALID_INDEX && (descriptor._writeLayers[i]._layer > 0u || descriptor._writeLayers[i]._cubeFace > 0u) )
451 {
452 needLayeredDepth = true;
453 targetDepthLayer = descriptor._writeLayers[i];
454 break;
455 }
456 }
457
458 vkTexture::CachedImageView::Descriptor imageViewDescriptor{};
459 imageViewDescriptor._subRange = {};
460
461 U16 layerCount = 1u;
462
463 U8 stagingIndex = 0u;
464
465 {
466 PROFILE_SCOPE( "Colour Attachments", Profiler::Category::Graphics );
467 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
468 {
469 if ( _attachmentsUsed[i] && descriptor._drawMask[i] )
470 {
471 vkTexture* vkTexRender = static_cast<vkTexture*>(Get(_attachments[i]->renderTexture()));
472 imageViewDescriptor._subRange = vkTexRender->getView()._subRange;
473 if ( descriptor._writeLayers[i]._layer != INVALID_INDEX || needLayeredColour )
474 {
475 layerCount = std::max( layerCount, vkTexRender->depth() );
476 targetColourLayer = descriptor._writeLayers[i]._layer == INVALID_INDEX ? targetColourLayer : descriptor._writeLayers[i];
477 if ( IsCubeTexture( vkTexRender->descriptor()._texType ) )
478 {
479 imageViewDescriptor._subRange._layerRange = { to_U16(targetColourLayer._cubeFace + (targetColourLayer._layer * 6u)), descriptor._layeredRendering ? U16_MAX : U16_ONE };
480 layerCount *= 6u;
481 }
482 else
483 {
484 assert( targetColourLayer._cubeFace == 0u );
485 imageViewDescriptor._subRange._layerRange = { targetColourLayer._layer, descriptor._layeredRendering ? U16_MAX : U16_ONE };
486 }
487 }
488 else if ( descriptor._mipWriteLevel > 0u )
489 {
490 imageViewDescriptor._subRange._mipLevels = { descriptor._mipWriteLevel, 1u };
491 }
492
493 imageViewDescriptor._resolveTarget = false;
494 imageViewDescriptor._format = vkTexRender->vkFormat();
495 imageViewDescriptor._type = imageViewDescriptor._subRange._layerRange._count > 1u ? TextureType::TEXTURE_2D_ARRAY : TextureType::TEXTURE_2D;
496 imageViewDescriptor._usage = ImageUsage::RT_COLOUR_ATTACHMENT;
497
498 VkRenderingAttachmentInfo& info = _colourAttachmentInfo[i];
499 info.imageView = vkTexRender->getImageView( imageViewDescriptor );
500 _colourAttachmentFormats[stagingIndex] = vkTexRender->vkFormat();
501
502 info.clearValue = {};
503 info.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
504
505 const bool resolveMSAA = descriptor._autoResolveMSAA && _attachmentsAutoResolve[i];
506 // If we specify a clear policy, we want to clear out attachment on load
507 if ( clearPolicy[i]._enabled )
508 {
509 *info.clearValue.color.float32 = *clearPolicy[i]._colour._v;
510
511 info.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
512 }
513 else if ( resolveMSAA && !descriptor._keepMSAADataAfterResolve && !_keptMSAAData)
514 {
515 info.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
516 }
517 else
518 {
519 info.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
520 }
521 // MSAA complicates things a lot. For best performance we want to inline resolve and also don't care about the msaa target's contents that much
522 // Ideally, we should not care about our MSAA load and store and just focus on the resolve target ...
523 if ( resolveMSAA )
524 {
525 imageViewDescriptor._resolveTarget = true;
526
527 if ( !descriptor._keepMSAADataAfterResolve )
528 {
529 info.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
530 }
531
532 info.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
533 info.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
534 info.resolveImageView = static_cast<vkTexture*>(Get(_attachments[i]->resolvedTexture()))->getImageView( imageViewDescriptor );
535 }
536
537 _stagingColourAttachmentInfo[stagingIndex] = info;
538 }
539 else
540 {
541 _colourAttachmentFormats[stagingIndex] = VK_FORMAT_UNDEFINED;
542 _stagingColourAttachmentInfo[stagingIndex] = {};
543 _stagingColourAttachmentInfo[stagingIndex].sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
544 }
545
546 ++stagingIndex;
547 }
548 }
549 pipelineRenderingCreateInfoOut.colorAttachmentCount = stagingIndex;
550 pipelineRenderingCreateInfoOut.pColorAttachmentFormats = _colourAttachmentFormats.data();
551
552 _renderingInfo.colorAttachmentCount = stagingIndex;
553 _renderingInfo.pColorAttachments = _stagingColourAttachmentInfo.data();
554
556 {
557 PROFILE_SCOPE( "Depth Attachment", Profiler::Category::Graphics );
558
559 const auto& att = _attachments[RT_DEPTH_ATTACHMENT_IDX];
560 const bool hasStencil = att->_descriptor._type == RTAttachmentType::DEPTH_STENCIL;
561
562 vkTexture* vkTexRender = static_cast<vkTexture*>(Get(att->renderTexture()));
563 imageViewDescriptor._subRange = vkTexRender->getView()._subRange;
564 if ( descriptor._writeLayers[RT_DEPTH_ATTACHMENT_IDX]._layer != INVALID_INDEX || needLayeredDepth )
565 {
566 layerCount = std::max( layerCount, vkTexRender->depth() );
567 targetDepthLayer = descriptor._writeLayers[RT_DEPTH_ATTACHMENT_IDX]._layer == INVALID_INDEX ? targetDepthLayer : descriptor._writeLayers[RT_DEPTH_ATTACHMENT_IDX];
568 if ( IsCubeTexture( vkTexRender->descriptor()._texType ) )
569 {
570 imageViewDescriptor._subRange._layerRange = { to_U16(targetDepthLayer._cubeFace + (targetDepthLayer._layer * 6u)), descriptor._layeredRendering ? U16_MAX : U16_ONE };
571 layerCount *= 6u;
572 }
573 else
574 {
575 assert( targetColourLayer._cubeFace == 0u );
576 imageViewDescriptor._subRange._layerRange = { targetDepthLayer._layer, descriptor._layeredRendering ? U16_MAX : U16_ONE };
577 }
578 }
579 else if ( descriptor._mipWriteLevel != U16_MAX )
580 {
581 imageViewDescriptor._subRange._mipLevels = { descriptor._mipWriteLevel, 1u };
582 }
583
584 imageViewDescriptor._resolveTarget = false;
585 imageViewDescriptor._format = vkTexRender->vkFormat();
586 imageViewDescriptor._type = imageViewDescriptor._subRange._layerRange._count > 1u ? TextureType::TEXTURE_2D_ARRAY : TextureType::TEXTURE_2D;
587 imageViewDescriptor._usage = hasStencil ? ImageUsage::RT_DEPTH_STENCIL_ATTACHMENT : ImageUsage::RT_DEPTH_ATTACHMENT;
588
589 _depthAttachmentInfo.imageView = vkTexRender->getImageView( imageViewDescriptor );
590
591 _depthAttachmentInfo.clearValue.depthStencil.depth = 1.f;
592
593 // We should always load/clear depth values since DONT_CARE will lead to failed depth tests
594 _depthAttachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
595 _depthAttachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
596
597 // If we specify a clear policy, we want to clear out attachment on load
598 if ( clearPolicy[RT_DEPTH_ATTACHMENT_IDX]._enabled )
599 {
600 _depthAttachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
601 _depthAttachmentInfo.clearValue.depthStencil.depth = clearPolicy[RT_DEPTH_ATTACHMENT_IDX]._colour.r;
602 _depthAttachmentInfo.clearValue.depthStencil.stencil = to_U32(clearPolicy[RT_DEPTH_ATTACHMENT_IDX]._colour.g);
603 }
604
605 const bool resolveMSAA = descriptor._autoResolveMSAA && _attachmentsAutoResolve[RT_DEPTH_ATTACHMENT_IDX];
606
607 if ( resolveMSAA )
608 {
609 imageViewDescriptor._resolveTarget = true;
610
611 if ( !descriptor._keepMSAADataAfterResolve )
612 {
613 _depthAttachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
614 }
615
616 _depthAttachmentInfo.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
617 _depthAttachmentInfo.resolveImageLayout = hasStencil ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
618 _depthAttachmentInfo.resolveImageView = static_cast<vkTexture*>(Get(att->resolvedTexture()))->getImageView( imageViewDescriptor );
619 }
620
621 pipelineRenderingCreateInfoOut.depthAttachmentFormat = vkTexRender->vkFormat();
622 _renderingInfo.pDepthAttachment = &_depthAttachmentInfo;
623 }
624 else
625 {
626 pipelineRenderingCreateInfoOut.depthAttachmentFormat = VK_FORMAT_UNDEFINED;
627 _renderingInfo.pDepthAttachment = nullptr;
628 }
629
630 _renderingInfo.layerCount = descriptor._layeredRendering ? layerCount : 1;
631 transitionAttachments( cmdBuffer, descriptor, s_defaultTransitionMask, true );
633 }
634
635 void vkRenderTarget::end( VkCommandBuffer cmdBuffer, const RTTransitionMask& mask )
636 {
638
639 transitionAttachments( cmdBuffer, _previousPolicy, mask, false );
640 }
641}; //namespace Divide
#define DIVIDE_ASSERT(...)
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
#define PROFILE_SCOPE(NAME, CATEGORY)
Definition: Profiler.h:86
#define PROFILE_VK_EVENT_AUTO_AND_CONTEX(BUFFER)
Definition: Profiler.h:101
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
Definition: GFXDevice.h:215
U16 getWidth() const noexcept
RenderTargetDescriptor _descriptor
Definition: RenderTarget.h:100
virtual bool create()
Init all attachments. Returns false if already called.
U16 getHeight() const noexcept
RTAttachment_uptr _attachments[RT_MAX_ATTACHMENT_COUNT]
Definition: RenderTarget.h:102
bool _attachmentsAutoResolve[RT_MAX_ATTACHMENT_COUNT]
Definition: RenderTarget.h:104
bool _attachmentsUsed[RT_MAX_ATTACHMENT_COUNT]
Definition: RenderTarget.h:103
ImageView getView() const noexcept
Definition: Texture.cpp:597
static void PushDebugMessage(VkCommandBuffer cmdBuffer, const char *message, U32 id=U32_MAX)
Definition: VKWrapper.cpp:3112
static void PopDebugMessage(VkCommandBuffer cmdBuffer)
Definition: VKWrapper.cpp:3131
void transitionAttachments(VkCommandBuffer cmdBuffer, const RTDrawDescriptor &descriptor, const RTTransitionMask &transitionMask, bool toWrite)
std::array< VkFormat, to_base(RTColourAttachmentSlot::COUNT)> _colourAttachmentFormats
std::array< VkRenderingAttachmentInfo, to_base(RTColourAttachmentSlot::COUNT)> _stagingColourAttachmentInfo
bool create() override
Init all attachments. Returns false if already called.
void begin(VkCommandBuffer cmdBuffer, const RTDrawDescriptor &descriptor, const RTClearDescriptor &clearPolicy, VkPipelineRenderingCreateInfo &pipelineRenderingCreateInfoOut)
void blitFrom(VkCommandBuffer cmdBuffer, vkRenderTarget *source, const RTBlitParams &params) noexcept
RTDrawDescriptor _previousPolicy
VkRenderingAttachmentInfo _depthAttachmentInfo
vkRenderTarget(GFXDevice &context, const RenderTargetDescriptor &descriptor)
std::array< VkImageSubresourceRange, RT_MAX_ATTACHMENT_COUNT > _subresourceRange
std::array< VkRenderingAttachmentInfo, to_base(RTColourAttachmentSlot::COUNT)> _colourAttachmentInfo
void end(VkCommandBuffer cmdBuffer, const RTTransitionMask &mask)
static void TransitionTexture(TransitionType type, const VkImageSubresourceRange &subresourceRange, VkImage image, VkImageMemoryBarrier2 &memBarrier)
Definition: vkTexture.cpp:1011
VkImageView getImageView(const CachedImageView::Descriptor &descriptor) const
Definition: vkTexture.cpp:914
static VkImageAspectFlags GetAspectFlags(const TextureDescriptor &descriptor) noexcept
Definition: vkTexture.cpp:177
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
VkDependencyInfo dependencyInfo()
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U16 MAX_BLIT_ENTRIES
constexpr U8 INVALID_INDEX
eastl::fixed_vector< RTBlitEntry, MAX_BLIT_ENTRIES, false > RTBlitParams
constexpr U32 to_U32(const T value)
static constexpr U32 RT_DEPTH_ATTACHMENT_IDX
Definition: RTAttachment.h:71
constexpr U16 to_U16(const T value)
uint8_t U8
bool IsCubeTexture(TextureType texType) noexcept
bool IsValid(const RTBlitParams &params) noexcept
bool IsDepthTexture(GFXImagePacking packing) noexcept
constexpr U16 U16_MAX
uint16_t U16
std::array< RTClearEntry, RT_MAX_ATTACHMENT_COUNT > RTClearDescriptor
bool[RT_MAX_ATTACHMENT_COUNT] RTTransitionMask
constexpr U16 U16_ONE
FORCE_INLINE T * Get(const Handle< T > handle)
Project const SceneEntry & entry
Definition: DefaultScene.h:41
constexpr auto to_base(const Type value) -> Type
U8 _cubeFace
Ignored for non cube textures.
U16 _layer
ImageSubRange _subRange
DrawLayerEntry _writeLayers[RT_MAX_ATTACHMENT_COUNT]
bool _layeredRendering
Set to true to bind all image layers to the render target (e.g. for Geometry Shader layered rendering...
#define VK_PROFILE(FUNCTION,...)
Definition: vkResources.h:340