diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index b671a97..b7ae8c2 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -11,6 +11,8 @@ endif() # TODO: Add tests and install targets if needed. + + # -- Biblioteca DirectxTK -- # Url: https://github.com/microsoft/DirectXTK/wiki/DirectXTK # @@ -29,5 +31,4 @@ endif() # } # find_package(directxtk CONFIG REQUIRED) - target_link_libraries(${PROJECT_NAME} D3d11.lib dxgi.lib dxguid.lib d3dcompiler.lib Microsoft::DirectXTK) diff --git a/framework/csharp/timespan.hpp b/framework/csharp/timespan.hpp index a8912ae..7bda83d 100644 --- a/framework/csharp/timespan.hpp +++ b/framework/csharp/timespan.hpp @@ -34,8 +34,8 @@ namespace xna { static constexpr int64_t MinutesPerHour = TicksPerHour / TicksPerMinute; static constexpr int64_t MinutesPerDay = TicksPerDay / TicksPerMinute; static constexpr int64_t HoursPerDay = TicksPerDay / TicksPerHour; - static constexpr int64_t MinTicks = std::numeric_limits::min(); - static constexpr int64_t MaxTicks = std::numeric_limits::max(); + static constexpr int64_t MinTicks = (std::numeric_limits::min)(); + static constexpr int64_t MaxTicks = (std::numeric_limits::max)(); static constexpr int64_t MinMicroseconds = MinTicks / TicksPerMicrosecond; static constexpr int64_t MaxMicroseconds = MaxTicks / TicksPerMicrosecond; static constexpr int64_t MinMilliseconds = MinTicks / TicksPerMillisecond; diff --git a/framework/graphics/adapter.hpp b/framework/graphics/adapter.hpp index b875328..081baa5 100644 --- a/framework/graphics/adapter.hpp +++ b/framework/graphics/adapter.hpp @@ -20,6 +20,9 @@ namespace xna { virtual Uint SubSystemId() const = 0; virtual Uint VendorId() const = 0; virtual UDisplayModeCollection SupportedDisplayModes() const = 0; + virtual UDisplayModeCollection SupportedDisplayModes(SurfaceFormat surfaceFormat) const = 0; + virtual PDisplayMode CurrentDisplayMode() = 0; + virtual void CurrentDisplayMode(SurfaceFormat surfaceFormat, Uint width, Uint height) = 0; static UGraphicsAdapter DefaultAdapter(); static void Adapters(std::vector& adapters); diff --git a/framework/graphics/displaymode.hpp b/framework/graphics/displaymode.hpp index a2a0f1b..0084f3d 100644 --- a/framework/graphics/displaymode.hpp +++ b/framework/graphics/displaymode.hpp @@ -19,8 +19,6 @@ namespace xna { class IDisplayModeCollection { public: virtual ~IDisplayModeCollection() {} - virtual std::vector At(SurfaceFormat format) const = 0; - virtual void At(SurfaceFormat format, std::vector& modes) const = 0; virtual size_t SurfaceCount(SurfaceFormat format) const = 0; }; } diff --git a/framework/graphics/presentparams.hpp b/framework/graphics/presentparams.hpp index 580c59a..3230467 100644 --- a/framework/graphics/presentparams.hpp +++ b/framework/graphics/presentparams.hpp @@ -1,8 +1,7 @@ #ifndef XNA_GRAPHICS_PRESENTPARAMS_HPP #define XNA_GRAPHICS_PRESENTPARAMS_HPP -#include "../types.hpp" -#include "../enums.hpp" +#include "../default.hpp" namespace xna { class PresentationParameters { diff --git a/framework/platform/adapter-dx.cpp b/framework/platform/adapter-dx.cpp index 8f6304f..8bf3ab8 100644 --- a/framework/platform/adapter-dx.cpp +++ b/framework/platform/adapter-dx.cpp @@ -1,7 +1,10 @@ #include "adapter-dx.hpp" #include "../helpers.hpp" +#include "gdevicemanager-dx.hpp" namespace xna { + static size_t getDisplayModesCount(IDXGIAdapter* adapter); + static UDisplayModeCollection createDisplayModeCollection(std::vector const& source); UGraphicsAdapter IGraphicsAdapter::DefaultAdapter() { IDXGIFactory1* pFactory = nullptr; @@ -15,7 +18,7 @@ namespace xna { auto adp = uNew(); adp->_index = 0; - adp->_adapter = pAdapter; + adp->dxadapter = pAdapter; return adp; } @@ -39,7 +42,7 @@ namespace xna { auto adp = New(); adp->_index = count; - adp->_adapter = pAdapter; + adp->dxadapter = pAdapter; adapters.push_back(adp); } @@ -61,7 +64,7 @@ namespace xna { auto adp = uNew(); adp->_index = count; - adp->_adapter = pAdapter; + adp->dxadapter = pAdapter; adapters.push_back(std::move(adp)); } @@ -71,30 +74,30 @@ namespace xna { } String GraphicsAdapter::Description() const { - if (!_adapter) return String(); + if (!dxadapter) return String(); DXGI_ADAPTER_DESC1 desc; - _adapter->GetDesc1(&desc); + dxadapter->GetDesc1(&desc); String description = XnaHToString(desc.Description); return description; } Uint GraphicsAdapter::DeviceId() const { - if (!_adapter) return 0; + if (!dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; - _adapter->GetDesc1(&desc); + dxadapter->GetDesc1(&desc); return static_cast(desc.DeviceId); } String GraphicsAdapter::DeviceName() const { - if (!_adapter) return String(); + if (!dxadapter) return String(); IDXGIOutput* pOutput = nullptr; DXGI_OUTPUT_DESC outputDesc; - if (_adapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { + if (dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { pOutput->GetDesc(&outputDesc); String deviceName = XnaHToString(outputDesc.DeviceName); @@ -108,12 +111,12 @@ namespace xna { } intptr_t GraphicsAdapter::MonitorHandle() const { - if (!_adapter) return 0; + if (!dxadapter) return 0; IDXGIOutput* pOutput = nullptr; DXGI_OUTPUT_DESC outputDesc; - if (_adapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { + if (dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { pOutput->GetDesc(&outputDesc); pOutput->Release(); @@ -126,32 +129,134 @@ namespace xna { } Uint GraphicsAdapter::Revision() const { - if (!_adapter) return 0; + if (!dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; - _adapter->GetDesc1(&desc); + dxadapter->GetDesc1(&desc); return static_cast(desc.Revision); } Uint GraphicsAdapter::SubSystemId() const { - if (!_adapter) return 0; + if (!dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; - _adapter->GetDesc1(&desc); + dxadapter->GetDesc1(&desc); return static_cast(desc.SubSysId); } Uint GraphicsAdapter::VendorId() const { - if (!_adapter) return 0; + if (!dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; - _adapter->GetDesc1(&desc); + dxadapter->GetDesc1(&desc); return static_cast(desc.VendorId); + } + + UDisplayModeCollection GraphicsAdapter::SupportedDisplayModes() const { + if (!dxadapter) return nullptr; + + const auto totalDisplay = getDisplayModesCount(dxadapter); + + if (totalDisplay == 0) + return nullptr; + + IDXGIOutput* pOutput = nullptr; + UINT bufferOffset = 0; + + std::vector buffer(totalDisplay); + + if (dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { + for (size_t f = 0; f < SURFACE_FORMAT_COUNT; ++f) { + const auto currentSurface = static_cast(f); + DXGI_FORMAT format = GraphicsAdapter::ToDXGI(currentSurface); + + UINT numModes = 0; + pOutput->GetDisplayModeList(format, 0, &numModes, nullptr); + + if (numModes == 0) + continue; + + pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data() + bufferOffset); + + bufferOffset += numModes; + } + } + + if (!pOutput) + return nullptr; + + pOutput->Release(); + pOutput = nullptr; + + return createDisplayModeCollection(buffer); } + UDisplayModeCollection GraphicsAdapter::SupportedDisplayModes(SurfaceFormat surfaceFormat) const + { + if (!dxadapter) return nullptr; + + IDXGIOutput* pOutput = nullptr; + UINT bufferOffset = 0; + + if (dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { + DXGI_FORMAT format = GraphicsAdapter::ToDXGI(surfaceFormat); + + UINT numModes = 0; + + pOutput->GetDisplayModeList(format, 0, &numModes, nullptr); + + if (numModes == 0) + return uNew(); + + std::vector buffer(numModes); + pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data()); + + pOutput->Release(); + pOutput = nullptr; + + return createDisplayModeCollection(buffer); + } + + return uNew(); + } + + PDisplayMode GraphicsAdapter::CurrentDisplayMode() { + if (!_currentDisplayMode) { + CurrentDisplayMode(SurfaceFormat::Color, GraphicsDeviceManager::DefaultBackBufferWidth, GraphicsDeviceManager::DefaultBackBufferHeight); + } + + return _currentDisplayMode; + } + + void GraphicsAdapter::CurrentDisplayMode(SurfaceFormat surfaceFormat, Uint width, Uint height) { + const auto modes = SupportedDisplayModes(surfaceFormat); + + for (size_t i = 0; i < modes->_displayModes.size(); ++i) { + auto& m = modes->_displayModes[i]; + + if (m->_format == surfaceFormat && m->_width == width && m->_height == height) { + _currentDisplayMode = m; + } + else if(i + 1 == modes->_displayModes.size()) { + _currentDisplayMode = m; + } + } + } + + bool GraphicsAdapter::GetOutput(UINT slot, IDXGIOutput*& output) { + if (!dxadapter) return false; + + if (dxadapter->EnumOutputs(slot, &output) != DXGI_ERROR_NOT_FOUND) + return true; + + return false; + } + + //INTERNAL FUNCTIONS + static size_t getDisplayModesCount(IDXGIAdapter* adapter) { IDXGIOutput* pOutput = nullptr; size_t numModes = 0; @@ -174,49 +279,14 @@ namespace xna { return numModes; } - UDisplayModeCollection GraphicsAdapter::SupportedDisplayModes() const { - if (!_adapter) return nullptr; - - const auto totalDisplay = getDisplayModesCount(_adapter); - - if (totalDisplay == 0) - return nullptr; - - IDXGIOutput* pOutput = nullptr; - UINT bufferOffset = 0; - - std::vector buffer(totalDisplay); - - if (_adapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { - for (size_t f = 0; f < SURFACE_FORMAT_COUNT; ++f) { - const auto currentSurface = static_cast(f); - DXGI_FORMAT format = GraphicsAdapter::ToDXGI(currentSurface); - - UINT numModes = 0; - pOutput->GetDisplayModeList(format, 0, &numModes, nullptr); - - if (numModes == 0) - continue; - - pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data() + bufferOffset); - - bufferOffset += numModes; - } - } - - if (!pOutput) - return nullptr; - - pOutput->Release(); - pOutput = nullptr; - + static UDisplayModeCollection createDisplayModeCollection(std::vector const& source) { auto collection = uNew(); DisplayMode currentDisplayMode; std::vector displayList; PDisplayMode pDisplay = nullptr; - for (size_t i = 0; i < totalDisplay; ++i) { - auto& modedesc = buffer[i]; + for (size_t i = 0; i < source.size(); ++i) { + auto& modedesc = source[i]; DisplayModeDescription description; description._refreshRate = modedesc.RefreshRate; @@ -238,16 +308,6 @@ namespace xna { collection->_displayModes = displayList; - return std::move(collection); - } - - bool GraphicsAdapter::GetOutput(UINT slot, IDXGIOutput*& output) { - if (!_adapter) return false; - - - if (_adapter->EnumOutputs(slot, &output) != DXGI_ERROR_NOT_FOUND) - return true; - - return false; + return collection; } } \ No newline at end of file diff --git a/framework/platform/adapter-dx.hpp b/framework/platform/adapter-dx.hpp index 5537b3d..5266b4c 100644 --- a/framework/platform/adapter-dx.hpp +++ b/framework/platform/adapter-dx.hpp @@ -13,9 +13,9 @@ namespace xna { GraphicsAdapter() {} virtual ~GraphicsAdapter() override { - if (_adapter) { - _adapter->Release(); - _adapter = nullptr; + if (dxadapter) { + dxadapter->Release(); + dxadapter = nullptr; } } @@ -27,13 +27,17 @@ namespace xna { virtual Uint SubSystemId() const override; virtual Uint VendorId() const override; virtual UDisplayModeCollection SupportedDisplayModes() const override; + virtual UDisplayModeCollection SupportedDisplayModes(SurfaceFormat surfaceFormat) const override; + virtual PDisplayMode CurrentDisplayMode() override; + virtual void CurrentDisplayMode(SurfaceFormat surfaceFormat, Uint width, Uint height) override; virtual constexpr bool IsDefaultAdapter() const { return _index == 0; } bool GetOutput(UINT slot, IDXGIOutput*& output); public: - IDXGIAdapter1* _adapter{ nullptr }; + IDXGIAdapter1* dxadapter{ nullptr }; private: - Uint _index{ 0 }; + Uint _index{ 0 }; + PDisplayMode _currentDisplayMode = nullptr; public: static constexpr DXGI_FORMAT ToDXGI(SurfaceFormat format) diff --git a/framework/platform/device-dx.cpp b/framework/platform/device-dx.cpp index 7b0e584..97dab66 100644 --- a/framework/platform/device-dx.cpp +++ b/framework/platform/device-dx.cpp @@ -6,16 +6,19 @@ #include "blendstate-dx.hpp" #include "gdeviceinfo-dx.hpp" #include "../common/color.hpp" +#include "gdevicemanager-dx.hpp" namespace xna { GraphicsDevice::GraphicsDevice() { _blendState = BlendState::NonPremultiplied(); _adapter = GraphicsAdapter::DefaultAdapter(); + _adapter->CurrentDisplayMode(SurfaceFormat::Color, GraphicsDeviceManager::DefaultBackBufferWidth, GraphicsDeviceManager::DefaultBackBufferHeight); } GraphicsDevice::GraphicsDevice(GraphicsDeviceInformation const& info) { - _adapter = info.Adapter(); + _adapter = info.Adapter(); _presentParameters = info.PresentationParameters(); + _adapter->CurrentDisplayMode(_presentParameters.BackBufferFormat, _presentParameters.BackBufferWidth, _presentParameters.BackBufferHeight); } bool GraphicsDevice::Initialize(GameWindow& gameWindow) { @@ -95,18 +98,11 @@ namespace xna { } bool GraphicsDevice::Present() { - _swapChain->_swapChain->Present(_usevsync, NULL); + const auto result = _swapChain->Present(_usevsync); _context->OMSetRenderTargets(1, &_renderTarget2D->_renderTargetView, nullptr); - return true; - } - - bool GraphicsDevice::GetSwapChainBackBuffer(ID3D11Texture2D*& texture2D) { - if FAILED(_swapChain->_swapChain->GetBuffer(0, __uuidof(texture2D), (void**)(&texture2D))) - return false; - - return true; - } + return result; + } bool GraphicsDevice::createDevice() { #if _DEBUG @@ -115,7 +111,7 @@ namespace xna { if FAILED( D3D11CreateDevice( - _adapter->_adapter, + _adapter->dxadapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, _createDeviceFlags, diff --git a/framework/platform/displaymode-dx.cpp b/framework/platform/displaymode-dx.cpp index 5f5e46b..8187bfc 100644 --- a/framework/platform/displaymode-dx.cpp +++ b/framework/platform/displaymode-dx.cpp @@ -1,31 +1,6 @@ #include "displaymode-dx.hpp" namespace xna { - std::vector DisplayModeCollection::At(SurfaceFormat format) const - { - std::vector modes; - At(format, modes); - return modes; - } - - void DisplayModeCollection::At(SurfaceFormat format, std::vector& modes) const - { - size_t counter = 0; - - for (size_t i = 0; i < _displayModes.size(); ++i) { - const auto& displayMode = _displayModes[i]; - - if (displayMode->Format() == format) - { - modes.push_back(displayMode); - ++counter; - } - } - - if (!modes.empty()) - modes.resize(counter); - } - size_t DisplayModeCollection::SurfaceCount(SurfaceFormat format) const { size_t counter = 0; @@ -38,4 +13,43 @@ namespace xna { return counter; } + + std::vector DisplayModeCollection::Query(SurfaceFormat format) const + { + const auto count = SurfaceCount(format); + + size_t index = 0; + std::vector modes(count); + + for (size_t i = 0; i < _displayModes.size(); ++i) { + if (_displayModes[i]->Format() == format) { + modes[index] = _displayModes[i]; + ++index; + } + + if (index == count) + break; + } + + return modes; + } + + PDisplayMode DisplayModeCollection::Query(SurfaceFormat format, Uint width, Uint height) const + { + PDisplayMode matched = nullptr; + + for (size_t i = 0; i < _displayModes.size(); ++i) { + const auto& mode = _displayModes[i]; + + if (mode->Format() == format && mode->_width == width && mode->_height == height) { + return _displayModes[i]; + } + else if(mode->Format() == format && mode->_width == width) { + matched = mode; + } + } + + return matched; + } + } \ No newline at end of file diff --git a/framework/platform/displaymode-dx.hpp b/framework/platform/displaymode-dx.hpp index 623f193..300263a 100644 --- a/framework/platform/displaymode-dx.hpp +++ b/framework/platform/displaymode-dx.hpp @@ -88,15 +88,10 @@ namespace xna { DisplayModeCollection(std::vector const& displayModes) : _displayModes(displayModes) {} - virtual std::vector At(SurfaceFormat format) const override; - - virtual void At(SurfaceFormat format, std::vector& modes) const override; - virtual size_t SurfaceCount(SurfaceFormat format) const override; - std::vector operator[](SurfaceFormat format) const { - return At(format); - } + std::vector Query(SurfaceFormat format) const; + PDisplayMode Query(SurfaceFormat format, Uint width, Uint height) const; public: std::vector _displayModes; diff --git a/framework/platform/dx/StepTimer.hpp b/framework/platform/dx/StepTimer.hpp new file mode 100644 index 0000000..2986e79 --- /dev/null +++ b/framework/platform/dx/StepTimer.hpp @@ -0,0 +1,191 @@ +// +// StepTimer.h - A simple timer that provides elapsed time information +// +// https://github.com/microsoft/DirectXTK/wiki/StepTimer + +#pragma once + +#include +#include +#include + + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() noexcept(false) : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw std::exception(); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception(); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = static_cast(m_qpcFrequency.QuadPart / 10); + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const noexcept { return m_elapsedTicks; } + double GetElapsedSeconds() const noexcept { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const noexcept { return m_totalTicks; } + double GetTotalSeconds() const noexcept { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const noexcept { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const noexcept { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) noexcept { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) noexcept { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) noexcept { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static constexpr uint64_t TicksPerSecond = 10000000; + + static constexpr double TicksToSeconds(uint64_t ticks) noexcept { return static_cast(ticks) / TicksPerSecond; } + static constexpr uint64_t SecondsToTicks(double seconds) noexcept { return static_cast(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw std::exception(); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw std::exception(); + } + + uint64_t timeDelta = static_cast(currentTime.QuadPart - m_qpcLastTime.QuadPart); + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= static_cast(m_qpcFrequency.QuadPart); + + const uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (static_cast(std::abs(static_cast(timeDelta - m_targetElapsedTicks))) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= static_cast(m_qpcFrequency.QuadPart); + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; + }; +} diff --git a/framework/platform/game-dx.cpp b/framework/platform/game-dx.cpp index c691bad..2532a8a 100644 --- a/framework/platform/game-dx.cpp +++ b/framework/platform/game-dx.cpp @@ -1,15 +1,21 @@ -#include "game-dx.hpp" -#include "window-dx.hpp" -#include "device-dx.hpp" -#include "Windows.h" +#define NOMINMAX #include "../game/time.hpp" +#include "audioengine-dx.hpp" +#include "device-dx.hpp" +#include "game-dx.hpp" +#include "gamepad-dx.hpp" #include "gdevicemanager-dx.hpp" #include "keyboard-dx.hpp" #include "mouse-dx.hpp" -#include "audioengine-dx.hpp" +#include "window-dx.hpp" +#include "Windows.h" namespace xna { Game::Game() { + Keyboard::_dxKeyboard = uNew(); + Mouse::_dxMouse = uNew(); + GamePad::_dxGamePad = uNew(); + _gameWindow = New(); _gameWindow->Color(255, 155, 55); _gameWindow->Title("XN65"); @@ -24,14 +30,8 @@ namespace xna { MessageBox(nullptr, "Ocorreu um erro ao executar a função CoInitializeEx", "XN65", MB_OK); } - _audioEngine = New(); - Keyboard::_dxKeyboard = uNew(); - Mouse::_dxMouse = uNew(); - } - - static void intializeAudioEngine() { - - } + _audioEngine = New(); + } void Game::Exit() { @@ -49,6 +49,10 @@ namespace xna { return startLoop(); } + void Game::Draw(GameTime const& gameTime) { + _graphicsDevice->Present(); + } + void Game::Initialize() { LoadContent(); } @@ -56,19 +60,19 @@ namespace xna { void Game::Update(GameTime const& gameTime) { _audioEngine->Update(); } - + int Game::startLoop() { - MSG msg{}; - _clock.Start(); + MSG msg{}; + _stepTimer = DX::StepTimer(); do { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { + { TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessage(&msg); } else { - tick(); + step(); } } while (msg.message != WM_QUIT); @@ -76,19 +80,19 @@ namespace xna { return static_cast(msg.wParam); } - void Game::tick() { - _clock.Reset(); + void Game::step() + { + _stepTimer.Tick([&]() + { + const auto elapsed = _stepTimer.GetElapsedSeconds(); + const auto total =_stepTimer.GetTotalSeconds(); + const auto elapsedTimeSpan = TimeSpan::FromSeconds(elapsed); + const auto totalTimeSpan = TimeSpan::FromSeconds(total); + _currentGameTime.ElapsedGameTime = elapsedTimeSpan; + _currentGameTime.TotalGameTime = totalTimeSpan; + Update(_currentGameTime); + }); - this->Update(_currentGameTime); - - _currentGameTime.ElapsedGameTime = _clock.ElapsedTime(); - _currentGameTime.TotalGameTime = _clock.TotalTime(); - - this->Draw(_currentGameTime); - - _graphicsDevice->Present(); - - _currentGameTime.ElapsedGameTime = _clock.ElapsedTime(); - _currentGameTime.TotalGameTime = _clock.TotalTime(); + Draw(_currentGameTime); } } diff --git a/framework/platform/game-dx.hpp b/framework/platform/game-dx.hpp index 84c471d..1fe6a32 100644 --- a/framework/platform/game-dx.hpp +++ b/framework/platform/game-dx.hpp @@ -4,8 +4,8 @@ #include "../default.hpp" #include "../game/game.hpp" #include "clock-dx.hpp" -#include "dxgi.h" -#include "d3d11.h" +#include "dxheaders.hpp" +#include "dx/StepTimer.hpp" namespace xna { class Game : public IGame { @@ -28,7 +28,7 @@ namespace xna { } protected: - virtual void Draw(GameTime const& gameTime) override{} + virtual void Draw(GameTime const& gameTime) override; virtual void Initialize() override; @@ -41,14 +41,14 @@ namespace xna { protected: PGameWindow _gameWindow{ nullptr }; - PAudioEngine _audioEngine = nullptr; + PAudioEngine _audioEngine = nullptr; - GameClock _clock{}; GameTime _currentGameTime{}; + DX::StepTimer _stepTimer; private: int startLoop(); - void tick(); + void step(); }; } diff --git a/framework/platform/gdevicemanager-dx.cpp b/framework/platform/gdevicemanager-dx.cpp index ad92ab9..001c256 100644 --- a/framework/platform/gdevicemanager-dx.cpp +++ b/framework/platform/gdevicemanager-dx.cpp @@ -20,6 +20,8 @@ namespace xna { PresentationParameters parameters; parameters.BackBufferWidth = _backBufferWidth; parameters.BackBufferHeight = _backBufferHeight; + parameters.BackBufferFormat = SurfaceFormat::Color; + parameters.IsFullScreen = false; information.PresentationParameters(parameters); information.Window(_game->Window()); @@ -39,13 +41,19 @@ namespace xna { auto& swap = _game->_graphicsDevice->_swapChain; BOOL state = false; - swap->_swapChain->GetFullscreenState(&state, nullptr); - swap->_swapChain->SetFullscreenState(!state, nullptr); + auto hr = swap->dxSwapChain->GetFullscreenState(&state, nullptr); + + if (FAILED(hr)) return; + + hr = swap->dxSwapChain->SetFullscreenState(!state, nullptr); + + if (FAILED(hr)) return; + + _ifFullScreen = !state; } void GraphicsDeviceManager::CreateDevice(GraphicsDeviceInformation const& info) { _device = New(info); - _device->Adapter(info.Adapter()); auto window = info.Window(); window->Size(_backBufferWidth, _backBufferHeight); diff --git a/framework/platform/gdevicemanager-dx.hpp b/framework/platform/gdevicemanager-dx.hpp index e514481..b7c5650 100644 --- a/framework/platform/gdevicemanager-dx.hpp +++ b/framework/platform/gdevicemanager-dx.hpp @@ -38,7 +38,7 @@ namespace xna { public: static constexpr int DefaultBackBufferWidth = 800;//800; - static constexpr int DefaultBackBufferHeight = 480;// 480; + static constexpr int DefaultBackBufferHeight = 600;// 480; private: Game* _game; @@ -46,6 +46,7 @@ namespace xna { Int _backBufferHeight{ DefaultBackBufferHeight }; bool _isDeviceDirty{ false }; PGraphicsDevice _device; + bool _ifFullScreen{ false }; }; } diff --git a/framework/platform/swapchain-dx.cpp b/framework/platform/swapchain-dx.cpp index f119873..a5136a7 100644 --- a/framework/platform/swapchain-dx.cpp +++ b/framework/platform/swapchain-dx.cpp @@ -13,7 +13,7 @@ namespace xna { } auto adapter = device.Adapter(); - auto dxAdapter = adapter->_adapter; + auto dxAdapter = adapter->dxadapter; IDXGIFactory1* dxFactory1 = nullptr; auto hr = dxAdapter->GetParent(IID_IDXGIFactory1, (void**)&dxFactory1); @@ -40,27 +40,46 @@ namespace xna { bool SwapChain::Initialize(GraphicsDevice& device, GameWindow const& gameWindow) { const auto bounds = gameWindow.ClientBounds(); - _description.Width = static_cast(bounds.Width); - _description.Height = static_cast(bounds.Height); - _description.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - _description.SampleDesc.Count = 1; - _description.SampleDesc.Quality = 0; - _description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - _description.BufferCount = 2; - _description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - _description.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - _description.AlphaMode = DXGI_ALPHA_MODE::DXGI_ALPHA_MODE_UNSPECIFIED; - _fullScreenDescription.RefreshRate.Numerator = 60; - _fullScreenDescription.RefreshRate.Denominator = 1; - _fullScreenDescription.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - _fullScreenDescription.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - _fullScreenDescription.Windowed = gameWindow.Mode() != GameWindowMode::Fullscreen; + dxDescription.Width = static_cast(bounds.Width); + dxDescription.Height = static_cast(bounds.Height); + dxDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dxDescription.SampleDesc.Count = 1; + dxDescription.SampleDesc.Quality = 0; + dxDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + dxDescription.BufferCount = 2; + dxDescription.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + dxDescription.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + dxDescription.AlphaMode = DXGI_ALPHA_MODE::DXGI_ALPHA_MODE_UNSPECIFIED; + dxFullScreenDescription.RefreshRate.Numerator = 60; + dxFullScreenDescription.RefreshRate.Denominator = 1; + dxFullScreenDescription.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + dxFullScreenDescription.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + dxFullScreenDescription.Windowed = gameWindow.Mode() != GameWindowMode::Fullscreen; - return internalInit(device, gameWindow, _swapChain, _description, _fullScreenDescription); + return internalInit(device, gameWindow, dxSwapChain, dxDescription, dxFullScreenDescription); } bool SwapChain::Initialize(GraphicsDevice& device, GameWindow const& gameWindow, DXGI_SWAP_CHAIN_DESC1 const& desc, DXGI_SWAP_CHAIN_FULLSCREEN_DESC const& fullScreenDesc) { - return internalInit(device, gameWindow, _swapChain, _description, _fullScreenDescription); + dxDescription = desc; + dxFullScreenDescription = fullScreenDesc; + return internalInit(device, gameWindow, dxSwapChain, dxDescription, dxFullScreenDescription); + } + + bool SwapChain::GetBackBuffer(ID3D11Texture2D*& texture2D) { + if (!dxSwapChain) + return false; + + const auto hr = dxSwapChain->GetBuffer(0, __uuidof(texture2D), (void**)(&texture2D)); + + return !FAILED(hr); + } + + bool SwapChain::Present(bool vsync) { + if (!dxSwapChain) + return false; + + const auto hr = dxSwapChain->Present(vsync, NULL); + return !FAILED(hr); } } \ No newline at end of file diff --git a/framework/platform/swapchain-dx.hpp b/framework/platform/swapchain-dx.hpp index e033c8b..2217649 100644 --- a/framework/platform/swapchain-dx.hpp +++ b/framework/platform/swapchain-dx.hpp @@ -9,26 +9,23 @@ namespace xna { class SwapChain : public ISwapChain{ public: virtual ~SwapChain() override { - if (_swapChain) { - _swapChain->Release(); - _swapChain = nullptr; + if (dxSwapChain) { + dxSwapChain->Release(); + dxSwapChain = nullptr; } } virtual bool Initialize(GraphicsDevice& device, GameWindow const& gameWindow) override; bool Initialize(GraphicsDevice& device, GameWindow const& gameWindow, DXGI_SWAP_CHAIN_DESC1 const& desc, DXGI_SWAP_CHAIN_FULLSCREEN_DESC const& fullScreenDesc); - bool GetBackBuffer(ID3D11Texture2D*& texture2D) { - if FAILED(_swapChain->GetBuffer(0, __uuidof(texture2D), (void**)(&texture2D))) - return false; + bool GetBackBuffer(ID3D11Texture2D*& texture2D); - return true; - } + bool Present(bool vsync); public: - IDXGISwapChain1* _swapChain{ nullptr }; - DXGI_SWAP_CHAIN_DESC1 _description{}; - DXGI_SWAP_CHAIN_FULLSCREEN_DESC _fullScreenDescription{}; + IDXGISwapChain1* dxSwapChain{ nullptr }; + DXGI_SWAP_CHAIN_DESC1 dxDescription{}; + DXGI_SWAP_CHAIN_FULLSCREEN_DESC dxFullScreenDescription{}; }; } diff --git a/framework/xna.cpp b/framework/xna.cpp index b44e540..21274ea 100644 --- a/framework/xna.cpp +++ b/framework/xna.cpp @@ -23,6 +23,7 @@ namespace xna { void Initialize() override { graphics->Initialize(); + const auto modes = _graphicsDevice->_adapter->SupportedDisplayModes(); Game::Initialize(); } @@ -41,18 +42,6 @@ namespace xna { if (Keyboard::GetState().IsKeyDown(Keys::Escape) || GamePad::GetState(PlayerIndex::One).IsButtonDown(Buttons::Back)) Exit(); - oldState = currentState; - currentState = Mouse::GetState(); - const auto rec = Rectangle((graphics->PreferredBackBufferWidth() / 2) - 100, (graphics->PreferredBackBufferHeight() / 2) - 100, 200, 200); - - if (currentState.LeftButton == ButtonState::Pressed && oldState.LeftButton == ButtonState::Released) { - graphics->ToggleFullScreen(); - } - - if (currentState.RightButton == ButtonState::Pressed && oldState.RightButton == ButtonState::Released) { - position.X += 50; - } - Game::Update(gameTime); } diff --git a/framework/xna.h b/framework/xna.h index d068113..e0935bb 100644 --- a/framework/xna.h +++ b/framework/xna.h @@ -4,21 +4,21 @@ #pragma once #define NOMINMAX -#include -#include "Windows.h" +#include "common/color.hpp" +#include "csharp/stream.hpp" #include "game/window.hpp" -#include "platform/window-dx.hpp" +#include "platform/adapter-dx.hpp" +#include "platform/audioengine-dx.hpp" #include "platform/device-dx.hpp" #include "platform/game-dx.hpp" -#include "csharp/stream.hpp" +#include "platform/gamepad-dx.hpp" #include "platform/gdevicemanager-dx.hpp" -#include "platform/texture-dx.hpp" -#include "platform/spritebatch-dx.hpp" -#include "common/color.hpp" #include "platform/keyboard-dx.hpp" #include "platform/mouse-dx.hpp" -#include "platform/gamepad-dx.hpp" -#include "platform/audioengine-dx.hpp" -#include "platform/adapter-dx.hpp" +#include "platform/spritebatch-dx.hpp" +#include "platform/texture-dx.hpp" +#include "platform/window-dx.hpp" +#include "Windows.h" +#include // TODO: Reference additional headers your program requires here.