Factor out common cache testing code.
- To be used for pipeline cache testing. - Plumbs overriding the platform to the adapters for testing. - Restructures build a little bit so that the test infrastructure can have full access to dawn native internals. Also differentiates end2end and white_box a bit more to make it clear that end2end should not have access to dawn native internals. Bug: dawn:549, dawn:1374 Change-Id: Ibcc6c44a116c7967ee2317c74409f613e896eb0a Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86841 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Loko Kung <lokokung@google.com>
This commit is contained in:
parent
12d45e2068
commit
4091e0fa9c
|
@ -164,6 +164,7 @@ namespace dawn::native {
|
||||||
// Enable debug capture on Dawn startup
|
// Enable debug capture on Dawn startup
|
||||||
void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
|
void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
|
||||||
|
|
||||||
|
// TODO(dawn:1374) Deprecate this once it is passed via the descriptor.
|
||||||
void SetPlatform(dawn::platform::Platform* platform);
|
void SetPlatform(dawn::platform::Platform* platform);
|
||||||
|
|
||||||
// Returns the underlying WGPUInstance object.
|
// Returns the underlying WGPUInstance object.
|
||||||
|
|
|
@ -240,6 +240,7 @@ namespace dawn::native {
|
||||||
mImpl->EnableBeginCaptureOnStartup(beginCaptureOnStartup);
|
mImpl->EnableBeginCaptureOnStartup(beginCaptureOnStartup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(dawn:1374) Deprecate this once it is passed via the descriptor.
|
||||||
void Instance::SetPlatform(dawn::platform::Platform* platform) {
|
void Instance::SetPlatform(dawn::platform::Platform* platform) {
|
||||||
mImpl->SetPlatform(platform);
|
mImpl->SetPlatform(platform);
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,15 +422,12 @@ namespace dawn::native {
|
||||||
mBlobCache = std::make_unique<BlobCache>(GetCachingInterface(platform));
|
mBlobCache = std::make_unique<BlobCache>(GetCachingInterface(platform));
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::platform::Platform* InstanceBase::GetPlatform() {
|
void InstanceBase::SetPlatformForTesting(dawn::platform::Platform* platform) {
|
||||||
if (mPlatform != nullptr) {
|
SetPlatform(platform);
|
||||||
return mPlatform;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDefaultPlatform == nullptr) {
|
dawn::platform::Platform* InstanceBase::GetPlatform() {
|
||||||
mDefaultPlatform = std::make_unique<dawn::platform::Platform>();
|
return mPlatform;
|
||||||
}
|
|
||||||
return mDefaultPlatform.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlobCache* InstanceBase::GetBlobCache() {
|
BlobCache* InstanceBase::GetBlobCache() {
|
||||||
|
|
|
@ -77,9 +77,10 @@ namespace dawn::native {
|
||||||
void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
|
void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
|
||||||
bool IsBeginCaptureOnStartupEnabled() const;
|
bool IsBeginCaptureOnStartupEnabled() const;
|
||||||
|
|
||||||
// TODO(dawn:1374): SetPlatform should become a private helper, and a NOT thread-safe
|
// TODO(dawn:1374): SetPlatform should become a private helper, and SetPlatformForTesting
|
||||||
// testing version exposed for special testing cases.
|
// will become the NOT thread-safe testing version exposed for special testing cases.
|
||||||
void SetPlatform(dawn::platform::Platform* platform);
|
void SetPlatform(dawn::platform::Platform* platform);
|
||||||
|
void SetPlatformForTesting(dawn::platform::Platform* platform);
|
||||||
dawn::platform::Platform* GetPlatform();
|
dawn::platform::Platform* GetPlatform();
|
||||||
BlobCache* GetBlobCache();
|
BlobCache* GetBlobCache();
|
||||||
|
|
||||||
|
|
|
@ -330,32 +330,76 @@ dawn_test("dawn_unittests") {
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Dawn end2end tests targets
|
# Dawn test infrastructure targets
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
source_set("end2end_tests_sources") {
|
source_set("test_infra_sources") {
|
||||||
configs += [ "${dawn_root}/src/dawn/common:internal_config" ]
|
configs += [ "${dawn_root}/src/dawn/native:internal" ]
|
||||||
testonly = true
|
testonly = true
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":gmock_and_gtest",
|
|
||||||
"${dawn_root}/src/dawn:cpp",
|
"${dawn_root}/src/dawn:cpp",
|
||||||
"${dawn_root}/src/dawn:proc",
|
"${dawn_root}/src/dawn:proc",
|
||||||
"${dawn_root}/src/dawn/common",
|
"${dawn_root}/src/dawn/common",
|
||||||
|
"${dawn_root}/src/dawn/native:sources",
|
||||||
# Statically linked because the end2end white_box tests use Dawn internals.
|
|
||||||
"${dawn_root}/src/dawn/native:static",
|
"${dawn_root}/src/dawn/native:static",
|
||||||
"${dawn_root}/src/dawn/platform:platform",
|
|
||||||
"${dawn_root}/src/dawn/utils",
|
"${dawn_root}/src/dawn/utils",
|
||||||
"${dawn_root}/src/dawn/wire",
|
"${dawn_root}/src/dawn/wire",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
public_deps = [ ":gmock_and_gtest" ]
|
||||||
|
|
||||||
|
if (dawn_supports_glfw_for_windowing || dawn_enable_opengl) {
|
||||||
|
assert(dawn_supports_glfw_for_windowing)
|
||||||
|
public_deps += [ "${dawn_root}/src/dawn/utils:glfw" ]
|
||||||
|
}
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
|
"DawnTest.cpp",
|
||||||
"DawnTest.h",
|
"DawnTest.h",
|
||||||
"MockCallback.h",
|
"MockCallback.h",
|
||||||
"ParamGenerator.h",
|
"ParamGenerator.h",
|
||||||
"ToggleParser.cpp",
|
"ToggleParser.cpp",
|
||||||
"ToggleParser.h",
|
"ToggleParser.h",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Dawn end2end tests targets
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Source code for mocks used for end2end testing are separated from the rest of
|
||||||
|
# sources so that they aren't included in non-test builds.
|
||||||
|
source_set("end2end_mocks_sources") {
|
||||||
|
configs += [ "${dawn_root}/src/dawn/native:internal" ]
|
||||||
|
testonly = true
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
":gmock_and_gtest",
|
||||||
|
"${dawn_root}/src/dawn/platform",
|
||||||
|
]
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
"end2end/mocks/CachingInterfaceMock.cpp",
|
||||||
|
"end2end/mocks/CachingInterfaceMock.h",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
source_set("end2end_tests_sources") {
|
||||||
|
testonly = true
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
":end2end_mocks_sources",
|
||||||
|
":test_infra_sources",
|
||||||
|
"${dawn_root}/src/dawn:cpp",
|
||||||
|
"${dawn_root}/src/dawn:proc",
|
||||||
|
"${dawn_root}/src/dawn/common",
|
||||||
|
"${dawn_root}/src/dawn/native:headers",
|
||||||
|
"${dawn_root}/src/dawn/utils",
|
||||||
|
"${dawn_root}/src/dawn/wire",
|
||||||
|
]
|
||||||
|
|
||||||
|
sources = [
|
||||||
"end2end/AdapterDiscoveryTests.cpp",
|
"end2end/AdapterDiscoveryTests.cpp",
|
||||||
"end2end/BasicTests.cpp",
|
"end2end/BasicTests.cpp",
|
||||||
"end2end/BindGroupTests.cpp",
|
"end2end/BindGroupTests.cpp",
|
||||||
|
@ -461,17 +505,12 @@ source_set("end2end_tests_sources") {
|
||||||
frameworks = [ "IOSurface.framework" ]
|
frameworks = [ "IOSurface.framework" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dawn_enable_opengl) {
|
|
||||||
assert(dawn_supports_glfw_for_windowing)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dawn_supports_glfw_for_windowing) {
|
if (dawn_supports_glfw_for_windowing) {
|
||||||
sources += [
|
sources += [
|
||||||
"end2end/SwapChainTests.cpp",
|
"end2end/SwapChainTests.cpp",
|
||||||
"end2end/SwapChainValidationTests.cpp",
|
"end2end/SwapChainValidationTests.cpp",
|
||||||
"end2end/WindowSurfaceTests.cpp",
|
"end2end/WindowSurfaceTests.cpp",
|
||||||
]
|
]
|
||||||
deps += [ "${dawn_root}/src/dawn/utils:glfw" ]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dawn_enable_d3d12 || (dawn_enable_vulkan && is_chromeos) ||
|
if (dawn_enable_d3d12 || (dawn_enable_vulkan && is_chromeos) ||
|
||||||
|
@ -492,23 +531,19 @@ source_set("white_box_tests_sources") {
|
||||||
testonly = true
|
testonly = true
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":gmock_and_gtest",
|
":test_infra_sources",
|
||||||
"${dawn_root}/src/dawn:cpp",
|
"${dawn_root}/src/dawn:cpp",
|
||||||
"${dawn_root}/src/dawn:proc",
|
"${dawn_root}/src/dawn:proc",
|
||||||
"${dawn_root}/src/dawn/common",
|
"${dawn_root}/src/dawn/common",
|
||||||
"${dawn_root}/src/dawn/native:sources",
|
|
||||||
|
|
||||||
# Statically linked because the end2end white_box tests use Dawn internals.
|
# Statically linked and with sources because the end2end white_box tests use Dawn internals.
|
||||||
|
"${dawn_root}/src/dawn/native:sources",
|
||||||
"${dawn_root}/src/dawn/native:static",
|
"${dawn_root}/src/dawn/native:static",
|
||||||
"${dawn_root}/src/dawn/utils",
|
"${dawn_root}/src/dawn/utils",
|
||||||
"${dawn_root}/src/dawn/wire",
|
"${dawn_root}/src/dawn/wire",
|
||||||
]
|
]
|
||||||
|
|
||||||
sources = [
|
sources = []
|
||||||
"DawnTest.h",
|
|
||||||
"ParamGenerator.h",
|
|
||||||
"ToggleParser.h",
|
|
||||||
]
|
|
||||||
|
|
||||||
if (dawn_enable_vulkan) {
|
if (dawn_enable_vulkan) {
|
||||||
deps += [ "${dawn_vulkan_headers_dir}:vulkan_headers" ]
|
deps += [ "${dawn_vulkan_headers_dir}:vulkan_headers" ]
|
||||||
|
@ -552,10 +587,6 @@ source_set("white_box_tests_sources") {
|
||||||
sources += [ "white_box/MetalAutoreleasePoolTests.mm" ]
|
sources += [ "white_box/MetalAutoreleasePoolTests.mm" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dawn_enable_opengl) {
|
|
||||||
deps += [ "${dawn_root}/src/dawn/utils:glfw" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dawn_enable_opengles && defined(dawn_angle_dir)) {
|
if (dawn_enable_opengles && defined(dawn_angle_dir)) {
|
||||||
sources += [ "white_box/EGLImageWrappingTests.cpp" ]
|
sources += [ "white_box/EGLImageWrappingTests.cpp" ]
|
||||||
deps += [ "${dawn_angle_dir}:libEGL" ]
|
deps += [ "${dawn_angle_dir}:libEGL" ]
|
||||||
|
@ -567,22 +598,11 @@ source_set("white_box_tests_sources") {
|
||||||
dawn_test("dawn_end2end_tests") {
|
dawn_test("dawn_end2end_tests") {
|
||||||
deps = [
|
deps = [
|
||||||
":end2end_tests_sources",
|
":end2end_tests_sources",
|
||||||
":gmock_and_gtest",
|
":test_infra_sources",
|
||||||
":white_box_tests_sources",
|
":white_box_tests_sources",
|
||||||
"${dawn_root}/src/dawn:cpp",
|
|
||||||
"${dawn_root}/src/dawn:proc",
|
|
||||||
"${dawn_root}/src/dawn/common",
|
|
||||||
"${dawn_root}/src/dawn/native:static",
|
|
||||||
"${dawn_root}/src/dawn/platform:platform",
|
|
||||||
"${dawn_root}/src/dawn/utils",
|
|
||||||
"${dawn_root}/src/dawn/wire",
|
|
||||||
]
|
|
||||||
|
|
||||||
sources = [
|
|
||||||
"DawnTest.cpp",
|
|
||||||
"DawnTest.h",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
sources = []
|
||||||
libs = []
|
libs = []
|
||||||
|
|
||||||
# When building inside Chromium, use their gtest main function because it is
|
# When building inside Chromium, use their gtest main function because it is
|
||||||
|
@ -593,10 +613,6 @@ dawn_test("dawn_end2end_tests") {
|
||||||
sources += [ "End2EndTestsMain.cpp" ]
|
sources += [ "End2EndTestsMain.cpp" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dawn_enable_opengl) {
|
|
||||||
deps += [ "${dawn_root}/src/dawn/utils:glfw" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_chromeos) {
|
if (is_chromeos) {
|
||||||
libs += [ "gbm" ]
|
libs += [ "gbm" ]
|
||||||
}
|
}
|
||||||
|
@ -608,22 +624,16 @@ dawn_test("dawn_end2end_tests") {
|
||||||
|
|
||||||
dawn_test("dawn_perf_tests") {
|
dawn_test("dawn_perf_tests") {
|
||||||
deps = [
|
deps = [
|
||||||
":gmock_and_gtest",
|
":test_infra_sources",
|
||||||
"${dawn_root}/src/dawn:cpp",
|
"${dawn_root}/src/dawn:cpp",
|
||||||
"${dawn_root}/src/dawn:proc",
|
"${dawn_root}/src/dawn:proc",
|
||||||
"${dawn_root}/src/dawn/common",
|
"${dawn_root}/src/dawn/common",
|
||||||
"${dawn_root}/src/dawn/native",
|
|
||||||
"${dawn_root}/src/dawn/platform",
|
"${dawn_root}/src/dawn/platform",
|
||||||
"${dawn_root}/src/dawn/utils",
|
"${dawn_root}/src/dawn/utils",
|
||||||
"${dawn_root}/src/dawn/wire",
|
"${dawn_root}/src/dawn/wire",
|
||||||
]
|
]
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
"DawnTest.cpp",
|
|
||||||
"DawnTest.h",
|
|
||||||
"ParamGenerator.h",
|
|
||||||
"ToggleParser.cpp",
|
|
||||||
"ToggleParser.h",
|
|
||||||
"perf_tests/BufferUploadPerf.cpp",
|
"perf_tests/BufferUploadPerf.cpp",
|
||||||
"perf_tests/DawnPerfTest.cpp",
|
"perf_tests/DawnPerfTest.cpp",
|
||||||
"perf_tests/DawnPerfTest.h",
|
"perf_tests/DawnPerfTest.h",
|
||||||
|
@ -648,8 +658,4 @@ dawn_test("dawn_perf_tests") {
|
||||||
if (dawn_enable_metal) {
|
if (dawn_enable_metal) {
|
||||||
frameworks = [ "IOSurface.framework" ]
|
frameworks = [ "IOSurface.framework" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dawn_enable_opengl) {
|
|
||||||
deps += [ "${dawn_root}/src/dawn/utils:glfw" ]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include "dawn/common/Platform.h"
|
#include "dawn/common/Platform.h"
|
||||||
#include "dawn/common/SystemUtils.h"
|
#include "dawn/common/SystemUtils.h"
|
||||||
#include "dawn/dawn_proc.h"
|
#include "dawn/dawn_proc.h"
|
||||||
|
#include "dawn/native/Instance.h"
|
||||||
|
#include "dawn/native/dawn_platform.h"
|
||||||
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
||||||
#include "dawn/utils/PlatformDebugLogger.h"
|
#include "dawn/utils/PlatformDebugLogger.h"
|
||||||
#include "dawn/utils/SystemUtils.h"
|
#include "dawn/utils/SystemUtils.h"
|
||||||
|
@ -921,9 +923,11 @@ void DawnTestBase::SetUp() {
|
||||||
mBackendAdapter = *it;
|
mBackendAdapter = *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the per-test platform. Tests can provide one by overloading CreateTestPlatform.
|
// Setup the per-test platform. Tests can provide one by overloading CreateTestPlatform. This is
|
||||||
|
// NOT a thread-safe operation and is allowed here for testing only.
|
||||||
mTestPlatform = CreateTestPlatform();
|
mTestPlatform = CreateTestPlatform();
|
||||||
gTestEnv->GetInstance()->SetPlatform(mTestPlatform.get());
|
dawn::native::FromAPI(gTestEnv->GetInstance()->Get())
|
||||||
|
->SetPlatformForTesting(mTestPlatform.get());
|
||||||
|
|
||||||
// Create the device from the adapter
|
// Create the device from the adapter
|
||||||
for (const char* forceEnabledWorkaround : mParam.forceEnabledWorkarounds) {
|
for (const char* forceEnabledWorkaround : mParam.forceEnabledWorkarounds) {
|
||||||
|
|
|
@ -13,97 +13,30 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "dawn/tests/DawnTest.h"
|
#include "dawn/tests/DawnTest.h"
|
||||||
|
#include "dawn/tests/end2end/mocks/CachingInterfaceMock.h"
|
||||||
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
||||||
#include "dawn/utils/WGPUHelpers.h"
|
#include "dawn/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
#define EXPECT_CACHE_HIT(N, statement) \
|
namespace {
|
||||||
do { \
|
using ::testing::NiceMock;
|
||||||
size_t before = mPersistentCache.mHitCount; \
|
} // namespace
|
||||||
statement; \
|
|
||||||
FlushWire(); \
|
|
||||||
size_t after = mPersistentCache.mHitCount; \
|
|
||||||
EXPECT_EQ(N, after - before); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
// FakePersistentCache implements a in-memory persistent cache.
|
|
||||||
class FakePersistentCache : public dawn::platform::CachingInterface {
|
|
||||||
public:
|
|
||||||
// PersistentCache API
|
|
||||||
void StoreData(const WGPUDevice device,
|
|
||||||
const void* key,
|
|
||||||
size_t keySize,
|
|
||||||
const void* value,
|
|
||||||
size_t valueSize) override {
|
|
||||||
if (mIsDisabled)
|
|
||||||
return;
|
|
||||||
const std::string keyStr(reinterpret_cast<const char*>(key), keySize);
|
|
||||||
|
|
||||||
const uint8_t* value_start = reinterpret_cast<const uint8_t*>(value);
|
|
||||||
std::vector<uint8_t> entry_value(value_start, value_start + valueSize);
|
|
||||||
|
|
||||||
EXPECT_TRUE(mCache.insert({keyStr, std::move(entry_value)}).second);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t LoadData(const WGPUDevice device,
|
|
||||||
const void* key,
|
|
||||||
size_t keySize,
|
|
||||||
void* value,
|
|
||||||
size_t valueSize) override {
|
|
||||||
const std::string keyStr(reinterpret_cast<const char*>(key), keySize);
|
|
||||||
auto entry = mCache.find(keyStr);
|
|
||||||
if (entry == mCache.end()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (valueSize >= entry->second.size()) {
|
|
||||||
memcpy(value, entry->second.data(), entry->second.size());
|
|
||||||
}
|
|
||||||
mHitCount++;
|
|
||||||
return entry->second.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
using Blob = std::vector<uint8_t>;
|
|
||||||
using FakeCache = std::unordered_map<std::string, Blob>;
|
|
||||||
|
|
||||||
FakeCache mCache;
|
|
||||||
|
|
||||||
size_t mHitCount = 0;
|
|
||||||
bool mIsDisabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test platform that only supports caching.
|
|
||||||
class DawnTestPlatform : public dawn::platform::Platform {
|
|
||||||
public:
|
|
||||||
explicit DawnTestPlatform(dawn::platform::CachingInterface* cachingInterface)
|
|
||||||
: mCachingInterface(cachingInterface) {
|
|
||||||
}
|
|
||||||
~DawnTestPlatform() override = default;
|
|
||||||
|
|
||||||
dawn::platform::CachingInterface* GetCachingInterface(const void* fingerprint,
|
|
||||||
size_t fingerprintSize) override {
|
|
||||||
return mCachingInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
dawn::platform::CachingInterface* mCachingInterface = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class D3D12CachingTests : public DawnTest {
|
class D3D12CachingTests : public DawnTest {
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<dawn::platform::Platform> CreateTestPlatform() override {
|
std::unique_ptr<dawn::platform::Platform> CreateTestPlatform() override {
|
||||||
return std::make_unique<DawnTestPlatform>(&mPersistentCache);
|
return std::make_unique<DawnCachingMockPlatform>(&mMockCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
FakePersistentCache mPersistentCache;
|
NiceMock<CachingInterfaceMock> mMockCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that duplicate WGSL still re-compiles HLSL even when the cache is not enabled.
|
// Test that duplicate WGSL still works (and re-compiles HLSL) when the cache is not enabled.
|
||||||
TEST_P(D3D12CachingTests, SameShaderNoCache) {
|
TEST_P(D3D12CachingTests, SameShaderNoCache) {
|
||||||
mPersistentCache.mIsDisabled = true;
|
mMockCache.Disable();
|
||||||
|
|
||||||
wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
|
wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
|
||||||
@stage(vertex) fn vertex_main() -> @builtin(position) vec4<f32> {
|
@stage(vertex) fn vertex_main() -> @builtin(position) vec4<f32> {
|
||||||
|
@ -122,11 +55,9 @@ TEST_P(D3D12CachingTests, SameShaderNoCache) {
|
||||||
desc.vertex.entryPoint = "vertex_main";
|
desc.vertex.entryPoint = "vertex_main";
|
||||||
desc.cFragment.module = module;
|
desc.cFragment.module = module;
|
||||||
desc.cFragment.entryPoint = "fragment_main";
|
desc.cFragment.entryPoint = "fragment_main";
|
||||||
|
EXPECT_CACHE_HIT(mMockCache, 0u, device.CreateRenderPipeline(&desc));
|
||||||
EXPECT_CACHE_HIT(0u, device.CreateRenderPipeline(&desc));
|
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(mMockCache.GetNumEntries(), 0u);
|
||||||
EXPECT_EQ(mPersistentCache.mCache.size(), 0u);
|
|
||||||
|
|
||||||
// Load the same WGSL shader from the cache.
|
// Load the same WGSL shader from the cache.
|
||||||
{
|
{
|
||||||
|
@ -135,11 +66,9 @@ TEST_P(D3D12CachingTests, SameShaderNoCache) {
|
||||||
desc.vertex.entryPoint = "vertex_main";
|
desc.vertex.entryPoint = "vertex_main";
|
||||||
desc.cFragment.module = module;
|
desc.cFragment.module = module;
|
||||||
desc.cFragment.entryPoint = "fragment_main";
|
desc.cFragment.entryPoint = "fragment_main";
|
||||||
|
EXPECT_CACHE_HIT(mMockCache, 0u, device.CreateRenderPipeline(&desc));
|
||||||
EXPECT_CACHE_HIT(0u, device.CreateRenderPipeline(&desc));
|
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(mMockCache.GetNumEntries(), 0u);
|
||||||
EXPECT_EQ(mPersistentCache.mCache.size(), 0u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test creating a pipeline from two entrypoints in multiple stages will cache the correct number
|
// Test creating a pipeline from two entrypoints in multiple stages will cache the correct number
|
||||||
|
@ -163,11 +92,9 @@ TEST_P(D3D12CachingTests, ReuseShaderWithMultipleEntryPointsPerStage) {
|
||||||
desc.vertex.entryPoint = "vertex_main";
|
desc.vertex.entryPoint = "vertex_main";
|
||||||
desc.cFragment.module = module;
|
desc.cFragment.module = module;
|
||||||
desc.cFragment.entryPoint = "fragment_main";
|
desc.cFragment.entryPoint = "fragment_main";
|
||||||
|
EXPECT_CACHE_HIT(mMockCache, 0u, device.CreateRenderPipeline(&desc));
|
||||||
EXPECT_CACHE_HIT(0u, device.CreateRenderPipeline(&desc));
|
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(mMockCache.GetNumEntries(), 2u);
|
||||||
EXPECT_EQ(mPersistentCache.mCache.size(), 2u);
|
|
||||||
|
|
||||||
// Load the same WGSL shader from the cache.
|
// Load the same WGSL shader from the cache.
|
||||||
{
|
{
|
||||||
|
@ -176,13 +103,9 @@ TEST_P(D3D12CachingTests, ReuseShaderWithMultipleEntryPointsPerStage) {
|
||||||
desc.vertex.entryPoint = "vertex_main";
|
desc.vertex.entryPoint = "vertex_main";
|
||||||
desc.cFragment.module = module;
|
desc.cFragment.module = module;
|
||||||
desc.cFragment.entryPoint = "fragment_main";
|
desc.cFragment.entryPoint = "fragment_main";
|
||||||
|
EXPECT_CACHE_HIT(mMockCache, 2u, device.CreateRenderPipeline(&desc));
|
||||||
// Cached HLSL shader calls LoadData twice (once to peek, again to get), so check 2 x
|
|
||||||
// kNumOfShaders hits.
|
|
||||||
EXPECT_CACHE_HIT(4u, device.CreateRenderPipeline(&desc));
|
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(mMockCache.GetNumEntries(), 2u);
|
||||||
EXPECT_EQ(mPersistentCache.mCache.size(), 2u);
|
|
||||||
|
|
||||||
// Modify the WGSL shader functions and make sure it doesn't hit.
|
// Modify the WGSL shader functions and make sure it doesn't hit.
|
||||||
wgpu::ShaderModule newModule = utils::CreateShaderModule(device, R"(
|
wgpu::ShaderModule newModule = utils::CreateShaderModule(device, R"(
|
||||||
|
@ -201,12 +124,9 @@ TEST_P(D3D12CachingTests, ReuseShaderWithMultipleEntryPointsPerStage) {
|
||||||
desc.vertex.entryPoint = "vertex_main";
|
desc.vertex.entryPoint = "vertex_main";
|
||||||
desc.cFragment.module = newModule;
|
desc.cFragment.module = newModule;
|
||||||
desc.cFragment.entryPoint = "fragment_main";
|
desc.cFragment.entryPoint = "fragment_main";
|
||||||
EXPECT_CACHE_HIT(0u, device.CreateRenderPipeline(&desc));
|
EXPECT_CACHE_HIT(mMockCache, 0u, device.CreateRenderPipeline(&desc));
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(mMockCache.GetNumEntries(), 4u);
|
||||||
// Cached HLSL shader calls LoadData twice (once to peek, again to get), so check 2 x
|
|
||||||
// kNumOfShaders hits.
|
|
||||||
EXPECT_EQ(mPersistentCache.mCache.size(), 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test creating a WGSL shader with two entrypoints in the same stage will cache the correct number
|
// Test creating a WGSL shader with two entrypoints in the same stage will cache the correct number
|
||||||
|
@ -232,33 +152,26 @@ TEST_P(D3D12CachingTests, ReuseShaderWithMultipleEntryPoints) {
|
||||||
wgpu::ComputePipelineDescriptor desc;
|
wgpu::ComputePipelineDescriptor desc;
|
||||||
desc.compute.module = module;
|
desc.compute.module = module;
|
||||||
desc.compute.entryPoint = "write1";
|
desc.compute.entryPoint = "write1";
|
||||||
EXPECT_CACHE_HIT(0u, device.CreateComputePipeline(&desc));
|
EXPECT_CACHE_HIT(mMockCache, 0u, device.CreateComputePipeline(&desc));
|
||||||
|
|
||||||
desc.compute.module = module;
|
desc.compute.module = module;
|
||||||
desc.compute.entryPoint = "write42";
|
desc.compute.entryPoint = "write42";
|
||||||
EXPECT_CACHE_HIT(0u, device.CreateComputePipeline(&desc));
|
EXPECT_CACHE_HIT(mMockCache, 0u, device.CreateComputePipeline(&desc));
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(mMockCache.GetNumEntries(), 2u);
|
||||||
EXPECT_EQ(mPersistentCache.mCache.size(), 2u);
|
|
||||||
|
|
||||||
// Load the same WGSL shader from the cache.
|
// Load the same WGSL shader from the cache.
|
||||||
{
|
{
|
||||||
wgpu::ComputePipelineDescriptor desc;
|
wgpu::ComputePipelineDescriptor desc;
|
||||||
desc.compute.module = module;
|
desc.compute.module = module;
|
||||||
desc.compute.entryPoint = "write1";
|
desc.compute.entryPoint = "write1";
|
||||||
|
EXPECT_CACHE_HIT(mMockCache, 1u, device.CreateComputePipeline(&desc));
|
||||||
// Cached HLSL shader calls LoadData twice (once to peek, again to get), so check 2 x
|
|
||||||
// kNumOfShaders hits.
|
|
||||||
EXPECT_CACHE_HIT(2u, device.CreateComputePipeline(&desc));
|
|
||||||
|
|
||||||
desc.compute.module = module;
|
desc.compute.module = module;
|
||||||
desc.compute.entryPoint = "write42";
|
desc.compute.entryPoint = "write42";
|
||||||
|
EXPECT_CACHE_HIT(mMockCache, 1u, device.CreateComputePipeline(&desc));
|
||||||
// Cached HLSL shader calls LoadData twice, so check 2 x kNumOfShaders hits.
|
|
||||||
EXPECT_CACHE_HIT(2u, device.CreateComputePipeline(&desc));
|
|
||||||
}
|
}
|
||||||
|
EXPECT_EQ(mMockCache.GetNumEntries(), 2u);
|
||||||
EXPECT_EQ(mPersistentCache.mCache.size(), 2u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(D3D12CachingTests, D3D12Backend());
|
DAWN_INSTANTIATE_TEST(D3D12CachingTests, D3D12Backend());
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright 2022 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/tests/end2end/mocks/CachingInterfaceMock.h"
|
||||||
|
|
||||||
|
using ::testing::Invoke;
|
||||||
|
|
||||||
|
CachingInterfaceMock::CachingInterfaceMock() {
|
||||||
|
ON_CALL(*this, LoadData).WillByDefault(Invoke([=](auto&&... args) {
|
||||||
|
return LoadDataDefault(args...);
|
||||||
|
}));
|
||||||
|
ON_CALL(*this, StoreData).WillByDefault(Invoke([=](auto&&... args) {
|
||||||
|
return StoreDataDefault(args...);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CachingInterfaceMock::Enable() {
|
||||||
|
mEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CachingInterfaceMock::Disable() {
|
||||||
|
mEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CachingInterfaceMock::GetHitCount() const {
|
||||||
|
return mHitCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CachingInterfaceMock::GetNumEntries() const {
|
||||||
|
return mCache.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CachingInterfaceMock::LoadDataDefault(const WGPUDevice device,
|
||||||
|
const void* key,
|
||||||
|
size_t keySize,
|
||||||
|
void* value,
|
||||||
|
size_t valueSize) {
|
||||||
|
if (!mEnabled) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string keyStr(reinterpret_cast<const char*>(key), keySize);
|
||||||
|
auto entry = mCache.find(keyStr);
|
||||||
|
if (entry == mCache.end()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (valueSize >= entry->second.size()) {
|
||||||
|
// Only consider a cache-hit on the memcpy, since peeks are implementation detail.
|
||||||
|
memcpy(value, entry->second.data(), entry->second.size());
|
||||||
|
mHitCount++;
|
||||||
|
}
|
||||||
|
return entry->second.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CachingInterfaceMock::StoreDataDefault(const WGPUDevice device,
|
||||||
|
const void* key,
|
||||||
|
size_t keySize,
|
||||||
|
const void* value,
|
||||||
|
size_t valueSize) {
|
||||||
|
if (!mEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string keyStr(reinterpret_cast<const char*>(key), keySize);
|
||||||
|
const uint8_t* it = reinterpret_cast<const uint8_t*>(value);
|
||||||
|
std::vector<uint8_t> entry(it, it + valueSize);
|
||||||
|
mCache.insert_or_assign(keyStr, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
DawnCachingMockPlatform::DawnCachingMockPlatform(dawn::platform::CachingInterface* cachingInterface)
|
||||||
|
: mCachingInterface(cachingInterface) {
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::platform::CachingInterface* DawnCachingMockPlatform::GetCachingInterface(
|
||||||
|
const void* fingerprint,
|
||||||
|
size_t fingerprintSize) {
|
||||||
|
return mCachingInterface;
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright 2022 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 SRC_DAWN_TESTS_END2END_MOCKS_CACHINGINTERFACEMOCK_H_
|
||||||
|
#define SRC_DAWN_TESTS_END2END_MOCKS_CACHINGINTERFACEMOCK_H_
|
||||||
|
|
||||||
|
#include <dawn/platform/DawnPlatform.h>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define EXPECT_CACHE_HIT(cache, N, statement) \
|
||||||
|
do { \
|
||||||
|
FlushWire(); \
|
||||||
|
size_t before = cache.GetHitCount(); \
|
||||||
|
statement; \
|
||||||
|
FlushWire(); \
|
||||||
|
size_t after = cache.GetHitCount(); \
|
||||||
|
EXPECT_EQ(N, after - before); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
// A mock caching interface class that also supplies an in memory cache for testing.
|
||||||
|
class CachingInterfaceMock : public dawn::platform::CachingInterface {
|
||||||
|
public:
|
||||||
|
CachingInterfaceMock();
|
||||||
|
|
||||||
|
// Toggles to disable/enable caching.
|
||||||
|
void Disable();
|
||||||
|
void Enable();
|
||||||
|
|
||||||
|
// Returns the number of cache hits up to this point.
|
||||||
|
size_t GetHitCount() const;
|
||||||
|
|
||||||
|
// Returns the number of entries in the cache.
|
||||||
|
size_t GetNumEntries() const;
|
||||||
|
|
||||||
|
MOCK_METHOD(size_t,
|
||||||
|
LoadData,
|
||||||
|
(const WGPUDevice, const void*, size_t, void*, size_t),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
StoreData,
|
||||||
|
(const WGPUDevice, const void*, size_t, const void*, size_t),
|
||||||
|
(override));
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t LoadDataDefault(const WGPUDevice device,
|
||||||
|
const void* key,
|
||||||
|
size_t keySize,
|
||||||
|
void* value,
|
||||||
|
size_t valueSize);
|
||||||
|
void StoreDataDefault(const WGPUDevice device,
|
||||||
|
const void* key,
|
||||||
|
size_t keySize,
|
||||||
|
const void* value,
|
||||||
|
size_t valueSize);
|
||||||
|
|
||||||
|
bool mEnabled = true;
|
||||||
|
size_t mHitCount = 0;
|
||||||
|
std::unordered_map<std::string, std::vector<uint8_t>> mCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Dawn platform used for testing with a mock caching interface.
|
||||||
|
class DawnCachingMockPlatform : public dawn::platform::Platform {
|
||||||
|
public:
|
||||||
|
explicit DawnCachingMockPlatform(dawn::platform::CachingInterface* cachingInterface);
|
||||||
|
dawn::platform::CachingInterface* GetCachingInterface(const void* fingerprint,
|
||||||
|
size_t fingerprintSize) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
dawn::platform::CachingInterface* mCachingInterface = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SRC_DAWN_TESTS_END2END_MOCKS_CACHINGINTERFACEMOCK_H_
|
Loading…
Reference in New Issue