blob: c641dc0c0270128a3c3f3c133ec17e2fee956b2d [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 Wallez0b186b12017-07-12 12:56:05 -040015#include "common/Platform.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040016#include "utils/BackendBinding.h"
Corentin Wallez0b186b12017-07-12 12:56:05 -040017#include "wire/TerribleCommandBuffer.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040018
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040019#include <nxt/nxt.h>
20#include <nxt/nxtcpp.h>
Kai Ninomiyac16a67a2017-07-27 18:30:57 -070021#include <nxt/nxt_wsi.h>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040022#include "GLFW/glfw3.h"
23
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040024#include <cstring>
25#include <iostream>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040026
Corentin Wallez4b410a32017-04-20 14:42:36 -040027void PrintDeviceError(const char* message, nxt::CallbackUserdata) {
28 std::cout << "Device error: " << message << std::endl;
29}
30
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040031enum class CmdBufType {
32 None,
33 Terrible,
Corentin Wallez682a8252017-05-09 15:34:13 +020034 //TODO(cwallez@chromium.org) double terrible cmdbuf
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040035};
36
Corentin Wallez275817a2017-07-12 12:43:24 -040037// Default to D3D12, Metal, Vulkan, OpenGL in that order as D3D12 and Metal are the preferred on
38// their respective platforms, and Vulkan is preferred to OpenGL
39#if defined(NXT_ENABLE_BACKEND_D3D12)
40 static utils::BackendType backendType = utils::BackendType::D3D12;
41#elif defined(NXT_ENABLE_BACKEND_METAL)
42 static utils::BackendType backendType = utils::BackendType::Metal;
Corentin Wallez275817a2017-07-12 12:43:24 -040043#elif defined(NXT_ENABLE_BACKEND_OPENGL)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -070044 static utils::BackendType backendType = utils::BackendType::OpenGL;
45#elif defined(NXT_ENABLE_BACKEND_VULKAN)
Corentin Wallez275817a2017-07-12 12:43:24 -040046 static utils::BackendType backendType = utils::BackendType::Vulkan;
Austin Engfc2bac72017-06-05 17:08:55 -040047#else
Corentin Wallez275817a2017-07-12 12:43:24 -040048 #error
Austin Engfc2bac72017-06-05 17:08:55 -040049#endif
50
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040051static CmdBufType cmdBufType = CmdBufType::Terrible;
Corentin Wallez1bd219d2017-06-19 12:53:38 -040052static utils::BackendBinding* binding = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040053
54static GLFWwindow* window = nullptr;
55
56static nxt::wire::CommandHandler* wireServer = nullptr;
Corentin Wallez682a8252017-05-09 15:34:13 +020057static nxt::wire::CommandHandler* wireClient = nullptr;
58static nxt::wire::TerribleCommandBuffer* c2sBuf = nullptr;
59static nxt::wire::TerribleCommandBuffer* s2cBuf = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040060
Corentin Wallez583e9a82017-05-29 11:30:29 -070061nxt::Device CreateCppNXTDevice() {
Corentin Wallez1bd219d2017-06-19 12:53:38 -040062 binding = utils::CreateBinding(backendType);
63 if (binding == nullptr) {
64 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040065 }
66
67 if (!glfwInit()) {
Corentin Wallez583e9a82017-05-29 11:30:29 -070068 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040069 }
70
71 binding->SetupGLFWWindowHints();
72 window = glfwCreateWindow(640, 480, "NXT window", nullptr, nullptr);
73 if (!window) {
Corentin Wallez583e9a82017-05-29 11:30:29 -070074 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040075 }
76
77 binding->SetWindow(window);
78
79 nxtDevice backendDevice;
80 nxtProcTable backendProcs;
81 binding->GetProcAndDevice(&backendProcs, &backendDevice);
82
Corentin Wallez583e9a82017-05-29 11:30:29 -070083 nxtDevice cDevice = nullptr;
84 nxtProcTable procs;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040085 switch (cmdBufType) {
86 case CmdBufType::None:
Corentin Wallez583e9a82017-05-29 11:30:29 -070087 procs = backendProcs;
88 cDevice = backendDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040089 break;
90
91 case CmdBufType::Terrible:
92 {
Corentin Wallez682a8252017-05-09 15:34:13 +020093 c2sBuf = new nxt::wire::TerribleCommandBuffer();
94 s2cBuf = new nxt::wire::TerribleCommandBuffer();
95
96 wireServer = nxt::wire::NewServerCommandHandler(backendDevice, backendProcs, s2cBuf);
97 c2sBuf->SetHandler(wireServer);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040098
99 nxtDevice clientDevice;
100 nxtProcTable clientProcs;
Corentin Wallez682a8252017-05-09 15:34:13 +0200101 wireClient = nxt::wire::NewClientDevice(&clientProcs, &clientDevice, c2sBuf);
102 s2cBuf->SetHandler(wireClient);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400103
Corentin Wallez583e9a82017-05-29 11:30:29 -0700104 procs = clientProcs;
105 cDevice = clientDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400106 }
107 break;
108 }
109
Corentin Wallez583e9a82017-05-29 11:30:29 -0700110 nxtSetProcs(&procs);
111 procs.deviceSetErrorCallback(cDevice, PrintDeviceError, 0);
112 return nxt::Device::Acquire(cDevice);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400113}
114
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700115uint64_t GetSwapChainImplementation() {
116 return binding->GetSwapChainImplementation();
117}
118
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400119nxt::TextureFormat GetPreferredSwapChainTextureFormat() {
120 return static_cast<nxt::TextureFormat>(binding->GetPreferredSwapChainTextureFormat());
121}
122
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700123nxt::SwapChain GetSwapChain(const nxt::Device &device) {
124 return device.CreateSwapChainBuilder()
125 .SetImplementation(GetSwapChainImplementation())
126 .GetResult();
127}
128
129nxt::RenderPass CreateDefaultRenderPass(const nxt::Device& device) {
130 return device.CreateRenderPassBuilder()
131 .SetAttachmentCount(2)
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400132 .AttachmentSetFormat(0, GetPreferredSwapChainTextureFormat())
Kai Ninomiyab9854312017-08-11 14:36:20 -0700133 .AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700134 .AttachmentSetFormat(1, nxt::TextureFormat::D32FloatS8Uint)
Kai Ninomiyab9854312017-08-11 14:36:20 -0700135 .AttachmentSetDepthStencilLoadOps(1, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700136 .SetSubpassCount(1)
137 .SubpassSetColorAttachment(0, 0, 0)
138 .SubpassSetDepthStencilAttachment(0, 1)
139 .GetResult();
140}
141
142nxt::TextureView CreateDefaultDepthStencilView(const nxt::Device& device) {
143 auto depthStencilTexture = device.CreateTextureBuilder()
144 .SetDimension(nxt::TextureDimension::e2D)
145 .SetExtent(640, 480, 1)
146 .SetFormat(nxt::TextureFormat::D32FloatS8Uint)
147 .SetMipLevels(1)
148 .SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment)
149 .GetResult();
150 depthStencilTexture.FreezeUsage(nxt::TextureUsageBit::OutputAttachment);
151 return depthStencilTexture.CreateTextureViewBuilder()
152 .GetResult();
153}
154
155void GetNextFramebuffer(const nxt::Device& device,
156 const nxt::RenderPass& renderpass,
157 const nxt::SwapChain& swapchain,
158 const nxt::TextureView& depthStencilView,
159 nxt::Texture* backbuffer,
160 nxt::Framebuffer* framebuffer) {
161 *backbuffer = swapchain.GetNextTexture();
162 auto backbufferView = backbuffer->CreateTextureViewBuilder().GetResult();
163 *framebuffer = device.CreateFramebufferBuilder()
164 .SetRenderPass(renderpass)
165 .SetDimensions(640, 480)
166 .SetAttachment(0, backbufferView)
167 .SetAttachment(1, depthStencilView)
168 .GetResult();
169}
170
Corentin Wallez9347e8f2017-06-19 13:15:13 -0400171bool InitSample(int argc, const char** argv) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400172 for (int i = 0; i < argc; i++) {
173 if (std::string("-b") == argv[i] || std::string("--backend") == argv[i]) {
174 i++;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400175 if (i < argc && std::string("d3d12") == argv[i]) {
176 backendType = utils::BackendType::D3D12;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400177 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400178 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400179 if (i < argc && std::string("metal") == argv[i]) {
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400180 backendType = utils::BackendType::Metal;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400181 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400182 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400183 if (i < argc && std::string("null") == argv[i]) {
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400184 backendType = utils::BackendType::Null;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400185 continue;
186 }
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400187 if (i < argc && std::string("opengl") == argv[i]) {
188 backendType = utils::BackendType::OpenGL;
189 continue;
190 }
191 if (i < argc && std::string("vulkan") == argv[i]) {
192 backendType = utils::BackendType::Vulkan;
193 continue;
194 }
195 fprintf(stderr, "--backend expects a backend name (opengl, metal, d3d12, null, vulkan)\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400196 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400197 }
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700198 if (std::string("-c") == argv[i] || std::string("--command-buffer") == argv[i]) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400199 i++;
200 if (i < argc && std::string("none") == argv[i]) {
201 cmdBufType = CmdBufType::None;
202 continue;
203 }
204 if (i < argc && std::string("terrible") == argv[i]) {
205 cmdBufType = CmdBufType::Terrible;
206 continue;
207 }
208 fprintf(stderr, "--command-buffer expects a command buffer name (none, terrible)\n");
209 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400210 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400211 if (std::string("-h") == argv[i] || std::string("--help") == argv[i]) {
212 printf("Usage: %s [-b BACKEND] [-c COMMAND_BUFFER]\n", argv[0]);
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400213 printf(" BACKEND is one of: d3d12, metal, null, opengl, vulkan\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400214 printf(" COMMAND_BUFFER is one of: none, terrible\n");
215 return false;
216 }
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400217 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400218 return true;
219}
220
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700221void DoFlush() {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400222 if (cmdBufType == CmdBufType::Terrible) {
223 c2sBuf->Flush();
224 s2cBuf->Flush();
225 }
226 glfwPollEvents();
Corentin Wallez931e6e82017-06-16 18:51:14 -0400227}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400228
Corentin Wallez931e6e82017-06-16 18:51:14 -0400229bool ShouldQuit() {
230 return glfwWindowShouldClose(window);
231}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400232
Corentin Wallez931e6e82017-06-16 18:51:14 -0400233GLFWwindow* GetGLFWWindow() {
234 return window;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400235}