blob: 92e60648206bc20dfa2444fa0a72dd1c45d1bd1a [file] [log] [blame]
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04001// Copyright 2017 The NXT Authors
2//
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 Wallez0b186b12017-07-12 12:56:05 -040020#include "wire/TerribleCommandBuffer.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040021
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040022#include <nxt/nxt.h>
23#include <nxt/nxtcpp.h>
Kai Ninomiyac16a67a2017-07-27 18:30:57 -070024#include <nxt/nxt_wsi.h>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040025#include "GLFW/glfw3.h"
26
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040027#include <cstring>
28#include <iostream>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040029
Corentin Wallez4b410a32017-04-20 14:42:36 -040030void PrintDeviceError(const char* message, nxt::CallbackUserdata) {
31 std::cout << "Device error: " << message << std::endl;
32}
33
Corentin Wallez52cbcb42018-01-19 12:52:03 -050034void PrintGLFWError(int code, const char* message) {
35 std::cout << "GLFW error: " << code << " - " << message << std::endl;
36}
37
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040038enum class CmdBufType {
39 None,
40 Terrible,
Corentin Wallez682a8252017-05-09 15:34:13 +020041 //TODO(cwallez@chromium.org) double terrible cmdbuf
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040042};
43
Corentin Wallez275817a2017-07-12 12:43:24 -040044// Default to D3D12, Metal, Vulkan, OpenGL in that order as D3D12 and Metal are the preferred on
45// their respective platforms, and Vulkan is preferred to OpenGL
46#if defined(NXT_ENABLE_BACKEND_D3D12)
47 static utils::BackendType backendType = utils::BackendType::D3D12;
48#elif defined(NXT_ENABLE_BACKEND_METAL)
49 static utils::BackendType backendType = utils::BackendType::Metal;
Corentin Wallez275817a2017-07-12 12:43:24 -040050#elif defined(NXT_ENABLE_BACKEND_OPENGL)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -070051 static utils::BackendType backendType = utils::BackendType::OpenGL;
52#elif defined(NXT_ENABLE_BACKEND_VULKAN)
Corentin Wallez275817a2017-07-12 12:43:24 -040053 static utils::BackendType backendType = utils::BackendType::Vulkan;
Austin Engfc2bac72017-06-05 17:08:55 -040054#else
Corentin Wallez275817a2017-07-12 12:43:24 -040055 #error
Austin Engfc2bac72017-06-05 17:08:55 -040056#endif
57
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040058static CmdBufType cmdBufType = CmdBufType::Terrible;
Corentin Wallez1bd219d2017-06-19 12:53:38 -040059static utils::BackendBinding* binding = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040060
61static GLFWwindow* window = nullptr;
62
63static nxt::wire::CommandHandler* wireServer = nullptr;
Corentin Wallez682a8252017-05-09 15:34:13 +020064static nxt::wire::CommandHandler* wireClient = nullptr;
65static nxt::wire::TerribleCommandBuffer* c2sBuf = nullptr;
66static nxt::wire::TerribleCommandBuffer* s2cBuf = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040067
Corentin Wallez583e9a82017-05-29 11:30:29 -070068nxt::Device CreateCppNXTDevice() {
Corentin Wallez1bd219d2017-06-19 12:53:38 -040069 binding = utils::CreateBinding(backendType);
70 if (binding == nullptr) {
71 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040072 }
73
Corentin Wallez52cbcb42018-01-19 12:52:03 -050074 glfwSetErrorCallback(PrintGLFWError);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040075 if (!glfwInit()) {
Corentin Wallez583e9a82017-05-29 11:30:29 -070076 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040077 }
78
79 binding->SetupGLFWWindowHints();
80 window = glfwCreateWindow(640, 480, "NXT window", nullptr, nullptr);
81 if (!window) {
Corentin Wallez583e9a82017-05-29 11:30:29 -070082 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040083 }
84
85 binding->SetWindow(window);
86
87 nxtDevice backendDevice;
88 nxtProcTable backendProcs;
89 binding->GetProcAndDevice(&backendProcs, &backendDevice);
90
Corentin Wallez583e9a82017-05-29 11:30:29 -070091 nxtDevice cDevice = nullptr;
92 nxtProcTable procs;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040093 switch (cmdBufType) {
94 case CmdBufType::None:
Corentin Wallez583e9a82017-05-29 11:30:29 -070095 procs = backendProcs;
96 cDevice = backendDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040097 break;
98
99 case CmdBufType::Terrible:
100 {
Corentin Wallez682a8252017-05-09 15:34:13 +0200101 c2sBuf = new nxt::wire::TerribleCommandBuffer();
102 s2cBuf = new nxt::wire::TerribleCommandBuffer();
103
104 wireServer = nxt::wire::NewServerCommandHandler(backendDevice, backendProcs, s2cBuf);
105 c2sBuf->SetHandler(wireServer);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400106
107 nxtDevice clientDevice;
108 nxtProcTable clientProcs;
Corentin Wallez682a8252017-05-09 15:34:13 +0200109 wireClient = nxt::wire::NewClientDevice(&clientProcs, &clientDevice, c2sBuf);
110 s2cBuf->SetHandler(wireClient);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400111
Corentin Wallez583e9a82017-05-29 11:30:29 -0700112 procs = clientProcs;
113 cDevice = clientDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400114 }
115 break;
116 }
117
Corentin Wallez583e9a82017-05-29 11:30:29 -0700118 nxtSetProcs(&procs);
119 procs.deviceSetErrorCallback(cDevice, PrintDeviceError, 0);
120 return nxt::Device::Acquire(cDevice);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400121}
122
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700123uint64_t GetSwapChainImplementation() {
124 return binding->GetSwapChainImplementation();
125}
126
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400127nxt::TextureFormat GetPreferredSwapChainTextureFormat() {
Corentin Wallezb91022d2018-01-19 12:52:25 -0500128 DoFlush();
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400129 return static_cast<nxt::TextureFormat>(binding->GetPreferredSwapChainTextureFormat());
130}
131
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700132nxt::SwapChain GetSwapChain(const nxt::Device &device) {
133 return device.CreateSwapChainBuilder()
134 .SetImplementation(GetSwapChainImplementation())
135 .GetResult();
136}
137
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700138nxt::TextureView CreateDefaultDepthStencilView(const nxt::Device& device) {
139 auto depthStencilTexture = device.CreateTextureBuilder()
140 .SetDimension(nxt::TextureDimension::e2D)
141 .SetExtent(640, 480, 1)
142 .SetFormat(nxt::TextureFormat::D32FloatS8Uint)
143 .SetMipLevels(1)
144 .SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment)
145 .GetResult();
146 depthStencilTexture.FreezeUsage(nxt::TextureUsageBit::OutputAttachment);
147 return depthStencilTexture.CreateTextureViewBuilder()
148 .GetResult();
149}
150
Corentin Wallez8d6b5d22018-05-11 13:04:44 -0400151void GetNextRenderPassDescriptor(const nxt::Device& device,
Corentin Wallez6f7749c2018-05-02 18:10:13 -0400152 const nxt::SwapChain& swapchain,
153 const nxt::TextureView& depthStencilView,
154 nxt::Texture* backbuffer,
Corentin Wallez8d6b5d22018-05-11 13:04:44 -0400155 nxt::RenderPassDescriptor* info) {
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700156 *backbuffer = swapchain.GetNextTexture();
157 auto backbufferView = backbuffer->CreateTextureViewBuilder().GetResult();
Corentin Wallez8d6b5d22018-05-11 13:04:44 -0400158 *info = device.CreateRenderPassDescriptorBuilder()
Corentin Wallez6f7749c2018-05-02 18:10:13 -0400159 .SetColorAttachment(0, backbufferView, nxt::LoadOp::Clear)
160 .SetDepthStencilAttachment(depthStencilView, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700161 .GetResult();
162}
163
Corentin Wallez9347e8f2017-06-19 13:15:13 -0400164bool InitSample(int argc, const char** argv) {
Corentin Wallez862f8842018-06-07 13:03:29 +0200165 for (int i = 1; i < argc; i++) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400166 if (std::string("-b") == argv[i] || std::string("--backend") == argv[i]) {
167 i++;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400168 if (i < argc && std::string("d3d12") == argv[i]) {
169 backendType = utils::BackendType::D3D12;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400170 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400171 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400172 if (i < argc && std::string("metal") == argv[i]) {
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400173 backendType = utils::BackendType::Metal;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400174 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400175 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400176 if (i < argc && std::string("null") == argv[i]) {
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400177 backendType = utils::BackendType::Null;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400178 continue;
179 }
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400180 if (i < argc && std::string("opengl") == argv[i]) {
181 backendType = utils::BackendType::OpenGL;
182 continue;
183 }
184 if (i < argc && std::string("vulkan") == argv[i]) {
185 backendType = utils::BackendType::Vulkan;
186 continue;
187 }
188 fprintf(stderr, "--backend expects a backend name (opengl, metal, d3d12, null, vulkan)\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400189 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400190 }
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700191 if (std::string("-c") == argv[i] || std::string("--command-buffer") == argv[i]) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400192 i++;
193 if (i < argc && std::string("none") == argv[i]) {
194 cmdBufType = CmdBufType::None;
195 continue;
196 }
197 if (i < argc && std::string("terrible") == argv[i]) {
198 cmdBufType = CmdBufType::Terrible;
199 continue;
200 }
201 fprintf(stderr, "--command-buffer expects a command buffer name (none, terrible)\n");
202 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400203 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400204 if (std::string("-h") == argv[i] || std::string("--help") == argv[i]) {
205 printf("Usage: %s [-b BACKEND] [-c COMMAND_BUFFER]\n", argv[0]);
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400206 printf(" BACKEND is one of: d3d12, metal, null, opengl, vulkan\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400207 printf(" COMMAND_BUFFER is one of: none, terrible\n");
208 return false;
209 }
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400210 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400211 return true;
212}
213
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700214void DoFlush() {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400215 if (cmdBufType == CmdBufType::Terrible) {
Kai Ninomiya21006bb2018-06-20 18:54:18 -0700216 ASSERT(c2sBuf->Flush());
217 ASSERT(s2cBuf->Flush());
Corentin Wallez931e6e82017-06-16 18:51:14 -0400218 }
219 glfwPollEvents();
Corentin Wallez931e6e82017-06-16 18:51:14 -0400220}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400221
Corentin Wallez931e6e82017-06-16 18:51:14 -0400222bool ShouldQuit() {
223 return glfwWindowShouldClose(window);
224}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400225
Corentin Wallez931e6e82017-06-16 18:51:14 -0400226GLFWwindow* GetGLFWWindow() {
227 return window;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400228}