diff --git a/dawn.json b/dawn.json index a2aa130c6b..9eecdf63be 100644 --- a/dawn.json +++ b/dawn.json @@ -501,6 +501,49 @@ {"value": 8, "name": "always"} ] }, + "compilation info": { + "category": "structure", + "extensible": false, + "members": [ + {"name": "message count", "type": "uint32_t"}, + {"name": "messages", "type": "compilation message", "annotation": "const*", "length": "message count"} + ] + }, + "compilation info callback": { + "category": "callback", + "args": [ + {"name": "status", "type": "compilation info request status"}, + {"name": "compilation info", "type": "compilation info", "annotation": "const*"}, + {"name": "userdata", "type": "void", "annotation": "*"} + ] + }, + "compilation info request status": { + "category": "enum", + "values": [ + {"value": 0, "name": "success"}, + {"value": 1, "name": "error"}, + {"value": 2, "name": "device lost"}, + {"value": 3, "name": "unknown"} + ] + }, + "compilation message": { + "category": "structure", + "extensible": false, + "members": [ + {"name": "message", "type": "char", "annotation": "const*", "length": "strlen", "optional": true}, + {"name": "type", "type": "compilation message type"}, + {"name": "line num", "type": "uint64_t"}, + {"name": "line pos", "type": "uint64_t"} + ] + }, + "compilation message type": { + "category": "enum", + "values": [ + {"value": 0, "name": "error"}, + {"value": 1, "name": "warning"}, + {"value": 2, "name": "info"} + ] + }, "compute pass descriptor": { "category": "structure", "extensible": true, @@ -1731,7 +1774,16 @@ ] }, "shader module": { - "category": "object" + "category": "object", + "methods": [ + { + "name": "get compilation info", + "args": [ + {"name": "callback", "type": "compilation info callback"}, + {"name": "userdata", "type": "void", "annotation": "*"} + ] + } + ] }, "shader module descriptor": { "category": "structure", diff --git a/dawn_wire.json b/dawn_wire.json index 1732781fbe..a6e39ed9ea 100644 --- a/dawn_wire.json +++ b/dawn_wire.json @@ -83,6 +83,10 @@ {"name": "data size", "type": "uint64_t"}, {"name": "data layout", "type": "texture data layout", "annotation": "const*"}, {"name": "writeSize", "type": "extent 3D", "annotation": "const*"} + ], + "shader module get compilation info": [ + { "name": "shader module id", "type": "ObjectId" }, + { "name": "request serial", "type": "uint64_t" } ] }, "return commands": { @@ -133,6 +137,12 @@ { "name": "queue", "type": "ObjectHandle", "handle_type": "queue" }, { "name": "request serial", "type": "uint64_t" }, { "name": "status", "type": "queue work done status" } + ], + "shader module get compilation info callback": [ + { "name": "shader module", "type": "ObjectHandle", "handle_type": "shader module" }, + { "name": "request serial", "type": "uint64_t" }, + { "name": "status", "type": "compilation info request status" }, + { "name": "info", "type": "compilation info", "annotation": "const*", "optional": true } ] }, "special items": { @@ -153,6 +163,7 @@ "DeviceSetUncapturedErrorCallback", "FenceGetCompletedValue", "FenceOnCompletion", + "ShaderModuleGetCompilationInfo", "QueueOnSubmittedWorkDone", "QueueWriteBuffer", "QueueWriteTexture" @@ -171,7 +182,8 @@ "Buffer", "Device", "Fence", - "Queue" + "Queue", + "ShaderModule" ], "server_custom_pre_handler_commands": [ "BufferDestroy", diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py index 8af22721f6..84a2b99c1a 100644 --- a/generator/dawn_json_generator.py +++ b/generator/dawn_json_generator.py @@ -593,7 +593,7 @@ def as_frontendType(typ): def as_wireType(typ): if typ.category == 'object': return typ.name.CamelCase() + '*' - elif typ.category in ['bitmask', 'enum']: + elif typ.category in ['bitmask', 'enum', 'structure']: return 'WGPU' + typ.name.CamelCase() else: return as_cppType(typ.name) diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn index 284e61f763..803ee30246 100644 --- a/src/dawn_native/BUILD.gn +++ b/src/dawn_native/BUILD.gn @@ -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", diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt index e6039b397d..ab80577f9d 100644 --- a/src/dawn_native/CMakeLists.txt +++ b/src/dawn_native/CMakeLists.txt @@ -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" diff --git a/src/dawn_native/CompilationMessages.cpp b/src/dawn_native/CompilationMessages.cpp new file mode 100644 index 0000000000..310b794405 --- /dev/null +++ b/src/dawn_native/CompilationMessages.cpp @@ -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 + +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(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 diff --git a/src/dawn_native/CompilationMessages.h b/src/dawn_native/CompilationMessages.h new file mode 100644 index 0000000000..02c449d0c0 --- /dev/null +++ b/src/dawn_native/CompilationMessages.h @@ -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 +#include + +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 mMessageStrings; + std::vector mMessages; + }; + +} // namespace dawn_native + +#endif // DAWNNATIVE_COMPILATIONMESSAGES_H_ \ No newline at end of file diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp index de290db641..f8b2980d27 100644 --- a/src/dawn_native/ShaderModule.cpp +++ b/src/dawn_native/ShaderModule.cpp @@ -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()) { 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()) { } 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> ShaderModuleBase::GeneratePullingSpirv( const std::vector& spirv, const VertexState& vertexState, diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h index 2f0096203f..059dee96fc 100644 --- a/src/dawn_native/ShaderModule.h +++ b/src/dawn_native/ShaderModule.h @@ -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& GetSpirv() const; const tint::Program* GetTintProgram() const; + void APIGetCompilationInfo(wgpu::CompilationInfoCallback callback, void* userdata); + ResultOrError> GeneratePullingSpirv( const std::vector& 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 ReflectShaderUsingSPIRVCross( @@ -175,6 +182,8 @@ namespace dawn_native { EntryPointMetadataTable mEntryPoints; std::vector mSpirv; std::unique_ptr mTintProgram; + + std::unique_ptr mCompilationMessages; }; } // namespace dawn_native diff --git a/src/dawn_wire/BUILD.gn b/src/dawn_wire/BUILD.gn index ad72394bb5..4a3f127583 100644 --- a/src/dawn_wire/BUILD.gn +++ b/src/dawn_wire/BUILD.gn @@ -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 diff --git a/src/dawn_wire/CMakeLists.txt b/src/dawn_wire/CMakeLists.txt index 77e96c0b69..b1f9ba4bc2 100644 --- a/src/dawn_wire/CMakeLists.txt +++ b/src/dawn_wire/CMakeLists.txt @@ -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 diff --git a/src/dawn_wire/client/ApiObjects.h b/src/dawn_wire/client/ApiObjects.h index f842d53f46..8ec482a971 100644 --- a/src/dawn_wire/client/ApiObjects.h +++ b/src/dawn_wire/client/ApiObjects.h @@ -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" diff --git a/src/dawn_wire/client/ClientDoers.cpp b/src/dawn_wire/client/ClientDoers.cpp index 2c6e23fbb1..4073baa2ff 100644 --- a/src/dawn_wire/client/ClientDoers.cpp +++ b/src/dawn_wire/client/ClientDoers.cpp @@ -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 diff --git a/src/dawn_wire/client/ShaderModule.cpp b/src/dawn_wire/client/ShaderModule.cpp new file mode 100644 index 0000000000..97e0204c92 --- /dev/null +++ b/src/dawn_wire/client/ShaderModule.cpp @@ -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 diff --git a/src/dawn_wire/client/ShaderModule.h b/src/dawn_wire/client/ShaderModule.h new file mode 100644 index 0000000000..add5b975ff --- /dev/null +++ b/src/dawn_wire/client/ShaderModule.h @@ -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 + +#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 mCompilationInfoRequests; + }; + +}} // namespace dawn_wire::client + +#endif // DAWNWIRE_CLIENT_SHADER_MODULE_H_ diff --git a/src/dawn_wire/server/Server.h b/src/dawn_wire/server/Server.h index 1124cba210..5baea199ea 100644 --- a/src/dawn_wire/server/Server.h +++ b/src/dawn_wire/server/Server.h @@ -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" diff --git a/src/dawn_wire/server/ServerShaderModule.cpp b/src/dawn_wire/server/ServerShaderModule.cpp new file mode 100644 index 0000000000..cec0dc4db3 --- /dev/null +++ b/src/dawn_wire/server/ServerShaderModule.cpp @@ -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 + +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(); + userdata->shaderModule = ObjectHandle{shaderModuleId, shaderModule->generation}; + userdata->requestSerial = requestSerial; + + mProcs.shaderModuleGetCompilationInfo( + shaderModule->handle, + ForwardToServer::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 diff --git a/src/tests/unittests/validation/ShaderModuleValidationTests.cpp b/src/tests/unittests/validation/ShaderModuleValidationTests.cpp index a1bea22015..ceb6e183cf 100644 --- a/src/tests/unittests/validation/ShaderModuleValidationTests.cpp +++ b/src/tests/unittests/validation/ShaderModuleValidationTests.cpp @@ -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 fragColor : vec4; + [[stage(fragment)]] fn main() -> void { + fragColor = vec4(0.0, 1.0, 0.0, 1.0); + })"; + wgpu::ShaderModule shaderModule = utils::CreateShaderModule(device, stream.str().c_str()); + + dawn_native::ShaderModuleBase* shaderModuleBase = + reinterpret_cast(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); +}