Commit 6fa22882 authored by Jiawei Shao's avatar Jiawei Shao Committed by Commit Bot

WebGPU: Implement returning adapter properties from GPU process

This patch implements sending the adapter properties from GPU process to
the renderer process in the call of adapter.RequestAdapter().

At the client side of WebGPU command buffer, before sending the request
of RequestAdapter() to the server side, a callback is saved in a map
whose key is the serial number of the request. After selecting the
preferred adapter, the GPU process will send the id and properties of
the adapter to the rendering process, the related callback will be
called to create the GPUAdapter object in Blink with the information
about this adapter from the GPU process.

BUG=chromium:996713

Change-Id: I81e252559a7d256213f4bf93405d63cd0e6fa02b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1897475Reviewed-by: default avatarCorentin Wallez <cwallez@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Reviewed-by: default avatarKai Ninomiya <kainino@chromium.org>
Reviewed-by: default avatarAustin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Cr-Commit-Position: refs/heads/master@{#716963}
parent 60e3aac0
...@@ -20,6 +20,7 @@ _NAMED_TYPE_INFO = { ...@@ -20,6 +20,7 @@ _NAMED_TYPE_INFO = {
'PowerPreference': { 'PowerPreference': {
'type': 'PowerPreference', 'type': 'PowerPreference',
'valid': [ 'valid': [
'PowerPreference::kDefault',
'PowerPreference::kHighPerformance', 'PowerPreference::kHighPerformance',
'PowerPreference::kLowPower', 'PowerPreference::kLowPower',
], ],
...@@ -62,7 +63,8 @@ _FUNCTION_INFO = { ...@@ -62,7 +63,8 @@ _FUNCTION_INFO = {
}, },
'RequestAdapter': { 'RequestAdapter': {
'impl_func': False, 'impl_func': False,
'cmd_args': 'uint32_t power_preference' 'internal': True,
'cmd_args': 'uint32_t request_adapter_serial, uint32_t power_preference'
}, },
} }
......
...@@ -43,10 +43,11 @@ void DissociateMailbox(GLuint texture_id, GLuint texture_generation) { ...@@ -43,10 +43,11 @@ void DissociateMailbox(GLuint texture_id, GLuint texture_generation) {
} }
} }
void RequestAdapter(uint32_t power_preference) { void RequestAdapter(uint32_t request_adapter_serial,
uint32_t power_preference) {
webgpu::cmds::RequestAdapter* c = GetCmdSpace<webgpu::cmds::RequestAdapter>(); webgpu::cmds::RequestAdapter* c = GetCmdSpace<webgpu::cmds::RequestAdapter>();
if (c) { if (c) {
c->Init(power_preference); c->Init(request_adapter_serial, power_preference);
} }
} }
......
...@@ -259,6 +259,32 @@ void WebGPUImplementation::OnGpuControlReturnData( ...@@ -259,6 +259,32 @@ void WebGPUImplementation::OnGpuControlReturnData(
NOTREACHED(); NOTREACHED();
} }
break; break;
case DawnReturnDataType::kRequestedDawnAdapterProperties: {
const cmds::DawnReturnAdapterInfo* returned_adapter_info =
reinterpret_cast<const cmds::DawnReturnAdapterInfo*>(
dawnReturnDataBody);
GLuint request_adapter_serial =
returned_adapter_info->adapter_ids.request_adapter_serial;
auto request_callback_iter =
request_adapter_callback_map_.find(request_adapter_serial);
if (request_callback_iter == request_adapter_callback_map_.end()) {
// TODO(jiawei.shao@intel.com): Lose the context.
NOTREACHED();
break;
}
auto& request_callback = request_callback_iter->second;
GLuint adapter_service_id =
returned_adapter_info->adapter_ids.adapter_service_id;
WGPUDeviceProperties adapter_properties = {};
const volatile char* deserialized_buffer =
reinterpret_cast<const volatile char*>(
returned_adapter_info->deserialized_buffer);
dawn_wire::DeserializeWGPUDeviceProperties(&adapter_properties,
deserialized_buffer);
std::move(request_callback).Run(adapter_service_id, adapter_properties);
request_adapter_callback_map_.erase(request_callback_iter);
} break;
default: default:
// TODO(jiawei.shao@intel.com): Lose the context. // TODO(jiawei.shao@intel.com): Lose the context.
NOTREACHED(); NOTREACHED();
...@@ -365,11 +391,30 @@ ReservedTexture WebGPUImplementation::ReserveTexture(WGPUDevice device) { ...@@ -365,11 +391,30 @@ ReservedTexture WebGPUImplementation::ReserveTexture(WGPUDevice device) {
#endif #endif
} }
void WebGPUImplementation::RequestAdapter(PowerPreference power_preference) { uint32_t WebGPUImplementation::NextRequestAdapterSerial() {
GPU_CLIENT_SINGLE_THREAD_CHECK(); return ++request_adapter_serial_;
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] wgRequestAdapter(" }
<< static_cast<uint32_t>(power_preference) << ")");
helper_->RequestAdapter(static_cast<uint32_t>(power_preference)); bool WebGPUImplementation::RequestAdapterAsync(
PowerPreference power_preference,
base::OnceCallback<void(uint32_t, const WGPUDeviceProperties&)>
request_adapter_callback) {
uint32_t request_adapter_serial = NextRequestAdapterSerial();
// Avoid the overflow of request_adapter_serial and old slot being reused.
if (request_adapter_callback_map_.find(request_adapter_serial) !=
request_adapter_callback_map_.end()) {
return false;
}
helper_->RequestAdapter(request_adapter_serial,
static_cast<uint32_t>(power_preference));
helper_->Flush();
request_adapter_callback_map_[request_adapter_serial] =
std::move(request_adapter_callback);
return true;
} }
} // namespace webgpu } // namespace webgpu
......
...@@ -119,10 +119,15 @@ class WEBGPU_EXPORT WebGPUImplementation final ...@@ -119,10 +119,15 @@ class WEBGPU_EXPORT WebGPUImplementation final
void FlushCommands() override; void FlushCommands() override;
WGPUDevice GetDefaultDevice() override; WGPUDevice GetDefaultDevice() override;
ReservedTexture ReserveTexture(WGPUDevice device) override; ReservedTexture ReserveTexture(WGPUDevice device) override;
bool RequestAdapterAsync(
PowerPreference power_preference,
base::OnceCallback<void(uint32_t, const WGPUDeviceProperties&)>
request_adapter_callback) override;
private: private:
const char* GetLogPrefix() const { return "webgpu"; } const char* GetLogPrefix() const { return "webgpu"; }
void CheckGLError() {} void CheckGLError() {}
uint32_t NextRequestAdapterSerial();
WebGPUCmdHelper* helper_; WebGPUCmdHelper* helper_;
#if BUILDFLAG(USE_DAWN) #if BUILDFLAG(USE_DAWN)
...@@ -137,6 +142,12 @@ class WEBGPU_EXPORT WebGPUImplementation final ...@@ -137,6 +142,12 @@ class WEBGPU_EXPORT WebGPUImplementation final
LogSettings log_settings_; LogSettings log_settings_;
base::flat_map<
uint32_t,
base::OnceCallback<void(uint32_t, const WGPUDeviceProperties&)>>
request_adapter_callback_map_;
uint32_t request_adapter_serial_ = 0;
DISALLOW_COPY_AND_ASSIGN(WebGPUImplementation); DISALLOW_COPY_AND_ASSIGN(WebGPUImplementation);
}; };
......
...@@ -22,7 +22,4 @@ void AssociateMailbox(GLuint device_id, ...@@ -22,7 +22,4 @@ void AssociateMailbox(GLuint device_id,
void DissociateMailbox(GLuint texture_id, GLuint texture_generation) override; void DissociateMailbox(GLuint texture_id, GLuint texture_generation) override;
void RequestAdapter(PowerPreference power_preference =
PowerPreference::kHighPerformance) override;
#endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_IMPLEMENTATION_AUTOGEN_H_ #endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_IMPLEMENTATION_AUTOGEN_H_
...@@ -39,15 +39,4 @@ TEST_F(WebGPUImplementationTest, DissociateMailbox) { ...@@ -39,15 +39,4 @@ TEST_F(WebGPUImplementationTest, DissociateMailbox) {
gl_->DissociateMailbox(1, 2); gl_->DissociateMailbox(1, 2);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
} }
TEST_F(WebGPUImplementationTest, RequestAdapter) {
struct Cmds {
cmds::RequestAdapter cmd;
};
Cmds expected;
expected.cmd.Init(1);
gl_->RequestAdapter(PowerPreference::kHighPerformance);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
#endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_IMPLEMENTATION_UNITTEST_AUTOGEN_H_ #endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_IMPLEMENTATION_UNITTEST_AUTOGEN_H_
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <dawn/dawn_proc_table.h> #include <dawn/dawn_proc_table.h>
#include <dawn/webgpu.h> #include <dawn/webgpu.h>
#include "base/callback.h"
#include "gpu/command_buffer/client/interface_base.h" #include "gpu/command_buffer/client/interface_base.h"
#include "gpu/command_buffer/common/webgpu_cmd_enums.h" #include "gpu/command_buffer/common/webgpu_cmd_enums.h"
...@@ -29,6 +30,10 @@ class WebGPUInterface : public InterfaceBase { ...@@ -29,6 +30,10 @@ class WebGPUInterface : public InterfaceBase {
virtual void FlushCommands() = 0; virtual void FlushCommands() = 0;
virtual WGPUDevice GetDefaultDevice() = 0; virtual WGPUDevice GetDefaultDevice() = 0;
virtual ReservedTexture ReserveTexture(WGPUDevice device) = 0; virtual ReservedTexture ReserveTexture(WGPUDevice device) = 0;
virtual bool RequestAdapterAsync(
PowerPreference power_preference,
base::OnceCallback<void(uint32_t, const WGPUDeviceProperties&)>
request_adapter_callback) = 0;
// Include the auto-generated part of this class. We split this because // Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in // it means we can easily edit the non-auto generated parts right here in
......
...@@ -21,6 +21,4 @@ virtual void AssociateMailbox(GLuint device_id, ...@@ -21,6 +21,4 @@ virtual void AssociateMailbox(GLuint device_id,
const GLbyte* mailbox) = 0; const GLbyte* mailbox) = 0;
virtual void DissociateMailbox(GLuint texture_id, virtual void DissociateMailbox(GLuint texture_id,
GLuint texture_generation) = 0; GLuint texture_generation) = 0;
virtual void RequestAdapter(
PowerPreference power_preference = PowerPreference::kHighPerformance) = 0;
#endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_INTERFACE_AUTOGEN_H_ #endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_INTERFACE_AUTOGEN_H_
...@@ -29,6 +29,12 @@ WGPUDevice WebGPUInterfaceStub::GetDefaultDevice() { ...@@ -29,6 +29,12 @@ WGPUDevice WebGPUInterfaceStub::GetDefaultDevice() {
ReservedTexture WebGPUInterfaceStub::ReserveTexture(WGPUDevice device) { ReservedTexture WebGPUInterfaceStub::ReserveTexture(WGPUDevice device) {
return {nullptr, 0, 0}; return {nullptr, 0, 0};
} }
bool WebGPUInterfaceStub::RequestAdapterAsync(
PowerPreference power_preference,
base::OnceCallback<void(uint32_t, const WGPUDeviceProperties&)>
request_adapter_callback) {
return false;
}
// Include the auto-generated part of this class. We split this because // Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in // it means we can easily edit the non-auto generated parts right here in
......
...@@ -27,6 +27,10 @@ class WebGPUInterfaceStub : public WebGPUInterface { ...@@ -27,6 +27,10 @@ class WebGPUInterfaceStub : public WebGPUInterface {
void FlushCommands() override; void FlushCommands() override;
WGPUDevice GetDefaultDevice() override; WGPUDevice GetDefaultDevice() override;
ReservedTexture ReserveTexture(WGPUDevice device) override; ReservedTexture ReserveTexture(WGPUDevice device) override;
bool RequestAdapterAsync(
PowerPreference power_preference,
base::OnceCallback<void(uint32_t, const WGPUDeviceProperties&)>
request_adapter_callback) override;
// Include the auto-generated part of this class. We split this because // Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in // it means we can easily edit the non-auto generated parts right here in
......
...@@ -19,5 +19,4 @@ void AssociateMailbox(GLuint device_id, ...@@ -19,5 +19,4 @@ void AssociateMailbox(GLuint device_id,
GLuint usage, GLuint usage,
const GLbyte* mailbox) override; const GLbyte* mailbox) override;
void DissociateMailbox(GLuint texture_id, GLuint texture_generation) override; void DissociateMailbox(GLuint texture_id, GLuint texture_generation) override;
void RequestAdapter(PowerPreference power_preference) override;
#endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_INTERFACE_STUB_AUTOGEN_H_ #endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_INTERFACE_STUB_AUTOGEN_H_
...@@ -20,6 +20,4 @@ void WebGPUInterfaceStub::AssociateMailbox(GLuint /* device_id */, ...@@ -20,6 +20,4 @@ void WebGPUInterfaceStub::AssociateMailbox(GLuint /* device_id */,
const GLbyte* /* mailbox */) {} const GLbyte* /* mailbox */) {}
void WebGPUInterfaceStub::DissociateMailbox(GLuint /* texture_id */, void WebGPUInterfaceStub::DissociateMailbox(GLuint /* texture_id */,
GLuint /* texture_generation */) {} GLuint /* texture_generation */) {}
void WebGPUInterfaceStub::RequestAdapter(
PowerPreference /* power_preference */) {}
#endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_INTERFACE_STUB_IMPL_AUTOGEN_H_ #endif // GPU_COMMAND_BUFFER_CLIENT_WEBGPU_INTERFACE_STUB_IMPL_AUTOGEN_H_
...@@ -11,11 +11,13 @@ namespace webgpu { ...@@ -11,11 +11,13 @@ namespace webgpu {
enum class PowerPreference : uint32_t { enum class PowerPreference : uint32_t {
kLowPower, kLowPower,
kHighPerformance, kHighPerformance,
kDefault,
kNumPowerPreferences kNumPowerPreferences
}; };
enum class DawnReturnDataType : uint32_t { enum class DawnReturnDataType : uint32_t {
kDawnCommands, kDawnCommands,
kRequestedDawnAdapterProperties,
kNumDawnReturnDataType kNumDawnReturnDataType
}; };
......
...@@ -31,6 +31,26 @@ static_assert( ...@@ -31,6 +31,26 @@ static_assert(
sizeof(DawnReturnDataHeader) % GPU_DAWN_RETURN_DATA_ALIGNMENT == 0, sizeof(DawnReturnDataHeader) % GPU_DAWN_RETURN_DATA_ALIGNMENT == 0,
"DawnReturnDataHeader must align to GPU_DAWN_RETURN_DATA_ALIGNMENT"); "DawnReturnDataHeader must align to GPU_DAWN_RETURN_DATA_ALIGNMENT");
struct alignas(GPU_DAWN_RETURN_DATA_ALIGNMENT) DawnReturnAdapterIDs {
uint32_t request_adapter_serial;
uint32_t adapter_service_id;
};
static_assert(
sizeof(DawnReturnAdapterIDs) % GPU_DAWN_RETURN_DATA_ALIGNMENT == 0,
"DawnReturnAdapterIDs must align to GPU_DAWN_RETURN_DATA_ALIGNMENT");
struct alignas(GPU_DAWN_RETURN_DATA_ALIGNMENT) DawnReturnAdapterInfo {
DawnReturnAdapterIDs adapter_ids;
char deserialized_buffer[];
};
static_assert(offsetof(DawnReturnAdapterInfo, deserialized_buffer) %
GPU_DAWN_RETURN_DATA_ALIGNMENT ==
0,
"The offset of deserialized_buffer must align to "
"GPU_DAWN_RETURN_DATA_ALIGNMENT");
// Command buffer is GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT byte aligned. // Command buffer is GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT byte aligned.
#pragma pack(push, 4) #pragma pack(push, 4)
static_assert(GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT == 4, static_assert(GPU_COMMAND_BUFFER_ENTRY_ALIGNMENT == 4,
......
...@@ -176,25 +176,32 @@ struct RequestAdapter { ...@@ -176,25 +176,32 @@ struct RequestAdapter {
void SetHeader() { header.SetCmd<ValueType>(); } void SetHeader() { header.SetCmd<ValueType>(); }
void Init(uint32_t _power_preference) { void Init(uint32_t _request_adapter_serial, uint32_t _power_preference) {
SetHeader(); SetHeader();
request_adapter_serial = _request_adapter_serial;
power_preference = _power_preference; power_preference = _power_preference;
} }
void* Set(void* cmd, uint32_t _power_preference) { void* Set(void* cmd,
static_cast<ValueType*>(cmd)->Init(_power_preference); uint32_t _request_adapter_serial,
uint32_t _power_preference) {
static_cast<ValueType*>(cmd)->Init(_request_adapter_serial,
_power_preference);
return NextCmdAddress<ValueType>(cmd); return NextCmdAddress<ValueType>(cmd);
} }
gpu::CommandHeader header; gpu::CommandHeader header;
uint32_t request_adapter_serial;
uint32_t power_preference; uint32_t power_preference;
}; };
static_assert(sizeof(RequestAdapter) == 8, static_assert(sizeof(RequestAdapter) == 12,
"size of RequestAdapter should be 8"); "size of RequestAdapter should be 12");
static_assert(offsetof(RequestAdapter, header) == 0, static_assert(offsetof(RequestAdapter, header) == 0,
"offset of RequestAdapter header should be 0"); "offset of RequestAdapter header should be 0");
static_assert(offsetof(RequestAdapter, power_preference) == 4, static_assert(offsetof(RequestAdapter, request_adapter_serial) == 4,
"offset of RequestAdapter power_preference should be 4"); "offset of RequestAdapter request_adapter_serial should be 4");
static_assert(offsetof(RequestAdapter, power_preference) == 8,
"offset of RequestAdapter power_preference should be 8");
#endif // GPU_COMMAND_BUFFER_COMMON_WEBGPU_CMD_FORMAT_AUTOGEN_H_ #endif // GPU_COMMAND_BUFFER_COMMON_WEBGPU_CMD_FORMAT_AUTOGEN_H_
...@@ -81,11 +81,13 @@ TEST_F(WebGPUFormatTest, DissociateMailbox) { ...@@ -81,11 +81,13 @@ TEST_F(WebGPUFormatTest, DissociateMailbox) {
TEST_F(WebGPUFormatTest, RequestAdapter) { TEST_F(WebGPUFormatTest, RequestAdapter) {
cmds::RequestAdapter& cmd = *GetBufferAs<cmds::RequestAdapter>(); cmds::RequestAdapter& cmd = *GetBufferAs<cmds::RequestAdapter>();
void* next_cmd = cmd.Set(&cmd, static_cast<uint32_t>(11)); void* next_cmd =
cmd.Set(&cmd, static_cast<uint32_t>(11), static_cast<uint32_t>(12));
EXPECT_EQ(static_cast<uint32_t>(cmds::RequestAdapter::kCmdId), EXPECT_EQ(static_cast<uint32_t>(cmds::RequestAdapter::kCmdId),
cmd.header.command); cmd.header.command);
EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
EXPECT_EQ(static_cast<uint32_t>(11), cmd.power_preference); EXPECT_EQ(static_cast<uint32_t>(11), cmd.request_adapter_serial);
EXPECT_EQ(static_cast<uint32_t>(12), cmd.power_preference);
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define GPU_COMMAND_BUFFER_SERVICE_WEBGPU_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_WEBGPU_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_
static const PowerPreference valid_power_preference_table[] = { static const PowerPreference valid_power_preference_table[] = {
PowerPreference::kDefault,
PowerPreference::kHighPerformance, PowerPreference::kHighPerformance,
PowerPreference::kLowPower, PowerPreference::kLowPower,
}; };
......
...@@ -45,6 +45,9 @@ class WireServerCommandSerializer : public dawn_wire::CommandSerializer { ...@@ -45,6 +45,9 @@ class WireServerCommandSerializer : public dawn_wire::CommandSerializer {
~WireServerCommandSerializer() override = default; ~WireServerCommandSerializer() override = default;
void* GetCmdSpace(size_t size) final; void* GetCmdSpace(size_t size) final;
bool Flush() final; bool Flush() final;
void SendAdapterProperties(uint32_t request_adapter_serial,
uint32_t adapter_server_id,
const dawn_native::Adapter& adapter);
private: private:
DecoderClient* client_; DecoderClient* client_;
...@@ -107,12 +110,48 @@ bool WireServerCommandSerializer::Flush() { ...@@ -107,12 +110,48 @@ bool WireServerCommandSerializer::Flush() {
return true; return true;
} }
void WireServerCommandSerializer::SendAdapterProperties(
uint32_t request_adapter_serial,
uint32_t adapter_service_id,
const dawn_native::Adapter& adapter) {
WGPUDeviceProperties adapter_properties = adapter.GetAdapterProperties();
size_t serialized_adapter_properties_size =
dawn_wire::SerializedWGPUDevicePropertiesSize(&adapter_properties);
std::vector<char> serialized_buffer(sizeof(cmds::DawnReturnDataHeader) +
sizeof(cmds::DawnReturnAdapterIDs) +
serialized_adapter_properties_size);
// Set Dawn return data header
reinterpret_cast<cmds::DawnReturnDataHeader*>(serialized_buffer.data())
->return_data_type = DawnReturnDataType::kRequestedDawnAdapterProperties;
// Set adapter ids
cmds::DawnReturnAdapterInfo* return_adapter_info =
reinterpret_cast<cmds::DawnReturnAdapterInfo*>(
serialized_buffer.data() + sizeof(cmds::DawnReturnDataHeader));
return_adapter_info->adapter_ids.request_adapter_serial =
request_adapter_serial;
return_adapter_info->adapter_ids.adapter_service_id = adapter_service_id;
// Set serialized adapter properties
dawn_wire::SerializeWGPUDeviceProperties(
&adapter_properties, return_adapter_info->deserialized_buffer);
client_->HandleReturnData(base::make_span(
reinterpret_cast<const uint8_t*>(serialized_buffer.data()),
serialized_buffer.size()));
}
dawn_native::DeviceType PowerPreferenceToDawnDeviceType( dawn_native::DeviceType PowerPreferenceToDawnDeviceType(
PowerPreference power_preference) { PowerPreference power_preference) {
switch (power_preference) { switch (power_preference) {
case PowerPreference::kLowPower: case PowerPreference::kLowPower:
return dawn_native::DeviceType::IntegratedGPU; return dawn_native::DeviceType::IntegratedGPU;
case PowerPreference::kHighPerformance: case PowerPreference::kHighPerformance:
// Currently for simplicity we always choose discrete GPU as the device
// related to default power preference.
case PowerPreference::kDefault:
return dawn_native::DeviceType::DiscreteGPU; return dawn_native::DeviceType::DiscreteGPU;
default: default:
NOTREACHED(); NOTREACHED();
...@@ -351,10 +390,9 @@ class WebGPUDecoderImpl final : public WebGPUDecoder { ...@@ -351,10 +390,9 @@ class WebGPUDecoderImpl final : public WebGPUDecoder {
void DiscoverAdapters(); void DiscoverAdapters();
dawn_native::Adapter GetPreferredAdapter( int32_t GetPreferredAdapterIndex(PowerPreference power_preference) const;
PowerPreference power_preference) const;
error::Error InitDawnDeviceAndSetWireServer(dawn_native::Adapter* adapter); error::Error InitDawnDeviceAndSetWireServer(int32_t requested_adapter_index);
std::unique_ptr<SharedImageRepresentationFactory> std::unique_ptr<SharedImageRepresentationFactory>
shared_image_representation_factory_; shared_image_representation_factory_;
...@@ -434,8 +472,8 @@ ContextResult WebGPUDecoderImpl::Initialize() { ...@@ -434,8 +472,8 @@ ContextResult WebGPUDecoderImpl::Initialize() {
} }
error::Error WebGPUDecoderImpl::InitDawnDeviceAndSetWireServer( error::Error WebGPUDecoderImpl::InitDawnDeviceAndSetWireServer(
dawn_native::Adapter* adapter) { int32_t requested_adapter_index) {
DCHECK(adapter != nullptr && (*adapter)); DCHECK_LE(0, requested_adapter_index);
// TODO(jiawei.shao@intel.com): support multiple Dawn devices. // TODO(jiawei.shao@intel.com): support multiple Dawn devices.
if (wgpu_device_ != nullptr) { if (wgpu_device_ != nullptr) {
...@@ -443,7 +481,9 @@ error::Error WebGPUDecoderImpl::InitDawnDeviceAndSetWireServer( ...@@ -443,7 +481,9 @@ error::Error WebGPUDecoderImpl::InitDawnDeviceAndSetWireServer(
return error::kNoError; return error::kNoError;
} }
wgpu_device_ = adapter->CreateDevice(); DCHECK_LT(static_cast<size_t>(requested_adapter_index),
dawn_adapters_.size());
wgpu_device_ = dawn_adapters_[requested_adapter_index].CreateDevice();
if (wgpu_device_ == nullptr) { if (wgpu_device_ == nullptr) {
return error::kLostContext; return error::kLostContext;
} }
...@@ -484,32 +524,33 @@ void WebGPUDecoderImpl::DiscoverAdapters() { ...@@ -484,32 +524,33 @@ void WebGPUDecoderImpl::DiscoverAdapters() {
} }
} }
dawn_native::Adapter WebGPUDecoderImpl::GetPreferredAdapter( int32_t WebGPUDecoderImpl::GetPreferredAdapterIndex(
PowerPreference power_preference) const { PowerPreference power_preference) const {
dawn_native::DeviceType preferred_device_type = dawn_native::DeviceType preferred_device_type =
PowerPreferenceToDawnDeviceType(power_preference); PowerPreferenceToDawnDeviceType(power_preference);
dawn_native::Adapter discrete_gpu_adapter = {}; int32_t discrete_gpu_adapter_index = -1;
dawn_native::Adapter integrated_gpu_adapter = {}; int32_t integrated_gpu_adapter_index = -1;
dawn_native::Adapter cpu_adapter = {}; int32_t cpu_adapter_index = -1;
dawn_native::Adapter unknown_adapter = {}; int32_t unknown_adapter_index = -1;
for (const dawn_native::Adapter& adapter : dawn_adapters_) { for (int32_t i = 0; i < static_cast<int32_t>(dawn_adapters_.size()); ++i) {
const dawn_native::Adapter& adapter = dawn_adapters_[i];
if (adapter.GetDeviceType() == preferred_device_type) { if (adapter.GetDeviceType() == preferred_device_type) {
return adapter; return i;
} }
switch (adapter.GetDeviceType()) { switch (adapter.GetDeviceType()) {
case dawn_native::DeviceType::DiscreteGPU: case dawn_native::DeviceType::DiscreteGPU:
discrete_gpu_adapter = adapter; discrete_gpu_adapter_index = i;
break; break;
case dawn_native::DeviceType::IntegratedGPU: case dawn_native::DeviceType::IntegratedGPU:
integrated_gpu_adapter = adapter; integrated_gpu_adapter_index = i;
break; break;
case dawn_native::DeviceType::CPU: case dawn_native::DeviceType::CPU:
cpu_adapter = adapter; cpu_adapter_index = i;
break; break;
case dawn_native::DeviceType::Unknown: case dawn_native::DeviceType::Unknown:
unknown_adapter = adapter; unknown_adapter_index = i;
break; break;
default: default:
NOTREACHED(); NOTREACHED();
...@@ -518,19 +559,19 @@ dawn_native::Adapter WebGPUDecoderImpl::GetPreferredAdapter( ...@@ -518,19 +559,19 @@ dawn_native::Adapter WebGPUDecoderImpl::GetPreferredAdapter(
} }
// For now, we always prefer the discrete GPU // For now, we always prefer the discrete GPU
if (discrete_gpu_adapter) { if (discrete_gpu_adapter_index >= 0) {
return discrete_gpu_adapter; return discrete_gpu_adapter_index;
} }
if (integrated_gpu_adapter) { if (integrated_gpu_adapter_index >= 0) {
return integrated_gpu_adapter; return integrated_gpu_adapter_index;
} }
if (cpu_adapter) { if (cpu_adapter_index >= 0) {
return cpu_adapter; return cpu_adapter_index;
} }
if (unknown_adapter) { if (unknown_adapter_index >= 0) {
return unknown_adapter; return unknown_adapter_index;
} }
return dawn_native::Adapter(); return -1;
} }
const char* WebGPUDecoderImpl::GetCommandName(unsigned int command_id) const { const char* WebGPUDecoderImpl::GetCommandName(unsigned int command_id) const {
...@@ -614,14 +655,22 @@ error::Error WebGPUDecoderImpl::HandleRequestAdapter( ...@@ -614,14 +655,22 @@ error::Error WebGPUDecoderImpl::HandleRequestAdapter(
PowerPreference power_preference = PowerPreference power_preference =
static_cast<PowerPreference>(c.power_preference); static_cast<PowerPreference>(c.power_preference);
dawn_native::Adapter requested_adapter = int32_t requested_adapter_index = GetPreferredAdapterIndex(power_preference);
GetPreferredAdapter(power_preference); if (requested_adapter_index < 0) {
if (!requested_adapter) {
return error::kLostContext; return error::kLostContext;
} }
// Currently we treat the index of the adapter in dawn_adapters_ as the id of
// the adapter in the server side.
DCHECK_LT(static_cast<size_t>(requested_adapter_index),
dawn_adapters_.size());
const dawn_native::Adapter& adapter = dawn_adapters_[requested_adapter_index];
wire_serializer_->SendAdapterProperties(
static_cast<uint32_t>(c.request_adapter_serial),
static_cast<uint32_t>(requested_adapter_index), adapter);
// TODO(jiawei.shao@intel.com): support creating device with device descriptor // TODO(jiawei.shao@intel.com): support creating device with device descriptor
return InitDawnDeviceAndSetWireServer(&requested_adapter); return InitDawnDeviceAndSetWireServer(requested_adapter_index);
} }
error::Error WebGPUDecoderImpl::HandleDawnCommands( error::Error WebGPUDecoderImpl::HandleDawnCommands(
......
...@@ -49,14 +49,17 @@ class WebGPUDecoderTest : public ::testing::Test { ...@@ -49,14 +49,17 @@ class WebGPUDecoderTest : public ::testing::Test {
gl_context_->MakeCurrent(gl_surface_.get()); gl_context_->MakeCurrent(gl_surface_.get());
decoder_client_.reset(new FakeDecoderClient());
command_buffer_service_.reset(new FakeCommandBufferServiceBase()); command_buffer_service_.reset(new FakeCommandBufferServiceBase());
decoder_.reset(WebGPUDecoder::Create(nullptr, command_buffer_service_.get(), decoder_.reset(WebGPUDecoder::Create(
&shared_image_manager_, nullptr, decoder_client_.get(), command_buffer_service_.get(),
&outputter_)); &shared_image_manager_, nullptr, &outputter_));
ASSERT_EQ(decoder_->Initialize(), ContextResult::kSuccess); ASSERT_EQ(decoder_->Initialize(), ContextResult::kSuccess);
constexpr uint32_t kadapter_client_id = 0;
cmds::RequestAdapter requestAdapterCmd; cmds::RequestAdapter requestAdapterCmd;
requestAdapterCmd.Init( requestAdapterCmd.Init(
kadapter_client_id,
static_cast<uint32_t>(webgpu::PowerPreference::kHighPerformance)); static_cast<uint32_t>(webgpu::PowerPreference::kHighPerformance));
ASSERT_EQ(error::kNoError, ExecuteCmd(requestAdapterCmd)); ASSERT_EQ(error::kNoError, ExecuteCmd(requestAdapterCmd));
...@@ -108,6 +111,7 @@ class WebGPUDecoderTest : public ::testing::Test { ...@@ -108,6 +111,7 @@ class WebGPUDecoderTest : public ::testing::Test {
protected: protected:
std::unique_ptr<FakeCommandBufferServiceBase> command_buffer_service_; std::unique_ptr<FakeCommandBufferServiceBase> command_buffer_service_;
std::unique_ptr<WebGPUDecoder> decoder_; std::unique_ptr<WebGPUDecoder> decoder_;
std::unique_ptr<FakeDecoderClient> decoder_client_;
gles2::TraceOutputter outputter_; gles2::TraceOutputter outputter_;
SharedImageManager shared_image_manager_; SharedImageManager shared_image_manager_;
std::unique_ptr<SharedImageFactory> factory_; std::unique_ptr<SharedImageFactory> factory_;
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
namespace gpu { namespace gpu {
namespace {
void OnRequestAdapterCallback(uint32_t adapter_server_id,
const WGPUDeviceProperties& properties) {}
} // anonymous namespace
WebGPUTest::Options::Options() = default; WebGPUTest::Options::Options() = default;
WebGPUTest::WebGPUTest() = default; WebGPUTest::WebGPUTest() = default;
...@@ -84,7 +91,9 @@ void WebGPUTest::Initialize(const Options& options) { ...@@ -84,7 +91,9 @@ void WebGPUTest::Initialize(const Options& options) {
image_factory, channel_manager); image_factory, channel_manager);
ASSERT_EQ(result, ContextResult::kSuccess); ASSERT_EQ(result, ContextResult::kSuccess);
webgpu()->RequestAdapter(webgpu::PowerPreference::kHighPerformance); ASSERT_TRUE(
webgpu()->RequestAdapterAsync(webgpu::PowerPreference::kDefault,
base::Bind(&OnRequestAdapterCallback)));
DawnProcTable procs = webgpu()->GetProcs(); DawnProcTable procs = webgpu()->GetProcs();
dawnProcSetProcs(&procs); dawnProcSetProcs(&procs);
......
...@@ -9,4 +9,4 @@ ...@@ -9,4 +9,4 @@
GL_APICALL void GL_APIENTRY wgDawnCommands (const char* commands, size_t size); GL_APICALL void GL_APIENTRY wgDawnCommands (const char* commands, size_t size);
GL_APICALL void GL_APIENTRY wgAssociateMailbox (GLuint device_id, GLuint device_generation, GLuint id, GLuint generation, GLuint usage, const GLbyte* mailbox); GL_APICALL void GL_APIENTRY wgAssociateMailbox (GLuint device_id, GLuint device_generation, GLuint id, GLuint generation, GLuint usage, const GLbyte* mailbox);
GL_APICALL void GL_APIENTRY wgDissociateMailbox (GLuint texture_id, GLuint texture_generation); GL_APICALL void GL_APIENTRY wgDissociateMailbox (GLuint texture_id, GLuint texture_generation);
GL_APICALL void GL_APIENTRY wgRequestAdapter (EnumClassPowerPreference power_preference = PowerPreference::kHighPerformance); GL_APICALL void GL_APIENTRY wgRequestAdapter (GLuint request_adapter_serial, EnumClassPowerPreference power_preference = PowerPreference::kDefault);
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_adapter.h" #include "third_party/blink/renderer/modules/webgpu/gpu_adapter.h"
...@@ -100,6 +101,14 @@ void GPU::ContextDestroyed(ExecutionContext* execution_context) { ...@@ -100,6 +101,14 @@ void GPU::ContextDestroyed(ExecutionContext* execution_context) {
dawn_control_client_->Destroy(); dawn_control_client_->Destroy();
} }
void GPU::OnRequestAdapterCallback(ScriptPromiseResolver* resolver,
uint32_t adapter_server_id,
const WGPUDeviceProperties& properties) {
GPUAdapter* adapter = GPUAdapter::Create("Default", adapter_server_id,
properties, dawn_control_client_);
resolver->Resolve(adapter);
}
ScriptPromise GPU::requestAdapter(ScriptState* script_state, ScriptPromise GPU::requestAdapter(ScriptState* script_state,
const GPURequestAdapterOptions* options) { const GPURequestAdapterOptions* options) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
...@@ -111,10 +120,15 @@ ScriptPromise GPU::requestAdapter(ScriptState* script_state, ...@@ -111,10 +120,15 @@ ScriptPromise GPU::requestAdapter(ScriptState* script_state,
if (options->powerPreference() == "low-power") { if (options->powerPreference() == "low-power") {
power_preference = gpu::webgpu::PowerPreference::kLowPower; power_preference = gpu::webgpu::PowerPreference::kLowPower;
} }
GPUAdapter* adapter =
GPUAdapter::Create("Default", power_preference, dawn_control_client_);
resolver->Resolve(adapter); if (!dawn_control_client_->GetInterface()->RequestAdapterAsync(
power_preference,
WTF::Bind(&GPU::OnRequestAdapterCallback, WrapPersistent(this),
WrapPersistent(resolver)))) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kOperationError, "Fail to request GPUAdapter"));
}
return promise; return promise;
} }
......
...@@ -11,9 +11,12 @@ ...@@ -11,9 +11,12 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
struct WGPUDeviceProperties;
namespace blink { namespace blink {
class GPURequestAdapterOptions; class GPURequestAdapterOptions;
class ScriptPromiseResolver;
class ScriptState; class ScriptState;
class WebGraphicsContext3DProvider; class WebGraphicsContext3DProvider;
class DawnControlClientHolder; class DawnControlClientHolder;
...@@ -39,6 +42,10 @@ class GPU final : public ScriptWrappable, public ContextLifecycleObserver { ...@@ -39,6 +42,10 @@ class GPU final : public ScriptWrappable, public ContextLifecycleObserver {
const GPURequestAdapterOptions* options); const GPURequestAdapterOptions* options);
private: private:
void OnRequestAdapterCallback(ScriptPromiseResolver* resolver,
uint32_t adapter_server_id,
const WGPUDeviceProperties& properties);
scoped_refptr<DawnControlClientHolder> dawn_control_client_; scoped_refptr<DawnControlClientHolder> dawn_control_client_;
DISALLOW_COPY_AND_ASSIGN(GPU); DISALLOW_COPY_AND_ASSIGN(GPU);
......
...@@ -13,24 +13,27 @@ namespace blink { ...@@ -13,24 +13,27 @@ namespace blink {
// static // static
GPUAdapter* GPUAdapter::Create( GPUAdapter* GPUAdapter::Create(
const String& name, const String& name,
gpu::webgpu::PowerPreference power_preference, uint32_t adapter_service_id,
const WGPUDeviceProperties& properties,
scoped_refptr<DawnControlClientHolder> dawn_control_client) { scoped_refptr<DawnControlClientHolder> dawn_control_client) {
return MakeGarbageCollected<GPUAdapter>(name, power_preference, return MakeGarbageCollected<GPUAdapter>(name, adapter_service_id, properties,
std::move(dawn_control_client)); std::move(dawn_control_client));
} }
GPUAdapter::GPUAdapter( GPUAdapter::GPUAdapter(
const String& name, const String& name,
gpu::webgpu::PowerPreference power_preference, uint32_t adapter_service_id,
const WGPUDeviceProperties& properties,
scoped_refptr<DawnControlClientHolder> dawn_control_client) scoped_refptr<DawnControlClientHolder> dawn_control_client)
: DawnObjectBase(dawn_control_client), name_(name) { : DawnObjectBase(dawn_control_client), name_(name) {
dawn_control_client->GetInterface()->RequestAdapter(power_preference); // TODO(jiawei.shao@intel.com): add GPUExtensions as a member of GPUAdapter
} }
const String& GPUAdapter::name() const { const String& GPUAdapter::name() const {
return name_; return name_;
} }
// TODO(jiawei.shao@intel.com) request device with adapter_server_id
ScriptPromise GPUAdapter::requestDevice(ScriptState* script_state, ScriptPromise GPUAdapter::requestDevice(ScriptState* script_state,
const GPUDeviceDescriptor* descriptor) { const GPUDeviceDescriptor* descriptor) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
......
...@@ -23,10 +23,12 @@ class GPUAdapter final : public ScriptWrappable, public DawnObjectBase { ...@@ -23,10 +23,12 @@ class GPUAdapter final : public ScriptWrappable, public DawnObjectBase {
public: public:
static GPUAdapter* Create( static GPUAdapter* Create(
const String& name, const String& name,
gpu::webgpu::PowerPreference power_preference, uint32_t adapter_service_id,
const WGPUDeviceProperties& properties,
scoped_refptr<DawnControlClientHolder> dawn_control_client); scoped_refptr<DawnControlClientHolder> dawn_control_client);
GPUAdapter(const String& name, GPUAdapter(const String& name,
gpu::webgpu::PowerPreference power_preference, uint32_t adapter_service_id,
const WGPUDeviceProperties& properties,
scoped_refptr<DawnControlClientHolder> dawn_control_client); scoped_refptr<DawnControlClientHolder> dawn_control_client);
const String& name() const; const String& name() const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment