| // Copyright 2017 The Dawn 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 "common/Assert.h" |
| #include "dawn/dawn.h" |
| #include "dawn_native/DawnNative.h" |
| #include "dawn_native/NullBackend.h" |
| |
| ValidationTest::ValidationTest() { |
| mInstance = std::make_unique<dawn_native::Instance>(); |
| mInstance->DiscoverDefaultAdapters(); |
| |
| std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters(); |
| |
| // Validation tests run against the null backend, find the corresponding adapter |
| bool foundNullAdapter = false; |
| dawn_native::Adapter nullAdapter; |
| for (auto adapter : adapters) { |
| if (adapter.GetBackendType() == dawn_native::BackendType::Null) { |
| nullAdapter = adapter; |
| foundNullAdapter = true; |
| break; |
| } |
| } |
| |
| ASSERT(foundNullAdapter); |
| device = dawn::Device::Acquire(nullAdapter.CreateDevice()); |
| |
| dawnProcTable procs = dawn_native::GetProcs(); |
| dawnSetProcs(&procs); |
| |
| device.SetErrorCallback(ValidationTest::OnDeviceError, static_cast<dawnCallbackUserdata>(reinterpret_cast<uintptr_t>(this))); |
| } |
| |
| ValidationTest::~ValidationTest() { |
| // We need to destroy Dawn objects before setting the procs to null otherwise the dawn*Release |
| // will call a nullptr |
| device = dawn::Device(); |
| dawnSetProcs(nullptr); |
| } |
| |
| void ValidationTest::TearDown() { |
| ASSERT_FALSE(mExpectError); |
| |
| for (auto& expectation : mExpectations) { |
| std::string name = expectation.debugName; |
| if (name.empty()) { |
| name = "<no debug name set>"; |
| } |
| |
| ASSERT_TRUE(expectation.gotStatus) << "Didn't get a status for " << name; |
| |
| ASSERT_NE(DAWN_BUILDER_ERROR_STATUS_UNKNOWN, expectation.status) << "Got unknown status for " << name; |
| |
| bool wasSuccess = expectation.status == DAWN_BUILDER_ERROR_STATUS_SUCCESS; |
| ASSERT_EQ(expectation.expectSuccess, wasSuccess) |
| << "Got wrong status value for " << name |
| << ", status was " << expectation.status << " with \"" << expectation.statusMessage << "\""; |
| } |
| } |
| |
| void ValidationTest::StartExpectDeviceError() { |
| mExpectError = true; |
| mError = false; |
| } |
| bool ValidationTest::EndExpectDeviceError() { |
| mExpectError = false; |
| return mError; |
| } |
| std::string ValidationTest::GetLastDeviceErrorMessage() const { |
| return mDeviceErrorMessage; |
| } |
| |
| dawn::RenderPassDescriptor ValidationTest::CreateSimpleRenderPass() { |
| dawn::TextureDescriptor descriptor; |
| descriptor.dimension = dawn::TextureDimension::e2D; |
| descriptor.size.width = 640; |
| descriptor.size.height = 480; |
| descriptor.size.depth = 1; |
| descriptor.arraySize = 1; |
| descriptor.sampleCount = 1; |
| descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm; |
| descriptor.levelCount = 1; |
| descriptor.usage = dawn::TextureUsageBit::OutputAttachment; |
| |
| auto colorBuffer = device.CreateTexture(&descriptor); |
| auto colorView = colorBuffer.CreateDefaultTextureView(); |
| dawn::RenderPassColorAttachmentDescriptor colorAttachment; |
| colorAttachment.attachment = colorView; |
| colorAttachment.resolveTarget = nullptr; |
| colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f }; |
| colorAttachment.loadOp = dawn::LoadOp::Clear; |
| colorAttachment.storeOp = dawn::StoreOp::Store; |
| return device.CreateRenderPassDescriptorBuilder() |
| .SetColorAttachments(1, &colorAttachment) |
| .GetResult(); |
| } |
| |
| void ValidationTest::OnDeviceError(const char* message, dawnCallbackUserdata userdata) { |
| auto self = reinterpret_cast<ValidationTest*>(static_cast<uintptr_t>(userdata)); |
| self->mDeviceErrorMessage = message; |
| |
| // Skip this one specific error that is raised when a builder is used after it got an error |
| // this is important because we don't want to wrap all creation tests in ASSERT_DEVICE_ERROR. |
| // Yes the error message is misleading. |
| if (self->mDeviceErrorMessage == "Builder cannot be used after GetResult") { |
| return; |
| } |
| |
| ASSERT_TRUE(self->mExpectError) << "Got unexpected device error: " << message; |
| ASSERT_FALSE(self->mError) << "Got two errors in expect block"; |
| self->mError = true; |
| } |
| |
| void ValidationTest::OnBuilderErrorStatus(dawnBuilderErrorStatus status, const char* message, dawn::CallbackUserdata userdata1, dawn::CallbackUserdata userdata2) { |
| auto* self = reinterpret_cast<ValidationTest*>(static_cast<uintptr_t>(userdata1)); |
| size_t index = static_cast<size_t>(userdata2); |
| |
| ASSERT_LT(index, self->mExpectations.size()); |
| |
| auto& expectation = self->mExpectations[index]; |
| ASSERT_FALSE(expectation.gotStatus); |
| expectation.gotStatus = true; |
| expectation.status = status; |
| expectation.statusMessage = message; |
| } |
| |
| ValidationTest::DummyRenderPass ValidationTest::CreateDummyRenderPass() { |
| DummyRenderPass dummy; |
| dummy.width = 400; |
| dummy.height = 400; |
| dummy.attachmentFormat = dawn::TextureFormat::R8G8B8A8Unorm; |
| |
| dawn::TextureDescriptor descriptor; |
| descriptor.dimension = dawn::TextureDimension::e2D; |
| descriptor.size.width = dummy.width; |
| descriptor.size.height = dummy.height; |
| descriptor.size.depth = 1; |
| descriptor.arraySize = 1; |
| descriptor.sampleCount = 1; |
| descriptor.format = dummy.attachmentFormat; |
| descriptor.levelCount = 1; |
| descriptor.usage = dawn::TextureUsageBit::OutputAttachment; |
| dummy.attachment = device.CreateTexture(&descriptor); |
| |
| dawn::TextureView view = dummy.attachment.CreateDefaultTextureView(); |
| dawn::RenderPassColorAttachmentDescriptor colorAttachment; |
| colorAttachment.attachment = view; |
| colorAttachment.resolveTarget = nullptr; |
| colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f }; |
| colorAttachment.loadOp = dawn::LoadOp::Clear; |
| colorAttachment.storeOp = dawn::StoreOp::Store; |
| dummy.renderPass = AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder()) |
| .SetColorAttachments(1, &colorAttachment) |
| .GetResult(); |
| |
| return dummy; |
| } |