WebGPU: Add DawnReturnDataType before the return data of WebGPU decoder

This patch adds an enum DawnReturnDataType before the return data from
the server side of WebGPU command buffer to the client side. This enum
will be used as a flag to specify different type of return data received
in the client side of WebGPU command buffer. Currently we only support
kDawnCommands, and we will support more kinds of the return values in
the following patches.

BUG=chromium:996713

Change-Id: I99f65a0b91808cea52728ea10b408c4ee9649d85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1877907
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#710662}
diff --git a/gpu/command_buffer/client/webgpu_implementation.cc b/gpu/command_buffer/client/webgpu_implementation.cc
index cee8140..4b01d2b 100644
--- a/gpu/command_buffer/client/webgpu_implementation.cc
+++ b/gpu/command_buffer/client/webgpu_implementation.cc
@@ -238,11 +238,32 @@
   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
                "WebGPUImplementation::OnGpuControlReturnData", "bytes",
                data.size());
-  if (!wire_client_->HandleCommands(
-      reinterpret_cast<const char*>(data.data()), data.size())) {
-    // TODO(enga): Lose the context.
+
+  if (data.size() <= sizeof(cmds::DawnReturnDataHeader)) {
+    // TODO(jiawei.shao@intel.com): Lose the context.
     NOTREACHED();
   }
+  const cmds::DawnReturnDataHeader& dawnReturnDataHeader =
+      *reinterpret_cast<const cmds::DawnReturnDataHeader*>(data.data());
+
+  const uint8_t* dawnReturnDataBody =
+      data.data() + sizeof(cmds::DawnReturnDataHeader);
+  size_t dawnReturnDataSize = data.size() - sizeof(cmds::DawnReturnDataHeader);
+
+  switch (dawnReturnDataHeader.return_data_type) {
+    case DawnReturnDataType::kDawnCommands:
+      if (!wire_client_->HandleCommands(
+              reinterpret_cast<const char*>(dawnReturnDataBody),
+              dawnReturnDataSize)) {
+        // TODO(enga): Lose the context.
+        NOTREACHED();
+      }
+      break;
+    default:
+      // TODO(jiawei.shao@intel.com): Lose the context.
+      NOTREACHED();
+      break;
+  }
 #endif
 }
 
diff --git a/gpu/command_buffer/common/webgpu_cmd_enums.h b/gpu/command_buffer/common/webgpu_cmd_enums.h
index 2f5c970b..01fd98d7 100644
--- a/gpu/command_buffer/common/webgpu_cmd_enums.h
+++ b/gpu/command_buffer/common/webgpu_cmd_enums.h
@@ -14,11 +14,10 @@
   kNumPowerPreferences
 };
 
-// These numbers must not change
-static_assert(static_cast<int>(PowerPreference::kLowPower) == 0,
-              "kLowPower should equal 0");
-static_assert(static_cast<int>(PowerPreference::kHighPerformance) == 1,
-              "kHighPerformance should equal 1");
+enum class DawnReturnDataType : uint32_t {
+  kDawnCommands,
+  kNumDawnReturnDataType
+};
 
 }  // namespace webgpu
 }  // namespace gpu
diff --git a/gpu/command_buffer/common/webgpu_cmd_format.h b/gpu/command_buffer/common/webgpu_cmd_format.h
index 09d6a09..6bb34fb 100644
--- a/gpu/command_buffer/common/webgpu_cmd_format.h
+++ b/gpu/command_buffer/common/webgpu_cmd_format.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "gpu/command_buffer/common/common_cmd_format.h"
 #include "gpu/command_buffer/common/gl2_types.h"
+#include "gpu/command_buffer/common/webgpu_cmd_enums.h"
 #include "gpu/command_buffer/common/webgpu_cmd_ids.h"
 #include "ui/gfx/buffer_types.h"
 
@@ -21,6 +22,15 @@
 namespace webgpu {
 namespace cmds {
 
+#define GPU_DAWN_RETURN_DATA_ALIGNMENT (8)
+struct alignas(GPU_DAWN_RETURN_DATA_ALIGNMENT) DawnReturnDataHeader {
+  DawnReturnDataType return_data_type;
+};
+
+static_assert(
+    sizeof(DawnReturnDataHeader) % GPU_DAWN_RETURN_DATA_ALIGNMENT == 0,
+    "DawnReturnDataHeader must align to GPU_DAWN_RETURN_DATA_ALIGNMENT");
+
 // Command buffer is GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT byte aligned.
 #pragma pack(push, 4)
 static_assert(GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT == 4,
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index 927f154..ce0325d9 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -53,11 +53,18 @@
 };
 
 WireServerCommandSerializer::WireServerCommandSerializer(DecoderClient* client)
-    : client_(client), buffer_(kMaxWireBufferSize), put_offset_(0) {}
+    : client_(client),
+      buffer_(kMaxWireBufferSize),
+      put_offset_(sizeof(cmds::DawnReturnDataHeader)) {
+  cmds::DawnReturnDataHeader* return_data_header =
+      reinterpret_cast<cmds::DawnReturnDataHeader*>(&buffer_[0]);
+  return_data_header->return_data_type = DawnReturnDataType::kDawnCommands;
+}
 
 void* WireServerCommandSerializer::GetCmdSpace(size_t size) {
-  // TODO(enga): Handle chunking commands if size > kMaxWireBufferSize.
-  if (size > kMaxWireBufferSize) {
+  // TODO(enga): Handle chunking commands if size +
+  // sizeof(cmds::DawnReturnDataHeader)> kMaxWireBufferSize.
+  if (size + sizeof(cmds::DawnReturnDataHeader) > kMaxWireBufferSize) {
     NOTREACHED();
     return nullptr;
   }
@@ -76,8 +83,8 @@
     // TODO(enga): Keep track of how much command space the application is using
     // and adjust the buffer size accordingly.
 
-    DCHECK_EQ(put_offset_, 0u);
-    next_offset = size;
+    DCHECK_EQ(put_offset_, sizeof(cmds::DawnReturnDataHeader));
+    next_offset = put_offset_ + size;
   }
 
   uint8_t* ptr = &buffer_[put_offset_];
@@ -86,7 +93,7 @@
 }
 
 bool WireServerCommandSerializer::Flush() {
-  if (put_offset_ > 0) {
+  if (put_offset_ > sizeof(cmds::DawnReturnDataHeader)) {
     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
                  "WireServerCommandSerializer::Flush", "bytes", put_offset_);
 
@@ -95,7 +102,7 @@
                             "DawnReturnCommands", return_trace_id++);
 
     client_->HandleReturnData(base::make_span(buffer_.data(), put_offset_));
-    put_offset_ = 0;
+    put_offset_ = sizeof(cmds::DawnReturnDataHeader);
   }
   return true;
 }