mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-30 00:45:52 +00:00
1. Auto-generate mutex locking code in DawnNative's ProcTable's functions. Using a mutex owned by the related Device. - Unless the function/class has "no autolock" attribute (new) in dawn.json. In which cases, no locking code will be auto-generated. - Currently Instance, Adapter, Surface, Encoder classes and Reference/Release method have "no autolock". 2. Added Feature::ImplicitDeviceSynchronization to enable Device's mutex. - If this feature is disabled, lock/unlock Device's mutex is no-op. Auto-generated locking code will have no effect. This is the default. - This approach is used instead of generating two sets of ProcTable because it's cleaner and the internal code doesn't need to care about whether there is a mutex being locked or not. Furthermore, if there were two sets of ProcTable, and user used dawnProcSetProcs() to set global ProcTable, it would affect all other modules using different Devices. Even though those modules don't need thread safety. Bug: dawn:1662 Change-Id: I75f0d28959f333318e4159916b259131581f79f5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/119940 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Quyen Le <lehoangquyen@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
193 lines
7.7 KiB
C++
193 lines
7.7 KiB
C++
//* 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.
|
|
|
|
{% set Prefix = metadata.proc_table_prefix %}
|
|
{% set prefix = Prefix.lower() %}
|
|
{% set impl_dir = metadata.impl_dir + "/" if metadata.impl_dir else "" %}
|
|
{% set namespace_name = Name(metadata.native_namespace) %}
|
|
{% set native_namespace = namespace_name.namespace_case() %}
|
|
{% set native_dir = impl_dir + namespace_name.Dirs() %}
|
|
#include "{{native_dir}}/{{prefix}}_platform.h"
|
|
#include "{{native_dir}}/{{Prefix}}Native.h"
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
|
|
{% for type in by_category["object"] %}
|
|
{% if type.name.canonical_case() not in ["texture view"] %}
|
|
#include "{{native_dir}}/{{type.name.CamelCase()}}.h"
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
namespace {{native_namespace}} {
|
|
|
|
{% for type in by_category["object"] %}
|
|
{% for method in c_methods(type) %}
|
|
{% set suffix = as_MethodSuffix(type.name, method.name) %}
|
|
|
|
{{as_cType(method.return_type.name)}} Native{{suffix}}(
|
|
{{-as_cType(type.name)}} cSelf
|
|
{%- for arg in method.arguments -%}
|
|
, {{as_annotated_cType(arg)}}
|
|
{%- endfor -%}
|
|
) {
|
|
//* Perform conversion between C types and frontend types
|
|
auto self = FromAPI(cSelf);
|
|
|
|
{% for arg in method.arguments %}
|
|
{% set varName = as_varName(arg.name) %}
|
|
{% if arg.type.category in ["enum", "bitmask"] and arg.annotation == "value" %}
|
|
auto {{varName}}_ = static_cast<{{as_frontendType(arg.type)}}>({{varName}});
|
|
{% elif arg.annotation != "value" or arg.type.category == "object" %}
|
|
auto {{varName}}_ = reinterpret_cast<{{decorate("", as_frontendType(arg.type), arg)}}>({{varName}});
|
|
{% else %}
|
|
auto {{varName}}_ = {{as_varName(arg.name)}};
|
|
{% endif %}
|
|
{%- endfor-%}
|
|
|
|
{% if method.autolock %}
|
|
{% if type.name.get() != "device" %}
|
|
auto device = self->GetDevice();
|
|
{% else %}
|
|
auto device = self;
|
|
{% endif %}
|
|
auto deviceLock(device->GetScopedLock());
|
|
{% else %}
|
|
// This method is specified to not use AutoLock in json script.
|
|
{% endif %}
|
|
|
|
{% if method.return_type.name.canonical_case() != "void" %}
|
|
auto result =
|
|
{%- endif %}
|
|
self->API{{method.name.CamelCase()}}(
|
|
{%- for arg in method.arguments -%}
|
|
{%- if not loop.first %}, {% endif -%}
|
|
{{as_varName(arg.name)}}_
|
|
{%- endfor -%}
|
|
);
|
|
{% if method.return_type.name.canonical_case() != "void" %}
|
|
{% if method.return_type.category in ["object", "enum", "bitmask"] %}
|
|
return ToAPI(result);
|
|
{% else %}
|
|
return result;
|
|
{% endif %}
|
|
{% endif %}
|
|
}
|
|
{% endfor %}
|
|
{% endfor %}
|
|
|
|
{% for function in by_category["function"] if function.name.canonical_case() != "get proc address" %}
|
|
{{as_cType(function.return_type.name)}} Native{{function.name.CamelCase()}}(
|
|
{%- for arg in function.arguments -%}
|
|
{%- if not loop.first %}, {% endif -%}
|
|
{{as_annotated_cType(arg)}}
|
|
{%- endfor -%}
|
|
) {
|
|
{% for arg in function.arguments %}
|
|
{% set varName = as_varName(arg.name) %}
|
|
{% if arg.type.category in ["enum", "bitmask"] and arg.annotation == "value" %}
|
|
auto {{varName}}_ = static_cast<{{as_frontendType(arg.type)}}>({{varName}});
|
|
{% elif arg.annotation != "value" or arg.type.category == "object" %}
|
|
auto {{varName}}_ = reinterpret_cast<{{decorate("", as_frontendType(arg.type), arg)}}>({{varName}});
|
|
{% else %}
|
|
auto {{varName}}_ = {{as_varName(arg.name)}};
|
|
{% endif %}
|
|
{%- endfor-%}
|
|
|
|
{% if function.return_type.name.canonical_case() != "void" %}
|
|
auto result =
|
|
{%- endif %}
|
|
API{{function.name.CamelCase()}}(
|
|
{%- for arg in function.arguments -%}
|
|
{%- if not loop.first %}, {% endif -%}
|
|
{{as_varName(arg.name)}}_
|
|
{%- endfor -%}
|
|
);
|
|
{% if function.return_type.name.canonical_case() != "void" %}
|
|
{% if function.return_type.category in ["object", "enum", "bitmask"] %}
|
|
return ToAPI(result);
|
|
{% else %}
|
|
return result;
|
|
{% endif %}
|
|
{% endif %}
|
|
}
|
|
{% endfor %}
|
|
|
|
namespace {
|
|
|
|
{% set c_prefix = metadata.c_prefix %}
|
|
struct ProcEntry {
|
|
{{c_prefix}}Proc proc;
|
|
const char* name;
|
|
};
|
|
static const ProcEntry sProcMap[] = {
|
|
{% for (type, method) in c_methods_sorted_by_name %}
|
|
{ reinterpret_cast<{{c_prefix}}Proc>(Native{{as_MethodSuffix(type.name, method.name)}}), "{{as_cMethod(type.name, method.name)}}" },
|
|
{% endfor %}
|
|
};
|
|
static constexpr size_t sProcMapSize = sizeof(sProcMap) / sizeof(sProcMap[0]);
|
|
|
|
} // anonymous namespace
|
|
|
|
WGPUProc NativeGetProcAddress(WGPUDevice, const char* procName) {
|
|
if (procName == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
const ProcEntry* entry = std::lower_bound(&sProcMap[0], &sProcMap[sProcMapSize], procName,
|
|
[](const ProcEntry &a, const char *b) -> bool {
|
|
return strcmp(a.name, b) < 0;
|
|
}
|
|
);
|
|
|
|
if (entry != &sProcMap[sProcMapSize] && strcmp(entry->name, procName) == 0) {
|
|
return entry->proc;
|
|
}
|
|
|
|
// Special case the free-standing functions of the API.
|
|
// TODO(dawn:1238) Checking string one by one is slow, it needs to be optimized.
|
|
{% for function in by_category["function"] %}
|
|
if (strcmp(procName, "{{as_cMethod(None, function.name)}}") == 0) {
|
|
return reinterpret_cast<{{c_prefix}}Proc>(Native{{as_cppType(function.name)}});
|
|
}
|
|
|
|
{% endfor %}
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<const char*> GetProcMapNamesForTestingInternal() {
|
|
std::vector<const char*> result;
|
|
result.reserve(sProcMapSize);
|
|
for (const ProcEntry& entry : sProcMap) {
|
|
result.push_back(entry.name);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static {{Prefix}}ProcTable gProcTable = {
|
|
{% for function in by_category["function"] %}
|
|
Native{{as_cppType(function.name)}},
|
|
{% endfor %}
|
|
{% for type in by_category["object"] %}
|
|
{% for method in c_methods(type) %}
|
|
Native{{as_MethodSuffix(type.name, method.name)}},
|
|
{% endfor %}
|
|
{% endfor %}
|
|
};
|
|
|
|
const {{Prefix}}ProcTable& GetProcsAutogen() {
|
|
return gProcTable;
|
|
}
|
|
}
|