Implement GPUCompilationInfo

Implements the GPUCompilationInfo and GPUCompilationMessage interfaces,
adds the GPUCompilationMessageType enum, and adds the compilationInfo
method to GPUShaderModule.

BUG: dawn:746
Change-Id: Ied70cbbfedbf4890916ec076993714e5042f70e4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/46600
Commit-Queue: Brandon Jones <bajones@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Brandon Jones
2021-04-05 23:34:17 +00:00
committed by Commit Bot service account
parent 68c226db43
commit 6f2bbe9896
18 changed files with 494 additions and 5 deletions

View File

@@ -194,6 +194,8 @@ source_set("dawn_native_sources") {
"CommandValidation.h",
"Commands.cpp",
"Commands.h",
"CompilationMessages.cpp",
"CompilationMessages.h",
"ComputePassEncoder.cpp",
"ComputePassEncoder.h",
"ComputePipeline.cpp",

View File

@@ -62,6 +62,8 @@ target_sources(dawn_native PRIVATE
"CommandValidation.h"
"Commands.cpp"
"Commands.h"
"CompilationMessages.cpp",
"CompilationMessages.h",
"ComputePassEncoder.cpp"
"ComputePassEncoder.h"
"ComputePipeline.cpp"

View File

@@ -0,0 +1,98 @@
// Copyright 2021 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 "dawn_native/CompilationMessages.h"
#include "common/Assert.h"
#include "dawn_native/dawn_platform.h"
#include <tint/tint.h>
namespace dawn_native {
namespace {
WGPUCompilationMessageType tintSeverityToMessageType(tint::diag::Severity severity) {
switch (severity) {
case tint::diag::Severity::Note:
return WGPUCompilationMessageType_Info;
case tint::diag::Severity::Warning:
return WGPUCompilationMessageType_Warning;
default:
return WGPUCompilationMessageType_Error;
}
}
} // anonymous namespace
OwnedCompilationMessages::OwnedCompilationMessages() {
mCompilationInfo.messageCount = 0;
mCompilationInfo.messages = nullptr;
}
void OwnedCompilationMessages::AddMessage(std::string message,
wgpu::CompilationMessageType type,
uint64_t lineNum,
uint64_t linePos) {
// Cannot add messages after GetCompilationInfo has been called.
ASSERT(mCompilationInfo.messages == nullptr);
mMessageStrings.push_back(message);
mMessages.push_back(
{nullptr, static_cast<WGPUCompilationMessageType>(type), lineNum, linePos});
}
void OwnedCompilationMessages::AddMessage(const tint::diag::Diagnostic& diagnostic) {
// Cannot add messages after GetCompilationInfo has been called.
ASSERT(mCompilationInfo.messages == nullptr);
mMessageStrings.push_back(diagnostic.message);
mMessages.push_back({nullptr, tintSeverityToMessageType(diagnostic.severity),
diagnostic.source.range.begin.line,
diagnostic.source.range.begin.column});
}
void OwnedCompilationMessages::AddMessages(const tint::diag::List& diagnostics) {
// Cannot add messages after GetCompilationInfo has been called.
ASSERT(mCompilationInfo.messages == nullptr);
for (const auto& diag : diagnostics) {
AddMessage(diag);
}
}
void OwnedCompilationMessages::ClearMessages() {
// Cannot clear messages after GetCompilationInfo has been called.
ASSERT(mCompilationInfo.messages == nullptr);
mMessageStrings.clear();
mMessages.clear();
}
const WGPUCompilationInfo* OwnedCompilationMessages::GetCompilationInfo() {
mCompilationInfo.messageCount = mMessages.size();
mCompilationInfo.messages = mMessages.data();
// Ensure every message points at the correct message string. Cannot do this earlier, since
// vector reallocations may move the pointers around.
for (size_t i = 0; i < mCompilationInfo.messageCount; ++i) {
WGPUCompilationMessage& message = mMessages[i];
std::string& messageString = mMessageStrings[i];
message.message = messageString.c_str();
}
return &mCompilationInfo;
}
} // namespace dawn_native

View File

@@ -0,0 +1,55 @@
// Copyright 2021 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.
#ifndef DAWNNATIVE_COMPILATIONMESSAGES_H_
#define DAWNNATIVE_COMPILATIONMESSAGES_H_
#include "dawn_native/dawn_platform.h"
#include "common/NonCopyable.h"
#include <string>
#include <vector>
namespace tint { namespace diag {
class Diagnostic;
class List;
}} // namespace tint::diag
namespace dawn_native {
class OwnedCompilationMessages : public NonCopyable {
public:
OwnedCompilationMessages();
~OwnedCompilationMessages() = default;
void AddMessage(std::string message,
wgpu::CompilationMessageType type = wgpu::CompilationMessageType::Info,
uint64_t lineNum = 0,
uint64_t linePos = 0);
void AddMessage(const tint::diag::Diagnostic& diagnostic);
void AddMessages(const tint::diag::List& diagnostics);
void ClearMessages();
const WGPUCompilationInfo* GetCompilationInfo();
private:
WGPUCompilationInfo mCompilationInfo;
std::vector<std::string> mMessageStrings;
std::vector<WGPUCompilationMessage> mMessages;
};
} // namespace dawn_native
#endif // DAWNNATIVE_COMPILATIONMESSAGES_H_

View File

@@ -16,6 +16,7 @@
#include "common/VertexFormatUtils.h"
#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/CompilationMessages.h"
#include "dawn_native/Device.h"
#include "dawn_native/ObjectContentHasher.h"
#include "dawn_native/Pipeline.h"
@@ -1195,7 +1196,9 @@ namespace dawn_native {
// ShaderModuleBase
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
: CachedObject(device), mType(Type::Undefined) {
: CachedObject(device),
mType(Type::Undefined),
mCompilationMessages(std::make_unique<OwnedCompilationMessages>()) {
ASSERT(descriptor->nextInChain != nullptr);
switch (descriptor->nextInChain->sType) {
case wgpu::SType::ShaderModuleSPIRVDescriptor: {
@@ -1218,7 +1221,9 @@ namespace dawn_native {
}
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: CachedObject(device, tag), mType(Type::Undefined) {
: CachedObject(device, tag),
mType(Type::Undefined),
mCompilationMessages(std::make_unique<OwnedCompilationMessages>()) {
}
ShaderModuleBase::~ShaderModuleBase() {
@@ -1265,6 +1270,16 @@ namespace dawn_native {
return mTintProgram.get();
}
void ShaderModuleBase::APIGetCompilationInfo(wgpu::CompilationInfoCallback callback,
void* userdata) {
if (callback == nullptr) {
return;
}
callback(WGPUCompilationInfoRequestStatus_Success,
mCompilationMessages->GetCompilationInfo(), userdata);
}
ResultOrError<std::vector<uint32_t>> ShaderModuleBase::GeneratePullingSpirv(
const std::vector<uint32_t>& spirv,
const VertexState& vertexState,

View File

@@ -48,6 +48,7 @@ namespace spirv_cross {
namespace dawn_native {
class OwnedCompilationMessages;
struct EntryPointMetadata;
// A map from name to EntryPointMetadata.
@@ -143,6 +144,8 @@ namespace dawn_native {
const std::vector<uint32_t>& GetSpirv() const;
const tint::Program* GetTintProgram() const;
void APIGetCompilationInfo(wgpu::CompilationInfoCallback callback, void* userdata);
ResultOrError<std::vector<uint32_t>> GeneratePullingSpirv(
const std::vector<uint32_t>& spirv,
const VertexState& vertexState,
@@ -155,6 +158,10 @@ namespace dawn_native {
const std::string& entryPoint,
BindGroupIndex pullingBufferBindingSet) const;
OwnedCompilationMessages* CompilationMessages() {
return mCompilationMessages.get();
}
protected:
MaybeError InitializeBase(ShaderModuleParseResult* parseResult);
static ResultOrError<EntryPointMetadataTable> ReflectShaderUsingSPIRVCross(
@@ -175,6 +182,8 @@ namespace dawn_native {
EntryPointMetadataTable mEntryPoints;
std::vector<uint32_t> mSpirv;
std::unique_ptr<tint::Program> mTintProgram;
std::unique_ptr<OwnedCompilationMessages> mCompilationMessages;
};
} // namespace dawn_native

View File

@@ -85,6 +85,8 @@ dawn_component("dawn_wire") {
"client/ObjectAllocator.h",
"client/Queue.cpp",
"client/Queue.h",
"client/ShaderModule.cpp",
"client/ShaderModule.h",
"server/ObjectStorage.h",
"server/Server.cpp",
"server/Server.h",
@@ -93,6 +95,7 @@ dawn_component("dawn_wire") {
"server/ServerFence.cpp",
"server/ServerInlineMemoryTransferService.cpp",
"server/ServerQueue.cpp",
"server/ServerShaderModule.cpp",
]
# Make headers publicly visible

View File

@@ -57,6 +57,8 @@ target_sources(dawn_wire PRIVATE
"client/ObjectAllocator.h"
"client/Queue.cpp"
"client/Queue.h"
"client/ShaderModule.cpp"
"client/ShaderModule.h"
"server/ObjectStorage.h"
"server/Server.cpp"
"server/Server.h"
@@ -65,6 +67,7 @@ target_sources(dawn_wire PRIVATE
"server/ServerFence.cpp"
"server/ServerInlineMemoryTransferService.cpp"
"server/ServerQueue.cpp"
"server/ServerShaderModule.cpp"
)
target_link_libraries(dawn_wire
PUBLIC dawn_headers

View File

@@ -21,6 +21,7 @@
#include "dawn_wire/client/Device.h"
#include "dawn_wire/client/Fence.h"
#include "dawn_wire/client/Queue.h"
#include "dawn_wire/client/ShaderModule.h"
#include "dawn_wire/client/ApiObjects_autogen.h"

View File

@@ -122,4 +122,15 @@ namespace dawn_wire { namespace client {
return device->OnCreateRenderPipelineAsyncCallback(requestSerial, status, message);
}
bool Client::DoShaderModuleGetCompilationInfoCallback(ShaderModule* shaderModule,
uint64_t requestSerial,
WGPUCompilationInfoRequestStatus status,
const WGPUCompilationInfo* info) {
// The shader module might have been deleted or recreated so this isn't an error.
if (shaderModule == nullptr) {
return true;
}
return shaderModule->GetCompilationInfoCallback(requestSerial, status, info);
}
}} // namespace dawn_wire::client

View File

@@ -0,0 +1,66 @@
// Copyright 2021 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 "dawn_wire/client/ShaderModule.h"
#include "dawn_wire/client/Client.h"
namespace dawn_wire { namespace client {
ShaderModule::~ShaderModule() {
// Callbacks need to be fired in all cases, as they can handle freeing resources. So we call
// them with "Unknown" status.
for (auto& it : mCompilationInfoRequests) {
if (it.second.callback) {
it.second.callback(WGPUCompilationInfoRequestStatus_Unknown, nullptr,
it.second.userdata);
}
}
mCompilationInfoRequests.clear();
}
void ShaderModule::GetCompilationInfo(WGPUCompilationInfoCallback callback, void* userdata) {
if (client->IsDisconnected()) {
callback(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, userdata);
return;
}
uint64_t serial = mCompilationInfoRequestSerial++;
ShaderModuleGetCompilationInfoCmd cmd;
cmd.shaderModuleId = this->id;
cmd.requestSerial = serial;
mCompilationInfoRequests[serial] = {callback, userdata};
client->SerializeCommand(cmd);
}
bool ShaderModule::GetCompilationInfoCallback(uint64_t requestSerial,
WGPUCompilationInfoRequestStatus status,
const WGPUCompilationInfo* info) {
auto requestIt = mCompilationInfoRequests.find(requestSerial);
if (requestIt == mCompilationInfoRequests.end()) {
return false;
}
// Remove the request data so that the callback cannot be called again.
// ex.) inside the callback: if the shader module is deleted, all callbacks reject.
CompilationInfoRequest request = std::move(requestIt->second);
mCompilationInfoRequests.erase(requestIt);
request.callback(status, info, request.userdata);
return true;
}
}} // namespace dawn_wire::client

View File

@@ -0,0 +1,46 @@
// Copyright 2021 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.
#ifndef DAWNWIRE_CLIENT_SHADER_MODULE_H_
#define DAWNWIRE_CLIENT_SHADER_MODULE_H_
#include <dawn/webgpu.h>
#include "common/SerialMap.h"
#include "dawn_wire/client/ObjectBase.h"
namespace dawn_wire { namespace client {
class ShaderModule final : public ObjectBase {
public:
using ObjectBase::ObjectBase;
~ShaderModule();
void GetCompilationInfo(WGPUCompilationInfoCallback callback, void* userdata);
bool GetCompilationInfoCallback(uint64_t requestSerial,
WGPUCompilationInfoRequestStatus status,
const WGPUCompilationInfo* info);
private:
struct CompilationInfoRequest {
WGPUCompilationInfoCallback callback = nullptr;
void* userdata = nullptr;
};
uint64_t mCompilationInfoRequestSerial = 0;
std::map<uint64_t, CompilationInfoRequest> mCompilationInfoRequests;
};
}} // namespace dawn_wire::client
#endif // DAWNWIRE_CLIENT_SHADER_MODULE_H_

View File

@@ -141,6 +141,13 @@ namespace dawn_wire { namespace server {
uint64_t requestSerial;
};
struct ShaderModuleGetCompilationInfoUserdata : CallbackUserdata {
using CallbackUserdata::CallbackUserdata;
ObjectHandle shaderModule;
uint64_t requestSerial;
};
struct QueueWorkDoneUserdata : CallbackUserdata {
using CallbackUserdata::CallbackUserdata;
@@ -218,6 +225,9 @@ namespace dawn_wire { namespace server {
WGPURenderPipeline pipeline,
const char* message,
CreatePipelineAsyncUserData* userdata);
void OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
const WGPUCompilationInfo* info,
ShaderModuleGetCompilationInfoUserdata* userdata);
#include "dawn_wire/server/ServerPrototypes_autogen.inc"

View File

@@ -0,0 +1,51 @@
// Copyright 2021 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 "dawn_wire/server/Server.h"
#include <memory>
namespace dawn_wire { namespace server {
bool Server::DoShaderModuleGetCompilationInfo(ObjectId shaderModuleId, uint64_t requestSerial) {
auto* shaderModule = ShaderModuleObjects().Get(shaderModuleId);
if (shaderModule == nullptr) {
return false;
}
auto userdata = MakeUserdata<ShaderModuleGetCompilationInfoUserdata>();
userdata->shaderModule = ObjectHandle{shaderModuleId, shaderModule->generation};
userdata->requestSerial = requestSerial;
mProcs.shaderModuleGetCompilationInfo(
shaderModule->handle,
ForwardToServer<decltype(&Server::OnShaderModuleGetCompilationInfo)>::Func<
&Server::OnShaderModuleGetCompilationInfo>(),
userdata.release());
return true;
}
void Server::OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
const WGPUCompilationInfo* info,
ShaderModuleGetCompilationInfoUserdata* data) {
ReturnShaderModuleGetCompilationInfoCallbackCmd cmd;
cmd.shaderModule = data->shaderModule;
cmd.requestSerial = data->requestSerial;
cmd.status = status;
cmd.info = info;
SerializeCommand(cmd);
}
}} // namespace dawn_wire::server

View File

@@ -14,6 +14,9 @@
#include "common/Constants.h"
#include "dawn_native/CompilationMessages.h"
#include "dawn_native/ShaderModule.h"
#include "tests/unittests/validation/ValidationTest.h"
#include "utils/WGPUHelpers.h"
@@ -153,3 +156,53 @@ TEST_F(ShaderModuleValidationTest, MultisampledArrayTexture) {
ASSERT_DEVICE_ERROR(utils::CreateShaderModuleFromASM(device, shader));
}
// Tests that shader module compilation messages can be queried.
TEST_F(ShaderModuleValidationTest, CompilationMessages) {
// This test works assuming ShaderModule is backed by a dawn_native::ShaderModuleBase, which
// is not the case on the wire.
DAWN_SKIP_TEST_IF(UsesWire());
std::ostringstream stream;
stream << R"([[location(0)]] var<out> fragColor : vec4<f32>;
[[stage(fragment)]] fn main() -> void {
fragColor = vec4<f32>(0.0, 1.0, 0.0, 1.0);
})";
wgpu::ShaderModule shaderModule = utils::CreateShaderModule(device, stream.str().c_str());
dawn_native::ShaderModuleBase* shaderModuleBase =
reinterpret_cast<dawn_native::ShaderModuleBase*>(shaderModule.Get());
shaderModuleBase->CompilationMessages()->ClearMessages();
shaderModuleBase->CompilationMessages()->AddMessage("Info Message");
shaderModuleBase->CompilationMessages()->AddMessage("Warning Message",
wgpu::CompilationMessageType::Warning);
shaderModuleBase->CompilationMessages()->AddMessage("Error Message",
wgpu::CompilationMessageType::Error, 3, 4);
auto callback = [](WGPUCompilationInfoRequestStatus status, const WGPUCompilationInfo* info,
void* userdata) {
ASSERT_EQ(WGPUCompilationInfoRequestStatus_Success, status);
ASSERT_NE(nullptr, info);
ASSERT_EQ(3u, info->messageCount);
const WGPUCompilationMessage* message = &info->messages[0];
ASSERT_STREQ("Info Message", message->message);
ASSERT_EQ(WGPUCompilationMessageType_Info, message->type);
ASSERT_EQ(0u, message->lineNum);
ASSERT_EQ(0u, message->linePos);
message = &info->messages[1];
ASSERT_STREQ("Warning Message", message->message);
ASSERT_EQ(WGPUCompilationMessageType_Warning, message->type);
ASSERT_EQ(0u, message->lineNum);
ASSERT_EQ(0u, message->linePos);
message = &info->messages[2];
ASSERT_STREQ("Error Message", message->message);
ASSERT_EQ(WGPUCompilationMessageType_Error, message->type);
ASSERT_EQ(3u, message->lineNum);
ASSERT_EQ(4u, message->linePos);
};
shaderModule.GetCompilationInfo(callback, nullptr);
}