C++ 에서 ^ ??

기초 2020. 11. 11. 15:14

directX 예제 코드를 보다가 

IFrameworkView^ Direct3DApplicationSource::CreateView()

 

이렇게 되어있는 코드가 있었다.

^(hat 이라 부른다)의미를 찾아보니 대충 스마트 포인터와 같은 의미인 것 같다.

 

공식 내용

docs.microsoft.com/en-us/cpp/extensions/handle-to-object-operator-hat-cpp-component-extensions?view=msvc-160

 

Handle to Object Operator (^) (C++/CLI and C++/CX)

Handle to Object Operator (^) (C++/CLI and C++/CX) In this article --> The handle declarator (^, pronounced "hat"), modifies the type specifier to mean that the declared object should be automatically deleted when the system determines that the object is n

docs.microsoft.com

ref new, gcnew 관련 ( ref new, gcnew 으로 생성(?) 시 ^ 형으로 반환된다는것 같다.)

docs.microsoft.com/en-us/cpp/extensions/ref-new-gcnew-cpp-component-extensions?view=msvc-160

 

ref new, gcnew (C++/CLI and C++/CX)

ref new, gcnew (C++/CLI and C++/CX) In this article --> The ref new aggregate keyword allocates an instance of a type that is garbage collected when the object becomes inaccessible, and that returns a handle (^) to the allocated object. All Runtimes Memory

docs.microsoft.com

 

'기초' 카테고리의 다른 글

C++ :: 의미  (0) 2020.07.20
간단히 적어놓는 논리연산자  (0) 2017.02.09
운영체제 스케줄링 기법  (0) 2016.10.20
까먹지 말자  (0) 2016.08.16
Hello world  (0) 2016.08.11
posted by 알쿠미

C++ :: 의미

기초 2020. 7. 20. 21:00

:: 는 "범위 지정 연산자"이다.

ClassName::

NameSpaceName::

::

사용하는 방법은 위에 가지가 있다.

class Name
{
    public:
    void Print();
};

void Name::Print()
{
}

 

위에 Name::Print()를 써서 Class Name안에 있는 함수에 접근해서 선언할 수 있다.

 

namespace a
{
    void Print()
    {
    }
}

namespace b
{
    void Print();
    {
    }
}

a::Print() - a NameSpace 범위의 Print()

b::Print() - b NameSpace 범위의 Print()

는 다른 의미가 된다.

 

* 그냥 :: 만 사용하게 되면

현재 존재하는 모든 전역변수와 전역함수들을 지역변수, 지역함수와 구분지어 사용할 수 있게된다.

 

사용자가 정의한 전역함수도 ::를 사용하여 호출 할 수 있다.

 

출처: https://xxxq.tistory.com/entry/c%EC%97%90%EC%84%9C-%EC%9D%B4-%EA%B8%B0%ED%98%B8%EC%9D%98-%EC%9D%98%EB%AF%B8

'기초' 카테고리의 다른 글

C++ 에서 ^ ??  (0) 2020.11.11
간단히 적어놓는 논리연산자  (0) 2017.02.09
운영체제 스케줄링 기법  (0) 2016.10.20
까먹지 말자  (0) 2016.08.16
Hello world  (0) 2016.08.11
posted by 알쿠미

자잘하게 까먹는 것들

이것저것 2018. 10. 24. 00:53

printf에서 변수 출력할 때 사용

서식 문자

출력 형태

%c

단일 문자

%s

문자열

%d

부호 있는 10진 정수

%f

 부호 있는 10진 실수

%x

 부호 없는 16진 정수, 소문자 사용

%X

 부호 없는 16진 정수, 대문자 사용

%o

부호 없는 8진 정수

%u

부호 없는 10진 정수

%e 

e 표기법에 의한 실수

%E

E 표기법에 의한 실수

%% 

% 기호 출력



1. 문자열 상수는 수정불가능한 char형 배열이다.

2. 배열은 그 자신의 첫번째 원소를 가리키는 포인터 주소값으로 자동 변환된다.

3. 2번에는 3가지 예외가 있는데, & 연산자의 피연산자, size of 연산자의 피연산자, 그리고 char형 배열을 초기화할 때 쓰였을 경우이다.

4. array[2] 는 *(array + 2) 와 완전히 동일한 표현이다.

char* str;

str = "abcd"; // str은 "abcd"의 첫번째 원소를 가리키는 주소값을 저장한다.

str[1] = 'c' // error "abcd"는 상수이므로 값을 바꿀수 없다.


char str[] = "abcd"

str[1] = 'b'; // 배열에 문자열 상수를 초기화하는 경우 새로운 배열이 만들어 지기 때문에 상수가 아니다. 따라서 대입가능


출처 : https://kldp.org/node/61290

posted by 알쿠미

Fbx logic tutorial

엔진 2017. 9. 15. 01:54

ImportExport의 ImportExport() 함수는 파일 변환의 메인 로직을 포함한다.


ImportExport()의 순서


* 프로그램에게서 다음의 매계변수를 받는다.

- import될 파일의 경로와 이름

- export될 파일의 경로와 이름

- export될 파일의 포멧


* SDK manager 오브젝트를 만들고 다른 FBX 오브젝트들이 사용하는 메모리를 관리한다.


* import 파일의 데이터를 hold하기 위해서 Scene오브젝트를 만든다.


* import파일의 데이터를 scene에 load한다.


* scene의 데이터를 export file에 저장한다.


* SDK manager를 비롯한 SDK와 관련된 FBX object등을 릴리즈한다.


SceneTreeView의 로직

* user

'엔진' 카테고리의 다른 글

3일차 헤더관련 and DX11Utils.h/cpp  (0) 2016.08.23
DX9와 DX11의 차이  (0) 2016.08.19
2일차 XLE 분석 및 구현 (160822)  (0) 2016.08.16
XLE 분석 ( FlexBegin / FlexEnd )  (0) 2016.03.02
조사해야될거  (0) 2016.03.01
posted by 알쿠미

간단히 적어놓는 논리연산자

기초 2017. 2. 9. 17:19

NOT ~a : a가 true이면 ~a는 false


AND(논리곱) a & b 둘다 true일때 true


OR(논리합) a | b 하나만 true여도 true


XOR(베타적 논리합) a ^ b 하나만 true 일때 true

'기초' 카테고리의 다른 글

C++ 에서 ^ ??  (0) 2020.11.11
C++ :: 의미  (0) 2020.07.20
운영체제 스케줄링 기법  (0) 2016.10.20
까먹지 말자  (0) 2016.08.16
Hello world  (0) 2016.08.11
posted by 알쿠미

16진수에 관해서

까먹지말자 2017. 2. 9. 17:12

16진수를 매번 볼때마다 헷갈려서 한번 정리를 해두는 것이 좋다고 생각되었습니다.

 

0x....하고 붙은 것이 16진수입니다.

 

컴퓨터에서 메모리의 최소의 기억단위를 8비트, 1바이트로 정했고 그래서 변수를 기억시키기 위해 1바이트 이상을 사용합니다.

 

1~9 A~F

16진수로 255 = 0xFF 16*15 + 15 = 1바이트

0xFFFF = 2바이트

 

16진수를 2진수로

0xF = 1111

0xFF = 1111 1111

 

35(10진수)를 2진수로 표현하기엔 계산을 해야하지만

0x23(16진수로 35) 를 2진수로 표현하면 0010(2) 0011(3) 이렇게 편하게 변환이 가능합니다. 

 

잘 정리된 글을 찾은 것 같다

 

출처 http://ideacoop.tistory.com/entry/%ED%8E%8C-0x01%EC%97%90%EC%84%9C-0x%EC%9D%98-%EC%9D%98%EB%AF%B8%EC%99%80-2-16%EC%A7%84%EC%88%98-%EC%82%AC%EC%9A%A9%EC%9D%B4%EC%9C%A0

 

내용출처 : 데브피아(http://www.devpia.com/)
이 글은 "데브피아"에서 작성된 글입니다.

 

posted by 알쿠미

운영체제 스케줄링 기법

기초 2016. 10. 20. 23:54

1. 비선점 스케줄링

- 할당된 CPU를 다른 프로세스가 강제로 빼앗을 수 없는 기법

- 필요성이 떨어지는 긴 프로세스가 선점하고 있을 때 기다리는 점이 발생

- 종류 : FCFS(FIFO), SJF(Shortest Job First), HRN, 기한부(DeadLine)


2. 선점 스케줄링

- 할당된 CPU를 다른 프로세스가 강제로 뺴앗아 사용할 수 있는 기법

- 빠른 응답시간을 요구하는 시분할 시스템에 사용

- 많은 오버헤드

- 인터럽트용 타이머 클럭필요( 프로세스가 자원을 독점하는 것을 방지)

- 종류 : RR(Round Robin, SRT, 선점 우선순위, 다단계 큐(MQ), 다단계 피드백 큐(MFQ)


3. 비전섬 스케줄링 종류

* FCFS( first Come First Service, 선입선출)

- 준비 상태 큐에 도착한 순서에 따라 차례로

* SJF 짧은 작업 우선

- 평균 대기시간이 가장 짧다.

- 실행시간이 긴 프로세스는 무기한 연장될 수 있다.

* HRN( Highest Response-ratio Next )

- SJF 기법의 보완

- 우선순위 공식을 이용해서 실생 시간이 짧은 프로세스나 대시시간이 긴 프로세스에게 우선 순위를 줌

- 우선순위 계산식 = ( 대기시간 + 실행시간 ) / 실행시간

* 기한부 ( Deadline )

- 일정시간동안 프로세스를 완료하는 기법

- 제한된 시간안에 프로세스들이 동시에 실행되면 스케줄링이 복잡해지며 실행시 직중적으로 요구되는 자원관리에 오버헤드가 발생한다.

* 우선순위 ( Priority )

- 프로세스마다 우선순위 부여

- 우선순위가 동일한경우 FCFS 기법으로 할당

- 가장 낮은 순위를 부여받은 프로세스는 무한 연기 또는 기아상태가 발생할 수있다.


4. 선점 스케줄링 종류

* Round Robin

- 시분할 시스템을 위해 고안한 방식, FCFS기법의 변형

- 각 프로세스는 시간 할당량 동안만 실행한 후 완료되지 않으면 다음 프로세스에게 CPU를 넘겨주고 준비상태 큐의 가장 뒤로 배치

- 할당된 시간이 클수록 FCFS와 같다

- 시간이 작을 수록 문맥교환과 오버헤드가 자주 발생


* SRT( Shortest Remaining Time )

- SJF기법의 번형

- 실행중인 프로세스의 남은 시간과 준비상태 큐에 새로 도착한 프로세스의 실행 시간을 비교하여 짧은 실행 시간을 요구하는 프로세스에게 CPU를 할당

- 준비상태 큐에 있는 프로세스의 실행 기간 추적으로 오버헤드 증가

* 다단계 큐

- 프로세스를 특정 그룹으로 분류할 수 있을 경우 그룹에 따라 각기 다른 준비단계 큐 사용

- 시스템, 대화형, 편집, 일괄처리 프로세스 등으로 분류

- 준비상태 큐마다 다른 스케줄링 기법 사용가능

- 다른 준비상태 큐로 이동 불가

- 하위 단계 준비큐에 있는 프로세스를 실행하는 도중이라도 상위 단계 준비상태 큐에 프로세스가 들어오면 상위단계 프로세스에게 CPU 할당


* 다단계 피드백 큐

- 다단계 큐 기법 개선하여 다른 준비상태 큐로 이동가능

- 각 큐마다 시간 할당량부여 시간동안 완료 되지 못한 프로세스는 다음 단계 큐로 이동

- 마지막 단계 큐에서는 RR스케줄링으로 할당


에이징(aging) = 시간이 지날수록 우선순위를 높혀주는것


참고 : http://visu4l.tistory.com/184

'기초' 카테고리의 다른 글

C++ :: 의미  (0) 2020.07.20
간단히 적어놓는 논리연산자  (0) 2017.02.09
까먹지 말자  (0) 2016.08.16
Hello world  (0) 2016.08.11
typedef 관련  (0) 2016.05.22
posted by 알쿠미

3일차 헤더관련 and DX11Utils.h/cpp

엔진 2016. 8. 23. 16:43

DX11.h (DX11 인터페이스 전방선언) 은 다른 클래스 헤더파일에 포함

DXUtils.h DX11.h와 (IncludeDX11.h를 포함하고있다.) cpp 파일에 포함

IncludeDX11.h (DX11을 포함하고 IncludeWindows.h(windows.h를 포함하고있다.)를와  d3d11.h를 포함하고있다.)

그리고 이런 문구가 적혀있다.

    // include windows in a controlled manner (before d3d11 includes it!)

    // (try to limit including DX11.h to just this place)


DXUtils.h


여긴 템플릿 특수화로 D3DTypeInfo를 알 수 있는 템플릿들이 있다.

(리소스의 타입을 알수있는것 같다.)



그리곤 ExtractResource( 뷰들을 통해서 리소스를 얻는다. )


QueryInterfaceCast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    templatetypename DestinationType, typename SourceType > // DestinationType의 intrusive_ptr을 반환하는 함수
        intrusive_ptr<DestinationType> QueryInterfaceCast(SourceType * sourceObject)
    {
        void * result = NULL; //DestinationType의 반환값을 넣을 void포인터
        HRESULT status = sourceObject->QueryInterface(__uuidof(DestinationType), &result);
        if (status != S_OK) { //
            if (result) ((DestinationType*)result)->Release(); // Query에 실패하면 Release 혹은 아무것도 없는 포인터 반환
            return intrusive_ptr<DestinationType>();
        }
        // return moveptr((DestinationType*)result);    (problem with multiple copies of intrusive_ptr)
        return intrusive_ptr<DestinationType>((DestinationType*)result, false/*take new reference*/);
    }
 
    template <typename DestinationType, typename SourceType>
        intrusive_ptr<DestinationType> QueryInterfaceCast(intrusive_ptr<SourceType>& sourceObject)
    {
        void * result = NULL;
        HRESULT status = sourceObject->QueryInterface(__uuidof(DestinationType), &result);
        if (status != S_OK) {
            if (result) ((DestinationType*)result)->Release();
            return intrusive_ptr<DestinationType>();
        }
        // return moveptr((DestinationType*)result);    (problem with multiple copies of intrusive_ptr)
        return intrusive_ptr<DestinationType>((DestinationType*)result, false);
    }



'엔진' 카테고리의 다른 글

Fbx logic tutorial  (0) 2017.09.15
DX9와 DX11의 차이  (0) 2016.08.19
2일차 XLE 분석 및 구현 (160822)  (0) 2016.08.16
XLE 분석 ( FlexBegin / FlexEnd )  (0) 2016.03.02
조사해야될거  (0) 2016.03.01
posted by 알쿠미

DX9와 DX11의 차이

엔진 2016. 8. 19. 15:48

DX9와 달리 DX11은 Device와 DeviceContext로 나누어져 있음


Device는 주로 resource 생성을 담당

- thread-safe

DeviceContext는 주로 rendering 을 담당

- thread-unsafe


* constant buffer 

cbuffer 키워드 안에 변수를 묶어서 정의

CreateBuffer로 constant buffer용 버퍼 생성

UpdateSubresource(Map)로 버퍼의 내용을 update

 - 이때 update를 하면 cbuffer의 내용 전부를 덮어씌운다.

( 그렇기 때문에 변수를 나누어서 cbuffer을 만들고 필요한 부분만 update를 효율적으로 하는게 중요하다.)


XXSetconstantBuffers로 레지스터에 바인드

 - VSSetConstantBuffers, PSsetConstantBuffer 등


VertextInputLayout - 버텍스 버퍼에 대한 정보를 GPU에 알려주기 위해서 사용한다.

CreateInputLayout을 이용해서 생성할 때 vertex shader와 매칭이 이루어지는데 

D3D11_INPUT_ELEMENT_DESC와 vertex shader semantic과 일치하면 success 불일치 하면 fail.


Shader reflection?

vertex shader를 reflection하여 semantic과 일치하는 VertexInputLayout을 미리생성

Shader semantic 기준으로 VertexInputLayout를 생성


MultiThread

immedidate context 

rendering 명령을 실행하는 오브젝트

1개만 생성가능 thread unsafe


deferred context

각 thread에서 모든 rendering 명령의 실행이 끝난 후에 FinishCommandList를 호출하여 command list를 얻어옴. 이후 command list를 immediate context 에서 실행


1. 생성

ID3D11DeviceContext* pImmediateContext;

ID3D11DeviceContext* pDeferredContext;


pDevice->CreateDeferredContext( 0, &pDeferredContext );


2. 각 Thread 마지막에 실행

pDeferredContext->FinishCommandList( FALSE, &pCommandList );


3. pImmediateContext->ExecuteCommandList( pCommandList, FALSE );




[참고]

http://www.slideshare.net/ssuserf07a43/kgc2014-dx9dx11-41292758?from_m_app=android

'엔진' 카테고리의 다른 글

Fbx logic tutorial  (0) 2017.09.15
3일차 헤더관련 and DX11Utils.h/cpp  (0) 2016.08.23
2일차 XLE 분석 및 구현 (160822)  (0) 2016.08.16
XLE 분석 ( FlexBegin / FlexEnd )  (0) 2016.03.02
조사해야될거  (0) 2016.03.01
posted by 알쿠미

2일차 XLE 분석 및 구현 (160822)

엔진 2016. 8. 16. 21:05

ObjectFactory로 D3D관련 객체를 만든다.

이렇게 하면 디버깅과 프로파일링 하기 편하다고 한다.


XLE에서 CommandList는 noncopyable과 RefCountedObject를 상속받고있다.

일단 나중에 CommandList를 구현할때쯤 RefCountedObject를 다시보고 참고해야겠다.


enum class {

};


형에 안전성을 가지고 있고 클래스로 덮혀있어서 이름이 겹치지 않는다.


'엔진' 카테고리의 다른 글

Fbx logic tutorial  (0) 2017.09.15
3일차 헤더관련 and DX11Utils.h/cpp  (0) 2016.08.23
DX9와 DX11의 차이  (0) 2016.08.19
XLE 분석 ( FlexBegin / FlexEnd )  (0) 2016.03.02
조사해야될거  (0) 2016.03.01
posted by 알쿠미

까먹지 말자

기초 2016. 8. 16. 18:29

mutual == const가 붙어있는 함수에서도 값을 바꿀 수 있는 키워드


unsigned 숫자 옆엔 u를 붙이자. 1u , 2u이렇게

'기초' 카테고리의 다른 글

간단히 적어놓는 논리연산자  (0) 2017.02.09
운영체제 스케줄링 기법  (0) 2016.10.20
Hello world  (0) 2016.08.11
typedef 관련  (0) 2016.05.22
using 키워드  (0) 2016.03.02
posted by 알쿠미

C++의 클래스는 기본적으로 다음의 특수한 멤버 함수를 생성합니다.

기본 생성자
복사 생성자
복사 대입 연산자
소멸자

클래스를 생성하고 아무것도 하지 않아도 위의 4개는 기본적으로 생성됩니다.


C++ 11 에서는 기본적으로 생성되는 특수 멤버 함수에 무브 생성자, 무브대입연산자가 추가 되었습니다.


NonCopyable 할때 사용하는 것이 default, delete

생성자 = default 를 사용하면 기본 생성자가 생성되고

NonCopyable은 복사생성자 대입연산자를 사용할 수 없어야하기 때문에

NonCopyable(const NonCopyable&) = delete;

NonCopyable& operator = (const NonCopyable& ) = delete;

이렇게 선언해서 disable을 해준다.


vs2013부터 사용된다.


[참고] 

http://psychoria.tistory.com/entry/C-11-default%EC%99%80-delete-%ED%82%A4%EC%9B%8C%EB%93%9C


http://egloos.zum.com/sweeper/v/2995404

'까먹지말자' 카테고리의 다른 글

16진수에 관해서  (1) 2017.02.09
posted by 알쿠미

Hello world

기초 2016. 8. 11. 17:28

cout 은 클래스다

<< 는 왼쪽 시프트 연산자

cout에서는 추출연산자.


문자와 문자열


문자는 1byte짜리 한글자

한글은 아스키 코드에 있지 않으므로 문자가 아니다.


유니코드 = 모든 글자를 2byte로 해뒀다.


2byte 이상은 문자열


문자는 'a' 문자열은 "a"


'\0' 는 문자 -> 이스케이프 문자열 이걸 만나면 문자열의 끝이다.


endl 은 함수 호출이다.


상수 - 변하지 않는 숫자


함수의 상수화

내가 만들어 놓은 함수를 바꾸지 않겠다.


변수 - 변할 가능성이 있는 숫자

정수 ( 양수 , 0 , 음수 ) 숫자의 크기가 정해져있다. 그 용량 만큼 변수를 사용하겠다는 의미

실수 - 양수 + 부호비트

문자열


자료형

char (1byte) 아스키 코드와 매칭되어있어서 숫자를 문자로 인식한다.

-128 ~ 127 / 0 ~ 255

short (2byte) 65536 개 0 ~ 65535 개 __int16

int (4byte) int가 4byte가 아닐때가 있었어서 long이랑 크기가 같다. __int32

long (4byte) __int32

long long (8byte) __int64


bit는 컴퓨터가 연산하는 단위 2의 제곱

byte 사용자가 저장하는 단위 2의 3제곱


unsigned 는 양수만 쓸때 정수형 자료형에만 쓸 수 있다.


실수 자료형

float (4byte) 2byte는 정수 2byte는 실수 / 소수점 이하 6~7자리

double (8byte) 4byte는 정수 4byte는 실수 / 소수점 이하 12~15자리


컴파일러에 따라서 유효숫자 갯수가 정해진다.


float a = 3.14; 실수를 발견하면 double로 간주한다.

그래서 경고가 뜬다. 8byte를 4byte로 바꾸는 것이기 때문에 그래서 3.14f를 사용해서 3.14f 0.f 이렇게 알려줘야한다.


char 65번 = A 97번 = a


bool (1byte) 저장하는 단위가 1byte부터이기 때문에 0이 아니면 다 1





'기초' 카테고리의 다른 글

운영체제 스케줄링 기법  (0) 2016.10.20
까먹지 말자  (0) 2016.08.16
typedef 관련  (0) 2016.05.22
using 키워드  (0) 2016.03.02
시스템  (0) 2016.01.18
posted by 알쿠미

Device , DeviceContext 생성

DirectX11 2016. 7. 3. 19:08

Device, DeviceContext 는 물리적인 그래픽 장치 하드웨어에 대한 소프트웨어 제어기라고 생각하면 된다.


ID3D11Device 인터페이스는 기능 지원 점검과 자원 할당에 쓰인다.


ID3D11DeviceContext 인터페이스는 렌더 대상을 설정하고, 자원을 그래픽 파이프 라인에 묶고, GPU가 렌더링 명령들을 지시하는 데 쓰인다.


Device와 DeviceContext를 생성하는 함수


HRESULT D3D11CreateDevice {

IDXGIAdapter *pAdapter, 

D3D_DRIVER_TYPE DriverType,

HMODULE Software,

UINT Flags,

CONST D3D_FEATURE_LEVEL *pFeatureLevels,

UINT FeatureLevels,

UINT SDKVersion,

ID3D11Device **ppDevice,

D3D__FEATURE_LEVEL *pFeatureLevel,

ID3D11DeviceContext **ppImmediateContext

};


1. pAdapter : 이 함수로 생성할 Device를 나타내는 디스플레이 어댑터를 지정한다.

이 메개 변수에 널 값을 지정하면 기본 디스플레이 어댑터가 사용된다.


2. DriverType : 일반적으로 렌더링에 3차원 그래픽 가속이 적용되게 하기 위해선 이 매개변수에 D3D_DRIVER_TYPE_HARDWARE를 지정한다.

다른 매개 변수로는 

ⓐ D3D_DRIVER_TYPE_REFERENCE

  - 표준 장치를 생성한다. 즉, 하드웨어가 지원하지 않는 기능을 시험할때, 구동기의 버그를 시험할때 사용한다.

ⓑ D3D_DRIVER_TYPE_SOFTWARE

  - 3차원 하드웨어를 흉내내는 소프트웨어 구동기를 생성한다.

ⓒ D3D_DRIVER_TYPE_WARP

  - Direct3D 10.1 소프트웨어 구동기를 생성한다. (D3D11버전을 지원하지 않는다.)


3. Software: 소프트웨어 구동기를 지정한다.


4. Flags: 추가적인 장치 플래그들을 지정한다.

(흔히 쓰이는 2개)

ⓐ D3D_CREATE_DEVICE_DEBUG : 디버그 모드 빌드에서 디버그 계층을 활성화 하려면 이 플래그를 설정 해야한다.

( 이 플래그를 지정하면 VC++출력창에 디버그 메세지를 보낸다. )


ⓑ D3D_CREATE_DEVICE_SINGLETHREADED : Direct3D가 여러 개의 스레드에서 호출되지 않는다는 보장이 있을 때, 이 플래그를 지정하면 성능이 향상된다.

( 이 플래그가 활성화 되면 ID3D11Device::CreateDeferredContext의 호출은 실패한다.)

5. pFeatureLevels : D3D_FEATURE_LEVEL 형식의 배열 (널 값이면 최고수준)


6. FeatureLevels : pFeatureLevels 의 갯수 (위에 값이 널값이면 0으로 지정하면 된다.)


7. SDKVersion : 항상 D3D11_SDK_VERSION을 지정한다.


8. ppDevice : 함수가 생성한 Device


9 pFeatureLevel : 위에서 설정된 FeatureLevel을 반영한다.


10. ppImmediateContext : 생성된 DeviceContext를 돌려준다.


위의 매개변수가 Immediate라는 것은 다른 지연된 DeferredContext도 있다.

주 렌더링 스레드에는 Immediate를 사용하고

워커 스레드 에선 임의의 갯수인 Deferred를 사용한다.

1. 각 워커 스레드는 그리기 명령들을 명령목록(ID3D11CommandList)에 기록한다.

2. 주 렌더링 스레드는 Immediate를 이용해서 워커 스레드 명령목록에 있는 명령들을 기록한다.

명령목록을 생성하는데 시간이 걸린다면 다중 코어 시스템에서 이처럼 명령목록들을 병렬로 생성하여 성능향상을 꾀할 수 있다.


posted by 알쿠미

텍스처 관련

DirectX11/Direct3D 초기화 2016. 7. 3. 17:31

자원 뷰 (Resource View)

자원 뷰는 자원을 파이프라인에 묶는데(bind) 사용되는 객체이다.


자원뷰의 종류

렌더 타겟 뷰 ( ID3D11RenderTargetView )

깊이/스텐실 뷰 ( ID3D11DepthStencilView )

셰이더 자원 뷰 ( ID3D11ShaderResourceView )

순서 없는 접근 뷰 ( ID3D11UnordereAccessView )


각각의 자원뷰에 대한 설명은 참고 링크에 있다.


자원 뷰들은 독립적으로 두가지 일을 한다.

1. Direct3D에게 자원의 사용방식(즉, 파이프라인의 어떤 단계에 묶을 것인지)을 알려주는 것

2. 생성 시점에서 무형식을 지정한 자원 형식의 구체적인 형식을 결정하는 것

( 무형식 자원의 경우 텍스처 원소를 한 파이프 라인 단계에서는 부동소수점 값으로서 사용하고 다른 단계에서는 정수로서 사용하는 것이 가능함을 뜻한다.)


D3D11 에선 리소스를 생성하고 자원 뷰를 사용해서 파이프 라인에 묶는다.

묶는 방법은

D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE 

위 처럼 단계를 지정한 결속 플래그를 사용해서 묶는다.


즉, 텍스처를 사용하기 위해선 그 텍스처에 자원뷰가 필요하고 자원뷰를 파이프라인에 묶어서 사용한다.(텍스처가 파이프라인에 묶이는것이 아니라 자원뷰가 묶이는 것)


텍스처의 플래그가 설정되지 않은 뷰에 대해선 뷰를 생성할 수 없다.

텍스처가 D3D11_BIND_DEOTG_STENCIL 플래스가 설정되지 않았으면 ID3D11DepthStencilView를 생성할 수 없다.


D3D11에서 이렇게 하는 이유는?

실행시점 모듈(런타임)과 구동기(드라이버)가 유효성 점검과 매핑을 뷰 생성 시점에서 수행할 수 있기 때문에 결속 시점에서의 형식 점검이 최소화된다.

따라서 텍스처를 렌더대상과 쉐이더 자원으로 사용할 때는 두 개의 뷰를 생성할 필요가 있다.


* 참고

[리소스 뷰에 대한 대략적인 설명]

http://grandstayner.tistory.com/entry/DirectX11%EC%9D%98-%EC%9E%90%EC%9B%90-%EB%B7%B0


[D3D11 텍스쳐 생성]

http://blog.naver.com/sorkelf/40169749877


[자원의 종류 등등]

http://grandstayner.tistory.com/entry/DirectX-11%EC%9D%98-%EC%9E%90%EC%9B%90%EB%93%A4%EC%9D%98-%EA%B0%9C%EC%9A%94


그 외 : 다중 표본화


이해한 것으로는 다중 표본화란 픽셀 하나만 가지고 하나의 픽셀을 출력하는 것이 아니라 화면을 부드럽게 만들기 위해 픽셀의 인접 픽셀들을 이용해서 화면을 부드럽게 출력하는 것이 아닐까 싶다...

 표본화를 많이 할수록 품질은 좋아지겠지만 속도가 느려진다.

#define D3D11_MAXMULTISAMPLE_SAMPLE_COUNT ( 32 )

 최대 표본 갯수는 32로 정해져 있지만 표본을 4개에서 8개 추출해서 하는 경우가 많다.

(심오한 내용으로 보이니 조금만 알고가는 정도로 넘어가자)

'DirectX11 > Direct3D 초기화' 카테고리의 다른 글

화면 출력  (0) 2016.07.02
Direct3D 기본  (0) 2016.07.02
posted by 알쿠미

화면 출력

DirectX11/Direct3D 초기화 2016. 7. 2. 23:11

1. 이중버퍼링

애니메이션이 깜빡대는 현상을 방지하기 위해 이중 버퍼를 사용한다.

하나는 화면 밖에서 그리고 바꿔치기 하는 것이다.

전면 버퍼와 후면버퍼를 교환해서 화면에 표시하는 것을 제시(Presenting)이라고 한다.


버퍼들을 바꾸는 것은 내용을 바꾸는 것이 아니라 포인터만 맞바꾸는 것이기 때문에 효율적이다.


* 후면 버퍼는 텍스처이므로 그 원소를 텍셀이라고 불러야 하지만, 여기선 그냥 픽셀이라고 한다.


2. 깊이 버퍼링

깊이 버퍼는 이미지 자료를 담지 않은 텍스처이다.

깊이 버퍼는 후면버퍼의 픽셀들과 일대일로 대응한다. 깊이는 0.0 ~1.0 커질수록 멀다.


한 물체의 픽셀들이 다른 물체보다 앞에 있는지 판정하기 위해, 깊이 버퍼링, z-버퍼링 이라는 기법을 사용한다.

깊이 버퍼링에서 물체를 그리는 순서는 중요하지 않다.


깊이 버퍼링 알고리즘

* 렌더링 되는 각 픽셀의 깊이 값을 계산해서 깊이 판정을 수행하고 깊이 값을 비교했을때 관찰자에 가장 가까운 픽셀이 승리하여 후면 버퍼에 기록된다.


깊이 버퍼도 텍스처이므로 특정한 자료형 형식을 지정해서 생성해야 한다.

ⓐ DXGI_FORMAT_D32_FLOAT_S8X24_UNIT : 각 텍셀은 32비트 부동소수점 깊이 값과 [0, 255] 구간으로 사상되는 8비트 부호 없는 정수 스텐실 값(스텐실 버퍼에 쓰임), 그리고 다른 용도 없이 채움(Padding)용으로만 쓰이는 24비트로 구성된다.


ⓑ DXGI_FORMAT_D32_FLOAT : 각 텍셀은 하나의 32비트 부동소수점 깊이 값이다.


ⓒ DXGI_FORMAT_D24_UNORM_S8_UNIT : 각 텍셀은 [0, 1] 구간으로 사상되는 부호 없는 24비트 깊이 값 하나와 [0, 255] 구간으로 사상되는 8비트 부호 없는 정수 스텐실 값으로 구성된다.


ⓓ DXGI_FORMAT_D16_UNORM : 각 텍셀은 [0, 1] 구간으로 사상되는 부호 없는 16비트 깊이 값이다.


(스텐실 버퍼를 반드시 사용하는 것은 아니지만 만일 사용해야 한다면 스텐실 버퍼를 깊이 버퍼에 부착해야 한다.)

'DirectX11 > Direct3D 초기화' 카테고리의 다른 글

텍스처 관련  (0) 2016.07.03
Direct3D 기본  (0) 2016.07.02
posted by 알쿠미

Direct3D 기본

DirectX11/Direct3D 초기화 2016. 7. 2. 22:16

1. Direct3D 9와 11의 차이점

Direct3D 9 과 Direct3D 11이 다른점 9는 능력 집합의 일부만 지원하고 하드웨어가 지원하지 않는 기능을 사용했을 때 지원하는지를 점검하고 지원하지 않으면 호출이 실패하게 되었지만 11에선 기능을 지원하는지 점검할 필요 없이 11의 대응장치이려면 반드시 능력집합 전체를 지원해야한다.

 

2. COM ( Component Object Model )

DirectX의 프로그래밍 언어 독립성과 하위 호환성을 가능하게 하는 기술이다.

흔히 인터페이스라고 불린다.

 

COM의 인터페이스는 C++의 new 키워드로 생성하지 않는다.

인터페이스를 사용하고 난 후에는 delete로 삭제하는 것이 아니라 그 인터페이스의 Release 메소드를 호출해 주어야 한다.

(COM인터페이스는 IUnknown이라는 COM 인터페이스의 기능을 상속받는데, 그 인터페이스가 Release라는 메서드를 제공한다.) - COM객체들이 자신만의 방법으로 메모리를 관리하기 때문이다.

 

3. 텍스처 및 자료 자원 형식

텍스처는 자료 원소들의 행렬이라고 생각하면된다. 2차원 텍스처엔 한 픽셀의 색상이 들어갈 수 있고 , 법선 맵핑에선 3차원 벡터가 들어갈 수도 있다.

하지만 모든 데이터가 들어갈수 있는것은 아니고 정해진 포멧을 따르는 자료만 담을 수 있다.

구체적인 형식은 DXGI_FORMAT이라는 열거형으로 지정한다.

 

ⓐ DXGI_FORMAT_R32G32B32_FLOAT : 각 원소는 32비트 부동소수점 성분 세개로 이루어진다.

 

ⓑ DXGI_FORMAT_R16G16B16A16_UNORM : 각 원소는 [0,1] 구간으로 사상되는 16비트 성분 네개로 이루어진다.

 

ⓒ DXGI_FORMAT_R32G32_UNIT : 각 원소는 32비트 부호없는 정수 성분 두 개로 이루어 진다.

 

ⓓ DXGI_FORMAT_R8G8B8A8_UNORM : 각 원소는 [0,1] 구간으로 사상되는 8비트 부호 없는 성분 네개로 이루어진다.

 

ⓔ DXGI_FORMAT_R8G8B8A8_SNORM : 각 원소는 [-1, 1] 구간으로 사상되는 8비트 부호 있는 성분 네개로 이루어진다.

 

ⓕ DXGI_FORMAT_R8G8B8A8_SINT : 각 원소는 [-128, 127] 구간으로 사상되는 8비트 부호있는 정수 성분 네 개로 이루어진다.

 

ⓖ DXGI_FORMAT_R8G8B8A8_UNIT : 각 원소는 [0, 255] 구간으로 사사아되는 8비트 부호 없는 정수 성분 네 개로 이루어진다.

 

DXGI_FORMAT_R8G8B8A8_TYPELESS 이런 무형식도 가능하고

DXGI_FORMAT_R32G32B32_FLOAT 이 형식을 사용하더라도 색이 아니라 3차원 벡터를 넣는 것도 가능하다.

 

'DirectX11 > Direct3D 초기화' 카테고리의 다른 글

텍스처 관련  (0) 2016.07.03
화면 출력  (0) 2016.07.02
posted by 알쿠미

XNA Math 라이브러리 (행렬)

DirectX11/수학관련 2016. 7. 2. 17:59

행렬을 클래스 자료멤버로 저장할 때엔 XMFLOAT4X4를 사용하는 것을 추천한다.


XMMATRIX의 선언은


union

{

XMVECTOR r[4]; // SIMD를 사용하기위해서 4개의 XMVECTOR을 이용한다.

struct

{

FLOAT _11, _12, _13, _14;

FLOAT _21, _22, _23, _24;

FLOAT _31, _32, _33, _34;

FLOAT _41, _42, _43, _44;

};

FLOAT m[4][4];

};


행렬관련 함수들


XMMATRIX XMMatrixIdentity(); // 단위행렬 I를 돌려준다.


BOOL XMMatrixIsIdentity(CXMMATRIX M); // 단위행렬 여부를 알려준다.

XMMATRIX XMMatrixMultiply(CXMMATRIX A, CXMMATRIX B); // 행렬 곱 AB를 돌려준다.


XMMATRIX XMMatrixTranspose( CMMATRIX M); // M의 전치행렬을 돌려준다.


XMVECTOR XMMatrixDeterminant ( CXMMATRIX M); (det M, det M, det M det M)을 돌려준다.


XMMATRIX XMMatrixInverse ( XMVECTOR* pDeterminant, CXMMATRIX M); M의 역행렬을 돌려준다.


XMMATRIX XMMatrixScaling( FLOAT ScaleX, FLOAT ScaleY, FLOAT ScaleZ)


XMMATRIX MXMatrixScalingFromVector( FXMVECTOR Scale );


XMMATRIX XMMatrixRotationX ( FLOAT Angle );


XMMATRIX XMMatrixRotationY( FLOAT Angle ) ;


XMMATRIX XMMatrixRotationZ( FLOAT Angle ) ;


XMMATRIX XMMatrixRotationAxis ( FXMVECTOR Axis, FLOAT Angle );


XMMATRIX XMMatrixTranslation( FLOAT OffsetX, FLOAT OffsetY, FLOAT OffsetZ)


XMMATRIX XMMatrixTranslationFromVector( FXMVECTOR Offset );

XMVECTOR XMVector3Transfrom( FXMVECTOR V, CXMMATRIXM ) ;


XMVECTOR XMVector3TransfromCoord ( FXMVECTOR V, CXMMATRIX M);


XMVECTOR XMVector3TrasnfromNormal ( FXMVECTOR V, CXMMATRIX M);


* 마지막 두함수에서 벡터의 w성분을 신경쓰지 않아도 된다. XMVector3TransfromCoord의 w 값은 항상 1이고 XMVector3TransformNormal은 항상 0이다.



'DirectX11 > 수학관련' 카테고리의 다른 글

XNA Math 라이브러리(벡터)  (0) 2016.07.02
posted by 알쿠미

XNA Math 라이브러리(벡터)

DirectX11/수학관련 2016. 7. 2. 16:30

* Direct3D 9 과 10에선 그래픽스에 필요한 벡터 및 다른 주요 3차원 수학 형식들을 지원하는 수학 유틸리티 라이브러리가 있지만 Direct11 라이브러리에는 3차원 수학코드가 포함되어 있지 않다.

(물론 d3dx10.h>를 포함시키고 d3dx10.lib를 링크해서 D3DX10 Math함수를 사용하는 것도 가능하다.

* XNA 라이브러리는 Windows와 Xbox360에서 사용가능한 특별한 하드웨어 레지스터들을 활용한다.

SIMD 명령 집합을 사용하기 때문에 float나 int네개를 한번에 처리할 수 있다.

- XNA라이브러리는 모든 코드가 인라인화 되어 있어서 헤더파일만 추가하고 따로 라이브러리를 링크할 필요가 없다.


1. XNA 라이브러리에서 벡터를 사용할 때

typedef __m128 XMVECTOR; XNA 라이브러리에서 벡터는 이렇게 선언되어 있다.

계산을 수행할 때 __m128형식은 SIMD의 장점을 취하게 된다.

하지만 XMVECTOR의 경우 16바이트 경계에 정렬되어야 하는데, 지역변수와 전역변수에서는 정렬이 자동으로 이루어진다. 클래스 자료 멤버의 경우에는 이 대신 XMFLOAT2, XMFLOAT3, XMFLOAT4를 사용하는 것이 바람직 하다.

이 구조체들은 이렇게 정의 된다.

typedef struct_XMFLOAT4{

FLOAT x;

FLOAT y;

FLOAT z;

FLOAT w;

} XMFLOAT4;


하지만 이 형식들은 SIMD의 장점을 취하지 못하므로 XMVECTOR형식으로 변환해서 계산해야 SIMD의 장점을 취할 수 있다.


* 적재 및 저장 함수들


XMFLOAT*를 XMVECTOR로

// XMFLOAT2 를 XMVECTOR2에 적재

XMVECTOR XMLoatFloat2( CONST XMFLOAT2 *pSource);


// XMFLOAT3 를 XMVECTOR3에 적재

XMVECTOR XMLoatFloat3( CONST XMFLOAT3 *pSource);


// XMFLOAT4 를 XMVECTOR4에 적재

XMVECTOR XMLoatFloat4( CONST XMFLOAT4 *pSource);


XMVECTOR를 XMFLOAT*로

VOID XMStoreFloat2(XMFLOAT2 *pDestination, FXMVECTOR V); // 3,4 도 있음


이 외에도 3원소 UINT, XMCOLOR, XMBYTE4 등 XMVECTOR로 변환하고 적재하는 함수들도 있다.


XMVECTOR 인스턴스의 성분 하나만 읽거나 변경하고 싶은 경우도 있다 그런경우에 사용하는 조회 설정 함수들도 있다.

FLOAT XMVectorGetX(FXMVECTOR V);

XMVECTOR XMVectorSetX(FXMVECTOR V, FLOAT x); // y,z,w까지 다 있다.


2. 매개변수 전달

SIMD의 장점을 취하려면 함수에 XMVECTOR 형식의 매개변수를 전달할 때 지켜야 할 규칙이 몇 가지 있다.

32비트 Windows와 64비트 WIndows, XBox 360의 규칙들이 서로 다르다.

플랫폼에 독립적인 코드를 위해 XMVECTOR형식의 매개변수에 대해 CXMVECTOR 형식과 FXMVECTOR 형식을 사용한다.

이 형식들은 다음과 같이 정의 되어 있다.


// 32비트 Windows

typedef const XMVECTOR FXMVECTOR;

typedef const XMVECTOR& CXMVECTOR;


// 64비트 Windows

typedef const XMVECTOR& FXMVECTOR;

typedef const XMVECTOR& CXMVECTOR;


구체적인 규칙으론 처음 3개의 매개변수는 FXMVECTOR 형식이어야하고 그 외의 매개변수는 반드시 CXMVECTOR 형식이어야 한다.

즉, 매개변수에 있는 XMVECTOR변수 처음 3개는 FXMVECTOR을 쓰고 이후엔 CXMVECTOR을 써야한다.


3. 상수 벡터

상수(const) XMVECTOR 인스턴스에는 반드시 XMVECTORF32 형식을 사용해야 한다.

간단히 말하면, 초기화 구문을 사용하고자 할 때에는 항상 XMVECTORF32를 사용해야 한다. (XMVECTORF32는 16바이트 경계로 정렬된 구조체로, XMVECTOR로의 변환 연산자를 지원한다.


4. 설정 함수

XMVECTOR XMVectorZero();

XMVECTOR XMVectorSplatOne(); // 벡터 (1, 1, 1, 1) 을 돌려준다.

XMVECTOR XMVectorSet( FLOAT x, FLOAT y, FLOAT z, FLOAT w) // 벡터(x, y, z, w)를 돌려준다.

XMVECTOR XMVectorReplicate( FLOAT s); // 벡터 (s, s, s, s)를 돌려준다.

XMVECTOR XMVectorSplatX( FXMVECTOR V); // 벡터 (Vx, Vx, Vx, Vx)를 돌려준다.


* 수학적 결과가 스칼라 값이라도 XMVECTOR변수를 반환한다 그 이후는 SIMD벡터 연산의 전환을 최소화 해서 SIMD로 유지하는 것이 효율적이기 때문이다.


5. 부동 소수점 연산

* 부동 소수점 연산을 할때에는 오차가 누적되서 변수가 근사값이 되는데 그때에 Epsilon을 두어서 상등을 판정할 수 있다. 

XNA라이브러리에는 두 벡터의 상등을 판정하는 XMVector3NearEqual이라는 함수가 있다. 이 함수는 Epsilon을 매개변수로 허용 오차를 받는다.


'DirectX11 > 수학관련' 카테고리의 다른 글

XNA Math 라이브러리 (행렬)  (0) 2016.07.02
posted by 알쿠미

문자열

1. 문자열의 문제점

문자열을 비교하는 함수 strcmp(), 문자열을 복사하는 함수 strcpy() 모드 O(n)의 동작이다.

ⓐ 문자열 클래스

- 문자열 객체를 넘길 때는 값이 아닌 참조로 넘길 것

- 일찍 코드를 프로파일링하고 자주해서 문자열 클래스가 프레임 저하의 주원인이 되지 않게 살필 것

ⓑ 고유 식별자

- 식별자에 문자을 쓰는 것은 자연스러운 일이지만 strcmp()를 사용하는 것은 너무 느리다.

- 그래서 해시 문자열ID를 사용한다.

- 문자열을 정수 처럼 비교하기 때문에 빠르다.

- 해시 테이블에 저장하면 해시 코드를 통해 언제든 문자열을 가져올 수 있다.


* 대부분의 게임 엔진들을 런타임에 해시 값을 계산하지 않는다. ( 해시 함수를 통가하는 속도는 느리기 때문)

* 그렇기 때문에 문자열을 해싱하는 것을 인턴이라고 하는데 인턴을 미리 해두고 저장해서 해시함수를 통과하지 않고 사용하는 것이 좋다.

    

2. 현지화

ⓐ 유니코드

- 영어와 다른 문자를 사용하기 위한 문자 셋 시스템

ⓑ UTF-8

- 각 문자 코드는 8비트지만 어떤 문자들은 1바이트 보다 큰 공간을 차지하기도 한다. ( 멀티 바이트 셋 MBCS)

- 장점은 ANSI 인코딩과 호환이 된다. 멀티바이트의 문자의 첫 바이트는 항상 가장 높은 비트가 1이기 때문이다.

ⓒ UTF-16

- 표준은 더 간단하지만 좀 더 비싼 방법을 사용한다.

- 와이드 캐릭터 셋(WCS) 이라고 부르는데 16비트를 사용한다.


ⓓ 윈도우 환경에서 유니코드

- UTF-16 하나의 데이터 타임은 wchat_t 이고 UTF-8이나 ANSI 문자열을 나타내는 것은 char이다.

- 캐릭터 셋에 무관하게 짤 수 있는 방법은 TCHAR을 사용하는 것이다.

( typedef를 사용해서 ANSI 모드에선 char이 되고 UTF-16(WCS)으로 컴파일 할 때는 wchar_t가 된다.)

- 모든 윈도우 API에서 접미사나 접두사로 w, wcs, W 가 붙은 것들은 와이드 문자를 의미한다.

- t, tcs, T 가 붙은 것들은 현재 사용하는 문자 타입을 의미한다.

ex) std::string은 STL의 ANSI문자열 클래스이고, std::wstring은 와이드 캐릭터 클래스다.

- 윈도우에서 WCS, MBCS 문자열 다루는 함수는 버전이 따로 존재한다.


ⓓ 콘솔에서의 유니코드

- 프로젝트에서 어떤 인코딩을 사용할지 가능한 한 빨리 정한 다음, 그 후 일관되게 사용하기만 한다면 실제로 어떤 것을 사용하는지는 별로 중요하지 않다.

posted by 알쿠미

STL의 장점

 * STL은 풍부한 기능들을 지원한다.

 * 다양한 플랫폼에서 쓸 수 있는 대체적으로 안정적인 구현들이 존재한다.

 * 거의 모든 C++ 컴파일러는 STL을 표준으로서 지원한다.


STL의 단점

 * STL은 처음에 배우기기 힘들다.

 * 구체적인 목적을 위한 자료구조에 비해 성능이 떨어진다.

 * 대부분의 경우 자체 제작한 자료 구조보다 메모리를 더 많이 먹는다.

 * 동적 메모리 할당을 많이 사용하다.

 * 여러 플랫폼을 지원하는 엔진에서 사용하기 힘들다.


1. 동적 배열과 메모리 할당

  동적 할당은 느리기 때문에 동적 배열은 개발기간에 사용하고 버퍼의 크기를 알게 되면 고정크기 배열로 바꾸어 사용하는 것도 좋다.


2. 연결 리스트

  ⓐ 고려사항

    - 빈 리스트에 첫 요소를 추가하는 경우

    - 현재의 머로 요소 앞에 새 요소를 추가하는 경우

    - 현재의 꼬리 요소 뒤에 새 요소를 추가하는 경우

    - 중간에 요소를 추가하는 경우


  ⓑ 링크 자료구조

template< typename ELEMENT >

struct Link

{

Link<ELEMENT>* m_pPrev;

Link<ELEMENT>* m_pNext;

Link<ELEMENT>* m_pElem;

};


  ⓒ 돌출 리스트 (extrusive list)

    - Link 자료구조와 요소 자료 구조가 완전 별개인 연결리스트 이다.

    - 연결리스트에 요소가 추가될 때면 링크를 하나 새로 할당하고 요소에 대한 포인터 및 다음과 이전 링크에 대한 포인터를 맞게 설정한다.

    - 장점은 한 요소가 동시에 여러 연결리스트에서 포함할 수 있다는 것이다.

    - 단점은 링크 객체를 동적할당 해야한다는 것이다. 링크는 언제나 크기가 같기 때문에 풀할당자를 사용하는 경우가 많다.


  ⓓ 함몰 리스트 (Instrusive list)

    - Link 자료구조가 요소의 자료구조 안에 포함되는 연결 리스트다.

    - 링크 객체를 동적 할당하지 않아도 되는 이점이 있다.

    - Link 안에는 요소를 가리키는 포인터가 있어야 하지만, 상속을 사용하면 없어도 된다.


  ⓓ 머리와 꼬리 포인터 : 순환리스트

    - Head 포인터와 tail 포인터를 가지고 있으면 삭제나 추가 시 복잡해진다.

    - 그러므로 이 두개의 포인터를 m_root포인터로 합치면 순환하는 리스트가 된다.


  ⓔ 단순 연결 리스트

    - 이전을 가리키는 포인터가 없기 때문에 제거 동작은 O(n)이고 이중연결리스트에선 O(1)이다.

    - 리스트의 Head나 Tail에서 제거 동작이 발생하는 경우에는 단순 연결로 메모리를 절약할 수 있다.


3. 사전과 해시 테이블

사전은 키-값 쌍의 테이블이다. 

사전은 대부분 이진트리나 해시테이블을 사용하는다.

이진트리의 검색 연산은 O(logn)이다.

해시 테이블은 키를 정수형태로 변환하고 모듈로(modulo) 연산으로 검색하기 때문에 O(1)이다.


  ⓐ 충돌 : 개방형 해시 테이블과 폐쇄형 해시 테이블

    - 개방형 해시 테이블은 충돌을 해결하기 위해 단순하게 인덱스 하나에 여러개의 키-값 쌍을 저장하는 방식을 쓴다.

    - 구현하기 쉽고 저장할 수 있는 키-값 쌍의 수에도 제약이 없지만 새로운 키-값 쌍을 추가할 때 동적 메모리 할당이 발생한다.

  

    - 폐쇄형 해시 테이블은 충돌이 발생하면 빈 슬롯을 찾을 때 까지 탐지하는 과정을 반복한다.

    - 구현이 까다롭고 키-값 쌍의 수에 제한이 있다. 하지만 정해진 양만큼의 메모리를 사용하고 동적 메모리 할당이 필요 없다.


  ⓑ 해시 값 계산

    - 해시 값 계산(Hashing)은 임의의 데이터 타입인 키 값을 정수로 부꾼 후 이 정수와 테이블 크기를 모듈로 연산해 테이블에 대한 인덱스를 얻는 과정이다.

    h = H(k)    i = h mod N

    - 해시 테이블의효율성은 해시 함수 품질에 달려 있다. 좋은 해시 함수란 모든 키값을 테이블 전체에 고르게 배분하는 함수이고, 충돌을 최소화 한다.

    - 결정적이어야 한다. 입력이 같으면 그 출력도 같아야 한다.


  ⓒ 폐쇄형 해시 테이블 구현

    - 폐쇄형 해시 테이블 상식에서는 키-값 쌍을 각 테이블 항목마다 하나씩 연결 리스트에 저장하는것이 아니라 테이블 안에 직접 저장한다.

    - 이렇게 되면 해시 테이블을 사용할 메모리 양을 미리 정확히 알 수 있다.

    - 충돌이 일어나서 탐자 과정을 할때 가장 간단한 방식은 선형 탐지다. 충돌이 일어난 곳 부터 하나씩 탐지하는 것이다.

    ( 요소들이 뭉치게 된다.)

    - 그래서 이차 탐지 알고리즘을 쓰는데 하나씩이 아니라 i의 제곱씩 늘려가며 탐색한다.

    - 폐쇄형 해시는 크기를 소수로 하는 것이 좋다. 이차 탐색을 했을 때 고르게 배치 할 수 있다.




  

'게임 엔진 아키텍처 > 5장 엔진 지원 시스템' 카테고리의 다른 글

문자열  (0) 2016.05.28
메모리 관리  (0) 2016.05.27
하부 시스템 시작과 종료  (0) 2016.05.27
posted by 알쿠미

소프트 웨어의 성능은 어떤 알고리즘을 썼느냐도 중요하지만 어떻게 RAM을 잘 활용했는지도 영향을 받는다.

메모리가 성능에 영향을 끼치는 형태는 다음 두가지가 있다.


* 동적 메모리 할당은 느리다. 동적 메모리할당을 피하거나, 할당비용을 줄일 수 있는 메모리 할당자를 직접 만들어야 한다.


* 메모리를 효율적으로 배치해되 있을수록 속도가 빠르다.


1. 동적 메모리 할당 최적화

 동적 메모리 할당이 느린 이유

  * 힙 할당자는 범용 목적이기 때문에 이렇게 하면 관리하는 부가적인 비용이 들기 때문이다.

  * malloc(), free()를 호출할 때 대부분 운영체제 에서는 먼저 유저 모드에서 커널 모드로 컨텍스트 전환을 하고, 필요한 동작을 수행한 후 다시 프로그램으로 컨텍스트 전환을 해야한다.


 사용자 제작 할당자가 빠른 점

  * 미리 할당된 블록을 이용할 수 있다. 즉, 유저모드에서만 처리하기 때문에 컨텍스트 스위칭이 일어나지 않는다.

  * 사용 패턴을 예측할 수 있기 때문에 범용 힙 할당자에 비해 훨씬 효율적으로 동작한다.


2. 커스텀 할당자의 종류

  ⓐ 스택 할당자 - 데이터를 쌓아가며 할당하고 그러므로 해제할땐 순서대로 해제해야 한다. 해제 시 해제하고 할당 된만큼 꼭대기의 주소를 내려줘야 한다.


  ⓑ 풀 할당자 - 개별 원소들의 크기에 정확히 배수가 되는 큰 메모리 블록을 할당하는 것이다. 처음에는 모든 풀의 원소들이 사용 가능 리스트에 들어가 있다가 할당 요청이 오면 제일 처음 원소를 가져와서 리턴한다.


  ⓒ 정렬된 할당자 - 실제 요청된 것보다 조금 큰 메모리를 할당하고 블록의 주소를 살짝 위로 조정해서 정렬을 맞춘 다음 조정된 주소를 리턴한다.


  ⓓ 단일 프레임 할당자 - 메모리를 해제하지 않고 한 프레임 마다 메모리 블록의 가장 아래로 꼭대기 포인터를 초기화 한다. 프레임 진행 중 할당이 일어나면 블록의 위방향으로 진행한다.


3. 메모리 단편화

 - 메모리가 충분히 있음에도 연속되 있지 않아서 할당에 실패한다.

해결 방안

 ⓐ 스택할당자와 풀할당자를 사용한다.

   - 이 두 할당자는 메모리 단편화를 겪지 않는다.

 ⓑ 조각 모음과 재배치

   - 할당된 메모리들을 메모리 구멍을을 메워가며 앞으로 당긴다.

   - 하지만 메모리를 가리키고 있는 포인터가 있을 경우 문제가 생길 수 있으니 메모리들을 옮기면서 이 과정 또한 다시 재배치 해주어야 한다.

    (스마트 포인터가 스스로 재배치를 하게 하거나 핸들을 사용한다.)

   - 조각 모음이 한 프레임에 모든 블록을 옮긴다면 속도가 굉장히 느릴 것이다 그러므로 한프레임당 8개나 16개 정도 갯수를 조정하는 것이 좋다.


4. 캐시 일관성

 시스템이 메인 RAM에 접근하는 일은 시작부터 끝까지 항상 수천 프로세스 주기가 걸리기 때문에 언제나 느리다.

 대게 수십주기, 어떤 경우는 한주기만에 끝나기도 하는 CPU 레지스터 접근과 비교하면 엄청난 차이다.

 메인 RAM에서 읽고 쓰는 평균적인 비용을 줄이기 위해 오늘날의 프로세서는 고성능 메모리 캐시를 이용한다.

 캐시는 특수한 형태의 메모리로 CPI가 읽고 쓰는 속도가 메인 RAM 보다 훨씬 빠르다.

 메모리 캐싱의 기본적 원리는 메인 RAM의 영역을 처음 읽을 때, 작은 메모리 조각을 고성능 캐시에 읽어 들이는 것이다.

 이 메모리 조각을 캐시라인이라고 하고 보통 8바이트에서 512바이트 사이의 값이다.

 요청한 데이터가 캐시에 있을 땐 캐시에서 바로 읽어 들이고 그렇지 않으면 메인 RAM에 접근한다. 이 경우를 캐시 미스라고 한다.

 캐시 미스가 발생하면 캐시라인을 다시 읽어 들일 때 까지 프로그램은 기다려야 한다.

 RAM에 데이터를 쓰거나 읽어야 하기 때문에 캐시 미스를 완전히 피할 수는 없다.


  ⓐ 명령어 캐시(instruction I 캐시) 데이터(Data D 캐시) 캐시

    - 명령어 캐시는 실행 파일의 명령어 코드가 실행되기 전에 미리 불러오는데 쓰인다.

    - 데이터 캐시는 데이터를 메인 RAM에 읽고 쓰는 속도를 빠르게 하는 데 쓰인다.


  ⓑ 데이터 캐시 미스를 피하는 가장 좋은 방법은 데이터를 잘개 쪼개어 연속적인 블록으로 배치하고 순서대로 접근하는 것이다.


  ⓒ 명령어 캐시 미스를 피하는 방법은 코드의 메모리에서의 모양은 데이터와 링커에 달려 있다 그래서 다음위 규칙을 이용하면 좋다.

    - 함수 하나를 나타내는 기계어 코드는 항상 메모리에서 연속적이다.

      (인라인 함수는 예외)

    - 번역 단위의 소스코드에 나오는 순서대로 함수들이 메모리에 배열된다.

    - 같은 번역 단위 안에 있는 함수들은 거의 대부분 메모리에서 연속적으로 놓인다.

      ( 링커는 여러 번역 단위를 컴파일한 결과물들을 서로 섞어서 놓지 않는다.)

  

  * 성능이 중요한 코드는 가능한 한 기계어 명령어 수가 적어야 한다.

  * 성능에 결정적인 영향을 끼치는 코드에서는 함수 호출을 피애햐 한다.

  * 함수를 반드시 호출해야 하는 경우에는 가능한 현재 함수와 가까운 곳에 배치해야 한다. 다른 번역 단위에 있는 함수를 호출하면 안된다.( 거리를 보장할 수 없기 때문)

  * 인라인 함수를 사용할 때는 조심해야 한다. 인라인 함수는 코드의 크기를 크게 할하기 때문에 결정적 영향을 끼치는 코드가 캐시에 한번에 다 못 들어 가는 경우가 생길 수 있다.



posted by 알쿠미

시작 하는 순서는 하부시스템의 연관성에 따라 묵시적으로 결정된다.

종료하는 순서는 대개 반대로 종료된다.


1. C++ 정적 초기화 순서

  * C++ 에선 정적 객체와 전역 객체가 초기화 되는 순서가 정해져 있지 않다.

    (만약 초기화 순서를 지정할 수 있었다면 싱글턴 클래스 인스턴스를 전역으로 정의해 동적 메모리 할당을 하지 않아도 됐을 것이다.)


2. 주문형 생성

 활용할 수 있는 C++의 트릭이 하나 있는데, 함수 안에서 선언된 정적 변수는 main() 실행 전이 아니라 해당 함수가 처음으로 호출될 때 생성된다는 점이다.


class RenderManager

{

public :

static RenderManager& get()

{

static RenderManager sSingleton;

return sSingleton;

}

}


그리고 동적할당을 이용한 방법

static RenderManager& get()

{

static RenderManager* gpSingleton = NULL;

if ( gpSingleton == NULL)

{

gpSingleton = new RenderManager;

}

ASSERT( gpSingleton );

return *gpSingleton;

}


이 방법을 이용한 간단한 방법은 생성자와 소멸자에선 아무것도 하지 않으며

생성하는 함수와 종료하는 함수를 따로 두어 전역으로 선언한 뒤 Main에서 시작할때 순서대로 실행하는 것이다. 종료도 마찬가지로 반대로 실행한다.


장점

  * 방식이 단순하고 구현하기 쉽다.

  * 명확하다. 코드를 보기만 하면 바로 시작 순서를 알아낼 수 있다.

  * 디버깅하고 유지하기 쉽다. 제때 시작이 안되거나 너무 일찍 시작되는 것이 있으면 코드 한 줄만 이동하면 된다.

'게임 엔진 아키텍처 > 5장 엔진 지원 시스템' 카테고리의 다른 글

문자열  (0) 2016.05.28
자체 구현 컨테이너 클래스 만들기  (0) 2016.05.28
메모리 관리  (0) 2016.05.27
posted by 알쿠미

1. 오일러 - 짐벌락이 있다.

* 짐벌락 - 축들은 종속적이라 회전 하다 축이 같게되면 회전하지 못하는 짐벌락이 발생한다.


2. 행렬

 회전 변환은 가독성이 좋지 않고 저장공간을 많이 차지한다.


3. 사원수

 회전 변환을 결합할 수 있다는 것과 사원수 곱을 통해 점과 벡터를 회전 변환할 수 있다. LERP, SLERP를 이용해서 회전 변환을 보간할 수 있다.


4. 기타 수학 개념

 평면 방정식 = Ax + By + Cz + D = 0

 여기서 A, B, C는 법선 벡터가 된다. 그리고 A, B, C가 정규화 되있다면 D는 평면과 원점사이의 거리가 된다. d 가 양수이면 법선 벡터가 원점을 향하고 음수이면 법선 벡트는 원점에서 멀어지는 방향이다.

 즉 평면은 법선벡터와 원점과의 거리만 있으면 표현할 수 있다.


5. SIMD single instruction multiple data / SSE Streaming SIMD Extension 

  CPU가 기계어 하나로 병렬 연산 하는 것으로 게임 엔진의 수학 라이브러리에서 널리 쓰인다. 자주 쓰이는 연산을 엄청 빠르게 할 수 있다.


6. 난수

 * 메르센 트위스터

  ⓐ 2^19937 - 1 이라는 긴 주기를 갖게 고안됬다.

  ⓑ 매우 높은 동일 분포 차원을 갖는다. 즉 생성된 난수들 사이에 연관성이 거의 없다.

  ⓒ 여러가지 무작위성 테스트를 통과했다

  ⓓ 빠르다.

'게임 엔진 아키텍처 > 4장 게임에 사용되는 수학' 카테고리의 다른 글

사원수  (0) 2016.05.26
행렬  (0) 2016.05.26
벡터  (0) 2016.05.25
posted by 알쿠미

회전변환에 행렬이 최선이 아닌 이유

  * 회전 변환에서는 피치, 요, 롤이 세가지 변수밖에 없는데, 이 것을 표현하기 위해 9개의 부동소수가 필요하다. 낭비다.

  * 벡터를 회전 변환하려면 행렬 곱셈을 해야하는데, 여기에는 3번의 내적 계산 즉 9번의 곱셈과 6번의 덧셈이 필요하다.

  * 두 회전 변환 사이의 주간 회전 변환을 구해야 할 때 행렬로는 중간 지점을 찾기가 힘들다.


1. 3D 회전 변환을 나타내는 단위 길이 사원수

 q = [qv qs] [asin(θ/2) cos(θ/2)]


2. 사원수 연산

 두 사원수가 있을 때 곱셈은 두 사원수의 회전을 합친 것이다.


 pq = [ (psqv + qspv + pv X qv) (psqs - pv*qv) ]


3. 결레와 역

 사원수의 역은 q^(-1) 이라고 쓰고 그 의미는 원래의 값과 곱하면 스칼라 값 1이 되는 사원수를 뜻한다.

 qq^(-1) = 0i + 0j + 0k +1

 켤레 사원수 = [ -qv qs ]

 사원수의 역 = 켤레 사원수 / 크기 절대값의 제곱


 사원수 곱셈에서

 (qp) 의 켤레 사원수는 반대 순서로 둘의 켤레사원수를 곱한것이며 사원수의 역도 반대 순서로 둘의 역을 곱한 것이다.


4. 사원수의 벡터를 이용한 회전

 벡터 v를 사원수로 바꿔쓰면 v = [ vx vy vz 0 ] 이다.

 이것을 회전한 결과는 v' = qvq^(-1) 단위길이라면 역대신 켤레가 들어가도 된다.

 

 회전을 여러번 할때의 사원수 계산은

 q3q2q1vq1^(-1)q2^(-1)q3^(-1)

 

5. 사원수의 계산으로 보간이 가능하다

하지만 회전에서 보간을 하려면 완전하지 선형보간 LERP를 써야하는데 구면 선형 보간 SLERP를 쓰기엔 너무 느리다.


 


'게임 엔진 아키텍처 > 4장 게임에 사용되는 수학' 카테고리의 다른 글

회전 변환 표현간 비교 / 기타 수학 개념  (0) 2016.05.26
행렬  (0) 2016.05.26
벡터  (0) 2016.05.25
posted by 알쿠미

행렬

행렬은 교환 법칙이 성립 하지 않는다. AB != AB


1. 단위 행렬 - 대각선 성분만 1이고 나머지는 0인 벡터


2. 역행렬 - AA' = A'A = 단위행렬

(모든 행렬에 역행렬이 있는 것은 아니다.)

하지만 모든 아핀행렬(회전, 평행이동,스케일, 층밀림 변환으로만 이뤄진 행렬)은 역행렬이 존재한다.

가우스 소거법이나 LU분해법을 이용하면 역행렬이 존재하는 경우에는 역행렬을 찾을 수있다.


3. 전치 행렬

전치 행렬은 대각선기준으로 행렬을 뒤집어 놓은 것이다. 즉, 원래 행렬의 행은 열이되고 열은 행이 되는 것이다.

 ex) 순수한 회전변환 행렬의 역행렬 = 전치행렬이라 자주 이용된다.

(ABC)t = CtBtAt


4. 동차 좌표

3차원 행렬로 3차원 회전은 표현할 수 있지만 평행이동은 표현할 수 없기에 n+1 행렬로 표현한다.


5. 방향 벡터 변환

동차 좌표에서 점의 w값은 1로 해두고 선의 w값은 0으로 해둔다.

즉, 3차원의 순수 방향 벡트는 4차원 동차 좌표에서는 무한대에 있는 점과 같은 역할을 한다.


6. 기본단위 변환 행렬

  ⓐ 평행 이동 _41, _42, _43

  ⓑ 회전 변환

    - x 축 회전은 _22 = cos, _32 = sin, _23 = -sin, _33 = cos

    - y 축 회전은 _11 = cos, _31 = -sin, _13 = sin, _33 = cos

    - z 측 회전은 _11 = cos, _21 = sin, _12 = -sin, _22 = cos

   * 회전 행렬의 3*3 부분의 1은 항상 회전하는 축에 해당하는 성분에 곱해지고 사인과 코사인은 그렇지 않다.

  * y축에 대한 행렬은 다른 행렬에 비교할 때 전치 행렬 같은 모양을 하고 있다.

  * 회전 변환의 역은 전치 행렬과 같다. cos(-θ) = cos(θ) 이고 sin(-θ) = -sin(θ)이기 따라서 각도의 부호를 바꾸면 사인 값은 위치를 서로 바꾼 것과 같고 코사인 값은 변하지 않는다.

  ⓒ 스케일 변환 _11, _22, _33



'게임 엔진 아키텍처 > 4장 게임에 사용되는 수학' 카테고리의 다른 글

회전 변환 표현간 비교 / 기타 수학 개념  (0) 2016.05.26
사원수  (0) 2016.05.26
벡터  (0) 2016.05.25
posted by 알쿠미

벡터

1. 벡터 연산


방향 + 방향 = 방향

방향 - 방향 = 방향

점 + 방향 = 점

점 - 점 =  방향

점 + 점 = 성립되지 않음

2. 벡터 크기 = 피타고라스의 정리를 이용하면 구할 수 있다.


3. 정규화와 단위 벡터

벡터 / 벡터 크기


4. 법선 벡터 ( 어떤 평면에 수직인 벡터를 법선 벡터라고 한다.)

 - 어떤 면과 그 면에 비치는 빛의 상대적인 각도를 계산하는데 사용된다.


5. 벡터 내적과 투영

 * 벡터 내적( Dot Product , 스칼라 곱)

 * 벡터 외적( Cross Product, 벡터 곱)


a*b = abx + aby + abz = d 스칼라 값 = IaIIbI cos()

a*b = b*a , sa*b = s(a*b)


6. 벡터 투영

벡터가 단위 벡터 일때, 어떤 벡터 a와 u의 내적은 a를 u방향의 무한히 긴 선에 투영한 크기가 된다.


7 내적으로 알아낼 수 있는것

 내적을 이용하면 두 벡터가 평행인지, 수직인지를 알 수 있고, 두 벡터가 가리키는 방향이 비슷한지 아니면 반대인지를 알 수 있다.

 - 평행이면서 같은 방향 벡터 (a * b) = IaIIbI = ab 이면 평행이면서 같은 방향벡터

 - 평행이면서 같은 방향 벡터 (a * b) = IaIIbI = -ab 이면 평행이면서 반대 방향벡터

 - 수직인 벡터는 (a * b) = 0 (두 벡터가 이루는 각이 90도)

 - 같은 방향인 벡터 (a * b) > 0 ( 두 벡터가 이루는 각이 90도 미만)

 - 다른 방향 벡터 ( a * b) < 0 ( 두 벡터가 이루는 각이 90도 보다 크다)


기타 내적의 활용

 - 평면과 점의 거리

 평면에 임의점 q를 잡고 거리를 알고자 하는 점과 벡터를 만들어서 평면의 법선 벡터에 투영하면 된다.


8. 벡터 외적

 두 벡터 외적의 결과는 두 개의 벡터와 수직인 벡터이다. 3차원에서가능

aXb = [(aybz - azby), (azbx - axbz), (axby- aybx)]


외적 벡터의 크기는 두 벡터의 크기 곱하기 두벡터 각도의 sin값이다.


외적 벡터의 방향은 손 좌표계를 따른다.


9. 외적의 활용

 두 벡터의 수직인 벡터, 평면에 수직인 벡터, 토크 N = r X F다.


10. 점과 벡터의 선형 보간

 L = LERP(A, B, k) = (1-k)A + kB

두개의 알려진 지점 사이의 중간 값을 계산 하는 수리연산


'게임 엔진 아키텍처 > 4장 게임에 사용되는 수학' 카테고리의 다른 글

회전 변환 표현간 비교 / 기타 수학 개념  (0) 2016.05.26
사원수  (0) 2016.05.26
행렬  (0) 2016.05.26
posted by 알쿠미

1. 에러 리턴코드 맨 처음 에러를 감지한 함수에서 특정한 에러 코드를 리턴하게 하는 방법


2. 예외 처리

에러처리 함수를 사용하려면 콜스택을 거슬러 내려가서 에러처리 함수까지 가야할수도 있다.

SEH(Structured Exception Handling)  위와 같은 일을 하지 않고 에러를 전달한다.

에러가 발생하면 예외 객차라는 자료 구조에 정보를 넣고 콜 스택을 자동으로 펼쳐 try - catch 블록을 찾았을 경우 예외 객체를 처리할 수있는 catch를 찾고 스택이 펼쳐지면서 자동 변수들의 파괴자는 자동으로 호출된다.


하지만 SEH는 프로그램에 많은 부담을 주므로 게임에선 사용하기 힘들다.


3. Assert

GPG에 비슷한 내용이 있다.

'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

객체 메모리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
posted by 알쿠미

클래스 정적멤버


static 키워드란?

* 파일 범위에서 사용하면 변수가 다른 cpp에서 보이지 않고 사용되지 못하게 하고 오직 그 cpp에서만 보이게 된다.


* 함수 범위에서 사용하면 변수가 전역 변수이고 자동 변수가 아니지만 그 함수안에서만 보이게 한다.


* 구조체와 클래스 선언에서 사용하면 변수가 보통 멤버 변수가 아니라 전역 변수처럼 동작한다.


클래스에서 쓰인 static 키워드는 변수의 보이는 범위를 지정하지는 않는다.

대신 일반적인 멤버 변수처럼 각 인스턴스마다 존재할지, 아니면 클래스에만 존재해서 전역 변수 처럼 쓰일지 지정한다.


보이는 범위는 public, protected, private 키워드를 통해 결정된다.

클래스 전역변수는 클래스 네임스페이스에 포함되기 때문에 클래스 이름을 함께 사용해야 한다.

클래스 정적 변수를 위한 메모리는 반드시 cpp파일에 정의돼야 한다.


F32 Foo::sClassStatic = -1.0f; // 이런식으로 메모리 할당



1. 메모리 상의 객체 구조

struct Foo

{

U32 mUnsignedvalue;

F32 mFloatValue;

bool mSignedValue;

};


 +0x0

 mUnsignedvalue

 +0x4

 mFloatValue

 +0x8

 mBlooleanValue


2. 메모리 정렬과 패킹

1. 바이트 정렬 객체는 어떤 메모리 주소에도 올 수 있다.

2. 2바이트 정렬 객체는 짝수인 주소에만 올 수 있다.

3. 4바이트 정렬 객체는 4의 배수가 되는 주소에만 올 수 있다.

4. 16바이트 정렬 객체는 16의 배수가 되는 주소에만 올 수 있다.


* 메모리 정렬이 중요한 이유는 메모리 정렬이 제대로 지켜진 데이터 블록만 읽고 쓸 수 있기 때문이다.


* 구조체 전체를 놓고 봤을 때는 멤버의 정렬 조건중 가장 큰 것이 그 구조체의 정렬 조건이 된다. 남는 메모리는 컴파일러가 패딩으로 채운다.


3. C++ 클래스의 메모리 구조

+0x0

+sizeof(A)

메모리 구조 관점에서 보면 C++클래스는 상속과 가상 함수 때문에 메모리가 더 붙는다. 각 클래스 사이에도 메모리 정렬조건 때문에 패딩이 들어갈 수 있다.


가상함수가 있다면 가상함수테이블을 가리키는 vptr포인터 4바이트가 추가되고

이 vtable은 이 클래스가 선언하거나 상속하는 모든 가상 함수를 가리키는 포인터를 갖고 있다.





'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

에러감지와 처리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
posted by 알쿠미

1. 실행파일 이미지

C/C++ 프로그램은 링커가 실행 파일을 만들면서 완성된다.


1. 텍스트 세그먼트

  - 코드 세그먼트라고 불린다. 프로그램에서 정의한 모든 함수의 기계어를 담고 있다.


2. 데이터 세그먼트 

  - 초기 값을 가진 전역 및 정적 변수가 자리한다.

  - 이 형태대로 프로그램이 실행 될 때 메모리에 배치되고 값들은 지정한 대로 초기화 돼있다. 따라서 실행 파일이 메모리에 로드될 때 전역변수와 정적 변수는 바로 사용할 수있다.


3. BSS 세그먼트 (block started by symbol)

  - 초기화 되지 않은 모든 전역변수와 정적변수가 자리한다.

  - C/C++에서는 초기화 되지 않은 전역변수와 정적변수가 0으로 초기화 되는데 몇개가 될지 모르는 0의 값들을 무작정 들고 있기 보다는 링커는 얼마나 많은 마이트의 0이 있는지만 기록한다.

  - 운영체제는 실행 파일이 메모리에 로드돼 시작점이 불리기 직전에 이 값을 보고 공간을 할당하고 0으로 채운다.


4. 읽기 전용 데이터 세그먼트

  - 읽기 전용(constant)인 전역 데이터가 자리한다. 부동 소수인 상수나, const 키워드로 정의된 전역 인스턴스 등이 여기에 해당한다.

  - 정수 타입인 상수는 매니페스트 상수처럼 취급돼 사용되는 기계어 코드위치에 직접 삽입되는 경우가 대부분이다.


5. 프로그램 스택

  - 프로그램이 메모리에 로드될 때 운영체제는 프로그램 스택이라는 메모리 공간을 마련한다.

  - 스택 프레임에는 세가지 종류가 저장된다.

   ⓐ 리턴주소 - 해당 함수를 호출한 곳(호출한 함수)의 주소인데, 이 함수가 리턴한 후 다음 실행될 프로그램 위치다.

   ⓑ CPU 레지스터 - 함수가 호출되기 이전의 레지스터 값들을 스택에 저장함으로써 함수는 이전의 상태를 훼손할 염려없이 레지스터를 자유롭게 사용할 수 있다.

   ⓒ 지역 변수 - 호출된 함수의 지역 변수들은 스택에 자리한다.


6. 동적 할당 힙

 동적으로 할당된 메모리는 힙에 올라간다. 6장에서 좀더 자세하게 다룬다.

'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

에러감지와 처리  (0) 2016.05.24
객체 메모리  (0) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
posted by 알쿠미