일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 26 |
27 | 28 | 29 | 30 |
- 팩터리 메서드
- 단순한 빌더
- 내부 팩터리
- 프로토타입
- 동적 데코레이터
- 싱글턴 패턴
- 브릿지 패턴
- 싱글톤
- 데커레이터
- 빌더 패턴
- 디자인 패턴
- 그루비 스타일 빌더
- 모던C++디자인패턴
- 동적 데커레이터
- 컴포지트
- 싱글톤 패턴
- 컴포지트 패턴
- 컴포지트 빌더
- 추상 팩터리
- 프로토타입 중복처리
- 팩터리 패턴
- 브릿지
- 빌더
- 팩터리
- 프로토타입 패턴
- 디자인패턴
- 싱글턴
- 흐름식 빌더
- 함수형 팩터리
- 데커레이터 패턴
- Today
- Total
GGym's Practice Notes
1. 삼각형 그리기 _ 1) 설정 /기본 코드 - Vulkan Tutorial 본문
일반적인 구조
이번 챕터는 이전 챕터 마지막의 예제에서부터 시작합니다.
#include <vulkan/vulkan.h>
#include <iostream>
#include <stdexcept>
#include <functional>
#include <cstdlib>
class HelloTriangleApplication {
public:
void run() {
initVulkan();
mainLoop();
cleanup();
}
private:
void initVulkan() {
}
void mainLoop() {
}
void cleanup() {
}
};
int main() {
HelloTriangleApplication app;
try {
app.run();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
먼저 vulkan 헤더를 포함하여 함수, 구조, 열거형을 제공합니다. iostream, stdexcept 헤더는 오류 보고 및 전파를 위해 포함시킵니다. funcional 헤더는 자원 관리 부분의 람다 기능에 사용됩니다. ctdlib 헤더는 EXIT_SUCCESS와 EXIT_FAILURE 매크로를 제공합니다.
프로그램 자체는 Vulkan 객체를 private 클래스 멤버로 저장하고 각 개체를 초기화하는 함수를 추가하여 래핑되며 initVulkan 함수에서 호출됩니다. 모든것이 준비되면 mainLoop에 들어가 렌더링 프레임을 시작합니다. 우리는 mainLoop함수에 창을 닫을 때까지 반복되는 루프를 작성합니다. 창이 닫히고 mainLoop가 반환되면 사용한 자원들을 cleanup 함수에서 해제 해야 합니다.
실행 중에 치명적인 오류가 발생하면 설명 메세지와 함께 std::runtime_error 예외를 발생시키고 main 함수를 거쳐 명령 프롬프트에 인쇄됩니다. 다양한 표준 예외 유형도 처리하기 위해 보다 일반적인 std::exception 을 catch 합니다. 곧 처리할 오류의 한 예는 특정 필수 확장이 지원되지 않는 것을 발견하는 것 입니다.
이번 챕터 뒤에 나오는 거의 모든 챕터는 initVulkan 에서 호출 될 하나의 새로운 함수와 하나 이상의 새로운 Vulkan 오브젝트를 정리 종료시 해제 해야하는 private 클래스 멤버에 추가합니다.
자원 관리
malloc 으로 할당한 각 메모리를 해제해야 하는 것처럼 우리가 생성하는 모든 Vulkan 객체는 더 이상 필요하지 않을때 명시적으로 제거해야 합니다. 최신 C++코드에서는 memory 헤더의 유틸리티를 통해 자동으로 자원 관리를 수행 할 수 있지만 이 자습서에서는 Vulkan 객체의 할당 및 할당 해제에 대해 명시적으로 할 것입니다. 결국 Vulkan을 사용하는데 실수를 피하기 위해서 모든 작업을 분명하게 알고, API의 작동방식을 배우기 위해 객체의 수명에 대하여 아는 것이 좋습니다.
이 자습서를 수행하고 std::shared_ptr 을 오버로드 하여 자동 자원 관리를 구현할 수 있습니다. 대규모 Vulkan 프로그램의 경우 RAII를 이점으로 사용하는 것이 권장되지만 학습 목적으로 항상 후에 진행되는 일에 대하여 아는 것이 좋습니다.
Vulkan 객체는 vkCreate___ 와 같은 기능으로 직접 생성되거나 vkAllocate___ 와 같은 기능으로 다른 객체를 통해 할당 됩니다. 객체가 더이상 어디에서도 사용되지 않는다는 것을 확인한 후에는 vkDestroy___ 와 vkFree___ 를 사용하여 객체를 제거해야 합니다. 이러한 함수의 매개 변수는 일반적으로 개체 유형에 따라 다르지만 모두 공유하는 매개 변수는 pAllocator 입니다. 이 매개변수는 사용자 정의 메모리 할당 자에 대한 콜백을 지정할 수 있는 선택적 매개 변수입니다. 튜토리얼에서는 이 매개변수를 무시하고 항상 nullptr을 인수로 전달합니다.
GLFW 통합
Vulkan은 off-screen 렌더링을 사용하려는 경우 창을 만들지 않고도 완벽하게 작동합니다. #include<vulkan/vulkan.h> 줄을 다음과 같이 바꾸세요.
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
이렇게 하면 GLFW는 자체 정의를 포함하고 Vulkan 헤더를 자동으로 로드합니다. initWindow 함수를 추가하고 다른 함수를 호출하기 전에 run 함수에 initWindow 를 호출하세요.
void run() {
initWindow();
initVulkan();
mainLoop();
cleanup();
}
private:
void initWindow() {
}
initWindow의 첫번째 호출은 GLFW 라이브러리를 초기화하는 glfwInit() 이어야 합니다. GLFW는 원래 OpenGL 문맥을 작성하도록 설계되었으므로 후속 호출로 OpenGL 문맥을 작성하지 않도록 지시해야 합니다.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
크기가 조정된 창을 처리하는 것은 나중에 살펴볼 것이기 때문에 다른 호출로 비활성화 하세요.
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
이제 남은 것은 실제 창을 만드는 것입니다. private 클래스 멤버로 GLFWwindow* window 를 추가하고 다음처럼 창을 초기화 하세요.
window = glfwCreateWindow(800, 600, "Vulkan", nullptr, nullptr);
이제 다음과 같이 initWindow 함수가 있어야 합니다.
void initWindow() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
}
오류가 발생하거나 창이 닫힐 때까지 응용 프로그램을 계속 실행하려면 다음과 같이 mainLoop 함수에 이벤트 루프를 추가해야 합니다.
void mainLoop() {
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
}
이 코드는 따로 설명이 필요없습니다. 사용자가 X 버튼을 누르거나 창을 닫는 이벤트를 반복해서 확인합니다. 이것은 단일 프레임 렌더링 함수를 호출하는 루프이기도 합니다.
창이 닫히면 자원을 제거하고 GLFW 자체를 종료하여 자원을 정리해야 합니다. 이것은 첫 번째 cleanup 코드입니다.
void cleanup() {
glfwDestroyWindow(window);
glfwTerminate();
}
이제 프로그램을 실행하면 창을 닫아 응용프로그램을 종료할때 까지 Vulkan이라는 제목의 창이 나타납니다. 이제 Vulkan 응용 프로그램의 기본 구조를 갖추었으므로 첫 번째 Vulkan 객체를 만들어 봅시다.
아래는 여기까지 작성된 코드입니다.
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
const int WIDTH = 800;
const int HEIGHT = 600;
class HelloTriangleApplication {
public:
void run() {
initWindow();
initVulkan();
mainLoop();
cleanup();
}
private:
GLFWwindow* window;
void initWindow() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
}
void initVulkan() {
}
void mainLoop() {
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
}
void cleanup() {
glfwDestroyWindow(window);
glfwTerminate();
}
};
int main() {
HelloTriangleApplication app;
try {
app.run();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
'Vulkan' 카테고리의 다른 글
Vulkan/GLFW/GLM 개발환경 세팅하기 (Windows/VS2017) (0) | 2020.01.19 |
---|