MethaneAsteroids

Форк
0
/
AsteroidsApp.cpp 
579 строк · 26.5 Кб
1
/******************************************************************************
2

3
Copyright 2019-2020 Evgeny Gorodetskiy
4

5
Licensed under the Apache License, Version 2.0 (the "License"),
6
you may not use this file except in compliance with the License.
7
You may obtain a copy of the License at
8

9
    http://www.apache.org/licenses/LICENSE-2.0
10

11
Unless required by applicable law or agreed to in writing, software
12
distributed under the License is distributed on an "AS IS" BASIS,
13
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
See the License for the specific language governing permissions and
15
limitations under the License.
16

17
*******************************************************************************
18

19
FILE: AsteroidsApp.cpp
20
Sample demonstrating parallel rendering of the distinct asteroids massive
21

22
******************************************************************************/
23

24
#include "AsteroidsApp.h"
25
#include "AsteroidsAppController.h"
26

27
#include <Methane/Graphics/AppCameraController.h>
28
#include <Methane/Data/TimeAnimation.h>
29
#include <Methane/Data/AppIconsProvider.h>
30
#include <Methane/Instrumentation.h>
31

32
#include <memory>
33
#include <thread>
34
#include <array>
35
#include <map>
36
#include <magic_enum.hpp>
37

38
namespace Methane::Samples
39
{
40

41
struct MutableParameters
42
{
43
    uint32_t instances_count;
44
    uint32_t unique_mesh_count;
45
    uint32_t textures_count;
46
    float    scale_ratio;
47
};
48

49
constexpr uint32_t g_max_complexity = 9;
50
static const std::array<MutableParameters, g_max_complexity+1> g_mutable_parameters{ {
51
    { 1000U,  35U,   10U, 0.6F  }, // 0
52
    { 2000U,  50U,   10U, 0.5F  }, // 1
53
    { 3000U,  75U,   20U, 0.45F }, // 2
54
    { 4000U,  100U,  20U, 0.4F  }, // 3
55
    { 5000U,  200U,  30U, 0.33F }, // 4
56
    { 10000U, 300U,  30U, 0.3F  }, // 5
57
    { 15000U, 400U,  40U, 0.27F }, // 6
58
    { 20000U, 500U,  40U, 0.23F }, // 7
59
    { 35000U, 750U,  50U, 0.2F  }, // 8
60
    { 50000U, 1000U, 50U, 0.17F }, // 9
61
} };
62

63
[[nodiscard]]
64
inline uint32_t GetDefaultComplexity()
65
{
66
#ifdef _DEBUG
67
    return 1U;
68
#else
69
    return std::thread::hardware_concurrency() / 2;
70
#endif
71
}
72

73
[[nodiscard]]
74
inline const MutableParameters& GetMutableParameters(uint32_t complexity)
75
{
76
    return g_mutable_parameters[std::min(complexity, g_max_complexity)];
77
}
78

79
[[nodiscard]]
80
inline const MutableParameters& GetMutableParameters()
81
{
82
    return GetMutableParameters(GetDefaultComplexity());
83
}
84

85
static const std::map<pin::Keyboard::State, AsteroidsAppAction> g_asteroids_action_by_keyboard_state{
86
    { { pin::Keyboard::Key::P            }, AsteroidsAppAction::SwitchParallelRendering     },
87
    { { pin::Keyboard::Key::L            }, AsteroidsAppAction::SwitchMeshLodsColoring      },
88
    { { pin::Keyboard::Key::Apostrophe   }, AsteroidsAppAction::IncreaseMeshLodComplexity   },
89
    { { pin::Keyboard::Key::Semicolon    }, AsteroidsAppAction::DecreaseMeshLodComplexity   },
90
    { { pin::Keyboard::Key::RightBracket }, AsteroidsAppAction::IncreaseComplexity          },
91
    { { pin::Keyboard::Key::LeftBracket  }, AsteroidsAppAction::DecreaseComplexity          },
92
    { { pin::Keyboard::Key::Num0         }, AsteroidsAppAction::SetComplexity0              },
93
    { { pin::Keyboard::Key::Num1         }, AsteroidsAppAction::SetComplexity1              },
94
    { { pin::Keyboard::Key::Num2         }, AsteroidsAppAction::SetComplexity2              },
95
    { { pin::Keyboard::Key::Num3         }, AsteroidsAppAction::SetComplexity3              },
96
    { { pin::Keyboard::Key::Num4         }, AsteroidsAppAction::SetComplexity4              },
97
    { { pin::Keyboard::Key::Num5         }, AsteroidsAppAction::SetComplexity5              },
98
    { { pin::Keyboard::Key::Num6         }, AsteroidsAppAction::SetComplexity6              },
99
    { { pin::Keyboard::Key::Num7         }, AsteroidsAppAction::SetComplexity7              },
100
    { { pin::Keyboard::Key::Num8         }, AsteroidsAppAction::SetComplexity8              },
101
    { { pin::Keyboard::Key::Num9         }, AsteroidsAppAction::SetComplexity9              },
102
};
103

104
void AsteroidsFrame::ReleaseScreenPassAttachmentTextures()
105
{
106
    META_FUNCTION_TASK();
107
    asteroids_pass.ReleaseAttachmentTextures();
108
    AppFrame::ReleaseScreenPassAttachmentTextures();
109
}
110

111
AsteroidsApp::AsteroidsApp()
112
    : UserInterfaceApp(
113
        Graphics::CombinedAppSettings
114
        {                                              // =========================
115
            Platform::IApp::Settings {                 // platform_app:
116
                "Methane Asteroids",                   //   - name
117
                { 0.8, 0.8 },                          //   - size
118
                { 640U, 480U },                        //   - min_size
119
                false,                                 //   - is_full_screen
120
                &Data::IconProvider::Get(),            //   - icon_resources_ptr
121
            },                                         // =========================
122
            Graphics::IApp::Settings {                 // graphics_app:
123
                rhi::RenderPassAccessMask{             //   - screen_pass_access
124
                    rhi::RenderPassAccess::ShaderResources,
125
                    rhi::RenderPassAccess::Samplers
126
                },
127
                true,                                  //   - animations_enabled
128
                true,                                  //   - show_hud_in_window_title
129
                0                                      //   - default_device_index
130
            },                                         // =========================
131
            rhi::RenderContext::Settings {             // render_context:
132
                gfx::FrameSize(),                      //   - frame_size
133
                gfx::PixelFormat::BGRA8Unorm,          //   - color_format
134
                gfx::PixelFormat::Depth32Float,        //   - depth_stencil_format
135
                std::nullopt,                          //   - clear_color
136
                gfx::DepthStencilValues(0.F, {}),      //   - clear_depth_stencil
137
                3U,                                    //   - frame_buffers_count
138
                false,                                 //   - vsync_enabled
139
                false,                                 //   - is_full_screen
140
                {},                                    //   - options_mask
141
                1000U,                                 //   - unsync_max_fps (MacOS only)
142
            }                                          // =========================
143
        },
144
        UserInterface::IApp::Settings
145
        {
146
            UserInterface::HeadsUpDisplayMode::UserInterface
147
        },
148
        "Methane Asteroids sample is demonstrating parallel rendering\nof massive asteroids field dynamic simulation.")
149
    , m_view_camera(GetAnimations(), gfx::ActionCamera::Pivot::Aim)
150
    , m_light_camera(m_view_camera, GetAnimations(), gfx::ActionCamera::Pivot::Aim)
151
    , m_asteroids_array_settings(                       // Asteroids array settings:
152
        {                                               // ================
153
            m_view_camera,                              // - view_camera
154
            m_scene_scale,                              // - scale
155
            GetMutableParameters().instances_count,     // - instance_count
156
            GetMutableParameters().unique_mesh_count,   // - unique_mesh_count
157
            4U,                                         // - subdivisions_count
158
            GetMutableParameters().textures_count,      // - textures_count
159
            { 256U, 256U },                             // - texture_dimensions
160
            1123U,                                      // - random_seed
161
            13.F,                                       // - orbit_radius_ratio
162
            4.F,                                        // - disc_radius_ratio
163
            0.06F,                                      // - mesh_lod_min_screen_size
164
            GetMutableParameters().scale_ratio / 10.F,  // - min_asteroid_scale_ratio
165
            GetMutableParameters().scale_ratio,         // - max_asteroid_scale_ratio
166
            true,                                       // - textures_array_enabled
167
            true                                        // - depth_reversed
168
        })
169
    , m_asteroids_complexity(GetDefaultComplexity())
170
{
171
    META_FUNCTION_TASK();
172

173
    // NOTE: Near and Far values are swapped in camera parameters (1st value is near = max depth, 2nd value is far = min depth)
174
    // for Reversed-Z buffer values range [ near: 1, far 0], instead of [ near 0, far 1]
175
    // which is used for "from near to far" drawing order for reducing pixels overdraw
176
    m_view_camera.ResetOrientation({ { -110.F, 75.F, 210.F }, { 0.F, -60.F, 25.F }, { 0.F, 1.F, 0.F } });
177
    m_view_camera.SetParameters({ 600.F /* near = max depth */, 0.01F /*far = min depth*/, 90.F /* FOV */ });
178
    m_view_camera.SetZoomDistanceRange({ 60.F , 400.F });
179

180
    m_light_camera.ResetOrientation({ { -100.F, 120.F, 0.F }, { 0.F, 0.F, 0.F }, { 0.F, 1.F, 0.F } });
181
    m_light_camera.SetProjection(gfx::Camera::Projection::Orthogonal);
182
    m_light_camera.SetParameters({ -300.F, 300.F, 90.F });
183
    m_light_camera.Resize(Data::FloatSize(120.F, 120.F));
184

185
    AddInputControllers({
186
        std::make_shared<AsteroidsAppController>(*this, g_asteroids_action_by_keyboard_state),
187
        std::make_shared<gfx::AppCameraController>(m_view_camera,  "VIEW CAMERA"),
188
        std::make_shared<gfx::AppCameraController>(m_light_camera, "LIGHT SOURCE",
189
            gfx::AppCameraController::ActionByMouseButton   { { pin::Mouse::Button::Right, gfx::ActionCamera::MouseAction::Rotate   } },
190
            gfx::AppCameraController::ActionByKeyboardState { { { pin::Keyboard::Key::LeftControl, pin::Keyboard::Key::L }, gfx::ActionCamera::KeyboardAction::Reset } },
191
            gfx::AppCameraController::ActionByKeyboardKey   { }),
192
    });
193

194
    const std::string options_group = "Asteroids Options";
195
    add_option_group(options_group);
196
    add_option("-c,--complexity",
197
               [this](const CLI::results_t& res)
198
               {
199
                   if (uint32_t complexity = 0;
200
                       CLI::detail::lexical_cast(res[0], complexity))
201
                   {
202
                       SetAsteroidsComplexity(complexity);
203
                       return true;
204
                   }
205
                   return false;
206
               }, "simulation complexity")
207
        ->default_val(m_asteroids_complexity)
208
        ->expected(0, static_cast<int>(g_max_complexity))
209
        ->group(options_group);
210
    add_option("-s,--subdiv-count", m_asteroids_array_settings.subdivisions_count, "mesh subdivisions count")->group(options_group);
211
    add_option("-t,--texture-array", m_asteroids_array_settings.textures_array_enabled, "texture array enabled")->group(options_group);
212
    add_option("-r,--parallel-render", m_is_parallel_rendering_enabled, "parallel rendering enabled")->group(options_group);
213

214
    // Setup animations
215
    GetAnimations().push_back(std::make_shared<Data::TimeAnimation>(std::bind(&AsteroidsApp::Animate, this, std::placeholders::_1, std::placeholders::_2)));
216

217
    // Enable dry updates on pause to keep asteroids in sync with projection matrix dependent on window size which may change
218
    GetAnimations().SetDryUpdateOnPauseEnabled(true);
219

220
    ShowParameters();
221
}
222

223
AsteroidsApp::~AsteroidsApp()
224
{
225
    META_FUNCTION_TASK();
226
    // Wait for GPU rendering is completed to release resources
227
    WaitForRenderComplete();
228
}
229

230
void AsteroidsApp::Init()
231
{
232
    META_FUNCTION_TASK();
233
    META_SCOPE_TIMER("AsteroidsApp::Init");
234

235
    // Create initial render-pass pattern for asteroids rendering
236
    rhi::RenderPattern::Settings asteroids_render_pattern_settings     = GetScreenRenderPatternSettings();
237
    asteroids_render_pattern_settings.color_attachments[0].load_action = rhi::RenderPass::Attachment::LoadAction::DontCare;
238
    asteroids_render_pattern_settings.depth_attachment->load_action    = rhi::RenderPass::Attachment::LoadAction::Clear;
239
    asteroids_render_pattern_settings.depth_attachment->store_action   = rhi::RenderPass::Attachment::StoreAction::Store;
240
    asteroids_render_pattern_settings.is_final_pass = false;
241
    m_asteroids_render_pattern = rhi::RenderPattern(GetRenderContext(), asteroids_render_pattern_settings);
242

243
    // Modify settings of the final screen render-pass pattern so that color and depth attachments are reused from initial asteroids render pass
244
    rhi::RenderPattern::Settings& screen_render_pattern_settings    = GetScreenRenderPatternSettings();
245
    screen_render_pattern_settings.color_attachments[0].load_action = rhi::RenderPass::Attachment::LoadAction::Load;
246
    screen_render_pattern_settings.depth_attachment->load_action    = rhi::RenderPass::Attachment::LoadAction::Load;
247

248
    // Screen render pattern and screen passes for all frames are initialized here based on modified settings
249
    UserInterfaceApp::Init();
250

251
    const rhi::RenderContext& context = GetRenderContext();
252
    rhi::CommandQueue render_cmd_queue = context.GetRenderCommandKit().GetQueue();
253
    const rhi::RenderContext::Settings& context_settings = context.GetSettings();
254
    m_view_camera.Resize(context_settings.frame_size);
255

256
    // Load cube-map texture images for Sky-box
257
    const rhi::Texture sky_box_texture = GetImageLoader().LoadImagesToTextureCube(render_cmd_queue,
258
        gfx::ImageLoader::CubeFaceResources
259
        {
260
            "Galaxy/PositiveX.jpg",
261
            "Galaxy/NegativeX.jpg",
262
            "Galaxy/PositiveY.jpg",
263
            "Galaxy/NegativeY.jpg",
264
            "Galaxy/PositiveZ.jpg",
265
            "Galaxy/NegativeZ.jpg"
266
        },
267
        { gfx::ImageOption::Mipmapped },
268
        "Sky-Box Texture"
269
    );
270

271
    // Create sky-box
272
    m_sky_box = gfx::SkyBox(render_cmd_queue, m_asteroids_render_pattern, sky_box_texture,
273
        gfx::SkyBox::Settings
274
        {
275
            m_view_camera,
276
            m_scene_scale * 100.F,
277
            { gfx::SkyBox::Option::DepthEnabled, gfx::SkyBox::Option::DepthReversed }
278
        });
279

280
    // Create planet
281
    m_planet_ptr = std::make_shared<Planet>(render_cmd_queue, m_asteroids_render_pattern, GetImageLoader(),
282
        Planet::Settings
283
        {
284
            m_view_camera,
285
            m_light_camera,
286
            "Planet/Mars.jpg",                      // texture_path
287
            hlslpp::float3(0.F, 0.F, 0.F),          // position
288
            m_scene_scale * 3.F,                    // scale
289
            0.1F,                                   // spin_velocity_rps
290
            true,                                   // depth_reversed
291
            { gfx::ImageOption::Mipmapped,          // image_options
292
              gfx::ImageOption::SrgbColorSpace },   //
293
            -1.F,                                   // lod_bias
294
        }
295
    );
296

297
    // Create asteroids array
298
    m_asteroids_array_ptr = m_asteroids_array_state_ptr
299
                          ? std::make_unique<AsteroidsArray>(render_cmd_queue, m_asteroids_render_pattern, m_asteroids_array_settings, *m_asteroids_array_state_ptr)
300
                          : std::make_unique<AsteroidsArray>(render_cmd_queue, m_asteroids_render_pattern, m_asteroids_array_settings);
301

302
    const auto       constants_data_size         = static_cast<Data::Size>(sizeof(hlslpp::SceneConstants));
303
    const auto       scene_uniforms_data_size    = static_cast<Data::Size>(sizeof(hlslpp::SceneUniforms));
304
    const Data::Size asteroid_uniforms_data_size = m_asteroids_array_ptr->GetUniformsBufferSize();
305

306
    // Create constants buffer for frame rendering
307
    m_const_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(constants_data_size));
308
    m_const_buffer.SetName("Constants Buffer");
309
    m_const_buffer.SetData(render_cmd_queue, {
310
        reinterpret_cast<Data::ConstRawPtr>(&m_scene_constants),
311
        sizeof(m_scene_constants)
312
    });
313

314
    // ========= Per-Frame Data =========
315
    for(AsteroidsFrame& frame : GetFrames())
316
    {
317
        // Create asteroids render pass
318
        frame.asteroids_pass = rhi::RenderPass(m_asteroids_render_pattern, frame.screen_pass.GetSettings());
319

320
        // Create parallel command list for asteroids rendering
321
        frame.parallel_cmd_list = rhi::ParallelRenderCommandList(context.GetRenderCommandKit().GetQueue(), frame.asteroids_pass);
322
        frame.parallel_cmd_list.SetParallelCommandListsCount(std::thread::hardware_concurrency());
323
        frame.parallel_cmd_list.SetName(fmt::format("Parallel Rendering {}", frame.index));
324
        frame.parallel_cmd_list.SetValidationEnabled(false);
325

326
        // Create serial command list for asteroids rendering
327
        frame.serial_cmd_list = rhi::RenderCommandList(context.GetRenderCommandKit().GetQueue(), frame.asteroids_pass);
328
        frame.serial_cmd_list.SetName(fmt::format("Serial Rendering {}", frame.index));
329
        frame.serial_cmd_list.SetValidationEnabled(false);
330

331
        // Create final command list for sky-box and planet rendering
332
        frame.final_cmd_list = rhi::RenderCommandList(context.GetRenderCommandKit().GetQueue(), frame.screen_pass);
333
        frame.final_cmd_list.SetName(fmt::format("Final Rendering {}", frame.index));
334
        frame.final_cmd_list.SetValidationEnabled(false);
335

336
        // Rendering command lists sequence
337
        frame.execute_cmd_list_set = CreateExecuteCommandListSet(frame);
338

339
        // Create uniforms buffer with volatile parameters for the whole scene rendering
340
        frame.scene_uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(scene_uniforms_data_size, false, true));
341
        frame.scene_uniforms_buffer.SetName(fmt::format("Scene Uniforms Buffer {}", frame.index));
342

343
        // Create uniforms buffer for Sky-Box rendering
344
        frame.sky_box.uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(gfx::SkyBox::GetUniformsSize(), false, true));
345
        frame.sky_box.uniforms_buffer.SetName(fmt::format("Sky-box Uniforms Buffer {}", frame.index));
346

347
        // Create uniforms buffer for Planet rendering
348
        frame.planet.uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(sizeof(hlslpp::PlanetUniforms), false, true));
349
        frame.planet.uniforms_buffer.SetName(fmt::format("Planet Uniforms Buffer {}", frame.index));
350

351
        // Create uniforms buffer for Asteroids array rendering
352
        frame.asteroids.uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(asteroid_uniforms_data_size, true, true));
353
        frame.asteroids.uniforms_buffer.SetName(fmt::format("Asteroids Array Uniforms Buffer {}", frame.index));
354

355
        // Resource bindings for Sky-Box rendering
356
        frame.sky_box.program_bindings = m_sky_box.CreateProgramBindings(frame.sky_box.uniforms_buffer, frame.index);
357
        frame.sky_box.program_bindings.SetName(fmt::format("Space Sky-Box Bindings {}", frame.index));
358

359
        // Resource bindings for Planet rendering
360
        frame.planet.program_bindings = m_planet_ptr->CreateProgramBindings(m_const_buffer, frame.planet.uniforms_buffer, frame.index);
361
        frame.planet.program_bindings.SetName(fmt::format("Planet Bindings {}", frame.index));
362

363

364
        // Resource bindings for Asteroids rendering
365
        frame.asteroids.program_bindings_per_instance = m_asteroids_array_ptr->CreateProgramBindings(m_const_buffer,
366
                                                                                                     frame.scene_uniforms_buffer,
367
                                                                                                     frame.asteroids.uniforms_buffer,
368
                                                                                                     frame.index);
369
    }
370

371
    // Update initial resource states before asteroids drawing without applying barriers on GPU (automatic state propagation from Common state works),
372
    // which is required for correct automatic resource barriers to be set after asteroids drawing, on planet drawing
373
    m_asteroids_array_ptr->CreateBeginningResourceBarriers(&m_const_buffer).ApplyTransitions();
374

375
    CompleteInitialization();
376
    META_LOG(GetParametersString());
377
}
378

379
bool AsteroidsApp::Resize(const gfx::FrameSize& frame_size, bool is_minimized)
380
{
381
    META_FUNCTION_TASK();
382

383
    // Resize screen color and depth textures
384
    if (!UserInterfaceApp::Resize(frame_size, is_minimized))
385
        return false;
386
    
387
    // Update frame buffer and depth textures in initial & final render passes
388
    for (const AsteroidsFrame& frame : GetFrames())
389
    {
390
        rhi::RenderPassSettings asteroids_pass_settings{
391
            {
392
                rhi::TextureView(frame.screen_texture.GetInterface()),
393
                rhi::TextureView(GetDepthTexture().GetInterface())
394
            },
395
            frame_size
396
        };
397
        frame.asteroids_pass.Update(asteroids_pass_settings);
398
    }
399

400
    m_view_camera.Resize(frame_size);
401

402
    return true;
403
}
404

405
bool AsteroidsApp::Update()
406
{
407
    META_FUNCTION_TASK();
408
    META_SCOPE_TIMER("AsteroidsApp::Update");
409

410
    if (!UserInterfaceApp::Update())
411
        return false;
412

413
    // Update scene uniforms
414
    m_scene_uniforms.view_proj_matrix = hlslpp::transpose(m_view_camera.GetViewProjMatrix());
415
    m_scene_uniforms.eye_position     = m_view_camera.GetOrientation().eye;
416
    m_scene_uniforms.light_position   = m_light_camera.GetOrientation().eye;
417

418
    m_sky_box.Update();
419
    return true;
420
}
421

422
bool AsteroidsApp::Animate(double elapsed_seconds, double delta_seconds) const
423
{
424
    META_FUNCTION_TASK();
425
    bool update_result = m_planet_ptr->Update(elapsed_seconds, delta_seconds);
426
    update_result     |= m_asteroids_array_ptr->Update(elapsed_seconds, delta_seconds);
427
    return update_result;
428
}
429

430
bool AsteroidsApp::Render()
431
{
432
    META_FUNCTION_TASK();
433
    META_SCOPE_TIMER("AsteroidsApp::Render");
434
    if (!UserInterfaceApp::Render())
435
        return false;
436

437
    // Upload uniform buffers to GPU
438
    const AsteroidsFrame& frame = GetCurrentFrame();
439
    rhi::CommandQueue render_cmd_queue = GetRenderContext().GetRenderCommandKit().GetQueue();
440
    frame.scene_uniforms_buffer.SetData(render_cmd_queue, m_scene_uniforms_subresource);
441

442
    // Asteroids rendering in parallel or in main thread
443
    if (m_is_parallel_rendering_enabled)
444
    {
445
        GetAsteroidsArray().DrawParallel(frame.parallel_cmd_list, frame.asteroids, GetViewState());
446
        frame.parallel_cmd_list.Commit();
447
    }
448
    else
449
    {
450
        GetAsteroidsArray().Draw(frame.serial_cmd_list, frame.asteroids, GetViewState());
451
        frame.serial_cmd_list.Commit();
452
    }
453
    
454
    // Draw planet and sky-box after asteroids to minimize pixel overdraw
455
    m_planet_ptr->Draw(frame.final_cmd_list, frame.planet, GetViewState());
456
    m_sky_box.Draw(frame.final_cmd_list, frame.sky_box, GetViewState());
457

458
    RenderOverlay(frame.final_cmd_list);
459
    frame.final_cmd_list.Commit();
460

461
    // Execute rendering commands and present frame to screen
462
    render_cmd_queue.Execute(frame.execute_cmd_list_set);
463
    GetRenderContext().Present();
464

465
    return true;
466
}
467

468
void AsteroidsApp::OnContextReleased(rhi::IContext& context)
469
{
470
    META_FUNCTION_TASK();
471
    META_SCOPE_TIMERS_FLUSH();
472

473
    if (m_asteroids_array_ptr)
474
    {
475
        m_asteroids_array_state_ptr = m_asteroids_array_ptr->GetState();
476
    }
477

478
    m_planet_ptr.reset();
479
    m_asteroids_array_ptr.reset();
480
    m_sky_box = {};
481
    m_const_buffer = {};
482
    m_asteroids_render_pattern = {};
483

484
    UserInterfaceApp::OnContextReleased(context);
485
}
486

487
void AsteroidsApp::SetAsteroidsComplexity(uint32_t asteroids_complexity)
488
{
489
    META_FUNCTION_TASK();
490

491
    asteroids_complexity = std::min(g_max_complexity, asteroids_complexity);
492
    if (m_asteroids_complexity == asteroids_complexity)
493
        return;
494

495
    if (GetRenderContext().IsInitialized())
496
    {
497
        WaitForRenderComplete();
498
    }
499

500
    m_asteroids_complexity = asteroids_complexity;
501

502
    const MutableParameters& mutable_parameters         = GetMutableParameters(m_asteroids_complexity);
503
    m_asteroids_array_settings.instance_count           = mutable_parameters.instances_count;
504
    m_asteroids_array_settings.unique_mesh_count        = mutable_parameters.unique_mesh_count;
505
    m_asteroids_array_settings.textures_count           = mutable_parameters.textures_count;
506
    m_asteroids_array_settings.min_asteroid_scale_ratio = mutable_parameters.scale_ratio / 10.F;
507
    m_asteroids_array_settings.max_asteroid_scale_ratio = mutable_parameters.scale_ratio;
508

509
    m_asteroids_array_ptr.reset();
510
    m_asteroids_array_state_ptr.reset();
511

512
    if (GetRenderContext().IsInitialized())
513
    {
514
        GetRenderContext().Reset();
515
    }
516

517
    UpdateParametersText();
518
}
519

520
void AsteroidsApp::SetParallelRenderingEnabled(bool is_parallel_rendering_enabled)
521
{
522
    META_FUNCTION_TASK();
523
    if (m_is_parallel_rendering_enabled == is_parallel_rendering_enabled)
524
        return;
525

526
    META_SCOPE_TIMERS_FLUSH();
527
    m_is_parallel_rendering_enabled = is_parallel_rendering_enabled;
528
    for(AsteroidsFrame& frame : GetFrames())
529
    {
530
        frame.execute_cmd_list_set = CreateExecuteCommandListSet(frame);
531
    }
532

533
    UpdateParametersText();
534
    META_LOG(GetParametersString());
535
}
536

537
AsteroidsArray& AsteroidsApp::GetAsteroidsArray() const
538
{
539
    META_FUNCTION_TASK();
540
    META_CHECK_ARG_NOT_NULL(m_asteroids_array_ptr);
541
    return *m_asteroids_array_ptr;
542
}
543

544
std::string AsteroidsApp::GetParametersString()
545
{
546
    META_FUNCTION_TASK();
547

548
    std::stringstream ss;
549
    ss << "Asteroids simulation parameters:"
550
       << std::endl << "  - simulation complexity [0.."  << g_max_complexity << "]: " << m_asteroids_complexity
551
       << std::endl << "  - asteroid instances count:     " << m_asteroids_array_settings.instance_count
552
       << std::endl << "  - unique meshes count:          " << m_asteroids_array_settings.unique_mesh_count
553
       << std::endl << "  - mesh subdivisions count:      " << m_asteroids_array_settings.subdivisions_count
554
       << std::endl << "  - unique textures count:        " << m_asteroids_array_settings.textures_count << " "
555
       << std::endl << "  - asteroid textures size:       " << static_cast<std::string>(m_asteroids_array_settings.texture_dimensions)
556
       << std::endl << "  - textures array binding:       " << (m_asteroids_array_settings.textures_array_enabled ? "ON" : "OFF")
557
       << std::endl << "  - parallel rendering:           " << (m_is_parallel_rendering_enabled ? "ON" : "OFF")
558
       << std::endl << "  - asteroid animations:          " << (!GetAnimations().IsPaused() ? "ON" : "OFF")
559
       << std::endl << "  - CPU h/w thread count:         " << std::thread::hardware_concurrency();
560

561
    return ss.str();
562
}
563

564
rhi::CommandListSet AsteroidsApp::CreateExecuteCommandListSet(const AsteroidsFrame& frame) const
565
{
566
    return rhi::CommandListSet({
567
        m_is_parallel_rendering_enabled
568
            ? static_cast<rhi::ICommandList&>(frame.parallel_cmd_list.GetInterface())
569
            : static_cast<rhi::ICommandList&>(frame.serial_cmd_list.GetInterface()),
570
        frame.final_cmd_list.GetInterface()
571
    }, frame.index);
572
}
573

574
} // namespace Methane::Samples
575

576
int main(int argc, const char* argv[])
577
{
578
    return Methane::Samples::AsteroidsApp().Run({ argc, argv });
579
}
580

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.