Browse Source

Vk: implement a buffer fill command.

pull/494/head
Vladimír Vondruš 5 years ago
parent
commit
7b431a6dfb
  1. 14
      doc/snippets/MagnumVk.cpp
  2. 2
      doc/vulkan-mapping.dox
  3. 6
      src/Magnum/Vk/Buffer.cpp
  4. 9
      src/Magnum/Vk/Buffer.h
  5. 30
      src/Magnum/Vk/CommandBuffer.h
  6. 48
      src/Magnum/Vk/Test/BufferVkTest.cpp

14
doc/snippets/MagnumVk.cpp

@ -227,6 +227,20 @@ buffer.bindMemory(memory, 0);
/* [Buffer-creation-custom-allocation] */ /* [Buffer-creation-custom-allocation] */
} }
{
Vk::Device device{NoCreate};
Vk::CommandBuffer cmd{NoCreate};
/* [Buffer-usage-fill] */
Vk::Buffer buffer{device, Vk::BufferCreateInfo{
Vk::BufferUsage::TransferDestination|DOXYGEN_IGNORE(Vk::BufferUsage{}), DOXYGEN_IGNORE(0)
}, DOXYGEN_IGNORE(Vk::MemoryFlag{})};
DOXYGEN_IGNORE()
cmd.fillBuffer(buffer, 0x00000000);
/* [Buffer-usage-fill] */
}
{ {
/* The include should be a no-op here since it was already included above */ /* The include should be a no-op here since it was already included above */
/* [CommandPool-creation] */ /* [CommandPool-creation] */

2
doc/vulkan-mapping.dox

@ -142,7 +142,7 @@ Vulkan function | Matching API
@fn_vk{CmdDrawIndirect} | | @fn_vk{CmdDrawIndirect} | |
@fn_vk{CmdDrawIndirectCount} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @fn_vk{CmdDrawIndirectCount} @m_class{m-label m-flat m-success} **KHR, 1.2** | |
@fn_vk{CmdExecuteCommands} | | @fn_vk{CmdExecuteCommands} | |
@fn_vk{CmdFillBuffer} | | @fn_vk{CmdFillBuffer} | @ref CommandBuffer::fillBuffer()
@fn_vk{CmdInsertDebugUtilsLabelEXT} @m_class{m-label m-flat m-warning} **EXT** | | @fn_vk{CmdInsertDebugUtilsLabelEXT} @m_class{m-label m-flat m-warning} **EXT** | |
@fn_vk{CmdPipelineBarrier} | @ref CommandBuffer::pipelineBarrier() @fn_vk{CmdPipelineBarrier} | @ref CommandBuffer::pipelineBarrier()
@fn_vk{CmdPushConstants} | | @fn_vk{CmdPushConstants} | |

6
src/Magnum/Vk/Buffer.cpp

@ -25,6 +25,7 @@
#include "Buffer.h" #include "Buffer.h"
#include "BufferCreateInfo.h" #include "BufferCreateInfo.h"
#include "CommandBuffer.h"
#include "Magnum/Vk/Assert.h" #include "Magnum/Vk/Assert.h"
#include "Magnum/Vk/Device.h" #include "Magnum/Vk/Device.h"
@ -159,4 +160,9 @@ VkResult Buffer::bindMemoryImplementation11(Device& device, UnsignedInt count, c
return device->BindBufferMemory2(device, count, infos); return device->BindBufferMemory2(device, count, infos);
} }
CommandBuffer& CommandBuffer::fillBuffer(const VkBuffer buffer, const UnsignedLong offset, const UnsignedLong size, UnsignedInt value) {
(**_device).CmdFillBuffer(_handle, buffer, offset, size, value);
return *this;
}
}} }}

9
src/Magnum/Vk/Buffer.h

@ -76,6 +76,15 @@ available through @ref dedicatedMemory(). This matches current behavior of the
above, except that you have more control over choosing and allocating the above, except that you have more control over choosing and allocating the
memory. memory.
@section Vk-Buffer-usage Buffer usage
@subsection Vk-Buffer-usage-fill Clearing / filling buffer data
The following snippet shows zero-filling the whole buffer using
@ref CommandBuffer::fillBuffer():
@snippet MagnumVk.cpp Buffer-usage-fill
@see @ref Image @see @ref Image
*/ */
class MAGNUM_VK_EXPORT Buffer { class MAGNUM_VK_EXPORT Buffer {

30
src/Magnum/Vk/CommandBuffer.h

@ -426,6 +426,36 @@ class MAGNUM_VK_EXPORT CommandBuffer {
/** @overload */ /** @overload */
CommandBuffer& pipelineBarrier(PipelineStages sourceStages, PipelineStages destinationStages, std::initializer_list<ImageMemoryBarrier> imageMemoryBarriers, DependencyFlags dependencyFlags = {}); CommandBuffer& pipelineBarrier(PipelineStages sourceStages, PipelineStages destinationStages, std::initializer_list<ImageMemoryBarrier> imageMemoryBarriers, DependencyFlags dependencyFlags = {});
/**
* @brief Fill a buffer region with a fixed value
* @param buffer Source @p Buffer or a raw Vulkan buffer handle to
* fill. Expected to have been created with
* @ref BufferUsage::TransferDestination.
* @param offset Offset of the region to fill, in bytes
* @param size Size of the region to fill, in bytes
* @param value A 4-byte value to repeat in the region, interpreted
* accoding to the machine endianness. If @p size is not divisible
* by 4, the last remaining bytes are not filled.
* @return Reference to self (for method chaining)
*
* Allowed only outside of a render pass. See @ref Vk-Buffer-usage-fill
* for a usage example.
* @see @fn_vk_keyword{CmdFillBuffer}
*/
CommandBuffer& fillBuffer(VkBuffer buffer, UnsignedLong offset, UnsignedLong size, UnsignedInt value);
/**
* @brief Fill the whole buffer with a fixed value
* @return Reference to self (for method chaining)
*
* Allowed only outside of a render pass. Equivalent to
* @ref fillBuffer(VkBuffer, UnsignedLong, UnsignedLong, UnsignedInt)
* with @p offset set to @cpp 0 @ce and @p size to @def_vk{WHOLE_SIZE}.
*/
CommandBuffer& fillBuffer(VkBuffer buffer, UnsignedInt value) {
return fillBuffer(buffer, 0, VK_WHOLE_SIZE, value);
}
private: private:
friend CommandPool; friend CommandPool;
friend Implementation::DeviceState; friend Implementation::DeviceState;

48
src/Magnum/Vk/Test/BufferVkTest.cpp

@ -23,12 +23,19 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/TestSuite/Compare/Numeric.h> #include <Corrade/TestSuite/Compare/Numeric.h>
#include <Corrade/Utility/Algorithms.h>
#include "Magnum/Vk/BufferCreateInfo.h" #include "Magnum/Vk/BufferCreateInfo.h"
#include "Magnum/Vk/CommandBuffer.h"
#include "Magnum/Vk/CommandPoolCreateInfo.h"
#include "Magnum/Vk/DeviceProperties.h" #include "Magnum/Vk/DeviceProperties.h"
#include "Magnum/Vk/Fence.h"
#include "Magnum/Vk/Handle.h" #include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/MemoryAllocateInfo.h" #include "Magnum/Vk/MemoryAllocateInfo.h"
#include "Magnum/Vk/Pipeline.h"
#include "Magnum/Vk/Result.h" #include "Magnum/Vk/Result.h"
#include "Magnum/Vk/VulkanTester.h" #include "Magnum/Vk/VulkanTester.h"
@ -48,6 +55,8 @@ struct BufferVkTest: VulkanTester {
void bindDedicatedMemory(); void bindDedicatedMemory();
void directAllocation(); void directAllocation();
void cmdFillBuffer();
}; };
BufferVkTest::BufferVkTest() { BufferVkTest::BufferVkTest() {
@ -61,9 +70,13 @@ BufferVkTest::BufferVkTest() {
&BufferVkTest::bindMemory, &BufferVkTest::bindMemory,
&BufferVkTest::bindDedicatedMemory, &BufferVkTest::bindDedicatedMemory,
&BufferVkTest::directAllocation}); &BufferVkTest::directAllocation,
&BufferVkTest::cmdFillBuffer});
} }
using namespace Containers::Literals;
void BufferVkTest::construct() { void BufferVkTest::construct() {
{ {
Buffer buffer{device(), BufferCreateInfo{BufferUsage::StorageBuffer, 1024}, NoAllocate}; Buffer buffer{device(), BufferCreateInfo{BufferUsage::StorageBuffer, 1024}, NoAllocate};
@ -169,6 +182,39 @@ void BufferVkTest::directAllocation() {
CORRADE_VERIFY(buffer.dedicatedMemory().handle()); CORRADE_VERIFY(buffer.dedicatedMemory().handle());
} }
void BufferVkTest::cmdFillBuffer() {
CommandPool pool{device(), CommandPoolCreateInfo{
device().properties().pickQueueFamily(QueueFlag::Graphics)}};
CommandBuffer cmd = pool.allocate();
Buffer a{device(), BufferCreateInfo{
BufferUsage::TransferSource|BufferUsage::TransferDestination, 16
}, MemoryFlag::HostVisible};
Utility::copy("0123456789abcdef"_s, a.dedicatedMemory().map());
cmd.begin()
.fillBuffer(a, 4, 8, 0x2e2e2e2e)
.pipelineBarrier(
PipelineStage::Transfer, PipelineStage::Host,
{{Access::TransferWrite, Access::HostRead}},
{}, {})
.end();
queue().submit({SubmitInfo{}.setCommandBuffers({cmd})}).wait();
CORRADE_COMPARE(arrayView(a.dedicatedMemory().mapRead()), "0123........cdef"_s);
/* Test the full fill as well */
pool.reset();
cmd.begin()
.fillBuffer(a, 0x2e2e2e2e)
.pipelineBarrier(
PipelineStage::Transfer, PipelineStage::Host,
{{Access::TransferWrite, Access::HostRead}},
{}, {})
.end();
queue().submit({SubmitInfo{}.setCommandBuffers({cmd})}).wait();
CORRADE_COMPARE(arrayView(a.dedicatedMemory().mapRead()), "................"_s);
}
}}}} }}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::BufferVkTest) CORRADE_TEST_MAIN(Magnum::Vk::Test::BufferVkTest)

Loading…
Cancel
Save