1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: gx_CommandCacheSimple.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 47228 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/types.h>
17
18 #include <nn/os.h>
19 #include <nn/fnd.h>
20 #include <nn/gx.h>
21 #include <nn/math.h>
22 #include <nn/fs.h>
23 #include <nn/init.h>
24 #include <nn/applet.h>
25
26 #include "demo.h"
27
28 // Save the command list and reuse it.
29 //
30 // This sample merely saves the command list and reuses it, and does not edit the saved command list.
31 //
32 #define USE_COMMAND_CACHE
33
34 namespace
35 {
36 GLuint s_CurrentCommandListId = 0;
37 GLuint s_SavedCommandListId = 0;
38 GLuint s_SavedCommandBufferOffset = 0;
39 GLsizei s_SavedCommandBufferSize = 0;
40 GLuint s_SavedCommandRequestBeginId = 0;
41 GLsizei s_SavedCommandRequestSize = 0;
42
43 GLbitfield s_StateMask = 0;
44
45 // References the 3D command buffer.
46 // GLboolean s_CopyCommandBuffer = GL_FALSE;
47 // Copies the 3D command buffer.
48 GLboolean s_CopyCommandBuffer = GL_TRUE;
49
50 GLuint s_ProgramId = 0;
51 GLuint s_ShaderId = 0;
52
53 nn::fnd::ExpHeap s_AppHeap;
54 uptr s_AddrForGxHeap;
55 const u32 s_GxHeapSize = 0x400000;
56
57 demo::RenderSystem s_RenderSystem;
58
59 nn::math::Vector3 s_CameraPosition(0.0f, 2.0f, 2.0f);
60 nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f);
61 nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f);
62
63 nn::math::Matrix34 s_ViewMatrix;
64 nn::math::Matrix44 s_Display0ProjectionMatrix;
65 nn::math::Matrix44 s_Display1ProjectionMatrix;
66
67 f32 s_GlobalAmbientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f};
68 f32 s_Light0Ambient[] = { 0.3f, 0.3f, 0.3f, 1.0f};
69 f32 s_Light0Diffuse[] = { 0.7f, 0.7f, 0.7f, 1.0f};
70 f32 s_Light0Position[] = {15.0f, 15.0f, 15.0f, 1.0f};
71
72 f32 s_MaterialAmbient[] = {0.3f, 0.3f, 0.3f, 1.0f};
73 f32 s_MaterialDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f};
74
75 demo::Cube s_Cube;
76 }
77
78 void InitializeGraphics(void);
79 void InitializeShader(void);
80
81 bool DrawFrame(void);
82 void UseShader(void);
83 void UpdateCamera(void);
84 void DrawDisplay0(void);
85 void DrawDisplay1(void);
86
87 void UpdateBody(demo::Body& body);
88 void DrawBody(demo::Body& body);
89
90 bool DrawFrameCommandCache(void);
91 void DrawDisplay0CommandCache(void);
92 void MakeDisplay0CommandCache(void);
93 void CopyCommandList(void);
94
Initialize(void)95 void Initialize(void)
96 {
97 // fs initialization
98 nn::fs::Initialize();
99
100 const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
101 static char buffer[ROMFS_BUFFER_SIZE];
102 NN_UTIL_PANIC_IF_FAILED(
103 nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
104
105 InitializeGraphics();
106 }
107
InitializeGraphics(void)108 void InitializeGraphics(void)
109 {
110 s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
111 nn::os::GetDeviceMemorySize() );
112 s_AddrForGxHeap = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
113
114 s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize);
115
116 glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
117 glClearDepthf(1.f);
118
119 glEnable(GL_DEPTH_TEST);
120 glDepthFunc(GL_LESS);
121
122 glEnable(GL_CULL_FACE);
123 glFrontFace(GL_CCW);
124 glCullFace(GL_BACK);
125
126 InitializeShader();
127
128 // Initialize projection matrix
129 nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f,
130 demo::DISPLAY0_ASPECT, 0.2f, 100.0f,
131 nn::math::PIVOT_UPSIDE_TO_TOP);
132
133 nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f,
134 demo::DISPLAY1_ASPECT, 0.2f, 100.0f,
135 nn::math::PIVOT_UPSIDE_TO_TOP);
136
137 // Initialize cube
138 u32 vertexAttributes = demo::VERTEX_POSITION_ATTRIBUTE |
139 demo::VERTEX_COLOR_ATTRIBUTE |
140 demo::VERTEX_NORMAL_ATTRIBUTE;
141 s_Cube.InitializeCube(vertexAttributes, 0.5f, 0.5f, 0.5f);
142 s_Cube.SetColor(1.0f, 0.0f, 0.0f);
143 s_Cube.SetWorldPosition(0.0f, 0.0f, 0.0f);
144 s_Cube.SetWorldAngle(0.0f, 45.0f, 0.0f);
145 }
146
InitializeShader(void)147 void InitializeShader(void)
148 {
149 s_ProgramId = glCreateProgram();
150
151 // Load vertex shader
152 s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
153 nn::fs::FileReader file(L"rom:/shader.shbin");
154 size_t fileSize = file.GetSize();
155 void* buf = s_AppHeap.Allocate(fileSize);
156 s32 read = file.Read(buf, fileSize);
157 glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
158 file.Finalize();
159 s_AppHeap.Free(buf);
160
161 glAttachShader(s_ProgramId, s_ShaderId);
162 glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
163
164 glBindAttribLocation(s_ProgramId, 0, "aPosition");
165 glBindAttribLocation(s_ProgramId, 1, "aColor");
166 glBindAttribLocation(s_ProgramId, 2, "aNormal");
167
168 glLinkProgram(s_ProgramId);
169 glValidateProgram(s_ProgramId);
170
171 demo::InitializeUniforms(s_ProgramId);
172 }
173
Finalize(void)174 void Finalize(void)
175 {
176 s_Cube.Finalize();
177
178 s_RenderSystem.Finalize();
179
180 s_AppHeap.Free(reinterpret_cast<void*>(s_AddrForGxHeap));
181 s_AppHeap.Finalize();
182 }
183
DrawFrame(void)184 bool DrawFrame(void)
185 {
186 UpdateCamera();
187 DrawDisplay0();
188 DrawDisplay1();
189
190 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
191
192 return true;
193 }
194
UpdateCamera(void)195 void UpdateCamera(void)
196 {
197 nn::math::MTX34LookAt(&s_ViewMatrix, &s_CameraPosition, &s_CameraUp, &s_CameraTarget);
198 }
199
DrawDisplay0(void)200 void DrawDisplay0(void)
201 {
202 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
203 s_RenderSystem.Clear();
204
205 UseShader();
206 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
207 1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
208
209 UpdateBody(s_Cube);
210 DrawBody(s_Cube);
211
212 s_RenderSystem.SwapBuffers();
213 }
214
UseShader(void)215 void UseShader(void)
216 {
217 glUseProgram(s_ProgramId);
218
219 // Fragment uniform
220 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE);
221
222 // Fragment uniform : Texture samplerType
223 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_FALSE);
224 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE);
225 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE);
226 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE);
227
228 // Fragment uniform : Fragment lighting
229 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE);
230 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight);
231 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE);
232 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_Light0Ambient);
233 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_Light0Diffuse);
234 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION], 1, s_Light0Position);
235
236 // Fragment uniform : Material
237 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient);
238 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse);
239
240 // Fragment uniform : Texture combiner
241 // Modulate fragment primary color and vertex color.
242 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
243 GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PRIMARY_COLOR, GL_PREVIOUS);
244 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
245 GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS);
246 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
247 GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
248 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
249 GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
250 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
251 GL_MODULATE);
252 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
253 GL_MODULATE);
254 }
255
DrawDisplay1(void)256 void DrawDisplay1(void)
257 {
258 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
259 s_RenderSystem.Clear();
260
261 s_RenderSystem.SwapBuffers();
262 }
263
UpdateBody(demo::Body & body)264 void UpdateBody(demo::Body& body)
265 {
266 f32 worldAngle[3];
267 body.GetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
268 worldAngle[1] += 1.0f;
269 if ( worldAngle[1] > 360.0f )
270 {
271 worldAngle[1] = 0.0f;
272 }
273 body.SetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
274 }
275
DrawBody(demo::Body & body)276 void DrawBody(demo::Body& body)
277 {
278 nn::math::MTX44 modelViewMatrix(s_ViewMatrix);
279 nn::math::Matrix44 worldMatrix = body.GetWorldMatrix();
280 nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &worldMatrix);
281 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW],
282 1, GL_TRUE, static_cast<f32*>(modelViewMatrix));
283
284 body.Draw();
285 }
286
DrawFrameCommandCache(void)287 bool DrawFrameCommandCache(void)
288 {
289 static bool s_InitializeCommandCache = false;
290 if (! s_InitializeCommandCache )
291 {
292 UpdateCamera();
293 // Creates and saves the command list.
294 MakeDisplay0CommandCache();
295 DrawDisplay1();
296 s_InitializeCommandCache = true;
297 }
298 else
299 {
300 UpdateCamera();
301 // Reuses the saved command list.
302 DrawDisplay0CommandCache();
303 DrawDisplay1();
304 }
305
306 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
307
308 return true;
309 }
310
MakeDisplay0CommandCache(void)311 void MakeDisplay0CommandCache(void)
312 {
313 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
314 s_RenderSystem.Clear();
315
316 // Starts saving the command list.
317 nngxStartCmdlistSave();
318
319 UseShader();
320 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
321 1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
322
323 UpdateBody(s_Cube);
324 DrawBody(s_Cube);
325
326 // Finishes saving the command list and copies it.
327 CopyCommandList();
328
329 s_RenderSystem.SwapBuffers();
330 }
331
DrawDisplay0CommandCache(void)332 void DrawDisplay0CommandCache(void)
333 {
334 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
335 s_RenderSystem.Clear();
336
337 // Adds the saved command list to the current command list.
338 nngxUseSavedCmdlist(s_SavedCommandListId,
339 s_SavedCommandBufferOffset, s_SavedCommandBufferSize,
340 s_SavedCommandRequestBeginId, s_SavedCommandRequestSize,
341 s_StateMask,
342 s_CopyCommandBuffer);
343
344 s_RenderSystem.SwapBuffers();
345 }
346
CopyCommandList(void)347 void CopyCommandList(void)
348 {
349 if (! s_CopyCommandBuffer )
350 {
351 nngxSplitDrawCmdlist();
352 }
353
354 // Ends saving the command list.
355 nngxStopCmdlistSave(&s_SavedCommandBufferOffset, &s_SavedCommandBufferSize,
356 &s_SavedCommandRequestBeginId, &s_SavedCommandRequestSize);
357 NN_LOG("Saved CommandList information\n");
358 NN_LOG(" bufferOffset = %d, bufferSize = %d\n", s_SavedCommandBufferOffset, s_SavedCommandBufferSize);
359 NN_LOG(" requestBeginId = %d, requestSize = %d\n", s_SavedCommandRequestBeginId, s_SavedCommandRequestSize);
360
361 // Allocates command list at the save destination.
362 nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, (GLint*)&s_CurrentCommandListId);
363 NN_LOG("CurrentCommandListId = %d\n", s_CurrentCommandListId);
364
365 nngxGenCmdlists(1, &s_SavedCommandListId);
366 NN_LOG("SavedCommandListId = %d\n", s_SavedCommandListId);
367 nngxBindCmdlist(s_SavedCommandListId);
368 nngxCmdlistStorage(0x10000, 32);
369
370 // Unbinds the current command list.
371 nngxBindCmdlist(0);
372
373 // Copies the current command list to the command list at the save destination.
374 nngxCopyCmdlist(s_CurrentCommandListId, s_SavedCommandListId);
375
376 // Bind the command list.
377 nngxBindCmdlist(s_CurrentCommandListId);
378
379 DEMO_ASSERT_GL_ERROR();
380 }
381
nnMain(void)382 void nnMain(void)
383 {
384 // Call only nn::applet::Enable to also allow execution from the HOME Menu
385 // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
386 nn::applet::Enable();
387
388 Initialize();
389
390 bool flag = true;
391 while ( flag )
392 {
393 #ifdef USE_COMMAND_CACHE
394 flag = DrawFrameCommandCache();
395 #else
396 flag = DrawFrame();
397 #endif
398 }
399
400 Finalize();
401 }
402