mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
512 lines
24 KiB
512 lines
24 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021, 2022, 2023, 2024, 2025 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
#include "Pipeline.h" |
|
#include "RasterizationPipelineCreateInfo.h" |
|
#include "ComputePipelineCreateInfo.h" |
|
#include "CommandBuffer.h" |
|
|
|
#include <Corrade/Containers/Array.h> |
|
#include <Corrade/Containers/BigEnumSet.hpp> |
|
|
|
#include "Magnum/Vk/Assert.h" |
|
#include "Magnum/Vk/Device.h" |
|
#include "Magnum/Vk/Handle.h" |
|
#include "Magnum/Vk/Image.h" |
|
#include "Magnum/Vk/Integration.h" |
|
#include "Magnum/Vk/MeshLayout.h" |
|
#include "Magnum/Vk/ShaderSet.h" |
|
|
|
namespace Magnum { namespace Vk { |
|
|
|
struct RasterizationPipelineCreateInfo::State { |
|
Containers::Array<VkPipelineColorBlendAttachmentState> colorBlendAttachments; |
|
|
|
/* The enum is saved as well to be subsequently available through |
|
Pipeline::dynamicRasterizationStates() */ |
|
DynamicRasterizationStates dynamicStates; |
|
Containers::Array<VkDynamicState> dynamicStateList; |
|
|
|
/** @todo make an array once we support multiview */ |
|
VkViewport viewport; |
|
VkRect2D scissor; |
|
}; |
|
|
|
RasterizationPipelineCreateInfo::RasterizationPipelineCreateInfo(const ShaderSet& shaderSet, const MeshLayout& meshLayout, const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass, const UnsignedInt subpass, const UnsignedInt subpassColorAttachmentCount, Flags flags): _info{}, _viewportInfo{}, _rasterizationInfo{}, _multisampleInfo{}, _depthStencilInfo{}, _colorBlendInfo{}, _dynamicInfo{}, _state{InPlaceInit} { |
|
_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; |
|
_info.flags = VkPipelineCreateFlags(flags); |
|
_info.stageCount = shaderSet.stages().size(); |
|
_info.pStages = shaderSet.stages(); |
|
_info.pVertexInputState = meshLayout; |
|
_info.pInputAssemblyState = meshLayout; |
|
|
|
/* pTesselationState is fine to be null */ |
|
/** @todo add it if we get passed a tessellation shader? or should the |
|
shader wrapper include it? */ |
|
|
|
/* Leaving pViewportState null as that gets (but doesn't have to, if |
|
rasterization is disabled) set by setViewport() */ |
|
|
|
_rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; |
|
_rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL; |
|
_rasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; |
|
_rasterizationInfo.lineWidth = 1.0f; |
|
_info.pRasterizationState = &_rasterizationInfo; |
|
|
|
_multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; |
|
_multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
|
_info.pMultisampleState = &_multisampleInfo; |
|
|
|
_depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; |
|
_info.pDepthStencilState = &_depthStencilInfo; |
|
|
|
_state->colorBlendAttachments = Containers::Array<VkPipelineColorBlendAttachmentState>{ValueInit, subpassColorAttachmentCount}; |
|
for(VkPipelineColorBlendAttachmentState& i: _state->colorBlendAttachments) { |
|
i.colorWriteMask = VK_COLOR_COMPONENT_R_BIT| |
|
VK_COLOR_COMPONENT_G_BIT| |
|
VK_COLOR_COMPONENT_B_BIT| |
|
VK_COLOR_COMPONENT_A_BIT; |
|
} |
|
|
|
_colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; |
|
_colorBlendInfo.attachmentCount = subpassColorAttachmentCount; |
|
_colorBlendInfo.pAttachments = _state->colorBlendAttachments; |
|
_info.pColorBlendState = &_colorBlendInfo; |
|
|
|
/* pDynamicState left null, gets set by setDynamicStates() if needed */ |
|
|
|
_info.layout = pipelineLayout; |
|
_info.renderPass = renderPass; |
|
_info.subpass = subpass; |
|
} |
|
|
|
RasterizationPipelineCreateInfo::RasterizationPipelineCreateInfo(NoInitT) noexcept {} |
|
|
|
RasterizationPipelineCreateInfo::RasterizationPipelineCreateInfo(const VkGraphicsPipelineCreateInfo& info): |
|
/* Can't use {} with GCC 4.8 here because it tries to initialize the first |
|
member instead of doing a copy */ |
|
_info(info) |
|
{ |
|
/* Copy and reroute all top-level nested structs as well */ |
|
if(info.pViewportState) |
|
_info.pViewportState = &(_viewportInfo = *info.pViewportState); |
|
if(info.pRasterizationState) |
|
_info.pRasterizationState = &(_rasterizationInfo = *info.pRasterizationState); |
|
if(info.pMultisampleState) |
|
_info.pMultisampleState = &(_multisampleInfo = *info.pMultisampleState); |
|
if(info.pDepthStencilState) |
|
_info.pDepthStencilState = &(_depthStencilInfo = *info.pDepthStencilState); |
|
if(info.pColorBlendState) |
|
_info.pColorBlendState = &(_colorBlendInfo = *info.pColorBlendState); |
|
if(info.pDynamicState) |
|
_info.pDynamicState = &(_dynamicInfo = *info.pDynamicState); |
|
} |
|
|
|
RasterizationPipelineCreateInfo::RasterizationPipelineCreateInfo(RasterizationPipelineCreateInfo&& other) noexcept: |
|
/* Can't use {} with GCC 4.8 here because it tries to initialize the first |
|
member instead of doing a copy */ |
|
_info(other._info), |
|
_viewportInfo(other._viewportInfo), |
|
_rasterizationInfo(other._rasterizationInfo), |
|
_multisampleInfo(other._multisampleInfo), |
|
_depthStencilInfo(other._depthStencilInfo), |
|
_colorBlendInfo(other._colorBlendInfo), |
|
_dynamicInfo(other._dynamicInfo), |
|
_state{Utility::move(other._state)} |
|
{ |
|
/* Reroute the pointers */ |
|
if(_info.pViewportState == &other._viewportInfo) |
|
_info.pViewportState = &_viewportInfo; |
|
if(_info.pRasterizationState == &other._rasterizationInfo) |
|
_info.pRasterizationState = &_rasterizationInfo; |
|
if(_info.pMultisampleState == &other._multisampleInfo) |
|
_info.pMultisampleState = &_multisampleInfo; |
|
if(_info.pDepthStencilState == &other._depthStencilInfo) |
|
_info.pDepthStencilState = &_depthStencilInfo; |
|
if(_info.pColorBlendState == &other._colorBlendInfo) |
|
_info.pColorBlendState = &_colorBlendInfo; |
|
if(_info.pDynamicState == &other._dynamicInfo) |
|
_info.pDynamicState = &_dynamicInfo; |
|
|
|
/* Ensure the previous instance doesn't reference state that's now ours */ |
|
/** @todo this is now more like a destructible move, do it more selectively |
|
and clear only what's really ours and not external? */ |
|
other._info.pNext = nullptr; |
|
other._info.stageCount = 0; |
|
other._info.pStages = nullptr; |
|
other._info.pVertexInputState = nullptr; |
|
other._info.pInputAssemblyState = nullptr; |
|
other._info.pTessellationState = nullptr; |
|
other._info.pViewportState = nullptr; |
|
other._info.pRasterizationState = nullptr; |
|
other._info.pMultisampleState = nullptr; |
|
other._info.pDepthStencilState = nullptr; |
|
other._info.pColorBlendState = nullptr; |
|
other._info.pDynamicState = nullptr; |
|
} |
|
|
|
RasterizationPipelineCreateInfo::~RasterizationPipelineCreateInfo() = default; |
|
|
|
RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::operator=(RasterizationPipelineCreateInfo&& other) noexcept { |
|
using Utility::swap; |
|
swap(other._info, _info); |
|
swap(other._viewportInfo, _viewportInfo); |
|
swap(other._rasterizationInfo, _rasterizationInfo); |
|
swap(other._multisampleInfo, _multisampleInfo); |
|
swap(other._depthStencilInfo, _depthStencilInfo); |
|
swap(other._colorBlendInfo, _colorBlendInfo); |
|
swap(other._dynamicInfo, _dynamicInfo); |
|
swap(other._state, _state); |
|
|
|
/* Reroute the pointers */ |
|
if(_info.pViewportState == &other._viewportInfo) |
|
_info.pViewportState = &_viewportInfo; |
|
if(_info.pRasterizationState == &other._rasterizationInfo) |
|
_info.pRasterizationState = &_rasterizationInfo; |
|
if(_info.pMultisampleState == &other._multisampleInfo) |
|
_info.pMultisampleState = &_multisampleInfo; |
|
if(_info.pDepthStencilState == &other._depthStencilInfo) |
|
_info.pDepthStencilState = &_depthStencilInfo; |
|
if(_info.pColorBlendState == &other._colorBlendInfo) |
|
_info.pColorBlendState = &_colorBlendInfo; |
|
if(_info.pDynamicState == &other._dynamicInfo) |
|
_info.pDynamicState = &_dynamicInfo; |
|
|
|
/* And other way around as well */ |
|
if(other._info.pViewportState == &_viewportInfo) |
|
other._info.pViewportState = &other._viewportInfo; |
|
if(other._info.pRasterizationState == &_rasterizationInfo) |
|
other._info.pRasterizationState = &other._rasterizationInfo; |
|
if(other._info.pMultisampleState == &_multisampleInfo) |
|
other._info.pMultisampleState = &other._multisampleInfo; |
|
if(other._info.pDepthStencilState == &_depthStencilInfo) |
|
other._info.pDepthStencilState = &other._depthStencilInfo; |
|
if(other._info.pColorBlendState == &_colorBlendInfo) |
|
other._info.pColorBlendState = &other._colorBlendInfo; |
|
if(other._info.pDynamicState == &_dynamicInfo) |
|
other._info.pDynamicState = &other._dynamicInfo; |
|
|
|
return *this; |
|
} |
|
|
|
RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::setViewport(const Range3D& viewport, const Range2Di& scissor) { |
|
_state->viewport = VkViewport(viewport); |
|
_state->scissor = VkRect2D(scissor); |
|
|
|
_viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; |
|
_viewportInfo.viewportCount = 1; |
|
_viewportInfo.pViewports = &_state->viewport; |
|
_viewportInfo.scissorCount = 1; |
|
_viewportInfo.pScissors = &_state->scissor; |
|
_info.pViewportState = &_viewportInfo; |
|
return *this; |
|
} |
|
|
|
RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::setViewport(const Range3D& viewport) { |
|
return setViewport(viewport, Range2Di{viewport.xy()}); |
|
} |
|
|
|
RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::setViewport(const Range2D& viewport, const Range2Di& scissor) { |
|
return setViewport(Range3D{{viewport.min(), 0.0f}, {viewport.max(), 1.0f}}, scissor); |
|
} |
|
|
|
RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::setViewport(const Range2D& viewport) { |
|
return setViewport(viewport, Range2Di{viewport}); |
|
} |
|
|
|
namespace { |
|
|
|
constexpr VkDynamicState DynamicRasterizationStateMapping[]{ |
|
#define _c(value, vkValue) VK_DYNAMIC_STATE_ ## vkValue, |
|
#include "Magnum/Vk/Implementation/dynamicRasterizationStateMapping.hpp" |
|
#undef _c |
|
}; |
|
|
|
} |
|
|
|
RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::setDynamicStates(const DynamicRasterizationStates& states) { |
|
/* Save the enum so we can store it in the created Pipeline object later */ |
|
_state->dynamicStates = states; |
|
|
|
/* Count the number of states set, allocate for that */ |
|
std::size_t count = 0; |
|
for(std::size_t i = 0; i != DynamicRasterizationStates::Size; ++i) |
|
count += Math::popcount(states.data()[i]); |
|
_state->dynamicStateList = Containers::Array<VkDynamicState>{NoInit, count}; |
|
|
|
std::size_t offset = 0; |
|
for(std::uint64_t i = 0; i != Containers::arraySize(DynamicRasterizationStateMapping); ++i) |
|
if(states & DynamicRasterizationState(i)) |
|
_state->dynamicStateList[offset++] = DynamicRasterizationStateMapping[i]; |
|
CORRADE_INTERNAL_ASSERT(offset == count); |
|
|
|
_dynamicInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; |
|
_dynamicInfo.dynamicStateCount = count; |
|
_dynamicInfo.pDynamicStates = _state->dynamicStateList; |
|
_info.pDynamicState = &_dynamicInfo; |
|
return *this; |
|
} |
|
|
|
ComputePipelineCreateInfo::ComputePipelineCreateInfo(const ShaderSet& shaderSet, const VkPipelineLayout pipelineLayout, const Flags flags): _info{} { |
|
CORRADE_ASSERT(shaderSet.stages().size() == 1, |
|
"Vk::ComputePipelineCreateInfo: the shader set has to contain exactly one shader, got" << shaderSet.stages().size(), ); |
|
|
|
_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; |
|
_info.flags = VkPipelineCreateFlags(flags); |
|
_info.stage = shaderSet.stages()[0]; |
|
_info.layout = pipelineLayout; |
|
} |
|
|
|
ComputePipelineCreateInfo::ComputePipelineCreateInfo(NoInitT) noexcept {} |
|
|
|
ComputePipelineCreateInfo::ComputePipelineCreateInfo(const VkComputePipelineCreateInfo& info): |
|
/* Can't use {} with GCC 4.8 here because it tries to initialize the first |
|
member instead of doing a copy */ |
|
_info(info) {} |
|
|
|
Pipeline Pipeline::wrap(Device& device, const PipelineBindPoint bindPoint, const VkPipeline handle, const DynamicRasterizationStates& dynamicStates, const HandleFlags flags) { |
|
Pipeline out{NoCreate}; |
|
out._device = &device; |
|
out._handle = handle; |
|
out._bindPoint = bindPoint; |
|
out._flags = flags; |
|
out._dynamicStates.rasterization = dynamicStates; |
|
return out; |
|
} |
|
|
|
Pipeline Pipeline::wrap(Device& device, const PipelineBindPoint bindPoint, const VkPipeline handle, const HandleFlags flags) { |
|
return wrap(device, bindPoint, handle, DynamicRasterizationStates{}, flags); |
|
} |
|
|
|
Pipeline::Pipeline(Device& device, const RasterizationPipelineCreateInfo& info): |
|
_device{&device}, |
|
#ifdef CORRADE_GRACEFUL_ASSERT |
|
/* Otherwise vkDestroyPipeline() crashes when we hit the assert */ |
|
_handle{}, |
|
#endif |
|
_bindPoint{PipelineBindPoint::Rasterization}, |
|
_flags{HandleFlag::DestroyOnDestruction}, |
|
_dynamicStates{info._state->dynamicStates} |
|
{ |
|
/* Doesn't check that the viewport is really a dynamic state, but should |
|
catch most cases without false positives */ |
|
CORRADE_ASSERT(info->pViewportState || info->pRasterizationState->rasterizerDiscardEnable || info->pDynamicState, |
|
"Vk::Pipeline: if rasterization discard is not enabled, the viewport has to be either dynamic or set via setViewport()", ); |
|
|
|
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateGraphicsPipelines(device, {}, 1, info, nullptr, &_handle)); |
|
} |
|
|
|
Pipeline::Pipeline(Device& device, const ComputePipelineCreateInfo& info): _device{&device}, _bindPoint{PipelineBindPoint::Compute}, _flags{HandleFlag::DestroyOnDestruction}, _dynamicStates{} { |
|
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateComputePipelines(device, {}, 1, info, nullptr, &_handle)); |
|
} |
|
|
|
Pipeline::Pipeline(NoCreateT): _device{}, _handle{}, _bindPoint{}, _dynamicStates{} {} |
|
|
|
Pipeline::Pipeline(Pipeline&& other) noexcept: _device{other._device}, _handle{other._handle}, _bindPoint{other._bindPoint}, _flags{other._flags}, |
|
/* Can't use {} with GCC 4.8 here because it tries to initialize the first |
|
member instead of doing a copy */ |
|
_dynamicStates(other._dynamicStates) |
|
{ |
|
other._handle = {}; |
|
} |
|
|
|
Pipeline::~Pipeline() { |
|
if(_handle && (_flags & HandleFlag::DestroyOnDestruction)) |
|
(**_device).DestroyPipeline(*_device, _handle, nullptr); |
|
} |
|
|
|
Pipeline& Pipeline::operator=(Pipeline&& other) noexcept { |
|
using Utility::swap; |
|
swap(other._device, _device); |
|
swap(other._handle, _handle); |
|
swap(other._bindPoint, _bindPoint); |
|
swap(other._flags, _flags); |
|
swap(other._dynamicStates, _dynamicStates); |
|
return *this; |
|
} |
|
|
|
DynamicRasterizationStates Pipeline::dynamicRasterizationStates() const { |
|
CORRADE_ASSERT(_bindPoint == PipelineBindPoint::Rasterization, |
|
"Vk::Pipeline::dynamicRasterizationStates(): not a rasterization pipeline", {}); |
|
return _dynamicStates.rasterization; |
|
} |
|
|
|
VkPipeline Pipeline::release() { |
|
const VkPipeline handle = _handle; |
|
_handle = {}; |
|
return handle; |
|
} |
|
|
|
MemoryBarrier::MemoryBarrier(const Accesses sourceAccesses, const Accesses destinationAccesses): _barrier{} { |
|
_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; |
|
_barrier.srcAccessMask = VkAccessFlags(sourceAccesses); |
|
_barrier.dstAccessMask = VkAccessFlags(destinationAccesses); |
|
} |
|
|
|
MemoryBarrier::MemoryBarrier(NoInitT) noexcept {} |
|
|
|
MemoryBarrier::MemoryBarrier(const VkMemoryBarrier& barrier): |
|
/* Can't use {} with GCC 4.8 here because it tries to initialize the first |
|
member instead of doing a copy */ |
|
_barrier(barrier) {} |
|
|
|
BufferMemoryBarrier::BufferMemoryBarrier(const Accesses sourceAccesses, const Accesses destinationAccesses, const VkBuffer buffer, const UnsignedLong offset, const UnsignedLong size): _barrier{} { |
|
_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
|
_barrier.srcAccessMask = VkAccessFlags(sourceAccesses); |
|
_barrier.dstAccessMask = VkAccessFlags(destinationAccesses); |
|
_barrier.buffer = buffer; |
|
_barrier.offset = offset; |
|
_barrier.size = size; |
|
} |
|
|
|
BufferMemoryBarrier::BufferMemoryBarrier(NoInitT) noexcept {} |
|
|
|
BufferMemoryBarrier::BufferMemoryBarrier(const VkBufferMemoryBarrier& barrier): |
|
/* Can't use {} with GCC 4.8 here because it tries to initialize the first |
|
member instead of doing a copy */ |
|
_barrier(barrier) {} |
|
|
|
ImageMemoryBarrier::ImageMemoryBarrier(const Accesses sourceAccesses, const Accesses destinationAccesses, const ImageLayout oldLayout, const ImageLayout newLayout, const VkImage image, const ImageAspects aspects, const UnsignedInt layerOffset, const UnsignedInt layerCount, const UnsignedInt levelOffset, const UnsignedInt levelCount): _barrier{} { |
|
_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; |
|
_barrier.srcAccessMask = VkAccessFlags(sourceAccesses); |
|
_barrier.dstAccessMask = VkAccessFlags(destinationAccesses); |
|
_barrier.oldLayout = VkImageLayout(oldLayout); |
|
_barrier.newLayout = VkImageLayout(newLayout); |
|
_barrier.image = image; |
|
_barrier.subresourceRange.aspectMask = VkImageAspectFlags(aspects); |
|
_barrier.subresourceRange.baseMipLevel = levelOffset; |
|
_barrier.subresourceRange.levelCount = levelCount; |
|
_barrier.subresourceRange.baseArrayLayer = layerOffset; |
|
_barrier.subresourceRange.layerCount = layerCount; |
|
} |
|
|
|
ImageMemoryBarrier::ImageMemoryBarrier(const Accesses sourceAccesses, const Accesses destinationAccesses, const ImageLayout oldLayout, const ImageLayout newLayout, Image& image, const UnsignedInt layerOffset, const UnsignedInt layerCount, const UnsignedInt levelOffset, const UnsignedInt levelCount): ImageMemoryBarrier{sourceAccesses, destinationAccesses, oldLayout, newLayout, image, imageAspectsFor(image.format()), layerOffset, layerCount, levelOffset, levelCount} {} |
|
|
|
ImageMemoryBarrier::ImageMemoryBarrier(NoInitT) noexcept {} |
|
|
|
ImageMemoryBarrier::ImageMemoryBarrier(const VkImageMemoryBarrier& barrier): |
|
/* Can't use {} with GCC 4.8 here because it tries to initialize the first |
|
member instead of doing a copy */ |
|
_barrier(barrier) {} |
|
|
|
CommandBuffer& CommandBuffer::bindPipeline(Pipeline& pipeline) { |
|
/* Save the set of dynamic states for future use */ |
|
if(pipeline.bindPoint() == PipelineBindPoint::Rasterization) |
|
_dynamicRasterizationStates = pipeline.dynamicRasterizationStates(); |
|
|
|
(**_device).CmdBindPipeline(_handle, VkPipelineBindPoint(pipeline.bindPoint()), pipeline); |
|
return *this; |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const Containers::ArrayView<const MemoryBarrier> memoryBarriers, const Containers::ArrayView<const BufferMemoryBarrier> bufferMemoryBarriers, const Containers::ArrayView<const ImageMemoryBarrier> imageMemoryBarriers, const DependencyFlags dependencyFlags) { |
|
/* Once these grow (VkSampleLocationsInfoEXT?), they will need to be |
|
linearized into a separate array first */ |
|
static_assert( |
|
sizeof(MemoryBarrier) == sizeof(VkMemoryBarrier) && |
|
sizeof(BufferMemoryBarrier) == sizeof(VkBufferMemoryBarrier) && |
|
sizeof(ImageMemoryBarrier) == sizeof(VkImageMemoryBarrier), |
|
""); |
|
(**_device).CmdPipelineBarrier(_handle, VkPipelineStageFlags(sourceStages), VkPipelineStageFlags(destinationStages), VkDependencyFlags(dependencyFlags), |
|
memoryBarriers.size(), memoryBarriers.isEmpty() ? nullptr : &*memoryBarriers.front(), |
|
bufferMemoryBarriers.size(), bufferMemoryBarriers.isEmpty() ? nullptr : &*bufferMemoryBarriers.front(), |
|
imageMemoryBarriers.size(), imageMemoryBarriers.isEmpty() ? nullptr : &*imageMemoryBarriers.front()); |
|
return *this; |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const std::initializer_list<MemoryBarrier> memoryBarriers, const std::initializer_list<BufferMemoryBarrier> bufferMemoryBarriers, const std::initializer_list<ImageMemoryBarrier> imageMemoryBarriers, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, Containers::arrayView(memoryBarriers), Containers::arrayView(bufferMemoryBarriers), Containers::arrayView(imageMemoryBarriers), dependencyFlags); |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, {}, {}, {}, dependencyFlags); |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const Containers::ArrayView<const MemoryBarrier> memoryBarriers, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, memoryBarriers, {}, {}, dependencyFlags); |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const std::initializer_list<MemoryBarrier> memoryBarriers, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, Containers::arrayView(memoryBarriers), dependencyFlags); |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const Containers::ArrayView<const BufferMemoryBarrier> bufferMemoryBarriers, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, {}, bufferMemoryBarriers, {}, dependencyFlags); |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const std::initializer_list<BufferMemoryBarrier> bufferMemoryBarriers, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, Containers::arrayView(bufferMemoryBarriers), dependencyFlags); |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const Containers::ArrayView<const ImageMemoryBarrier> imageMemoryBarriers, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, {}, {}, imageMemoryBarriers, dependencyFlags); |
|
} |
|
|
|
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const std::initializer_list<ImageMemoryBarrier> imageMemoryBarriers, const DependencyFlags dependencyFlags) { |
|
return pipelineBarrier(sourceStages, destinationStages, Containers::arrayView(imageMemoryBarriers), dependencyFlags); |
|
} |
|
|
|
Debug& operator<<(Debug& debug, const PipelineBindPoint value) { |
|
debug << "Vk::PipelineBindPoint" << Debug::nospace; |
|
|
|
switch(value) { |
|
/* LCOV_EXCL_START */ |
|
#define _c(value) case Vk::PipelineBindPoint::value: return debug << "::" << Debug::nospace << #value; |
|
_c(Rasterization) |
|
_c(RayTracing) |
|
_c(Compute) |
|
#undef _c |
|
/* LCOV_EXCL_STOP */ |
|
} |
|
|
|
/* Vulkan docs have the values in decimal, so not converting to hex */ |
|
return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; |
|
} |
|
|
|
namespace { |
|
|
|
constexpr const char* DynamicRasterizationStateNames[]{ |
|
#define _c(value, vkValue) #value, |
|
#include "Magnum/Vk/Implementation/dynamicRasterizationStateMapping.hpp" |
|
#undef _c |
|
}; |
|
|
|
} |
|
|
|
Debug& operator<<(Debug& debug, const DynamicRasterizationState value) { |
|
debug << "Vk::DynamicRasterizationState" << Debug::nospace; |
|
|
|
if(UnsignedInt(value) < Containers::arraySize(DynamicRasterizationStateNames)) { |
|
return debug << "::" << Debug::nospace << DynamicRasterizationStateNames[UnsignedInt(value)]; |
|
} |
|
|
|
return debug << "(" << Debug::nospace << Debug::hex << UnsignedByte(value) << Debug::nospace << ")"; |
|
} |
|
|
|
Debug& operator<<(Debug& debug, const DynamicRasterizationStates& value) { |
|
return Containers::bigEnumSetDebugOutput(debug, value, "Vk::DynamicRasterizationStates{}"); |
|
} |
|
|
|
}}
|
|
|