void GraphicsCommandListImmediate::SortCommandsForMetal() { static_assert(static_cast<int>(GraphicsCommandType::DrawCommand) == 0, ""); static_assert(static_cast<int>(GraphicsCommandType::DrawIndexedCommand) == 1, ""); static_assert(static_cast<int>(GraphicsCommandType::DrawInstancedCommand) == 2, ""); static_assert(static_cast<int>(GraphicsCommandType::DrawIndexedInstancedCommand) == 3, ""); static_assert(static_cast<int>(GraphicsCommandType::SetPrimitiveTopologyCommand) == 4, ""); static_assert(static_cast<int>(GraphicsCommandType::SetBlendFactorCommand) == 5, ""); static_assert(static_cast<int>(GraphicsCommandType::SetVertexBuffersCommand) == 6, ""); static_assert(static_cast<int>(GraphicsCommandType::SetIndexBufferCommand) == 7, ""); static_assert(static_cast<int>(GraphicsCommandType::SetPipelineStateCommand) == 8, ""); static_assert(static_cast<int>(GraphicsCommandType::SetConstantBufferCommand) == 9, ""); static_assert(static_cast<int>(GraphicsCommandType::SetSamplerStateCommand) == 10, ""); static_assert(static_cast<int>(GraphicsCommandType::SetTextureCommand) == 11, ""); static_assert(static_cast<int>(GraphicsCommandType::SetTextureRenderTarget2DCommand) == 12, ""); static_assert(static_cast<int>(GraphicsCommandType::SetRenderPassCommand) == 13, ""); constexpr std::int8_t priorityDrawCommand = 31; constexpr std::int8_t priorityDefault = 30; const std::array<std::int8_t, 14> priorities = {{ priorityDrawCommand, // DrawCommand priorityDrawCommand, // DrawIndexedCommand priorityDrawCommand, // DrawInstancedCommand priorityDrawCommand, // DrawIndexedInstancedCommand priorityDefault, // SetPrimitiveTopologyCommand priorityDefault, // SetBlendFactorCommand priorityDefault, // SetVertexBuffersCommand priorityDefault, // SetIndexBufferCommand priorityDefault, // SetPipelineStateCommand priorityDefault, // SetConstantBufferCommand priorityDefault, // SetSamplerStateCommand priorityDefault, // SetTextureCommand priorityDefault, // SetTextureRenderTarget2DCommand 0, // SetRenderPassCommand }}; // NOTE: Sort commands for MTLRenderCommandEncoder by using odd-even sort. for (size_t k = 0; k < commands.size(); ++k) { bool swapped = false; for (size_t i = 1 + (k % 2); i < commands.size(); i += 2) { auto & a = commands[i - 1]; auto & b = commands[i]; const auto x = static_cast<std::int8_t>(a->commandType); const auto y = static_cast<std::int8_t>(b->commandType); POMDOG_ASSERT(x <= static_cast<std::int8_t>(priorities.size())); POMDOG_ASSERT(y <= static_cast<std::int8_t>(priorities.size())); if ((priorities[x] > priorities[y]) && (priorities[x] != priorityDrawCommand)) { std::swap(a, b); swapped = true; } } if (!swapped && (k > 0)) { break; } } #if 0 // NOTE: Remove a redundant 'SetRenderPassCommand' command. bool isPrevRenderPassCommand = false; for (auto iter = commands.rbegin(); iter != commands.rend();) { if ((*iter)->commandType == GraphicsCommandType::SetRenderPassCommand) { if (isPrevRenderPassCommand) { std::advance(iter, 1); commands.erase(iter.base()); continue; } isPrevRenderPassCommand = true; } else { isPrevRenderPassCommand = false; } ++iter; } #endif // NOTE: Duplicate missing commands for MTLRenderCommandEncoder. std::size_t renderPassCommandIndex = 0; std::optional<std::size_t> setPipelineStateCommand; std::optional<std::size_t> setPrimitiveTopologyCommand; std::optional<std::size_t> setBlendFactorCommand; std::optional<std::size_t> setVertexBuffersCommand; std::optional<std::size_t> setIndexBufferCommand; std::vector<std::optional<std::size_t>> setConstantBufferCommands; std::vector<std::optional<std::size_t>> setSamplerCommands; std::vector<std::optional<std::size_t>> setTextureCommands; setConstantBufferCommands.resize(8, std::nullopt); setSamplerCommands.resize(8, std::nullopt); setTextureCommands.resize(8, std::nullopt); std::vector<std::shared_ptr<GraphicsCommand>> oldCommands; bool needToFlushCommands = true; std::swap(commands, oldCommands); for (auto & command : oldCommands) { POMDOG_ASSERT(command != nullptr); bool isDrawCommand = false; switch (command->commandType) { case GraphicsCommandType::SetRenderPassCommand: renderPassCommandIndex = commands.size(); needToFlushCommands = true; break; case GraphicsCommandType::SetPipelineStateCommand: setPipelineStateCommand = commands.size(); break; case GraphicsCommandType::SetPrimitiveTopologyCommand: setPrimitiveTopologyCommand = commands.size(); break; case GraphicsCommandType::SetBlendFactorCommand: setBlendFactorCommand = commands.size(); break; case GraphicsCommandType::SetVertexBuffersCommand: setVertexBuffersCommand = commands.size(); break; case GraphicsCommandType::SetIndexBufferCommand: setIndexBufferCommand = commands.size(); break; case GraphicsCommandType::SetConstantBufferCommand: { auto c = std::static_pointer_cast<SetConstantBufferCommand>(command); POMDOG_ASSERT(c->slotIndex < static_cast<int>(setConstantBufferCommands.size())); setConstantBufferCommands[c->slotIndex] = commands.size(); break; } case GraphicsCommandType::SetSamplerStateCommand: { auto c = std::static_pointer_cast<SetSamplerStateCommand>(command); POMDOG_ASSERT(c->slotIndex < static_cast<int>(setSamplerCommands.size())); setSamplerCommands[c->slotIndex] = commands.size(); break; } case GraphicsCommandType::SetTextureCommand: { auto c = std::static_pointer_cast<SetTextureCommand>(command); POMDOG_ASSERT(c->slotIndex < static_cast<int>(setTextureCommands.size())); setTextureCommands[c->slotIndex] = commands.size(); break; } case GraphicsCommandType::SetTextureRenderTarget2DCommand: { auto c = std::static_pointer_cast<SetTextureRenderTarget2DCommand>(command); POMDOG_ASSERT(c->slotIndex < static_cast<int>(setTextureCommands.size())); setTextureCommands[c->slotIndex] = commands.size(); break; } case GraphicsCommandType::DrawCommand: case GraphicsCommandType::DrawIndexedCommand: case GraphicsCommandType::DrawInstancedCommand: case GraphicsCommandType::DrawIndexedInstancedCommand: { isDrawCommand = true; break; } } if (isDrawCommand && needToFlushCommands) { if (setPipelineStateCommand && (*setPipelineStateCommand < renderPassCommandIndex)) { commands.push_back(commands[*setPipelineStateCommand]); } if (setPrimitiveTopologyCommand && (*setPrimitiveTopologyCommand < renderPassCommandIndex)) { commands.push_back(commands[*setPrimitiveTopologyCommand]); } if (setBlendFactorCommand && (*setBlendFactorCommand < renderPassCommandIndex)) { commands.push_back(commands[*setBlendFactorCommand]); } if (setVertexBuffersCommand && (*setVertexBuffersCommand < renderPassCommandIndex)) { commands.push_back(commands[*setVertexBuffersCommand]); } if (setIndexBufferCommand && (*setIndexBufferCommand < renderPassCommandIndex)) { commands.push_back(commands[*setIndexBufferCommand]); } for (auto & commandIndex : setConstantBufferCommands) { if (commandIndex && (*commandIndex < renderPassCommandIndex)) { commands.push_back(commands[*commandIndex]); } } for (auto & commandIndex : setSamplerCommands) { if (commandIndex && (*commandIndex < renderPassCommandIndex)) { commands.push_back(commands[*commandIndex]); } } for (auto & commandIndex : setTextureCommands) { if (commandIndex && (*commandIndex < renderPassCommandIndex)) { commands.push_back(commands[*commandIndex]); } } needToFlushCommands = false; } commands.push_back(std::move(command)); } }
//----------------------------------------------------------------------- void Animator::SetBool(std::string const& name, bool value) { POMDOG_ASSERT(impl); impl->SetBool(name, value); }
void AudioEngineAL::SetMasterVolume(float volume) { POMDOG_ASSERT(volume >= 0.0f); alListenerf(AL_GAIN, volume); }
//----------------------------------------------------------------------- void Animator::Play(std::string const& state) { POMDOG_ASSERT(impl); impl->Play(state); }
//----------------------------------------------------------------------- void Animator::PlaybackRate(float playbackRate) { POMDOG_ASSERT(impl); impl->PlaybackRate(playbackRate); }
void OpenGLContextWin32::MakeCurrent() { POMDOG_ASSERT(hdc); POMDOG_ASSERT(glrc); wglMakeCurrent(hdc.get(), glrc.get()); }
//----------------------------------------------------------------------- void Animator::Update(Duration const& frameDuration) { POMDOG_ASSERT(impl); impl->Update(frameDuration); }
bool FileSystem::CreateDirectory(const std::string& path) { // 'CreateDirectory' means 'CreateDirectoryA' in Win32. POMDOG_ASSERT(!path.empty()); return fs::create_directory(path); }
bool FileSystem::CreateDirectories(const std::string& path) { POMDOG_ASSERT(!path.empty()); return fs::create_directories(path); }
GLuint BufferGL4<Tag>::GetBuffer() const { POMDOG_ASSERT(bufferObject); return bufferObject->value; }
BufferGL4<Tag>::BufferGL4(std::size_t sizeInBytes, BufferUsage bufferUsage) : BufferGL4(nullptr, sizeInBytes, bufferUsage) { POMDOG_ASSERT(bufferUsage != BufferUsage::Immutable); }
void BufferGL4<Tag>::BindBuffer() { POMDOG_ASSERT(bufferObject); TypesafeHelperGL4::BindBuffer(*bufferObject); POMDOG_CHECK_ERROR_GL4("glBindBuffer"); }
~ScopeGuard() { POMDOG_ASSERT(func); func(); }
Connection LogChannel::Connect(std::function<void(const LogEntry&)> && slot) { POMDOG_ASSERT(slot); return signal.Connect(std::move(slot)); }
void AudioEngine::SetMasterVolume(float volume) { POMDOG_ASSERT(volume >= 0); POMDOG_ASSERT(nativeAudioEngine); nativeAudioEngine->SetMasterVolume(volume); }
bool FileSystem::Exists(const std::string& path) { POMDOG_ASSERT(!path.empty()); return fs::exists(path); }
Detail::SoundSystem::NativeAudioEngine* AudioEngine::GetNativeAudioEngine() { POMDOG_ASSERT(nativeAudioEngine); return nativeAudioEngine.get(); }
bool FileSystem::IsDirectory(const std::string& path) { POMDOG_ASSERT(!path.empty()); return fs::is_directory(path); }
void PolygonShapeBuilder::DrawSphere( const Vector3& position, float radius, const Color& color, int segments) { POMDOG_ASSERT(segments >= 4); POMDOG_ASSERT(radius >= 0); if (radius <= 0) { return; } const auto rings = std::max(static_cast<int>(segments), 4); const auto sectors = std::max(static_cast<int>(segments), 4); std::vector<Vector3> sphereVertices; sphereVertices.reserve(rings * sectors); const auto R = 1.0f / static_cast<float>(rings - 1); const auto S = 1.0f / static_cast<float>(sectors - 1); for (int ring = 0; ring < rings; ++ring) { const auto latitude = Math::Pi<float> * ring * R; const auto y = std::cos(latitude); const auto r = std::sin(latitude); for (int s = 0; s < sectors; ++s) { const auto longitude = Math::TwoPi<float> * s * S; const auto x = r * std::cos(longitude); const auto z = r * std::sin(longitude); sphereVertices.push_back(Vector3{x, y, z} * radius + position); } } const auto colorVector = color.ToVector4(); const auto drawIndices = [&](std::size_t a, std::size_t b, std::size_t c, std::size_t d) { POMDOG_ASSERT(a < sphereVertices.size()); POMDOG_ASSERT(b < sphereVertices.size()); POMDOG_ASSERT(c < sphereVertices.size()); POMDOG_ASSERT(d < sphereVertices.size()); DrawTriangle( sphereVertices[a], sphereVertices[c], sphereVertices[b], colorVector, colorVector, colorVector); DrawTriangle( sphereVertices[c], sphereVertices[a], sphereVertices[d], colorVector, colorVector, colorVector); }; for (int r = 0; r < rings - 1; ++r) { for (int s = 0; s < sectors - 1; ++s) { drawIndices( r * sectors + s, (r + 1) * sectors + s, (r + 1) * sectors + (s + 1), r * sectors + (s + 1)); } } }
//----------------------------------------------------------------------- Joint const& Skeleton::Root() const { POMDOG_ASSERT(!joints.empty()); return joints.front(); }
//----------------------------------------------------------------------- void Animator::CrossFade(std::string const& state, Duration const& transitionDuration) { POMDOG_ASSERT(impl); impl->CrossFade(state, transitionDuration); }
//----------------------------------------------------------------------- Joint const& Skeleton::Joints(JointIndex const& jointIndex) const { POMDOG_ASSERT(jointIndex); POMDOG_ASSERT(*jointIndex < joints.size()); return joints[*jointIndex]; }
//----------------------------------------------------------------------- float Animator::PlaybackRate() const { POMDOG_ASSERT(impl); return impl->PlaybackRate(); }
//----------------------------------------------------------------------- std::uint16_t Skeleton::JointCount() const { POMDOG_ASSERT(joints.size() < std::numeric_limits<std::uint16_t>::max()); return static_cast<std::uint16_t>(joints.size()); }
//----------------------------------------------------------------------- void Animator::SetFloat(std::string const& name, float value) { POMDOG_ASSERT(impl); impl->SetFloat(name, value); }
CompressedFloat(float scalar) : data(scalar * Denominator) { POMDOG_ASSERT(scalar < Max()); POMDOG_ASSERT(scalar >= Min()); }
//----------------------------------------------------------------------- std::string Animator::GetCurrentStateName() const { POMDOG_ASSERT(impl); return impl->GetCurrentStateName(); }
float AudioEngine::GetMasterVolume() const { POMDOG_ASSERT(nativeAudioEngine); return nativeAudioEngine->GetMasterVolume(); }
void LightningTestGame::Initialize() { window->SetTitle("TestApp - Enjoy Game Dev, Have Fun."); window->SetAllowUserResizing(true); auto assets = gameHost->AssetManager(); auto clientBounds = window->GetClientBounds(); { gameEditor = std::make_unique<SceneEditor::InGameEditor>(gameHost); editorBackground = std::make_unique<SceneEditor::EditorBackground>(gameHost); } { commandList = std::make_shared<GraphicsCommandList>(*graphicsDevice); //samplerPoint = SamplerState::CreatePointWrap(graphicsDevice); texture = assets->Load<Texture2D>("Particles/lightning.png"); } { renderTarget = std::make_shared<RenderTarget2D>(graphicsDevice, clientBounds.Width, clientBounds.Height, false, SurfaceFormat::R8G8B8A8_UNorm, DepthFormat::None); } { spriteBatch = std::make_unique<SpriteBatch>(graphicsDevice, *assets); spriteRenderer = std::make_unique<SpriteRenderer>(graphicsDevice, *assets); fxaa = std::make_unique<FXAA>(graphicsDevice, *assets); fxaa->SetViewport(clientBounds.Width, clientBounds.Height); screenQuad = std::make_unique<ScreenQuad>(graphicsDevice); } { mainCamera = gameWorld.CreateObject(); mainCamera.AddComponent<Transform2D>(); mainCamera.AddComponent<Camera2D>(); } // { // auto gameObject = gameWorld.CreateObject(); // // auto & sprite = gameObject->AddComponent<Sprite>(); // sprite.Origin = Vector2{0.5f, 0.5f}; // sprite.Subrect = Rectangle(0, 0, texture->Width(), texture->Height()); // // gameObject->AddComponent<Transform2D>(); // gameObject->AddComponent<CanvasItem>(); // // auto transform = gameObject->Component<Transform2D>(); // transform->Position = {0, 0}; // transform->Scale = {2, 2}; // // auto node = std::make_shared<HierarchyNode>(gameObject); // rootNode->AddChild(node); // } // // for (int i = 0; i < 10; ++i) // { // auto gameObject = gameWorld.CreateObject(); // gameObject->AddComponent<CanvasItem>(); // // auto & sprite = gameObject->AddComponent<Sprite>(); // auto & transform = gameObject->AddComponent<Transform2D>(); // // transform.Position = {i * 64 * 2.0f, 0}; // transform.Scale = {2.0f, 2.0f}; // transform.Rotation = (0.5f * i) * Math::PiOver4<float>; // sprite.Origin = Vector2{0.5f, 0.5f}; // sprite.Subrect = Rectangle(0, 0, texture->Width(), texture->Height());//Rectangle(0, 0, 16, 28); // // auto node = std::make_shared<HierarchyNode>(gameObject); // rootNode->AddChild(node); // } touchPoint = {0, -300}; { scenePanel = std::make_shared<UI::ScenePanel>(clientBounds.Width, clientBounds.Height); scenePanel->cameraObject = mainCamera; gameEditor->AddView(scenePanel); } { auto stackPanel = std::make_shared<UI::StackPanel>(124, 170); stackPanel->Transform(Matrix3x2::CreateTranslation(Vector2{5, 10})); gameEditor->AddView(stackPanel); { auto navigator = std::make_shared<UI::DebugNavigator>(gameHost->Clock()); stackPanel->AddChild(navigator); } { slider1 = std::make_shared<UI::Slider>(0, 100); slider1->Value(34); stackPanel->AddChild(slider1); } { slider2 = std::make_shared<UI::Slider>(0.1, 4.0); slider2->Value(1.2); stackPanel->AddChild(slider2); } { slider3 = std::make_shared<UI::Slider>(0.0f, 1.0f); slider3->Value(0.2f); stackPanel->AddChild(slider3); } { slider4 = std::make_shared<UI::Slider>(0.0f, 70.0f); slider4->Value(8.0f); stackPanel->AddChild(slider4); } { slider5 = std::make_shared<UI::Slider>(0.0f, 70.0f); slider5->Value(8.0f); stackPanel->AddChild(slider5); } } clientViewport = Viewport{0, 0, clientBounds.Width, clientBounds.Height}; connections.Connect(scenePanel->SceneTouch, [this](Vector2 const& positionInView) { auto transform = mainCamera.Component<Transform2D>(); auto camera = mainCamera.Component<Camera2D>(); POMDOG_ASSERT(transform && camera); auto inverseViewMatrix3D = Matrix4x4::Invert(SandboxHelper::CreateViewMatrix(*transform, *camera)); auto position = Vector3::Transform(Vector3( positionInView.X - clientViewport.Width / 2, positionInView.Y - clientViewport.Height / 2, 0), inverseViewMatrix3D); touchPoint = Vector2{position.X, position.Y}; }); connections.Connect(window->ClientSizeChanged, [this](int width, int height) { clientViewport = Viewport{0, 0, width, height}; renderTarget = std::make_shared<RenderTarget2D>( graphicsDevice, width, height, false, SurfaceFormat::R8G8B8A8_UNorm, DepthFormat::None); fxaa->SetViewport(width, height); spriteRenderer->SetProjectionMatrix(Matrix4x4::CreateOrthographicLH(width, height, 1.0f, 100.0f)); }); }
//----------------------------------------------------------------------- Detail::SoundSystem::NativeAudioClip* AudioClip::NativeAudioClip() { POMDOG_ASSERT(nativeAudioClip); return nativeAudioClip.get(); }