blob: 0d271266c728c6a48b631dcdc66a8b5e9350bfd3 [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
Corentin Wallez0b186b12017-07-12 12:56:05 -040017#include "common/Platform.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040018#include "utils/BackendBinding.h"
Corentin Wallez0b186b12017-07-12 12:56:05 -040019#include "wire/TerribleCommandBuffer.h"
Corentin Wallez1bd219d2017-06-19 12:53:38 -040020
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040021#include <nxt/nxt.h>
22#include <nxt/nxtcpp.h>
Kai Ninomiyac16a67a2017-07-27 18:30:57 -070023#include <nxt/nxt_wsi.h>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040024#include "GLFW/glfw3.h"
25
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040026#include <cstring>
27#include <iostream>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040028
Corentin Wallez4b410a32017-04-20 14:42:36 -040029void PrintDeviceError(const char* message, nxt::CallbackUserdata) {
30 std::cout << "Device error: " << message << std::endl;
31}
32
Corentin Wallez52cbcb42018-01-19 12:52:03 -050033void PrintGLFWError(int code, const char* message) {
34 std::cout << "GLFW error: " << code << " - " << message << std::endl;
35}
36
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040037enum class CmdBufType {
38 None,
39 Terrible,
Corentin Wallez682a8252017-05-09 15:34:13 +020040 //TODO(cwallez@chromium.org) double terrible cmdbuf
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040041};
42
Corentin Wallez275817a2017-07-12 12:43:24 -040043// Default to D3D12, Metal, Vulkan, OpenGL in that order as D3D12 and Metal are the preferred on
44// their respective platforms, and Vulkan is preferred to OpenGL
45#if defined(NXT_ENABLE_BACKEND_D3D12)
46 static utils::BackendType backendType = utils::BackendType::D3D12;
47#elif defined(NXT_ENABLE_BACKEND_METAL)
48 static utils::BackendType backendType = utils::BackendType::Metal;
Corentin Wallez275817a2017-07-12 12:43:24 -040049#elif defined(NXT_ENABLE_BACKEND_OPENGL)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -070050 static utils::BackendType backendType = utils::BackendType::OpenGL;
51#elif defined(NXT_ENABLE_BACKEND_VULKAN)
Corentin Wallez275817a2017-07-12 12:43:24 -040052 static utils::BackendType backendType = utils::BackendType::Vulkan;
Austin Engfc2bac72017-06-05 17:08:55 -040053#else
Corentin Wallez275817a2017-07-12 12:43:24 -040054 #error
Austin Engfc2bac72017-06-05 17:08:55 -040055#endif
56
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040057static CmdBufType cmdBufType = CmdBufType::Terrible;
Corentin Wallez1bd219d2017-06-19 12:53:38 -040058static utils::BackendBinding* binding = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040059
60static GLFWwindow* window = nullptr;
61
62static nxt::wire::CommandHandler* wireServer = nullptr;
Corentin Wallez682a8252017-05-09 15:34:13 +020063static nxt::wire::CommandHandler* wireClient = nullptr;
64static nxt::wire::TerribleCommandBuffer* c2sBuf = nullptr;
65static nxt::wire::TerribleCommandBuffer* s2cBuf = nullptr;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040066
Corentin Wallez583e9a82017-05-29 11:30:29 -070067nxt::Device CreateCppNXTDevice() {
Corentin Wallez1bd219d2017-06-19 12:53:38 -040068 binding = utils::CreateBinding(backendType);
69 if (binding == nullptr) {
70 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040071 }
72
Corentin Wallez52cbcb42018-01-19 12:52:03 -050073 glfwSetErrorCallback(PrintGLFWError);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040074 if (!glfwInit()) {
Corentin Wallez583e9a82017-05-29 11:30:29 -070075 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040076 }
77
78 binding->SetupGLFWWindowHints();
79 window = glfwCreateWindow(640, 480, "NXT window", nullptr, nullptr);
80 if (!window) {
Corentin Wallez583e9a82017-05-29 11:30:29 -070081 return nxt::Device();
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040082 }
83
84 binding->SetWindow(window);
85
86 nxtDevice backendDevice;
87 nxtProcTable backendProcs;
88 binding->GetProcAndDevice(&backendProcs, &backendDevice);
89
Corentin Wallez583e9a82017-05-29 11:30:29 -070090 nxtDevice cDevice = nullptr;
91 nxtProcTable procs;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040092 switch (cmdBufType) {
93 case CmdBufType::None:
Corentin Wallez583e9a82017-05-29 11:30:29 -070094 procs = backendProcs;
95 cDevice = backendDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040096 break;
97
98 case CmdBufType::Terrible:
99 {
Corentin Wallez682a8252017-05-09 15:34:13 +0200100 c2sBuf = new nxt::wire::TerribleCommandBuffer();
101 s2cBuf = new nxt::wire::TerribleCommandBuffer();
102
103 wireServer = nxt::wire::NewServerCommandHandler(backendDevice, backendProcs, s2cBuf);
104 c2sBuf->SetHandler(wireServer);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400105
106 nxtDevice clientDevice;
107 nxtProcTable clientProcs;
Corentin Wallez682a8252017-05-09 15:34:13 +0200108 wireClient = nxt::wire::NewClientDevice(&clientProcs, &clientDevice, c2sBuf);
109 s2cBuf->SetHandler(wireClient);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400110
Corentin Wallez583e9a82017-05-29 11:30:29 -0700111 procs = clientProcs;
112 cDevice = clientDevice;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400113 }
114 break;
115 }
116
Corentin Wallez583e9a82017-05-29 11:30:29 -0700117 nxtSetProcs(&procs);
118 procs.deviceSetErrorCallback(cDevice, PrintDeviceError, 0);
119 return nxt::Device::Acquire(cDevice);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400120}
121
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700122uint64_t GetSwapChainImplementation() {
123 return binding->GetSwapChainImplementation();
124}
125
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400126nxt::TextureFormat GetPreferredSwapChainTextureFormat() {
Corentin Wallezb91022d2018-01-19 12:52:25 -0500127 DoFlush();
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400128 return static_cast<nxt::TextureFormat>(binding->GetPreferredSwapChainTextureFormat());
129}
130
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700131nxt::SwapChain GetSwapChain(const nxt::Device &device) {
132 return device.CreateSwapChainBuilder()
133 .SetImplementation(GetSwapChainImplementation())
134 .GetResult();
135}
136
137nxt::RenderPass CreateDefaultRenderPass(const nxt::Device& device) {
138 return device.CreateRenderPassBuilder()
139 .SetAttachmentCount(2)
Corentin Wallez2e31e8f2017-09-21 12:54:53 -0400140 .AttachmentSetFormat(0, GetPreferredSwapChainTextureFormat())
Kai Ninomiyab9854312017-08-11 14:36:20 -0700141 .AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700142 .AttachmentSetFormat(1, nxt::TextureFormat::D32FloatS8Uint)
Kai Ninomiyab9854312017-08-11 14:36:20 -0700143 .AttachmentSetDepthStencilLoadOps(1, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700144 .SetSubpassCount(1)
145 .SubpassSetColorAttachment(0, 0, 0)
146 .SubpassSetDepthStencilAttachment(0, 1)
147 .GetResult();
148}
149
150nxt::TextureView CreateDefaultDepthStencilView(const nxt::Device& device) {
151 auto depthStencilTexture = device.CreateTextureBuilder()
152 .SetDimension(nxt::TextureDimension::e2D)
153 .SetExtent(640, 480, 1)
154 .SetFormat(nxt::TextureFormat::D32FloatS8Uint)
155 .SetMipLevels(1)
156 .SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment)
157 .GetResult();
158 depthStencilTexture.FreezeUsage(nxt::TextureUsageBit::OutputAttachment);
159 return depthStencilTexture.CreateTextureViewBuilder()
160 .GetResult();
161}
162
163void GetNextFramebuffer(const nxt::Device& device,
164 const nxt::RenderPass& renderpass,
165 const nxt::SwapChain& swapchain,
166 const nxt::TextureView& depthStencilView,
167 nxt::Texture* backbuffer,
168 nxt::Framebuffer* framebuffer) {
169 *backbuffer = swapchain.GetNextTexture();
170 auto backbufferView = backbuffer->CreateTextureViewBuilder().GetResult();
171 *framebuffer = device.CreateFramebufferBuilder()
172 .SetRenderPass(renderpass)
173 .SetDimensions(640, 480)
174 .SetAttachment(0, backbufferView)
175 .SetAttachment(1, depthStencilView)
176 .GetResult();
177}
178
Corentin Wallez9347e8f2017-06-19 13:15:13 -0400179bool InitSample(int argc, const char** argv) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400180 for (int i = 0; i < argc; i++) {
181 if (std::string("-b") == argv[i] || std::string("--backend") == argv[i]) {
182 i++;
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400183 if (i < argc && std::string("d3d12") == argv[i]) {
184 backendType = utils::BackendType::D3D12;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400185 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400186 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400187 if (i < argc && std::string("metal") == argv[i]) {
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400188 backendType = utils::BackendType::Metal;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400189 continue;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400190 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400191 if (i < argc && std::string("null") == argv[i]) {
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400192 backendType = utils::BackendType::Null;
Corentin Wallez931e6e82017-06-16 18:51:14 -0400193 continue;
194 }
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400195 if (i < argc && std::string("opengl") == argv[i]) {
196 backendType = utils::BackendType::OpenGL;
197 continue;
198 }
199 if (i < argc && std::string("vulkan") == argv[i]) {
200 backendType = utils::BackendType::Vulkan;
201 continue;
202 }
203 fprintf(stderr, "--backend expects a backend name (opengl, metal, d3d12, null, vulkan)\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400204 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400205 }
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700206 if (std::string("-c") == argv[i] || std::string("--command-buffer") == argv[i]) {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400207 i++;
208 if (i < argc && std::string("none") == argv[i]) {
209 cmdBufType = CmdBufType::None;
210 continue;
211 }
212 if (i < argc && std::string("terrible") == argv[i]) {
213 cmdBufType = CmdBufType::Terrible;
214 continue;
215 }
216 fprintf(stderr, "--command-buffer expects a command buffer name (none, terrible)\n");
217 return false;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400218 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400219 if (std::string("-h") == argv[i] || std::string("--help") == argv[i]) {
220 printf("Usage: %s [-b BACKEND] [-c COMMAND_BUFFER]\n", argv[0]);
Corentin Wallez1bd219d2017-06-19 12:53:38 -0400221 printf(" BACKEND is one of: d3d12, metal, null, opengl, vulkan\n");
Corentin Wallez931e6e82017-06-16 18:51:14 -0400222 printf(" COMMAND_BUFFER is one of: none, terrible\n");
223 return false;
224 }
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400225 }
Corentin Wallez931e6e82017-06-16 18:51:14 -0400226 return true;
227}
228
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700229void DoFlush() {
Corentin Wallez931e6e82017-06-16 18:51:14 -0400230 if (cmdBufType == CmdBufType::Terrible) {
231 c2sBuf->Flush();
232 s2cBuf->Flush();
233 }
234 glfwPollEvents();
Corentin Wallez931e6e82017-06-16 18:51:14 -0400235}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400236
Corentin Wallez931e6e82017-06-16 18:51:14 -0400237bool ShouldQuit() {
238 return glfwWindowShouldClose(window);
239}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400240
Corentin Wallez931e6e82017-06-16 18:51:14 -0400241GLFWwindow* GetGLFWWindow() {
242 return window;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400243}