blob: b78cf58e0ec0d4e7325d04972ce60e0481d4e873 [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 Wallez0b186b12017-07-12 12:56:05 -040018#include "common/Platform.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040019#include "utils/BackendBinding.h"
Corentin Wallezbdc86772018-07-26 15:07:57 +020020#include "utils/TerribleCommandBuffer.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040021
Corentin Wallez046cb462018-07-18 14:28:38 +020022#include <dawn/dawn.h>
Corentin Wallez3e371b12018-07-18 14:32:45 +020023#include <dawn/dawn_wsi.h>
Austin Enge2c85132019-02-11 21:50:16 +000024#include <dawn/dawncpp.h>
Corentin Wallezdcb71a12018-08-02 22:27:57 +020025#include <dawn_native/DawnNative.h>
Austin Enge2c85132019-02-11 21:50:16 +000026#include <dawn_wire/WireClient.h>
27#include <dawn_wire/WireServer.h>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040028#include "GLFW/glfw3.h"
29
Corentin Wallezbb5696b2019-02-12 15:48:15 +000030#include <algorithm>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040031#include <cstring>
32#include <iostream>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040033
Corentin Wallez4828d922018-07-18 13:45:46 +020034void PrintDeviceError(const char* message, dawn::CallbackUserdata) {
Corentin Wallez4b410a32017-04-20 14:42:36 -040035 std::cout << "Device error: " << message << std::endl;
36}
37
Corentin Wallez52cbcb42018-01-19 12:52:03 -050038void PrintGLFWError(int code, const char* message) {
39 std::cout << "GLFW error: " << code << " - " << message << std::endl;
40}
41
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040042enum class CmdBufType {
43 None,
44 Terrible,
Corentin Wallez682a8252017-05-09 15:34:13 +020045 //TODO(cwallez@chromium.org) double terrible cmdbuf
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040046};
47
Corentin Wallez275817a2017-07-12 12:43:24 -040048// Default to D3D12, Metal, Vulkan, OpenGL in that order as D3D12 and Metal are the preferred on
49// their respective platforms, and Vulkan is preferred to OpenGL
Corentin Wallezf1ded9b2018-07-18 13:52:46 +020050#if defined(DAWN_ENABLE_BACKEND_D3D12)
Corentin Wallez8c88e1d2019-02-05 12:17:20 +000051 static dawn_native::BackendType backendType = dawn_native::BackendType::D3D12;
Corentin Wallezf1ded9b2018-07-18 13:52:46 +020052#elif defined(DAWN_ENABLE_BACKEND_METAL)
Corentin Wallez8c88e1d2019-02-05 12:17:20 +000053 static dawn_native::BackendType backendType = dawn_native::BackendType::Metal;
Corentin Wallezf1ded9b2018-07-18 13:52:46 +020054#elif defined(DAWN_ENABLE_BACKEND_OPENGL)
Corentin Wallez8c88e1d2019-02-05 12:17:20 +000055 static dawn_native::BackendType backendType = dawn_native::BackendType::OpenGL;
Corentin Wallezf1ded9b2018-07-18 13:52:46 +020056#elif defined(DAWN_ENABLE_BACKEND_VULKAN)
Corentin Wallez8c88e1d2019-02-05 12:17:20 +000057 static dawn_native::BackendType backendType = dawn_native::BackendType::Vulkan;
Austin Engfc2bac72017-06-05 17:08:55 -040058#else
Corentin Wallez275817a2017-07-12 12:43:24 -040059 #error
Austin Engfc2bac72017-06-05 17:08:55 -040060#endif
61
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040062static CmdBufType cmdBufType = CmdBufType::Terrible;
Corentin Wallezbb5696b2019-02-12 15:48:15 +000063static std::unique_ptr<dawn_native::Instance> instance;
Corentin Wallez1bd219d2017-06-19 12:53:38 -040064static utils::BackendBinding* binding = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040065
66static GLFWwindow* window = nullptr;
67
Austin Enge2c85132019-02-11 21:50:16 +000068static dawn_wire::WireServer* wireServer = nullptr;
69static dawn_wire::WireClient* wireClient = nullptr;
Corentin Wallezbdc86772018-07-26 15:07:57 +020070static utils::TerribleCommandBuffer* c2sBuf = nullptr;
71static utils::TerribleCommandBuffer* s2cBuf = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040072
Corentin Wallez39039fa2018-07-18 14:06:10 +020073dawn::Device CreateCppDawnDevice() {
Corentin Wallez52cbcb42018-01-19 12:52:03 -050074 glfwSetErrorCallback(PrintGLFWError);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040075 if (!glfwInit()) {
Corentin Wallez4828d922018-07-18 13:45:46 +020076 return dawn::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040077 }
78
Corentin Wallezbb5696b2019-02-12 15:48:15 +000079 // Create the test window and discover adapters using it (esp. for OpenGL)
80 utils::SetupGLFWWindowHintsForBackend(backendType);
Corentin Wallez6ed9cbf2018-07-18 15:32:04 +020081 window = glfwCreateWindow(640, 480, "Dawn window", nullptr, nullptr);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040082 if (!window) {
Corentin Wallez4828d922018-07-18 13:45:46 +020083 return dawn::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040084 }
85
Corentin Wallezbb5696b2019-02-12 15:48:15 +000086 instance = std::make_unique<dawn_native::Instance>();
87 utils::DiscoverAdapter(instance.get(), window, backendType);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040088
Corentin Wallezbb5696b2019-02-12 15:48:15 +000089 // Get an adapter for the backend to use, and create the device.
90 dawn_native::Adapter backendAdapter;
91 {
92 std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
93 auto adapterIt = std::find_if(adapters.begin(), adapters.end(),
94 [](const dawn_native::Adapter adapter) -> bool {
95 return adapter.GetBackendType() == backendType;
96 });
97 ASSERT(adapterIt != adapters.end());
98 backendAdapter = *adapterIt;
99 }
100
101 dawnDevice backendDevice = backendAdapter.CreateDevice();
Corentin Wallezdcb71a12018-08-02 22:27:57 +0200102 dawnProcTable backendProcs = dawn_native::GetProcs();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400103
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000104 binding = utils::CreateBinding(backendType, window, backendDevice);
105 if (binding == nullptr) {
106 return dawn::Device();
107 }
108
109 // Choose whether to use the backend procs and devices directly, or set up the wire.
Corentin Wallezb1669e32018-07-18 15:12:52 +0200110 dawnDevice cDevice = nullptr;
Corentin Wallezbe5ca382018-07-18 15:15:07 +0200111 dawnProcTable procs;
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000112
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400113 switch (cmdBufType) {
114 case CmdBufType::None:
Corentin Wallez583e9a82017-05-29 11:30:29 -0700115 procs = backendProcs;
116 cDevice = backendDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400117 break;
118
119 case CmdBufType::Terrible:
120 {
Corentin Wallezbdc86772018-07-26 15:07:57 +0200121 c2sBuf = new utils::TerribleCommandBuffer();
122 s2cBuf = new utils::TerribleCommandBuffer();
Corentin Wallez682a8252017-05-09 15:34:13 +0200123
Austin Enge2c85132019-02-11 21:50:16 +0000124 wireServer = new dawn_wire::WireServer(backendDevice, backendProcs, s2cBuf);
Corentin Wallez682a8252017-05-09 15:34:13 +0200125 c2sBuf->SetHandler(wireServer);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400126
Austin Enge2c85132019-02-11 21:50:16 +0000127 wireClient = new dawn_wire::WireClient(c2sBuf);
128 dawnDevice clientDevice = wireClient->GetDevice();
129 dawnProcTable clientProcs = wireClient->GetProcs();
Corentin Wallez682a8252017-05-09 15:34:13 +0200130 s2cBuf->SetHandler(wireClient);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400131
Corentin Wallez583e9a82017-05-29 11:30:29 -0700132 procs = clientProcs;
133 cDevice = clientDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400134 }
135 break;
136 }
137
Corentin Wallezbe5ca382018-07-18 15:15:07 +0200138 dawnSetProcs(&procs);
Corentin Wallez583e9a82017-05-29 11:30:29 -0700139 procs.deviceSetErrorCallback(cDevice, PrintDeviceError, 0);
Corentin Wallez4828d922018-07-18 13:45:46 +0200140 return dawn::Device::Acquire(cDevice);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400141}
142
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700143uint64_t GetSwapChainImplementation() {
144 return binding->GetSwapChainImplementation();
145}
146
Corentin Wallez4828d922018-07-18 13:45:46 +0200147dawn::TextureFormat GetPreferredSwapChainTextureFormat() {
Corentin Wallezb91022d2018-01-19 12:52:25 -0500148 DoFlush();
Corentin Wallez4828d922018-07-18 13:45:46 +0200149 return static_cast<dawn::TextureFormat>(binding->GetPreferredSwapChainTextureFormat());
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400150}
151
Corentin Wallez4828d922018-07-18 13:45:46 +0200152dawn::SwapChain GetSwapChain(const dawn::Device &device) {
Corentin Wallez7be2a712019-02-15 11:15:58 +0000153 dawn::SwapChainDescriptor swapChainDesc;
154 swapChainDesc.implementation = GetSwapChainImplementation();
155 return device.CreateSwapChain(&swapChainDesc);
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700156}
157
Corentin Wallez4828d922018-07-18 13:45:46 +0200158dawn::TextureView CreateDefaultDepthStencilView(const dawn::Device& device) {
Jiawei Shao425428f2018-08-27 08:44:48 +0800159 dawn::TextureDescriptor descriptor;
160 descriptor.dimension = dawn::TextureDimension::e2D;
Corentin Wallez29353d62018-09-18 12:49:22 +0000161 descriptor.size.width = 640;
162 descriptor.size.height = 480;
163 descriptor.size.depth = 1;
Jiawei Shao20301662019-02-21 00:45:19 +0000164 descriptor.arrayLayerCount = 1;
Jiawei Shao8bff3b22018-12-12 09:27:16 +0000165 descriptor.sampleCount = 1;
Jiawei Shao425428f2018-08-27 08:44:48 +0800166 descriptor.format = dawn::TextureFormat::D32FloatS8Uint;
Jiawei Shao20301662019-02-21 00:45:19 +0000167 descriptor.mipLevelCount = 1;
Jiawei Shao425428f2018-08-27 08:44:48 +0800168 descriptor.usage = dawn::TextureUsageBit::OutputAttachment;
169 auto depthStencilTexture = device.CreateTexture(&descriptor);
Jiawei Shao3d670502018-09-18 00:31:57 +0000170 return depthStencilTexture.CreateDefaultTextureView();
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700171}
172
Corentin Wallez4828d922018-07-18 13:45:46 +0200173void GetNextRenderPassDescriptor(const dawn::Device& device,
174 const dawn::SwapChain& swapchain,
175 const dawn::TextureView& depthStencilView,
176 dawn::Texture* backbuffer,
177 dawn::RenderPassDescriptor* info) {
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700178 *backbuffer = swapchain.GetNextTexture();
Jiawei Shao3d670502018-09-18 00:31:57 +0000179 auto backbufferView = backbuffer->CreateDefaultTextureView();
Jiawei Shao5e811ae2018-12-19 08:21:13 +0000180 dawn::RenderPassColorAttachmentDescriptor colorAttachment;
181 colorAttachment.attachment = backbufferView;
182 colorAttachment.resolveTarget = nullptr;
183 colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
184 colorAttachment.loadOp = dawn::LoadOp::Clear;
185 colorAttachment.storeOp = dawn::StoreOp::Store;
186
187 dawn::RenderPassDepthStencilAttachmentDescriptor depthStencilAttachment;
188 depthStencilAttachment.attachment = depthStencilView;
189 depthStencilAttachment.depthLoadOp = dawn::LoadOp::Clear;
190 depthStencilAttachment.stencilLoadOp = dawn::LoadOp::Clear;
191 depthStencilAttachment.clearDepth = 1.0f;
192 depthStencilAttachment.clearStencil = 0;
193 depthStencilAttachment.depthStoreOp = dawn::StoreOp::Store;
194 depthStencilAttachment.stencilStoreOp = dawn::StoreOp::Store;
195
Corentin Wallez8d6b5d22018-05-11 13:04:44 -0400196 *info = device.CreateRenderPassDescriptorBuilder()
Jiawei Shao5e811ae2018-12-19 08:21:13 +0000197 .SetColorAttachments(1, &colorAttachment)
198 .SetDepthStencilAttachment(&depthStencilAttachment)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700199 .GetResult();
200}
201
Corentin Wallez9347e8f2017-06-19 13:15:13 -0400202bool InitSample(int argc, const char** argv) {
Corentin Wallez862f8842018-06-07 13:03:29 +0200203 for (int i = 1; i < argc; i++) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400204 if (std::string("-b") == argv[i] || std::string("--backend") == argv[i]) {
205 i++;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400206 if (i < argc && std::string("d3d12") == argv[i]) {
Corentin Wallez8c88e1d2019-02-05 12:17:20 +0000207 backendType = dawn_native::BackendType::D3D12;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400208 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400209 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400210 if (i < argc && std::string("metal") == argv[i]) {
Corentin Wallez8c88e1d2019-02-05 12:17:20 +0000211 backendType = dawn_native::BackendType::Metal;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400212 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400213 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400214 if (i < argc && std::string("null") == argv[i]) {
Corentin Wallez8c88e1d2019-02-05 12:17:20 +0000215 backendType = dawn_native::BackendType::Null;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400216 continue;
217 }
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400218 if (i < argc && std::string("opengl") == argv[i]) {
Corentin Wallez8c88e1d2019-02-05 12:17:20 +0000219 backendType = dawn_native::BackendType::OpenGL;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400220 continue;
221 }
222 if (i < argc && std::string("vulkan") == argv[i]) {
Corentin Wallez8c88e1d2019-02-05 12:17:20 +0000223 backendType = dawn_native::BackendType::Vulkan;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400224 continue;
225 }
226 fprintf(stderr, "--backend expects a backend name (opengl, metal, d3d12, null, vulkan)\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400227 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400228 }
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700229 if (std::string("-c") == argv[i] || std::string("--command-buffer") == argv[i]) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400230 i++;
231 if (i < argc && std::string("none") == argv[i]) {
232 cmdBufType = CmdBufType::None;
233 continue;
234 }
235 if (i < argc && std::string("terrible") == argv[i]) {
236 cmdBufType = CmdBufType::Terrible;
237 continue;
238 }
239 fprintf(stderr, "--command-buffer expects a command buffer name (none, terrible)\n");
240 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400241 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400242 if (std::string("-h") == argv[i] || std::string("--help") == argv[i]) {
243 printf("Usage: %s [-b BACKEND] [-c COMMAND_BUFFER]\n", argv[0]);
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400244 printf(" BACKEND is one of: d3d12, metal, null, opengl, vulkan\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400245 printf(" COMMAND_BUFFER is one of: none, terrible\n");
246 return false;
247 }
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400248 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400249 return true;
250}
251
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700252void DoFlush() {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400253 if (cmdBufType == CmdBufType::Terrible) {
Corentin Walleza5696c72018-08-13 08:24:01 +0200254 bool c2sSuccess = c2sBuf->Flush();
255 bool s2cSuccess = s2cBuf->Flush();
256
257 ASSERT(c2sSuccess && s2cSuccess);
Corentin Wallez931e6e82017-06-16 18:51:14 -0400258 }
259 glfwPollEvents();
Corentin Wallez931e6e82017-06-16 18:51:14 -0400260}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400261
Corentin Wallez931e6e82017-06-16 18:51:14 -0400262bool ShouldQuit() {
263 return glfwWindowShouldClose(window);
264}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400265
Corentin Wallez931e6e82017-06-16 18:51:14 -0400266GLFWwindow* GetGLFWWindow() {
267 return window;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400268}