diff --git a/src/backend/null/NullBackend.cpp b/src/backend/null/NullBackend.cpp index 397e4b420b..b5d5b083fd 100644 --- a/src/backend/null/NullBackend.cpp +++ b/src/backend/null/NullBackend.cpp @@ -14,6 +14,8 @@ #include "backend/null/NullBackend.h" +#include "backend/Commands.h" + #include namespace backend { @@ -36,46 +38,46 @@ namespace null { } BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) { - return new BindGroupBase(builder); + return new BindGroup(builder); } BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) { - return new BindGroupLayoutBase(builder); + return new BindGroupLayout(builder); } BufferBase* Device::CreateBuffer(BufferBuilder* builder) { return new Buffer(builder); } BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) { - return new BufferViewBase(builder); + return new BufferView(builder); } CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBufferBase(builder); + return new CommandBuffer(builder); } DepthStencilStateBase* Device::CreateDepthStencilState(DepthStencilStateBuilder* builder) { - return new DepthStencilStateBase(builder); + return new DepthStencilState(builder); } InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { - return new InputStateBase(builder); + return new InputState(builder); } FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) { - return new FramebufferBase(builder); + return new Framebuffer(builder); } PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) { - return new PipelineBase(builder); + return new Pipeline(builder); } PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { - return new PipelineLayoutBase(builder); + return new PipelineLayout(builder); } QueueBase* Device::CreateQueue(QueueBuilder* builder) { return new Queue(builder); } RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) { - return new RenderPassBase(builder); + return new RenderPass(builder); } SamplerBase* Device::CreateSampler(SamplerBuilder* builder) { - return new SamplerBase(builder); + return new Sampler(builder); } ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) { - auto module = new ShaderModuleBase(builder); + auto module = new ShaderModule(builder); spirv_cross::Compiler compiler(builder->AcquireSpirv()); module->ExtractSpirvInfo(compiler); @@ -86,7 +88,7 @@ namespace null { return new Texture(builder); } TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) { - return new TextureViewBase(builder); + return new TextureView(builder); } void Device::TickImpl() { @@ -155,6 +157,39 @@ namespace null { void Buffer::TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) { } + // CommandBuffer + + CommandBuffer::CommandBuffer(CommandBufferBuilder* builder) + : CommandBufferBase(builder), commands(builder->AcquireCommands()) { + } + + CommandBuffer::~CommandBuffer() { + FreeCommands(&commands); + } + + void CommandBuffer::Execute() { + Command type; + while (commands.NextCommandId(&type)) { + switch (type) { + case Command::TransitionBufferUsage: + { + TransitionBufferUsageCmd* cmd = commands.NextCommand(); + cmd->buffer->UpdateUsageInternal(cmd->usage); + } + break; + case Command::TransitionTextureUsage: + { + TransitionTextureUsageCmd* cmd = commands.NextCommand(); + cmd->texture->UpdateUsageInternal(cmd->usage); + } + break; + default: + SkipCommand(&commands, type); + break; + } + } + } + // Queue Queue::Queue(QueueBuilder* builder) @@ -171,6 +206,10 @@ namespace null { operation->Execute(); } + for (uint32_t i = 0; i < numCommands; ++i) { + commands[i]->Execute(); + } + operations.clear(); } diff --git a/src/backend/null/NullBackend.h b/src/backend/null/NullBackend.h index 0c5ea7b4df..2701bbc1fd 100644 --- a/src/backend/null/NullBackend.h +++ b/src/backend/null/NullBackend.h @@ -41,7 +41,7 @@ namespace null { using BindGroupLayout = BindGroupLayoutBase; class Buffer; using BufferView = BufferViewBase; - using CommandBuffer = CommandBufferBase; + class CommandBuffer; using DepthStencilState = DepthStencilStateBase; class Device; using InputState = InputStateBase; @@ -136,6 +136,17 @@ namespace null { std::unique_ptr backingData; }; + class CommandBuffer : public CommandBufferBase { + public: + CommandBuffer(CommandBufferBuilder* builder); + ~CommandBuffer(); + + void Execute(); + + private: + CommandIterator commands; + }; + class Queue : public QueueBase { public: Queue(QueueBuilder* builder); diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 6eb9ab35d1..8d5b0f4299 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -36,6 +36,7 @@ add_executable(nxt_unittests ${VALIDATION_TESTS_DIR}/FramebufferValidationTests.cpp ${VALIDATION_TESTS_DIR}/InputStateValidationTests.cpp ${VALIDATION_TESTS_DIR}/RenderPassValidationTests.cpp + ${VALIDATION_TESTS_DIR}/UsageValidationTests.cpp ${VALIDATION_TESTS_DIR}/ValidationTest.cpp ${VALIDATION_TESTS_DIR}/ValidationTest.h ${TESTS_DIR}/UnittestsMain.cpp diff --git a/src/tests/unittests/validation/UsageValidationTests.cpp b/src/tests/unittests/validation/UsageValidationTests.cpp new file mode 100644 index 0000000000..6f58b95809 --- /dev/null +++ b/src/tests/unittests/validation/UsageValidationTests.cpp @@ -0,0 +1,56 @@ +// 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 "tests/unittests/validation/ValidationTest.h" + +#include + +using namespace testing; + +class UsageValidationTest : public ValidationTest { + protected: + nxt::Queue queue; + + private: + void SetUp() override { + ValidationTest::SetUp(); + queue = device.CreateQueueBuilder().GetResult(); + } +}; + +// Test that command buffer submit changes buffer usage +TEST_F(UsageValidationTest, UsageAfterCommandBuffer) { + // TODO(kainino@chromium.org): This needs to be tested on every backend. + // Should we make an end2end test that tests this as well? + + nxt::Buffer buf = device.CreateBufferBuilder() + .SetSize(4) + .SetAllowedUsage(nxt::BufferUsageBit::TransferDst | nxt::BufferUsageBit::Vertex) + .SetInitialUsage(nxt::BufferUsageBit::TransferDst) + .GetResult(); + + uint32_t foo = 0; + buf.SetSubData(0, 1, &foo); + + buf.TransitionUsage(nxt::BufferUsageBit::Vertex); + ASSERT_DEVICE_ERROR(buf.SetSubData(0, 1, &foo)); + + nxt::CommandBuffer cmdbuf = device.CreateCommandBufferBuilder() + .TransitionBufferUsage(buf, nxt::BufferUsageBit::TransferDst) + .GetResult(); + queue.Submit(1, &cmdbuf); + // buf should be in TransferDst usage + + buf.SetSubData(0, 1, &foo); +}