blob: f1fbb6c261db213e5e1256e31c228eece3ef3b2d [file] [log] [blame]
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02001// Copyright 2017 The Dawn Authors
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Corentin Wallezb91022d2018-01-19 12:52:25 -050015#include "SampleUtils.h"
16
Kai Ninomiya21006bb2018-06-20 18:54:18 -070017#include "common/Assert.h"
Corentin Wallez95586ff2019-12-05 11:13:01 +000018#include "common/Log.h"
Corentin Wallez0b186b12017-07-12 12:56:05 -040019#include "common/Platform.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040020#include "utils/BackendBinding.h"
Corentin Wallez3a1746e2020-01-15 13:14:12 +000021#include "utils/GLFWUtils.h"
Corentin Wallezbdc86772018-07-26 15:07:57 +020022#include "utils/TerribleCommandBuffer.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040023
Corentin Wallez96496822019-10-15 11:44:38 +000024#include <dawn/dawn_proc.h>
Corentin Wallez3e371b12018-07-18 14:32:45 +020025#include <dawn/dawn_wsi.h>
Corentin Wallezdcb71a12018-08-02 22:27:57 +020026#include <dawn_native/DawnNative.h>
Austin Enge2c85132019-02-11 21:50:16 +000027#include <dawn_wire/WireClient.h>
28#include <dawn_wire/WireServer.h>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040029#include "GLFW/glfw3.h"
30
Corentin Wallezbb5696b2019-02-12 15:48:15 +000031#include <algorithm>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040032#include <cstring>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040033
Corentin Wallez04863c42019-10-25 11:36:47 +000034void PrintDeviceError(WGPUErrorType errorType, const char* message, void*) {
Corentin Wallez95586ff2019-12-05 11:13:01 +000035 const char* errorTypeName = "";
Austin Engcb0cb652019-08-27 21:41:56 +000036 switch (errorType) {
Corentin Wallez04863c42019-10-25 11:36:47 +000037 case WGPUErrorType_Validation:
Corentin Wallez95586ff2019-12-05 11:13:01 +000038 errorTypeName = "Validation";
Austin Engcb0cb652019-08-27 21:41:56 +000039 break;
Corentin Wallez04863c42019-10-25 11:36:47 +000040 case WGPUErrorType_OutOfMemory:
Corentin Wallez95586ff2019-12-05 11:13:01 +000041 errorTypeName = "Out of memory";
Austin Engcb0cb652019-08-27 21:41:56 +000042 break;
Corentin Wallez04863c42019-10-25 11:36:47 +000043 case WGPUErrorType_Unknown:
Corentin Wallez95586ff2019-12-05 11:13:01 +000044 errorTypeName = "Unknown";
Austin Engcb0cb652019-08-27 21:41:56 +000045 break;
Corentin Wallez04863c42019-10-25 11:36:47 +000046 case WGPUErrorType_DeviceLost:
Corentin Wallez95586ff2019-12-05 11:13:01 +000047 errorTypeName = "Device lost";
Austin Engcb0cb652019-08-27 21:41:56 +000048 break;
49 default:
50 UNREACHABLE();
51 return;
52 }
Corentin Wallezdc3317d2019-12-06 18:21:39 +000053 dawn::ErrorLog() << errorTypeName << " error: " << message;
Corentin Wallez4b410a32017-04-20 14:42:36 -040054}
55
Corentin Wallez52cbcb42018-01-19 12:52:03 -050056void PrintGLFWError(int code, const char* message) {
Corentin Wallezdc3317d2019-12-06 18:21:39 +000057 dawn::ErrorLog() << "GLFW error: " << code << " - " << message;
Corentin Wallez52cbcb42018-01-19 12:52:03 -050058}
59
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040060enum class CmdBufType {
61 None,
62 Terrible,
Kai Ninomiya2afea0c2020-07-10 20:33:08 +000063 // TODO(cwallez@chromium.org): double terrible cmdbuf
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040064};
65
Corentin Wallez275817a2017-07-12 12:43:24 -040066// Default to D3D12, Metal, Vulkan, OpenGL in that order as D3D12 and Metal are the preferred on
67// their respective platforms, and Vulkan is preferred to OpenGL
Corentin Wallezf1ded9b2018-07-18 13:52:46 +020068#if defined(DAWN_ENABLE_BACKEND_D3D12)
Corentin Wallezf12c9db2020-01-10 13:28:18 +000069static wgpu::BackendType backendType = wgpu::BackendType::D3D12;
Corentin Wallezf1ded9b2018-07-18 13:52:46 +020070#elif defined(DAWN_ENABLE_BACKEND_METAL)
Corentin Wallezf12c9db2020-01-10 13:28:18 +000071static wgpu::BackendType backendType = wgpu::BackendType::Metal;
Corentin Wallezf1ded9b2018-07-18 13:52:46 +020072#elif defined(DAWN_ENABLE_BACKEND_VULKAN)
Corentin Wallezf12c9db2020-01-10 13:28:18 +000073static wgpu::BackendType backendType = wgpu::BackendType::Vulkan;
74#elif defined(DAWN_ENABLE_BACKEND_OPENGL)
75static wgpu::BackendType backendType = wgpu::BackendType::OpenGL;
Austin Engfc2bac72017-06-05 17:08:55 -040076#else
Kai Ninomiya2afea0c2020-07-10 20:33:08 +000077# error
Austin Engfc2bac72017-06-05 17:08:55 -040078#endif
79
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040080static CmdBufType cmdBufType = CmdBufType::Terrible;
Corentin Wallezbb5696b2019-02-12 15:48:15 +000081static std::unique_ptr<dawn_native::Instance> instance;
Corentin Wallez1bd219d2017-06-19 12:53:38 -040082static utils::BackendBinding* binding = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040083
84static GLFWwindow* window = nullptr;
85
Austin Enge2c85132019-02-11 21:50:16 +000086static dawn_wire::WireServer* wireServer = nullptr;
87static dawn_wire::WireClient* wireClient = nullptr;
Corentin Wallezbdc86772018-07-26 15:07:57 +020088static utils::TerribleCommandBuffer* c2sBuf = nullptr;
89static utils::TerribleCommandBuffer* s2cBuf = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040090
Corentin Wallez04863c42019-10-25 11:36:47 +000091wgpu::Device CreateCppDawnDevice() {
Corentin Wallez52cbcb42018-01-19 12:52:03 -050092 glfwSetErrorCallback(PrintGLFWError);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040093 if (!glfwInit()) {
Corentin Wallez04863c42019-10-25 11:36:47 +000094 return wgpu::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040095 }
96
Corentin Wallezbb5696b2019-02-12 15:48:15 +000097 // Create the test window and discover adapters using it (esp. for OpenGL)
98 utils::SetupGLFWWindowHintsForBackend(backendType);
Corentin Wallez47a6a942020-10-17 23:31:37 +000099 glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
Corentin Wallez6ed9cbf2018-07-18 15:32:04 +0200100 window = glfwCreateWindow(640, 480, "Dawn window", nullptr, nullptr);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400101 if (!window) {
Corentin Wallez04863c42019-10-25 11:36:47 +0000102 return wgpu::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400103 }
104
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000105 instance = std::make_unique<dawn_native::Instance>();
106 utils::DiscoverAdapter(instance.get(), window, backendType);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400107
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000108 // Get an adapter for the backend to use, and create the device.
109 dawn_native::Adapter backendAdapter;
110 {
111 std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
112 auto adapterIt = std::find_if(adapters.begin(), adapters.end(),
113 [](const dawn_native::Adapter adapter) -> bool {
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000114 wgpu::AdapterProperties properties;
115 adapter.GetProperties(&properties);
116 return properties.backendType == backendType;
117 });
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000118 ASSERT(adapterIt != adapters.end());
119 backendAdapter = *adapterIt;
120 }
121
Corentin Wallez04863c42019-10-25 11:36:47 +0000122 WGPUDevice backendDevice = backendAdapter.CreateDevice();
Austin Eng45f97302019-03-11 16:52:42 +0000123 DawnProcTable backendProcs = dawn_native::GetProcs();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400124
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000125 binding = utils::CreateBinding(backendType, window, backendDevice);
126 if (binding == nullptr) {
Corentin Wallez04863c42019-10-25 11:36:47 +0000127 return wgpu::Device();
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000128 }
129
130 // Choose whether to use the backend procs and devices directly, or set up the wire.
Corentin Wallez04863c42019-10-25 11:36:47 +0000131 WGPUDevice cDevice = nullptr;
Austin Eng45f97302019-03-11 16:52:42 +0000132 DawnProcTable procs;
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000133
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400134 switch (cmdBufType) {
135 case CmdBufType::None:
Corentin Wallez583e9a82017-05-29 11:30:29 -0700136 procs = backendProcs;
137 cDevice = backendDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400138 break;
139
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000140 case CmdBufType::Terrible: {
141 c2sBuf = new utils::TerribleCommandBuffer();
142 s2cBuf = new utils::TerribleCommandBuffer();
Corentin Wallez682a8252017-05-09 15:34:13 +0200143
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000144 dawn_wire::WireServerDescriptor serverDesc = {};
145 serverDesc.device = backendDevice;
146 serverDesc.procs = &backendProcs;
147 serverDesc.serializer = s2cBuf;
Austin Eng6a5418a2019-07-19 16:01:48 +0000148
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000149 wireServer = new dawn_wire::WireServer(serverDesc);
150 c2sBuf->SetHandler(wireServer);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400151
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000152 dawn_wire::WireClientDescriptor clientDesc = {};
153 clientDesc.serializer = c2sBuf;
Austin Eng6a5418a2019-07-19 16:01:48 +0000154
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000155 wireClient = new dawn_wire::WireClient(clientDesc);
Austin Eng87509132020-10-16 15:21:16 +0000156 cDevice = wireClient->GetDevice();
157 procs = dawn_wire::client::GetProcs();
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000158 s2cBuf->SetHandler(wireClient);
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000159 } break;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400160 }
161
Corentin Wallez96496822019-10-15 11:44:38 +0000162 dawnProcSetProcs(&procs);
Austin Eng45ea7e62019-08-27 21:43:56 +0000163 procs.deviceSetUncapturedErrorCallback(cDevice, PrintDeviceError, nullptr);
Corentin Wallez04863c42019-10-25 11:36:47 +0000164 return wgpu::Device::Acquire(cDevice);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400165}
166
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700167uint64_t GetSwapChainImplementation() {
168 return binding->GetSwapChainImplementation();
169}
170
Corentin Wallez04863c42019-10-25 11:36:47 +0000171wgpu::TextureFormat GetPreferredSwapChainTextureFormat() {
Corentin Wallezb91022d2018-01-19 12:52:25 -0500172 DoFlush();
Corentin Wallez04863c42019-10-25 11:36:47 +0000173 return static_cast<wgpu::TextureFormat>(binding->GetPreferredSwapChainTextureFormat());
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400174}
175
Corentin Wallez04863c42019-10-25 11:36:47 +0000176wgpu::SwapChain GetSwapChain(const wgpu::Device& device) {
177 wgpu::SwapChainDescriptor swapChainDesc;
Corentin Wallez7be2a712019-02-15 11:15:58 +0000178 swapChainDesc.implementation = GetSwapChainImplementation();
Corentin Wallezd87e6762020-01-23 17:20:38 +0000179 return device.CreateSwapChain(nullptr, &swapChainDesc);
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700180}
181
Corentin Wallez04863c42019-10-25 11:36:47 +0000182wgpu::TextureView CreateDefaultDepthStencilView(const wgpu::Device& device) {
183 wgpu::TextureDescriptor descriptor;
184 descriptor.dimension = wgpu::TextureDimension::e2D;
Corentin Wallez29353d62018-09-18 12:49:22 +0000185 descriptor.size.width = 640;
186 descriptor.size.height = 480;
187 descriptor.size.depth = 1;
Jiawei Shao8bff3b22018-12-12 09:27:16 +0000188 descriptor.sampleCount = 1;
Corentin Wallez04863c42019-10-25 11:36:47 +0000189 descriptor.format = wgpu::TextureFormat::Depth24PlusStencil8;
Jiawei Shao20301662019-02-21 00:45:19 +0000190 descriptor.mipLevelCount = 1;
Corentin Wallez04863c42019-10-25 11:36:47 +0000191 descriptor.usage = wgpu::TextureUsage::OutputAttachment;
Jiawei Shao425428f2018-08-27 08:44:48 +0800192 auto depthStencilTexture = device.CreateTexture(&descriptor);
Kai Ninomiya4078ed82019-08-27 17:56:23 +0000193 return depthStencilTexture.CreateView();
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700194}
195
Corentin Wallez9347e8f2017-06-19 13:15:13 -0400196bool InitSample(int argc, const char** argv) {
Corentin Wallez862f8842018-06-07 13:03:29 +0200197 for (int i = 1; i < argc; i++) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400198 if (std::string("-b") == argv[i] || std::string("--backend") == argv[i]) {
199 i++;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400200 if (i < argc && std::string("d3d12") == argv[i]) {
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000201 backendType = wgpu::BackendType::D3D12;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400202 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400203 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400204 if (i < argc && std::string("metal") == argv[i]) {
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000205 backendType = wgpu::BackendType::Metal;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400206 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400207 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400208 if (i < argc && std::string("null") == argv[i]) {
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000209 backendType = wgpu::BackendType::Null;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400210 continue;
211 }
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400212 if (i < argc && std::string("opengl") == argv[i]) {
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000213 backendType = wgpu::BackendType::OpenGL;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400214 continue;
215 }
216 if (i < argc && std::string("vulkan") == argv[i]) {
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000217 backendType = wgpu::BackendType::Vulkan;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400218 continue;
219 }
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000220 fprintf(stderr,
221 "--backend expects a backend name (opengl, metal, d3d12, null, vulkan)\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400222 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400223 }
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700224 if (std::string("-c") == argv[i] || std::string("--command-buffer") == argv[i]) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400225 i++;
226 if (i < argc && std::string("none") == argv[i]) {
227 cmdBufType = CmdBufType::None;
228 continue;
229 }
230 if (i < argc && std::string("terrible") == argv[i]) {
231 cmdBufType = CmdBufType::Terrible;
232 continue;
233 }
234 fprintf(stderr, "--command-buffer expects a command buffer name (none, terrible)\n");
235 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400236 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400237 if (std::string("-h") == argv[i] || std::string("--help") == argv[i]) {
238 printf("Usage: %s [-b BACKEND] [-c COMMAND_BUFFER]\n", argv[0]);
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400239 printf(" BACKEND is one of: d3d12, metal, null, opengl, vulkan\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400240 printf(" COMMAND_BUFFER is one of: none, terrible\n");
241 return false;
242 }
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400243 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400244 return true;
245}
246
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700247void DoFlush() {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400248 if (cmdBufType == CmdBufType::Terrible) {
Corentin Walleza5696c72018-08-13 08:24:01 +0200249 bool c2sSuccess = c2sBuf->Flush();
250 bool s2cSuccess = s2cBuf->Flush();
251
252 ASSERT(c2sSuccess && s2cSuccess);
Corentin Wallez931e6e82017-06-16 18:51:14 -0400253 }
254 glfwPollEvents();
Corentin Wallez931e6e82017-06-16 18:51:14 -0400255}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400256
Corentin Wallez931e6e82017-06-16 18:51:14 -0400257bool ShouldQuit() {
258 return glfwWindowShouldClose(window);
259}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400260
Corentin Wallez931e6e82017-06-16 18:51:14 -0400261GLFWwindow* GetGLFWWindow() {
262 return window;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400263}