null backend: fix resource usage after cmdbuf transition (#63)
and test it.
This commit is contained in:
parent
fa37f2239c
commit
794d4faece
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "backend/null/NullBackend.h"
|
#include "backend/null/NullBackend.h"
|
||||||
|
|
||||||
|
#include "backend/Commands.h"
|
||||||
|
|
||||||
#include <spirv-cross/spirv_cross.hpp>
|
#include <spirv-cross/spirv_cross.hpp>
|
||||||
|
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
@ -36,46 +38,46 @@ namespace null {
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
|
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
|
||||||
return new BindGroupBase(builder);
|
return new BindGroup(builder);
|
||||||
}
|
}
|
||||||
BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) {
|
BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) {
|
||||||
return new BindGroupLayoutBase(builder);
|
return new BindGroupLayout(builder);
|
||||||
}
|
}
|
||||||
BufferBase* Device::CreateBuffer(BufferBuilder* builder) {
|
BufferBase* Device::CreateBuffer(BufferBuilder* builder) {
|
||||||
return new Buffer(builder);
|
return new Buffer(builder);
|
||||||
}
|
}
|
||||||
BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) {
|
BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) {
|
||||||
return new BufferViewBase(builder);
|
return new BufferView(builder);
|
||||||
}
|
}
|
||||||
CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) {
|
CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) {
|
||||||
return new CommandBufferBase(builder);
|
return new CommandBuffer(builder);
|
||||||
}
|
}
|
||||||
DepthStencilStateBase* Device::CreateDepthStencilState(DepthStencilStateBuilder* builder) {
|
DepthStencilStateBase* Device::CreateDepthStencilState(DepthStencilStateBuilder* builder) {
|
||||||
return new DepthStencilStateBase(builder);
|
return new DepthStencilState(builder);
|
||||||
}
|
}
|
||||||
InputStateBase* Device::CreateInputState(InputStateBuilder* builder) {
|
InputStateBase* Device::CreateInputState(InputStateBuilder* builder) {
|
||||||
return new InputStateBase(builder);
|
return new InputState(builder);
|
||||||
}
|
}
|
||||||
FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) {
|
FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) {
|
||||||
return new FramebufferBase(builder);
|
return new Framebuffer(builder);
|
||||||
}
|
}
|
||||||
PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) {
|
PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) {
|
||||||
return new PipelineBase(builder);
|
return new Pipeline(builder);
|
||||||
}
|
}
|
||||||
PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) {
|
PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) {
|
||||||
return new PipelineLayoutBase(builder);
|
return new PipelineLayout(builder);
|
||||||
}
|
}
|
||||||
QueueBase* Device::CreateQueue(QueueBuilder* builder) {
|
QueueBase* Device::CreateQueue(QueueBuilder* builder) {
|
||||||
return new Queue(builder);
|
return new Queue(builder);
|
||||||
}
|
}
|
||||||
RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) {
|
RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) {
|
||||||
return new RenderPassBase(builder);
|
return new RenderPass(builder);
|
||||||
}
|
}
|
||||||
SamplerBase* Device::CreateSampler(SamplerBuilder* builder) {
|
SamplerBase* Device::CreateSampler(SamplerBuilder* builder) {
|
||||||
return new SamplerBase(builder);
|
return new Sampler(builder);
|
||||||
}
|
}
|
||||||
ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) {
|
ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) {
|
||||||
auto module = new ShaderModuleBase(builder);
|
auto module = new ShaderModule(builder);
|
||||||
|
|
||||||
spirv_cross::Compiler compiler(builder->AcquireSpirv());
|
spirv_cross::Compiler compiler(builder->AcquireSpirv());
|
||||||
module->ExtractSpirvInfo(compiler);
|
module->ExtractSpirvInfo(compiler);
|
||||||
|
@ -86,7 +88,7 @@ namespace null {
|
||||||
return new Texture(builder);
|
return new Texture(builder);
|
||||||
}
|
}
|
||||||
TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) {
|
TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) {
|
||||||
return new TextureViewBase(builder);
|
return new TextureView(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::TickImpl() {
|
void Device::TickImpl() {
|
||||||
|
@ -155,6 +157,39 @@ namespace null {
|
||||||
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) {
|
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<TransitionBufferUsageCmd>();
|
||||||
|
cmd->buffer->UpdateUsageInternal(cmd->usage);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Command::TransitionTextureUsage:
|
||||||
|
{
|
||||||
|
TransitionTextureUsageCmd* cmd = commands.NextCommand<TransitionTextureUsageCmd>();
|
||||||
|
cmd->texture->UpdateUsageInternal(cmd->usage);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkipCommand(&commands, type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Queue
|
// Queue
|
||||||
|
|
||||||
Queue::Queue(QueueBuilder* builder)
|
Queue::Queue(QueueBuilder* builder)
|
||||||
|
@ -171,6 +206,10 @@ namespace null {
|
||||||
operation->Execute();
|
operation->Execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numCommands; ++i) {
|
||||||
|
commands[i]->Execute();
|
||||||
|
}
|
||||||
|
|
||||||
operations.clear();
|
operations.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace null {
|
||||||
using BindGroupLayout = BindGroupLayoutBase;
|
using BindGroupLayout = BindGroupLayoutBase;
|
||||||
class Buffer;
|
class Buffer;
|
||||||
using BufferView = BufferViewBase;
|
using BufferView = BufferViewBase;
|
||||||
using CommandBuffer = CommandBufferBase;
|
class CommandBuffer;
|
||||||
using DepthStencilState = DepthStencilStateBase;
|
using DepthStencilState = DepthStencilStateBase;
|
||||||
class Device;
|
class Device;
|
||||||
using InputState = InputStateBase;
|
using InputState = InputStateBase;
|
||||||
|
@ -136,6 +136,17 @@ namespace null {
|
||||||
std::unique_ptr<char[]> backingData;
|
std::unique_ptr<char[]> backingData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CommandBuffer : public CommandBufferBase {
|
||||||
|
public:
|
||||||
|
CommandBuffer(CommandBufferBuilder* builder);
|
||||||
|
~CommandBuffer();
|
||||||
|
|
||||||
|
void Execute();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CommandIterator commands;
|
||||||
|
};
|
||||||
|
|
||||||
class Queue : public QueueBase {
|
class Queue : public QueueBase {
|
||||||
public:
|
public:
|
||||||
Queue(QueueBuilder* builder);
|
Queue(QueueBuilder* builder);
|
||||||
|
|
|
@ -36,6 +36,7 @@ add_executable(nxt_unittests
|
||||||
${VALIDATION_TESTS_DIR}/FramebufferValidationTests.cpp
|
${VALIDATION_TESTS_DIR}/FramebufferValidationTests.cpp
|
||||||
${VALIDATION_TESTS_DIR}/InputStateValidationTests.cpp
|
${VALIDATION_TESTS_DIR}/InputStateValidationTests.cpp
|
||||||
${VALIDATION_TESTS_DIR}/RenderPassValidationTests.cpp
|
${VALIDATION_TESTS_DIR}/RenderPassValidationTests.cpp
|
||||||
|
${VALIDATION_TESTS_DIR}/UsageValidationTests.cpp
|
||||||
${VALIDATION_TESTS_DIR}/ValidationTest.cpp
|
${VALIDATION_TESTS_DIR}/ValidationTest.cpp
|
||||||
${VALIDATION_TESTS_DIR}/ValidationTest.h
|
${VALIDATION_TESTS_DIR}/ValidationTest.h
|
||||||
${TESTS_DIR}/UnittestsMain.cpp
|
${TESTS_DIR}/UnittestsMain.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 <gmock/gmock.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
Loading…
Reference in New Issue