컨디션 관리를 못하여 중간에 뻗어버린 관계로 오늘은 부득이하게 쉬고 가겠습니다.

'개발일지' 카테고리의 다른 글

20.07.14 비개발일지  (0) 2020.07.14
20.07.01 비개발일지  (0) 2020.07.01
20.06.13 비개발일지  (0) 2020.06.13
20.05.02 비개발일지  (0) 2020.05.02
20.04.25 비개발일지  (0) 2020.04.25
#include "Common\StepTimer.h"
#include "Common\DeviceResources.h"
#include "Content\Sample3DSceneRenderer.h"

// Renders Direct3D content on the screen.
namespace ExampleCreation
{
	class ExampleCreationMain
	{
	public:
		ExampleCreationMain();
		void CreateRenderers(const std::shared_ptr<DX::DeviceResources>& deviceResources);
		void Update();
		bool Render();

		void OnWindowSizeChanged();
		void OnSuspending();
		void OnResuming();
		void OnDeviceRemoved();

	private:
		// TODO: Replace with your own content renderers.
		std::unique_ptr<Sample3DSceneRenderer> m_sceneRenderer;

		// Rendering loop timer.
		DX::StepTimer m_timer;
	};
}

Direct3D Content를 화면에 출력하는 코드들을 엮은 ExampleCreationMain class이다.

Function은 구현체를 보면서 이야기 할테니, Field들을 살펴보자.

 

StepTimer는 MS에서 제공하는 코드이다.

https://github.com/microsoft/DirectXTK/wiki/StepTimer

 

microsoft/DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++ - microsoft/DirectXTK

github.com

대부분의 기능은 Tick과 관련되어 있으며, 여타 다른 함수들과 마찬가지로 상시 적용을 해야 하는 부분이다.

 

Sample3DSceneRenderer는 TODO에 적혀있는대로, 화면에 출력 될 내용에 관한 함수이다.

즉, ExampleCreationMain도 결국 주어진 함수를 출력만 하는 코드라는 것이다.

밑에 Function 별 기능에 대해 설명은 하겠지만, 보면 실질적으로 직접 무언가 하는 작업은 없다.

다른 Function 호출이 대부분이다.

 

그런 의미에서 빠르게 Function별 설명으로 넘어가자.

해당 Function이 어떤 기능을 하고, 내부에서 어떤 구현이 있는지를 주로 볼 것이다.

 

// Loads and initializes application assets when the application is loaded.
ExampleCreationMain::ExampleCreationMain()
{
	// TODO: Change the timer settings if you want something other than the default variable timestep mode.
	// e.g. for 60 FPS fixed timestep update logic, call:
	/*
	m_timer.SetFixedTimeStep(true);
	m_timer.SetTargetElapsedSeconds(1.0 / 60);
	*/
}

생성자 안에는 아무런 선언이 없다. 

다만, FPS 고정 수치를 변경하는 등의 기능을 생성자 안에서 어떻게 할 수 있는지 주석으로 설명이 되어 있다.

 

// Creates and initializes the renderers.
void ExampleCreationMain::CreateRenderers(const std::shared_ptr<DX::DeviceResources>& deviceResources)
{
	// TODO: Replace this with your app's content initialization.
	m_sceneRenderer = std::unique_ptr<Sample3DSceneRenderer>(new Sample3DSceneRenderer(deviceResources));

	OnWindowSizeChanged();
}

CreateRenderes는 Renderer를 생성하고 초기화 하는 구문이다.

App class에서 GetDeviceREsources에서 호출이 되는 함수로, Sample3DSceneRenderer 객체를 생성하고,

내용물에 따른 화면 크기 변화에 대비한 OnWindowSizeChanged를 호출한다.

 

// Updates the application state once per frame.
void ExampleCreationMain::Update()
{
	// Update scene objects.
	m_timer.Tick([&]()
	{
		// TODO: Replace this with your app's content update functions.
		m_sceneRenderer->Update(m_timer);
	});
}

Update는 매 프레임마다 바뀌는 위상에 대한 정보를 연산하는 기능을 한다.

App의 Run 함수에서 호출이 되며, m_timer의 Tick 함수에

Sample3DSceneREnderer의 Update 함수에 m_timer를 인자로 넘기는 것을 lambda로 호출한다.

 

// Renders the current frame according to the current application state.
// Returns true if the frame was rendered and is ready to be displayed.
bool ExampleCreationMain::Render()
{
	// Don't try to render anything before the first Update.
	if (m_timer.GetFrameCount() == 0)
	{
		return false;
	}

	// Render the scene objects.
	// TODO: Replace this with your app's content rendering functions.
	return m_sceneRenderer->Render();
}

역시나 App의 Run 함수에서 호출되는 Render는 매 프레임마다 바뀌는 정보로

해당 프레임에 적절한 위상을 변경하는 역할을 한다.

단, 첫 프레임일 때에는 이 작업을 하지 않는다.

 

// Updates application state when the window's size changes (e.g. device orientation change)
void ExampleCreationMain::OnWindowSizeChanged()
{
	// TODO: Replace this with the size-dependent initialization of your app's content.
	m_sceneRenderer->CreateWindowSizeDependentResources();
}

Window 크기가 조절될 때 호출되는 OnWindowSizeChanged는 우리가 구현했던

Sample3DSceneRenderer의 CreateWindowSizeDependentResources를 호출한다.

뒤에 설명을 하겠지만, 이는 화면 크기가 변할 때마다 바뀌어야 할 관련 수치들을 변경해주는 역할을 한다.

 

// Notifies the app that it is being suspended.
void ExampleCreationMain::OnSuspending()
{
	// TODO: Replace this with your app's suspending logic.

	// Process lifetime management may terminate suspended apps at any time, so it is
	// good practice to save any state that will allow the app to restart where it left off.

	m_sceneRenderer->SaveState();

	// If your application uses video memory allocations that are easy to re-create,
	// consider releasing that memory to make it available to other applications.
}

App이 종료 될 때 호출되는 OnSuspending이다.

현재까지 적용된 상태들이 온전히 적용될 수 있도록 저장을 한다.

 

// Notifes the app that it is no longer suspended.
void ExampleCreationMain::OnResuming()
{
	// TODO: Replace this with your app's resuming logic.
}

Suspend 상태가 해제 될 때 호출되는 OnResuming이다.

현재 아무런 구현이 되어있지 않다.

 

// Notifies renderers that device resources need to be released.
void ExampleCreationMain::OnDeviceRemoved()
{
	// TODO: Save any necessary application or renderer state and release the renderer
	// and its resources which are no longer valid.
	m_sceneRenderer->SaveState();
	m_sceneRenderer = nullptr;
}

마지막으로 device resources가 해제 될 때 Renderer에 이벤트를 넣는 OnDeviceRemoved이다.

이 경우에도 Suspend와 마찬가지로 SaveState를 통해 상태저장을 하고, 더 나아가 SceneRender를 해제하기까지 한다.

 

결국 ExampleCreationMain까지도 코드에서 제공하는 일종의 Frame 중 하나였다.

예시만 따라한다면, 무엇 하나 바꿀 필요가 없다. m_sceneRenderer를 제외하고는.

 

이렇게 일주일이 더 지났고, 예시를 적용하기 위해서 우리가 변경해야 할 코드는 Sample3DSceneRenderer로 좁혀졌다.

가능하면 더 시간을 끌고 싶지 않았지만, Sample3DSceneRenderer가 꽤 길고 복잡하다.

게다가 C++/CX를 사용하는 구문도 조금 있어서 지금 컨디션에 바로 하기 힘들 것 같다.

 

때문에 금요일로 조금 미루겠습니다.

https://www.acmicpc.net/problem/10989

 

10989번: 수 정렬하기 3

첫째 줄에 수의 개수 N(1 ≤ N ≤ 10,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 숫자가 주어진다. 이 수는 10,000보다 작거나 같은 자연수이다.

www.acmicpc.net

10M의 숫자를 3초 안에 오름차순으로 sorting 하는 문제입니다.

 

처음에는 간단하게 Insertion Sort를 시도 했으나, 시간이 초과되었습니다.

그 다음은 STL에서 제공하는 heap Sort를 시도 했으나, 이번에는 메모리가 초과하였습니다.

세번째는 입력 값이 10K 이하 자연수이기에 10K 사이즈의 Array를 두고, Array 값에 들어온 횟수를 저장해보았습니다.

Insertion Sort보다는 더 오래 갔지만 결국 시간이 초과되었습니다.

 

아마 Sort를 직접 구현하게 하려는 문제인 것 같습니다.

그래서 내일은 Merge Sort를 직접 구현해보려 합니다.

오늘은 Rope의 FSM 부분에 Blend by Bool로 분기를 나누어
Montage로 만든 ExitFromRope Animation들을 적용해보았습니다.

 

아직 완전히 정상적으로 작동하지는 않지만, 몇가지 공유할 사항들을 적어보고자 합니다.

 

우선 제가 한동안 Montage를 건들지 않는 사이에 Montage의 UI가 바뀌었습니다.

대체로 예전보다 더 한 눈에 잘 들어오지만, 예시를 보면서 따라하기에는 조금 불편했습니다.

 

FSM의 Cache 생성은 Animation Node 가장 밖에서만 가능하다는 것도 배웠습니다.

내부에서는 Cache 생성이 안떠서 원래 했던 것과 비교하기 위해 시도를 해보았는데,

가장 밖에서만 가능하다는 것을 발견하였습니다.

 

구현 방식은 Notify를 사용할까 하다가 Animation당 Montage를 따로 만들었습니다.

그리고 Montage의 종료를 AnimInstance의 OnMontageEnded에서 판단을 하였습니다.

해당 함수는 Montage가 종료 될 때마다 호출이 되는 함수이기에 불가피하게 if문으로 기능 여부를 판단하고 있습니다.

ExitClimbMontage인 경우, 기존에 호출되던 트리거 일괄 변경 함수인 ExitClimb가 호출이 됩니다.

그리고 기존의 ExitClimb가 호출되는 곳에서는 IdleType에 맞춰 적절한 ExitClimbMontage가 재생되도록 하였습니다.

 

하지만 현재 Montage 재생과 종료 시 함수는 호출이 되고 있는데, 애니메이션은 제대로 작동하지 않고 있습니다.

몇가지 예상되는 원인은 있습니다.

입력이 연속덕으로 들어가 재생이 연속적으로 되는 경우.

조건문이 잘못된 경우.

 

다음에는 입력을 제한해보려 합니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.06.25 개발일지 2  (0) 2020.06.25
20.06.25 개발일지  (0) 2020.06.25
20.06.20 개발일지  (0) 2020.06.20
20.06.15 개발일지  (0) 2020.06.17
20.06.15 개발일지  (0) 2020.06.15

어제 필기시험을 연장 5시간정도 보고 곧바로 운동 하다 보니까 무언가를 할 시간이 없어서 따로 바로 쉬었습니다.

그러다보니 일지를 적지 못했습니다.

 

오늘은 Animation FSM을 살펴보며 Notify를 사용하지 않거나,

사용하더라도 Animation을 사용하는 방법이 있는지 찾아보았습니다.

결과적으로, Exit from Climb Animation은 Montage로 제작하여 Notify Event를 받아야 할 것 같습니다.

 

우선, FSM 변경으로 문제가 해결이 가능한지 고려를 해보았는데,

현재 Sub-FSM으로 묶여 있는 FullBodyMotion 밖에 복잡한 조건문을 받아 Blending 해야 했습니다.

그리고 이런 와중에서도 Animation 종료 시점은 확인해야 하기에 Notify 문제를 해결하지 못했습니다.

 

그 다음은 Animation에서 Notify Event를 받을 수 있는지 확인하는 것이었습니다만, 

이 역시 불가능 한 것 같습니다.

 

결국 이러나 저러나 Notify는 써야 하는데, 이걸 쓰려면 Montage를 써야 할 것 같습니다.

Climb 종류별로 Sub-FSM을 받는데, 이를 blend by bool로 분류하는 것을 생각 중입니다.

한가지 걱정인 것은 예전에 Blend by -를 여러개 중첩해서 쓰면 문제가 발생할 수 있다고 예전에 본 기억이 있습니다.

그리고 Montage와 Notify를 사용한지 굉장히 오래되어서 좀 걱정입니다.

 

오늘은 이왕 이렇게 된거 좀 더 쉬고, 월요일에 참고자료 보면서 만들어보려 합니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.06.25 개발일지  (0) 2020.06.25
20.06.22 개발일지  (0) 2020.06.22
20.06.15 개발일지  (0) 2020.06.17
20.06.15 개발일지  (0) 2020.06.15
20.06.11 개발일지  (0) 2020.06.11

여러 테스트케이스를 추출해보고 값을 비교해 보았으나, 틀린 점을 발견하지 못했습니다.

물론 제출 시 계속 통과도 하지 못했습니다.

그래서 다른 사람의 답안을 보고 다시 작성하였습니다.

 

더보기
#include <iostream>
#include <array>
#include <algorithm>

using namespace std;

int main()
{
    int N = 0, temp = 0;
    array<int, 1000> Series;
    array<int, 1000> Sublength;
    Series.fill(-1);
    Sublength.fill(1);

    cin >> N;
    for (int i = 0; i < N; ++i)
    {
        cin >> temp;
        Series[i] = temp;
    }

    int sol = 1;
    for (int i = 0; i < N; ++i)
    {
        Sublength[i] = 1;
        for (int j = 0; j < i; ++j)
        {
            if (Series[i] > Series[j])
            {
                Sublength[i] = (Sublength[i] > Sublength[j] + 1) ? Sublength[i] : (Sublength[j] + 1);
            }
        }
        sol = (sol > Sublength[i]) ? sol : Sublength[i];
    }

    cout << sol << endl;

    return 0;
}

자신보다 앞의 있는 숫자가 자신보다 작을 경우,

그 숫자의 sublength + 1과 자신의 현재 sublength중 큰 수를 저장합니다.

그리고 현재의 solution과 비교하여 solution보다 클 경우, 그 값을 solution으로 저장합니다.

 

정석적인 DP 풀이인데, 이걸 보니까 제가 짰던 것이 DP가 아니라 Greedy Algorithm이었던 것 같습니다.

그 와중에 예외를 찾지 못했다는 점이 한탄스러울 뿐입니다.

오늘도 문제가 해결되지는 않았지만, 몇가지 확인해볼 수는 있었습니다.

 

1. State 이동 조건을 변경하였습니다.

원래는 ClimbTrigger의 Overlap 여하에 따라 이동 여부를 확인했는데,

생각해보니 이에 따라 Climb 상태에서 탈출할 때 발생하는 몇몇 trigger 값의 변경이 있었습니다.

그래서 이들 중 하나를 조건으로 잡았습니다.

 

2. 결국은 조건의 문제였습니다.

Exit State에 하나의 Animation만 붙여보기도 했고, Exit 발생 시 Pawn을 teleport 시켜보기도 했습니다만

Animation이 정상적으로 재생되지 않고 있습니다.

State 안 조건문 문제는 아닌 것 같습니다.

 

이렇게 적어두고 잠깐 생각을 해보니, Climb 상태에서 빠져나오는 순간 Climb 상태에서 빠져나옵니다.

이 때 FullBodyMotion도 false가 되는데, 이 때문에 뒤에 붙은 Animation이 재생되지 않는 것일 수도 있겠습니다.

 

금요일에 다른 회사 온라인 테스트가 있는 관계로, 내일은 개발을 하지 못할 것 같습니다.

토요일에 Notify를 사용하거나 하여 Animation 재생이 끝난 후에 ExitClimb가 발생하도록 구상을 해볼 예정입니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.06.22 개발일지  (0) 2020.06.22
20.06.20 개발일지  (0) 2020.06.20
20.06.15 개발일지  (0) 2020.06.15
20.06.11 개발일지  (0) 2020.06.11
20.06.08 개발일지  (0) 2020.06.08

https://www.acmicpc.net/problem/11053

 

11053번: 가장 긴 증가하는 부분 수열

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이

www.acmicpc.net

주어진 예시와 따로 작성한 예시가 모두 통과 했는데 런타임 에러가 발생했습니다. 

 

내일 예시를 몇개 더 적어보면서 문제점을 찾아볼까 합니다.

오늘은 DirectX12 template의 예시 프로젝트에서 Rendering 부분.

즉, DirectX를 사용하는 부분에 대해 분석을 해볼 차례이다.

그 중 먼저 살펴볼 것은 DeviceResources이다.

 

저번 글에서 DeviceResources는 DirectX에서 제공하는 Device Resource들을 관리한다고 언급했다.

Document에서는 해당 코드를 소유한 Application에 장치 손실 또는 생성에 대한 알림을 받을 수 있는 Interface를 제공한다고 설명하고 있다.

https://docs.microsoft.com/ko-kr/windows/uwp/gaming/user-interface 

 

DirectX 게임 프로젝트 템플릿 - UWP applications

UWP(유니버설 Windows 플랫폼) 및 DirectX 게임을 만드는 템플릿에 대해 알아봅니다.

docs.microsoft.com

https://github.com/Microsoft/DirectXTK/wiki/DeviceResources

 

microsoft/DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++ - microsoft/DirectXTK

github.com

github wiki에서는 device & swapchain, 선택적 깊이 버퍼에 대한 추상화를 제공한다고 설명하고 있다.

그 외에 설명으로는 단순히 'boilerplate'를 별도의 파일로 정리 한 것이라고 되어 있다.

여기서 boilerplate란, 최소한의 수정만을 거쳐 여러 곳에 필수적으로 사용되는 코드를 지칭한다.

https://en.wikipedia.org/wiki/Boilerplate_code

 

Boilerplate code - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Code that has to be included in many places with little or no alteration In computer programming, boilerplate code or just boilerplate are sections of code that have to be included in

en.wikipedia.org

그리하여 DeviceResources는 가능하면 건드리지 않는 것이 좋은 코드라는 것을 나름 긴 설명을 통해 깨달았다.

이제 본격적으로 코드를 파헤쳐보자.

#pragma once

namespace DX
{
	static const UINT c_frameCount = 3;		// Use triple buffering.

	// Controls all the DirectX device resources.
	class DeviceResources
	{
	public:
		DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT);
		void SetWindow(Windows::UI::Core::CoreWindow^ window);
		void SetLogicalSize(Windows::Foundation::Size logicalSize);
		void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation);
		void SetDpi(float dpi);
		void ValidateDevice();
		void Present();
		void WaitForGpu();

		// The size of the render target, in pixels.
		Windows::Foundation::Size	GetOutputSize() const				{ return m_outputSize; }

		// The size of the render target, in dips.
		Windows::Foundation::Size	GetLogicalSize() const				{ return m_logicalSize; }

		float						GetDpi() const						{ return m_effectiveDpi; }
		bool						IsDeviceRemoved() const				{ return m_deviceRemoved; }

		// D3D Accessors.
		ID3D12Device*				GetD3DDevice() const				{ return m_d3dDevice.Get(); }
		IDXGISwapChain3*			GetSwapChain() const				{ return m_swapChain.Get(); }
		ID3D12Resource*				GetRenderTarget() const				{ return m_renderTargets[m_currentFrame].Get(); }
		ID3D12Resource*				GetDepthStencil() const				{ return m_depthStencil.Get(); }
		ID3D12CommandQueue*			GetCommandQueue() const				{ return m_commandQueue.Get(); }
		ID3D12CommandAllocator*		GetCommandAllocator() const			{ return m_commandAllocators[m_currentFrame].Get(); }
		DXGI_FORMAT					GetBackBufferFormat() const			{ return m_backBufferFormat; }
		DXGI_FORMAT					GetDepthBufferFormat() const		{ return m_depthBufferFormat; }
		D3D12_VIEWPORT				GetScreenViewport() const			{ return m_screenViewport; }
		DirectX::XMFLOAT4X4			GetOrientationTransform3D() const	{ return m_orientationTransform3D; }
		UINT						GetCurrentFrameIndex() const		{ return m_currentFrame; }

		CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const
		{
			return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_currentFrame, m_rtvDescriptorSize);
		}
		CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const
		{
			return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
		}

	private:
		void CreateDeviceIndependentResources();
		void CreateDeviceResources();
		void CreateWindowSizeDependentResources();
		void UpdateRenderTargetSize();
		void MoveToNextFrame();
		DXGI_MODE_ROTATION ComputeDisplayRotation();
		void GetHardwareAdapter(IDXGIAdapter1** ppAdapter);

		UINT											m_currentFrame;

		// Direct3D objects.
		Microsoft::WRL::ComPtr<ID3D12Device>			m_d3dDevice;
		Microsoft::WRL::ComPtr<IDXGIFactory4>			m_dxgiFactory;
		Microsoft::WRL::ComPtr<IDXGISwapChain3>			m_swapChain;
		Microsoft::WRL::ComPtr<ID3D12Resource>			m_renderTargets[c_frameCount];
		Microsoft::WRL::ComPtr<ID3D12Resource>			m_depthStencil;
		Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>	m_rtvHeap;
		Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>	m_dsvHeap;
		Microsoft::WRL::ComPtr<ID3D12CommandQueue>		m_commandQueue;
		Microsoft::WRL::ComPtr<ID3D12CommandAllocator>	m_commandAllocators[c_frameCount];
		DXGI_FORMAT										m_backBufferFormat;
		DXGI_FORMAT										m_depthBufferFormat;
		D3D12_VIEWPORT									m_screenViewport;
		UINT											m_rtvDescriptorSize;
		bool											m_deviceRemoved;

		// CPU/GPU Synchronization.
		Microsoft::WRL::ComPtr<ID3D12Fence>				m_fence;
		UINT64											m_fenceValues[c_frameCount];
		HANDLE											m_fenceEvent;

		// Cached reference to the Window.
		Platform::Agile<Windows::UI::Core::CoreWindow>	m_window;

		// Cached device properties.
		Windows::Foundation::Size						m_d3dRenderTargetSize;
		Windows::Foundation::Size						m_outputSize;
		Windows::Foundation::Size						m_logicalSize;
		Windows::Graphics::Display::DisplayOrientations	m_nativeOrientation;
		Windows::Graphics::Display::DisplayOrientations	m_currentOrientation;
		float											m_dpi;

		// This is the DPI that will be reported back to the app. It takes into account whether the app supports high resolution screens or not.
		float											m_effectiveDpi;

		// Transforms used for display orientation.
		DirectX::XMFLOAT4X4								m_orientationTransform3D;
	};
}

DeviceResources.h이다.

Method 중 'Get'으로 시작하거나 'Is'로 시작하는 method, 'Set'으로 시작하는 method들은 설명을 생략하겠다.

이들은 대체로 field들의 Getter, Setter 함수들이기에 값을 받아오거나 설정하는 기능으로만 기억하면 된다.

중요한 것은 이런 method가 아니라 그것이 가르키는 field가 무엇인지 아니겠는가?

 

#include "pch.h"
#include "DeviceResources.h"
#include "DirectXHelper.h"

using namespace DirectX;
using namespace Microsoft::WRL;
using namespace Windows::Foundation;
using namespace Windows::Graphics::Display;
using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml::Controls;
using namespace Platform;

namespace DisplayMetrics
{
	// High resolution displays can require a lot of GPU and battery power to render.
	// High resolution phones, for example, may suffer from poor battery life if
	// games attempt to render at 60 frames per second at full fidelity.
	// The decision to render at full fidelity across all platforms and form factors
	// should be deliberate.
	static const bool SupportHighResolutions = false;

	// The default thresholds that define a "high resolution" display. If the thresholds
	// are exceeded and SupportHighResolutions is false, the dimensions will be scaled
	// by 50%.
	static const float DpiThreshold = 192.0f;		// 200% of standard desktop display.
	static const float WidthThreshold = 1920.0f;	// 1080p width.
	static const float HeightThreshold = 1080.0f;	// 1080p height.
};

// Constants used to calculate screen rotations.
namespace ScreenRotation
{
	// 0-degree Z-rotation
	static const XMFLOAT4X4 Rotation0(
		1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f
		);

	// 90-degree Z-rotation
	static const XMFLOAT4X4 Rotation90(
		0.0f, 1.0f, 0.0f, 0.0f,
		-1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f
		);

	// 180-degree Z-rotation
	static const XMFLOAT4X4 Rotation180(
		-1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, -1.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f
		);

	// 270-degree Z-rotation
	static const XMFLOAT4X4 Rotation270(
		0.0f, -1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f
		);
};

DeviceResources.cpp에서 header나 namespace 선언, 상수 선언 부분만 가져온 것이다.

 

먼저 DisplayMatrics namespace 안에 선언된 상수들을 살펴보자.

SupportHighResolutions는 High Resolution을 지원하는지를 판단하는 변수이다.

High Resolution은 많은 GPU resource와 전력을 소모하는 작업이다.

그렇기에 예시에서는 이를 지원하지 않는 것으로 결정 한 것 같다.

WidthThreshold, HeightThreshold는 화면의 너비와 높이 크기 제한을 결정한다.

DpiThreshold 역시 해상도의 제한을 결정하며, 192.0은 보통 데스크탑 화면의 200% 정도이다.

 

ScreenRotation은 4×4 Matrix 상에서 Z축을 기준으로 0, 90, 180, 360 회전 연산을 Matrix로 표현한 것이다.

 

이 중 다시 한번 낯선 것이 있다.

Header에 보면 [DirectXHelper.h]라는 header 파일이 보일 것이다.

DirectXHelper.h는 Microsoft에서 제공하는 DirectX 개발을 지원하는 코드이다.

#pragma once

#include <ppltasks.h>	// For create_task

namespace DX
{
	inline void ThrowIfFailed(HRESULT hr)
	{
		if (FAILED(hr))
		{
			// Set a breakpoint on this line to catch Win32 API errors.
			throw Platform::Exception::CreateException(hr);
		}
	}

	// Function that reads from a binary file asynchronously.
	inline Concurrency::task<std::vector<byte>> ReadDataAsync(const std::wstring& filename)
	{
		using namespace Windows::Storage;
		using namespace Concurrency;

		auto folder = Windows::ApplicationModel::Package::Current->InstalledLocation;

		return create_task(folder->GetFileAsync(Platform::StringReference(filename.c_str()))).then([](StorageFile^ file)
		{
			return FileIO::ReadBufferAsync(file);
		}).then([](Streams::IBuffer^ fileBuffer) -> std::vector<byte>
		{
			std::vector<byte> returnBuffer;
			returnBuffer.resize(fileBuffer->Length);
			Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference<byte>(returnBuffer.data(), fileBuffer->Length));
			return returnBuffer;
		});
	}

	// Converts a length in device-independent pixels (DIPs) to a length in physical pixels.
	inline float ConvertDipsToPixels(float dips, float dpi)
	{
		static const float dipsPerInch = 96.0f;
		return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
	}

	// Assign a name to the object to aid with debugging.
#if defined(_DEBUG)
	inline void SetName(ID3D12Object* pObject, LPCWSTR name)
	{
		pObject->SetName(name);
	}
#else
	inline void SetName(ID3D12Object*, LPCWSTR)
	{
	}
#endif
}

// Naming helper function for ComPtr<T>.
// Assigns the name of the variable as the name of the object.
#define NAME_D3D12_OBJECT(x) DX::SetName(x.Get(), L#x)

ThrowIfFailed는 DirectX Win32 API에서 반환된 오류 HRESULT 값을 Windows Runtime Exception으로 변환한다.

이를 이용해 DirectX Error를 Debug 하기 위한 중단점을 배치한다.

https://github.com/Microsoft/DirectXTK/wiki/ThrowIfFailed

 

microsoft/DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++ - microsoft/DirectXTK

github.com

ReadDataAsync는 binary file을 비동기적으로 읽는 함수이다.

마지막으로 ConvertDipsToPixels는 DIP의 길이를 실제 Pixel의 길이로 변환하는 함수이다.

 

다음은 DeviceResources의 생성자 부분이다.

// Constructor for DeviceResources.
DX::DeviceResources::DeviceResources(DXGI_FORMAT backBufferFormat, DXGI_FORMAT depthBufferFormat) :
	m_currentFrame(0),
	m_screenViewport(),
	m_rtvDescriptorSize(0),
	m_fenceEvent(0),
	m_backBufferFormat(backBufferFormat),
	m_depthBufferFormat(depthBufferFormat),
	m_fenceValues{},
	m_d3dRenderTargetSize(),
	m_outputSize(),
	m_logicalSize(),
	m_nativeOrientation(DisplayOrientations::None),
	m_currentOrientation(DisplayOrientations::None),
	m_dpi(-1.0f),
	m_effectiveDpi(-1.0f),
	m_deviceRemoved(false)
{
	CreateDeviceIndependentResources();
	CreateDeviceResources();
}

// Configures resources that don't depend on the Direct3D device.
void DX::DeviceResources::CreateDeviceIndependentResources()
{
}

생성자에서는 크게 2가지 작업이 이루어지고 있다.

하나는 field의 초기화. 다른 하나는 Resources를 생성하고 있다.

Resource는 두가지로 분류된다. Direct3D device와 독립적인 것과, 연관된 것.

본 예시는 DirectX12를 사용하기 대문에 독립적인 부분인 CreateDeviceIndependentResources는 빈 함수이다.

 

그렇다면 남은 함수인 CreateDeviceResources를 보자.

// Configures the Direct3D device, and stores handles to it and the device context.
void DX::DeviceResources::CreateDeviceResources()
{
#if defined(_DEBUG)
	// If the project is in a debug build, enable debugging via SDK Layers.
	{
		ComPtr<ID3D12Debug> debugController;
		if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
		{
			debugController->EnableDebugLayer();
		}
	}
#endif

	DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&m_dxgiFactory)));

	ComPtr<IDXGIAdapter1> adapter;
	GetHardwareAdapter(&adapter);

	// Create the Direct3D 12 API device object
	HRESULT hr = D3D12CreateDevice(
		adapter.Get(),					// The hardware adapter.
		D3D_FEATURE_LEVEL_11_0,			// Minimum feature level this app can support.
		IID_PPV_ARGS(&m_d3dDevice)		// Returns the Direct3D device created.
		);

#if defined(_DEBUG)
	if (FAILED(hr))
	{
		// If the initialization fails, fall back to the WARP device.
		// For more information on WARP, see: 
		// https://go.microsoft.com/fwlink/?LinkId=286690

		ComPtr<IDXGIAdapter> warpAdapter;
		DX::ThrowIfFailed(m_dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));

		hr = D3D12CreateDevice(warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_d3dDevice));
	}
#endif

	DX::ThrowIfFailed(hr);

	// Create the command queue.
	D3D12_COMMAND_QUEUE_DESC queueDesc = {};
	queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
	queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;

	DX::ThrowIfFailed(m_d3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));
	NAME_D3D12_OBJECT(m_commandQueue);

	// Create descriptor heaps for render target views and depth stencil views.
	D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
	rtvHeapDesc.NumDescriptors = c_frameCount;
	rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
	rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	DX::ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)));
	NAME_D3D12_OBJECT(m_rtvHeap);

	m_rtvDescriptorSize = m_d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);

	D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
	dsvHeapDesc.NumDescriptors = 1;
	dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
	dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	ThrowIfFailed(m_d3dDevice->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap)));
	NAME_D3D12_OBJECT(m_dsvHeap);

	for (UINT n = 0; n < c_frameCount; n++)
	{
		DX::ThrowIfFailed(
			m_d3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))
			);
	}

	// Create synchronization objects.
	DX::ThrowIfFailed(m_d3dDevice->CreateFence(m_fenceValues[m_currentFrame], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)));
	m_fenceValues[m_currentFrame]++;

	m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
	if (m_fenceEvent == nullptr)
	{
		DX::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
	}
}

간단하게 설명을 하자면

1) DXGIFactory1을 생성하면서 실패 시 Error를 throw 한다.

2) 1)이 문제 없이 동작하면 Comptr<IDXGIAdapter1>에 GetHardwareAdapter의 반환 값을 저장한다.

GetHardWareAdpater는 Direct3D 12를 제공하는 사용 가능한 Hardware Adapter 중 첫번째를 반환한다.

// This method acquires the first available hardware adapter that supports Direct3D 12.
// If no such adapter can be found, *ppAdapter will be set to nullptr.
void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter)
{
	ComPtr<IDXGIAdapter1> adapter;
	*ppAdapter = nullptr;

	for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, &adapter); adapterIndex++)
	{
		DXGI_ADAPTER_DESC1 desc;
		adapter->GetDesc1(&desc);

		if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
		{
			// Don't select the Basic Render Driver adapter.
			continue;
		}

		// Check to see if the adapter supports Direct3D 12, but don't create the
		// actual device yet.
		if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
		{
			break;
		}
	}

	*ppAdapter = adapter.Detach();
}

3) 2)에서 저장한 HardwareAdapter와 이 Application이 제공 할 최소 Direct3D feature level, 생성 될 Direct3D device를 저장 할 변수를 넣어 Direct3D 12 API Device Object를 생성한다.

4) 3)에서 생성한 Device Object 값이 유효한지 검사한다.

5) command queue를 생성한다.

6) render target views와 depth stencil vies에 사용될 descriptor heap을 생성한다.

7) 동기화 오브젝트를 생성한다.

 

솔직히 적으면서도 정확히 어떤 의미인지 파악이 잘 되지 않는다.

하지만 DeviceResources를 살펴보면서 몇가지 느낀 점이 있다.

1. DeviceResources가 하고 있는 작업은 입문자가 따로 처리하기 복잡한 작업들이다.

2. DeviceResources는 따로 제공을 하는 파일이다.

3. DirectX와 관련된 작업들이기는 하나, Rendering과 직접 연관이 있는 것은 아니다. 편의성, 성능과 연관된 작업이다.

 

그렇기에 DeviceResources와 관련된 설명은 아래 링크로 대체한다.

https://github.com/Microsoft/DirectXTK/wiki/DeviceResources

 

microsoft/DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++ - microsoft/DirectXTK

github.com

결국 DeviceResources도 이전에 살펴보았던 App과 마찬가지로 수정할 수 없는 부분이었다.

정확히는 d3d12.h, DirectXHelper.h와 더 비슷한 것 같다.

더불어 Rendering 부분에서 사용하는 StepTimer.h도 이와 비슷한 부류라 생각한다.

이들의 공통적은 Project 상에서 Common 폴더 밑에 존재한다는 점이다.

 

자세한 것은 살펴봐야 알겠지만 Template Project에서 directory에 따라 기능이 나뉘는 것 같다.

Common/*: Project 전반적으로 사용되는 코드나 함수들. 주로 Microsoft에서 편의성을 위해 제공되는 함수들이 포함됨

Content/*: 실질적으로 Rendering과 관련된 코드들. hlsl등도 여기에 포함 됨.

기타 파일들 : Rendering을 제외한 Windows Application과 관련된 코드. 혹은 이를 Rendering과 연결하는 코드.

 

다음에는 ExampleCreateionMain을 시작으로 Rendering 관련 부분들을 살펴보도록 하겠습니다.

https://www.acmicpc.net/problem/11053

 

11053번: 가장 긴 증가하는 부분 수열

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이

www.acmicpc.net

 

문제 항목이 Dynamic Programming이라 어떻게 연산을 할까 고민하다가 뒤에서부터 연산하는 방식을 생각했습니다.

 

먼저 각 index는 부여된 값과 더불어 index와 sublength를 가지고 있습니다.

index는 해당 위치 다음에 올 index, sublength는 자신 뒤의 수열의 길이를 뜻합니다.

 

index와 sublength는 기존 수열의 역순으로 연산을 합니다.

자신의 뒤 숫자의 값이 자신보다 크거나 같을 때, sublength와 index 값을 저장합니다.

 

단, 같은 조건에서는 숫자의 값이 작은 것이 우선권을 가집니다. 

이런 식으로 구현을 하는데 제시된 예시는 해결하나 추가로 생각한 예시를 해결하지 못했습니다.

 

뒷 숫자와 이어지지 않는 경우를 먼저 탐색하지 못 해서 문제가 생기는 것으로 예상되며,

내일 이 문제를 해결해보려 합니다.

+ Recent posts