Vulkan: Handle CopyBufferToBuffer commands
This as this is the first command handled by the Vulkan backend, this commit also introduces the b:✌️:CommandBUffer class and implements b:✌️:Queue::Submit. Also enables the BufferSetSubData tests that are now passing on Vulkan even though the buffer transitions are unimplemented.
This commit is contained in:
parent
a9b98af710
commit
77a1d908b6
|
@ -293,6 +293,8 @@ if (NXT_ENABLE_VULKAN)
|
|||
${VULKAN_DIR}/BufferUploader.h
|
||||
${VULKAN_DIR}/BufferVk.cpp
|
||||
${VULKAN_DIR}/BufferVk.h
|
||||
${VULKAN_DIR}/CommandBufferVk.cpp
|
||||
${VULKAN_DIR}/CommandBufferVk.h
|
||||
${VULKAN_DIR}/FencedDeleter.cpp
|
||||
${VULKAN_DIR}/FencedDeleter.h
|
||||
${VULKAN_DIR}/MemoryAllocator.cpp
|
||||
|
|
|
@ -168,6 +168,7 @@ namespace backend {
|
|||
|
||||
// This needs to be called before the CommandIterator is freed so that the Ref<> present in
|
||||
// the commands have a chance to run their destructor and remove internal references.
|
||||
class CommandIterator;
|
||||
void FreeCommands(CommandIterator* commands);
|
||||
void SkipCommand(CommandIterator* commands, Command type);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace backend { namespace d3d12 {
|
|||
Device* mDevice;
|
||||
CommandIterator mCommands;
|
||||
};
|
||||
|
||||
}} // namespace backend::d3d12
|
||||
|
||||
#endif // BACKEND_D3D12_COMMANDBUFFERD3D12_H_
|
||||
|
|
|
@ -102,6 +102,10 @@ namespace backend { namespace vulkan {
|
|||
CallMapReadCallback(mapSerial, NXT_BUFFER_MAP_READ_STATUS_SUCCESS, data);
|
||||
}
|
||||
|
||||
VkBuffer Buffer::GetHandle() const {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) {
|
||||
BufferUploader* uploader = ToBackend(GetDevice())->GetBufferUploader();
|
||||
uploader->BufferSubData(mHandle, start * sizeof(uint32_t), count * sizeof(uint32_t), data);
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace backend { namespace vulkan {
|
|||
|
||||
void OnMapReadCommandSerialFinished(uint32_t mapSerial, const void* data);
|
||||
|
||||
VkBuffer GetHandle() const;
|
||||
|
||||
private:
|
||||
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override;
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2017 The NXT Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "backend/vulkan/CommandBufferVk.h"
|
||||
|
||||
#include "backend/Commands.h"
|
||||
#include "backend/vulkan/BufferVk.h"
|
||||
#include "backend/vulkan/VulkanBackend.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace backend { namespace vulkan {
|
||||
|
||||
CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
|
||||
: CommandBufferBase(builder), mCommands(builder->AcquireCommands()) {
|
||||
}
|
||||
|
||||
CommandBuffer::~CommandBuffer() {
|
||||
FreeCommands(&mCommands);
|
||||
}
|
||||
|
||||
void CommandBuffer::RecordCommands(VkCommandBuffer commands) {
|
||||
Device* device = ToBackend(GetDevice());
|
||||
|
||||
Command type;
|
||||
while (mCommands.NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::CopyBufferToBuffer: {
|
||||
CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
|
||||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
|
||||
VkBufferCopy region;
|
||||
region.srcOffset = src.offset;
|
||||
region.dstOffset = dst.offset;
|
||||
region.size = copy->size;
|
||||
|
||||
VkBuffer srcHandle = ToBackend(src.buffer)->GetHandle();
|
||||
VkBuffer dstHandle = ToBackend(dst.buffer)->GetHandle();
|
||||
device->fn.CmdCopyBuffer(commands, srcHandle, dstHandle, 1, ®ion);
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage: {
|
||||
SkipCommand(&mCommands, type);
|
||||
} break;
|
||||
|
||||
default: { UNREACHABLE(); } break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace backend::vulkan
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2017 The NXT Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BACKEND_VULKAN_COMMANDBUFFERVK_H_
|
||||
#define BACKEND_VULKAN_COMMANDBUFFERVK_H_
|
||||
|
||||
#include "backend/CommandBuffer.h"
|
||||
|
||||
#include "backend/vulkan/vulkan_platform.h"
|
||||
|
||||
namespace backend { namespace vulkan {
|
||||
|
||||
class CommandBuffer : public CommandBufferBase {
|
||||
public:
|
||||
CommandBuffer(CommandBufferBuilder* builder);
|
||||
~CommandBuffer();
|
||||
|
||||
void RecordCommands(VkCommandBuffer commands);
|
||||
|
||||
private:
|
||||
CommandIterator mCommands;
|
||||
};
|
||||
|
||||
}} // namespace backend::vulkan
|
||||
|
||||
#endif // BACKEND_VULKAN_COMMANDBUFFERVK_H_
|
|
@ -13,4 +13,5 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "backend/vulkan/BufferVk.h"
|
||||
#include "backend/vulkan/CommandBufferVk.h"
|
||||
#include "backend/vulkan/VulkanBackend.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "backend/Commands.h"
|
||||
#include "backend/vulkan/BufferUploader.h"
|
||||
#include "backend/vulkan/BufferVk.h"
|
||||
#include "backend/vulkan/CommandBufferVk.h"
|
||||
#include "backend/vulkan/FencedDeleter.h"
|
||||
#include "common/Platform.h"
|
||||
|
||||
|
@ -246,6 +247,11 @@ namespace backend { namespace vulkan {
|
|||
|
||||
if (mPendingCommands.pool != VK_NULL_HANDLE) {
|
||||
SubmitPendingCommands();
|
||||
} else if (mCompletedSerial == mNextSerial - 1) {
|
||||
// If there's no GPU work in flight we still need to artificially increment the serial
|
||||
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
||||
mCompletedSerial++;
|
||||
mNextSerial++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -584,7 +590,15 @@ namespace backend { namespace vulkan {
|
|||
Queue::~Queue() {
|
||||
}
|
||||
|
||||
void Queue::Submit(uint32_t, CommandBuffer* const*) {
|
||||
void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
|
||||
Device* device = ToBackend(GetDevice());
|
||||
|
||||
VkCommandBuffer commandBuffer = device->GetPendingCommandBuffer();
|
||||
for (uint32_t i = 0; i < numCommands; ++i) {
|
||||
commands[i]->RecordCommands(commandBuffer);
|
||||
}
|
||||
|
||||
device->SubmitPendingCommands();
|
||||
}
|
||||
|
||||
// Texture
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "backend/BindGroup.h"
|
||||
#include "backend/BindGroupLayout.h"
|
||||
#include "backend/BlendState.h"
|
||||
#include "backend/CommandBuffer.h"
|
||||
#include "backend/ComputePipeline.h"
|
||||
#include "backend/DepthStencilState.h"
|
||||
#include "backend/Device.h"
|
||||
|
@ -50,7 +49,7 @@ namespace backend { namespace vulkan {
|
|||
using BlendState = BlendStateBase;
|
||||
class Buffer;
|
||||
using BufferView = BufferViewBase;
|
||||
using CommandBuffer = CommandBufferBase;
|
||||
class CommandBuffer;
|
||||
using ComputePipeline = ComputePipelineBase;
|
||||
using DepthStencilState = DepthStencilStateBase;
|
||||
class Device;
|
||||
|
|
|
@ -136,10 +136,10 @@ TEST_P(BufferSetSubDataTests, SmallDataAtOffset) {
|
|||
|
||||
// Stress test for many calls to SetSubData
|
||||
TEST_P(BufferSetSubDataTests, ManySetSubData) {
|
||||
if (IsD3D12() || IsMetal()) {
|
||||
if (IsD3D12() || IsMetal() || IsVulkan()) {
|
||||
// TODO(cwallez@chromium.org): Use ringbuffers for SetSubData on explicit APIs.
|
||||
// otherwise this creates too many resources and can take freeze the driver(?)
|
||||
std::cout << "Test skipped on D3D12 and Metal" << std::endl;
|
||||
std::cout << "Test skipped on D3D12, Metal and Vulkan" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -180,4 +180,8 @@ TEST_P(BufferSetSubDataTests, LargeSetSubData) {
|
|||
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), buffer, 0, kElements);
|
||||
}
|
||||
|
||||
NXT_INSTANTIATE_TEST(BufferSetSubDataTests, D3D12Backend, MetalBackend, OpenGLBackend)
|
||||
NXT_INSTANTIATE_TEST(BufferSetSubDataTests,
|
||||
D3D12Backend,
|
||||
MetalBackend,
|
||||
OpenGLBackend,
|
||||
VulkanBackend)
|
||||
|
|
Loading…
Reference in New Issue