Skip to content

Commit 71bf897

Browse files
committed
ko-translate memory
1 parent 45860e6 commit 71bf897

File tree

7 files changed

+43
-43
lines changed

7 files changed

+43
-43
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Memory Allocation
1+
# 메모리 할당
22

3-
Being an explicit API, [allocating memory](https://docs.vulkan.org/guide/latest/memory_allocation.html) in Vulkan that can be used by the device is the application's responsibility. The specifics can get quite complicated, but as recommended by the spec, we shall simply defer all that to a library: [Vulkan Memory Allocator (VMA)](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator).
3+
명시적인 API인 Vulkan에서는 디바이스가 사용할 메모리를 애플리케이션이 직접 [메모리 할당](https://docs.vulkan.org/guide/latest/memory_allocation.html)을 해야 합니다. 이 과정은 다소 복잡할 수 있기 때문에, Vulkan 사양에서 권장하듯이 이 모든 세부 사항을 [Vulkan Memory Allocator (VMA)](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)에 맡겨 간단하게 처리할 것입니다.
44

5-
Vulkan exposes two kinds of objects that use such allocated memory: Buffers and Images, VMA offers transparent support for both: we just have to allocate/free buffers and images through VMA instead of the device directly. Unlike memory allocation / object construction on the CPU, there are many more parameters (than say alignment and size) to provide for the creation of buffers and images. As you might have guessed, we shall constrain ourselves to a subset that's relevant for shader resources: vertex buffers, uniform/storage buffers, and texture images.
5+
Vulkan은 할당된 메모리를 사용하는 두 가지 객체 유형을 제공합니다. 버퍼와 이미지입니다. VMA는 이 둘에 대해 투명한(transparent) 지원을 제공합니다. 우리는 그저 버퍼와 이미지를 디바이스를 통해 직접 할당하는 대신, VMA를 통해 할당 및 해제하면 됩니다. CPU에서의 메모리 할당과 객체 생성과는 달리, Vulkan에는 버퍼와 이미지 생성에는 정렬(alignment)이나 크기(size) 외에도 훨씬 더 많은 파라미터가 필요합니다. 예상하셨겠지만, 여기서는 정점 버퍼, 유니폼/스토리지 버퍼, 그리고 텍스쳐 이미지와 같은 셰이더 자원과 관련된 하위 집합만을 다룰 예정입니다.

guide/translations/ko-KR/src/memory/buffers.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Buffers
1+
# 버퍼
22

3-
First add the RAII wrapper components for VMA buffers:
3+
먼저 VMA 버퍼를 위한 RAII 래퍼 컴포넌트를 추가합니다.
44

55
```cpp
66
struct RawBuffer {
@@ -28,7 +28,7 @@ void BufferDeleter::operator()(RawBuffer const& raw_buffer) const noexcept {
2828
}
2929
```
3030
31-
Buffers can be backed by host (RAM) or device (VRAM) memory: the former is mappable and thus useful for data that changes every frame, latter is faster to access for the GPU but needs more complex methods to copy data to. Add the related types and a create function:
31+
버퍼는 호스트(RAM)와 디바이스(VRAM) 메모리를 기반으로 할당될 수 있습니다. 호스트 메모리는 매핑이 가능하므로 매 프레임마다 바뀌는 정보를 담기에 적합하며, 디바이스 메모리는 GPU에서 접근하기에 빠르지만 데이터를 복사하는 데 더 복잡한 절차가 필요합니다. 이를 고려하여 관련된 타입과 생성 함수를 추가하겠습니다.
3232
3333
```cpp
3434
struct BufferCreateInfo {

guide/translations/ko-KR/src/memory/command_block.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Command Block
22

3-
Long-lived vertex buffers perform better when backed by Device memory, especially for 3D meshes. Data is transferred to device buffers in two steps:
3+
오래 유지되는 정점 버퍼의 경우 디바이스 메모리에 위치하는 편이 더 나은 성능을 보입니다. 특히 3D 메시와 같은 경우에 그렇습니다. 데이터를 디바이스 버퍼로 전송하려면 두 단계가 필요합니다.
44

5-
1. Allocate a host buffer and copy the data to its mapped memory
6-
1. Allocate a device buffer, record a Buffer Copy operation and submit it
5+
1. 호스트 버퍼를 할당하고 데이터를 매핑된 메모리로 복사합니다.
6+
2. 디바이스 버퍼를 할당하고 메모리 복사 명령을 기록한 뒤, 이를 제출합니다.
77

8-
The second step requires a command buffer and queue submission (_and_ waiting for the submitted work to complete). Encapsulate this behavior into a class, it will also be used for creating images:
8+
두 번째 단계는 커맨드 버퍼와 큐 제출이 필요하며, 제출된 작업이 완료될 때까지 기다려야 합니다. 이 동작을 클래스로 캡슐화하겠습니다. 이 구조는 이미지를 생성할때에도 쓰일 수 있습니다.
99

1010
```cpp
1111
class CommandBlock {
@@ -26,7 +26,7 @@ class CommandBlock {
2626
};
2727
```
2828
29-
The constructor takes an existing command pool created for such ad-hoc allocations, and the queue for submission later. This way it can be passed around after creation and used by other code.
29+
이 클래스의 생성자는 임시 할당용으로 미리 생성된 커맨드 풀과, 나중에 명령을 제출할 큐를 인자로 받습니다. 이렇게 하면 해당 객체를 생성 후 다른 코드로 전달해 재사용할 수 있습니다.
3030
3131
```cpp
3232
CommandBlock::CommandBlock(vk::Device const device, vk::Queue const queue,
@@ -50,7 +50,7 @@ CommandBlock::CommandBlock(vk::Device const device, vk::Queue const queue,
5050
}
5151
```
5252

53-
`submit_and_wait()` resets the unique command buffer at the end, to free it from its command pool:
53+
`submit_and_wait()`은 커맨드 버퍼의 작업이 끝난 뒤 리셋하여 커맨드 풀로 반환합니다.
5454

5555
```cpp
5656
void CommandBlock::submit_and_wait() {
@@ -77,8 +77,8 @@ void CommandBlock::submit_and_wait() {
7777
}
7878
```
7979

80-
## Multithreading considerations
80+
## 멀티쓰레딩 시 고려사항
8181

82-
Instead of blocking the main thread on every Command Block's `submit_and_wait()`, you might be wondering if command block usage could be multithreaded. The answer is yes! But with some extra work: each thread will require its own command pool - just using one owned (unique) pool per Command Block (with no need to free the buffer) is a good starting point. All queue operations need to be synchronized, ie a critical section protected by a mutex. This includes Swapchain acquire/present calls, and Queue submissions. A `class Queue` value type that stores a copy of the `vk::Queue` and a pointer/reference to its `std::mutex` - and wraps the submit call - can be passed to command blocks. Just this much will enable asynchronous asset loading etc, as each loading thread will use its own command pool, and queue submissions all around will be critical sections. `VmaAllocator` is internally synchronized (can be disabled at build time), so performing allocations through the same allocator on multiple threads is safe.
82+
"`submit_and_wait()`를 호출할 때마다 메인 쓰레드를 블록하는 대신, 멀티쓰레드로 CommandBlock을 구현하는 편이 낫지 않을까?" 라고 생각하실 수 있습니다. 맞습니다! 하지만 멀티 쓰레딩을 위해서는 몇 가지 추가 작업이 필요합니다. 각 쓰레드가 고유한 커맨드 풀이 필요합니다. CommandBlock마다 하나의 고유한 커맨드 풀을 사용하며, 임계 영역을 뮤텍스로 보호하는 것, 스왑체인으로부터 이미지를 가져오고 표시하는 작업 등 큐에 대한 모든 작업은 동기화되어야 합니다. 이를 위해 `vk::Queue`객체와 해당 큐를 보호하는 `std::mutex` 포인터 혹은 참조를 보관하는 `class Queue`를 설계할 수 있으며, 큐 제출은 이 클래스를 통해 수행할 것입니다. 이렇게 하면 각 에셋을 불러오는 쓰레드가 고유한 커맨드 풀을 사용하면서도 큐 제출은 안전하게 이루어질 수 있습니다. `VmaAllocator`는 내부적으로 동기화되어 있으며, 빌드 시 동기화를 끌 수도 있지만 기본적으로는 멀티쓰레드 환경에서 안전하게 사용할 수 있습니다.
8383

84-
For multi-threaded rendering, use a Secondary command buffer per thread to record rendering commands, accumulate and execute them in the main (Primary) command buffer currently in `RenderSync`. This is not particularly helpful unless you have thousands of expensive draw calls and dozens of render passes, as recording even a hundred draws will likely be faster on a single thread.
84+
멀티쓰레드 렌더링을 구현하려면 각 쓰레드에서 Secondary 커맨드 버퍼에 렌더링 명령을 기록한 후, 이를 Primary 커맨드 버퍼로 모아 `RenderSync`에서 실행할 수 있습니다. 다만 수백개의 드로우콜 정도는 하나의 쓰레드에서 처리하는 편이 더 빠르기 때문에, 수천개의 비싼 드로우콜과 수십개의 렌더패스를 사용하지 않는 한 사용할 일이 없습니다.

guide/translations/ko-KR/src/memory/device_buffers.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Device Buffers
1+
# 디바이스 버퍼
22

3-
This guide will only use device buffers for vertex buffers, where both vertex and index data will be strung together in a single VBO. The create function can thus take the data and perform the buffer copy operation before returning. In essence this return value is a "GPU const" buffer. To enable utilizing separate spans for vertices and indices (instead of forcing allocation of a contiguous bytestream and copying the data), the create function takes a slightly awkward span of spans:
3+
여기서는 정점 버퍼에 디바이스 버퍼만을 사용합니다. 정점과 인덱스 정보를 하나의 VBO로 묶어 사용할 것입니다. 따라서 생성 함수는 데이터를 받아 버퍼 복사를 수행한 후 반환합니다. 기본적으로 반환값은 "GPU 상수" 버퍼일 것입니다. 정점과 인덱스 데이터를 하나의 연속된 바이트로 강제로 묶는 대신, 각 데이터를 별도의 범위로 사용할 수 있도록 생성 함수는 span을 인자로 받습니다.
44

55
```cpp
66
// disparate byte spans.
@@ -12,7 +12,7 @@ using ByteSpans = std::span<std::span<std::byte const> const>;
1212
ByteSpans const& byte_spans) -> Buffer;
1313
```
1414
15-
Implement `create_device_buffer()`:
15+
`create_device_buffer()`는 다음과 같습니다.
1616
1717
```cpp
1818
auto vma::create_device_buffer(BufferCreateInfo const& create_info,
@@ -62,7 +62,7 @@ auto vma::create_device_buffer(BufferCreateInfo const& create_info,
6262
}
6363
```
6464

65-
Add a command block pool to `App`, and a helper function to create command blocks:
65+
`App`에 command block pool을 추가하고 commandblock을 생성하는 함수를 추가합니다.
6666

6767
```cpp
6868
void App::create_cmd_block_pool() {
@@ -80,7 +80,7 @@ auto App::create_command_block() const -> CommandBlock {
8080
}
8181
```
8282

83-
Update `create_vertex_buffer()` to create a quad with indices:
83+
`create_vertex_buffer()`를 업데이트하여 사각형을 생성하도록 합니다.
8484

8585
```cpp
8686
template <typename T>
@@ -115,7 +115,7 @@ void App::create_vertex_buffer() {
115115
}
116116
```
117117
118-
Update `draw()`:
118+
`draw()`함수를 이에 맞춰 변경합니다.
119119
120120
```cpp
121121
void App::draw(vk::CommandBuffer const command_buffer) const {

guide/translations/ko-KR/src/memory/images.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Images
1+
# 이미지
22

3-
Images have a lot more properties and creation parameters than buffers. We shall constrain ourselves to just two kinds: sampled images (textures) for shaders, and depth images for rendering. For now add the foundation types and functions:
3+
이미지는 버퍼보다 훨씬 더 많은 속성과 생성 파라미터를 가지고 있습니다. 여기서는 두 종류로 나누겠습니다. 셰이더에서 샘플링될 이미지(텍스쳐), 그리고 렌더링에 사용할 깊이 이미지입니다. 지금은 이러한 이미지를 위한 기본 타입과 함수만 추가하겠습니다.
44

55
```cpp
66
struct RawImage {
@@ -31,7 +31,7 @@ struct ImageCreateInfo {
3131
-> Image;
3232
```
3333
34-
Implementation:
34+
구현은 다음과 같습니다.
3535
3636
```cpp
3737
void ImageDeleter::operator()(RawImage const& raw_image) const noexcept {
@@ -82,7 +82,7 @@ auto vma::create_image(ImageCreateInfo const& create_info,
8282
}
8383
```
8484

85-
For creating sampled images, we need both the image bytes and size (extent). Wrap that into a struct:
85+
샘플링할 이미지(텍스쳐)를 생성하기 위해 이미지 바이트 데이터와 크기(extent)가 필요합니다. 이를 구조체로 감싸 사용하겠습니다.
8686

8787
```cpp
8888
struct Bitmap {
@@ -91,12 +91,12 @@ struct Bitmap {
9191
};
9292
```
9393
94-
The creation process is similar to device buffers: requiring a staging copy, but it also needs layout transitions. In short:
94+
생성 과정은 디바이스 버퍼와 유사합니다. 스테이징 버퍼를 복사하고, 레이아웃 전환을 수행해야 합니다. 요약하면 다음과 같습니다.
9595
96-
1. Create the image and staging buffer
97-
1. Transition the layout from Undefined to TransferDst
98-
1. Record a buffer image copy operation
99-
1. Transition the layout from TransferDst to ShaderReadOnlyOptimal
96+
1. 이미지와 스테이징 버퍼를 생성합니다.
97+
2. 이미지의 레이아웃을 Undefined에서 TransferDst로 전환합니다.
98+
3. 버퍼에서 이미지로 복사하는 명령을 기록합니다.
99+
4. 이미지의 레이아웃을 TransferDst에서 ShaderReadOnlyOptimal로 변경합니다.
100100
101101
```cpp
102102
auto vma::create_sampled_image(ImageCreateInfo const& create_info,
@@ -181,4 +181,4 @@ auto vma::create_sampled_image(ImageCreateInfo const& create_info,
181181
}
182182
```
183183

184-
Before such images can be used as textures, we need to set up Descriptor Set infrastructure.
184+
이미지를 텍스쳐로 사용하기 전에 디스크립터 셋을 구성해야 합니다.

guide/translations/ko-KR/src/memory/vertex_buffer.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Vertex Buffer
1+
# 정점 버퍼
22

3-
The goal here is to move the hard-coded vertices in the shader to application code. For the time being we will use an ad-hoc Host `vma::Buffer` and focus more on the rest of the infrastructure like vertex attributes.
3+
여기서의 목표는 셰이더에 하드코딩되어 있던 정점 정보를 애플리케이션 코드로 옮기는 것입니다. 당분간은 임시로 호스트 메모리에 위치한 `vma::Buffer`를 사용하고, 정점 속성과 같은 나머지 구조에 더 집중하겠습니다.
44

5-
First add a new header, `vertex.hpp`:
5+
먼저 새로운 헤더 `vertex.hpp`를 추가합니다.
66

77
```cpp
88
struct Vertex {
@@ -28,7 +28,7 @@ constexpr auto vertex_bindings_v = std::array{
2828
};
2929
```
3030
31-
Add the vertex attributes and bindings to the Shader Create Info:
31+
ShaderCreateInfo에 정점 속성과 바인딩 정보를 추가합니다.
3232
3333
```cpp
3434
// ...
@@ -46,7 +46,7 @@ auto const shader_ci = ShaderProgram::CreateInfo{
4646
// ...
4747
```
4848

49-
With the vertex input defined, we can update the vertex shader and recompile it:
49+
정점 입력이 정의되었으므로 정점 셰이더를 업데이트하고 다시 컴파일합니다.
5050

5151
```glsl
5252
#version 450 core
@@ -64,7 +64,7 @@ void main() {
6464
}
6565
```
6666

67-
Add a VBO (Vertex Buffer Object) member and create it:
67+
VBO(Vertex Buffer Object) 멤버를 추가하고, 해당 버퍼를 생성합니다.
6868

6969
```cpp
7070
void App::create_vertex_buffer() {
@@ -89,7 +89,7 @@ void App::create_vertex_buffer() {
8989
}
9090
```
9191

92-
Bind the VBO before recording the draw call:
92+
드로우 콜을 기록하기 전에 VBO를 바인딩합니다.
9393

9494
```cpp
9595
// single VBO at binding 0 at no offset.
@@ -99,6 +99,6 @@ command_buffer.bindVertexBuffers(0, m_vbo->get_raw().buffer,
9999
command_buffer.draw(3, 1, 0, 0);
100100
```
101101

102-
You should see the same triangle as before. But now we can use whatever set of vertices we like! The Primitive Topology is Triange List by default, so every three vertices in the array is drawn as a triangle, eg for 9 vertices: `[[0, 1, 2], [3, 4, 5], [6, 7, 8]]`, where each inner `[]` represents a triangle comprised of the vertices at those indices. Try playing around with customized vertices and topologies, use Render Doc to debug unexpected outputs / bugs.
102+
아마 이전과 동일한 삼각형을 볼 수 있을 것입니다. 하지만 이제는 원하는 정점 데이터를 자유롭게 사용할 수 있습니다. 프리미티브 토폴로지는 기본적으로 Triangle List로 설정하며, 정점 배열에서 매 3개의 정점이 삼각형으로 그려질 것입니다. 예를 들어 정점 9개가 `[[0, 1, 2], [3, 4, 5], [6, 7, 8]]` 있다면, 각 3개의 정점이 하나의 삼각형을 형성하게 됩니다. 정점 데이터와 토폴로지를 다양하게 바꿔보며 실험해 보세요. 예상치 못한 출력이나 버그가 발생한다면 RenderDoc을 사용해 디버깅할 수 있습니다.
103103

104-
Host Vertex Buffers are useful for primitives that are temporary and/or frequently changing, such as UI objects. A 2D framework can use such VBOs exclusively: a simple approach would be a pool of buffers per virtual frame where for each draw a buffer is obtained from the current virtual frame's pool and vertices are copied in.
104+
호스트 정점 버퍼는 UI 객체처럼 임시로 쓰이거나 자주 변경되는 프리미티브에 유용합니다. 2D 프레임워크에서는 이러한 VBO를 독점적으로 사용하는 것도 가능합니다. 예를 들어, 가상 프레임마다 별도의 버퍼 풀을 두고, 각 드로우마다 현재 프레임의 풀에서 버퍼를 하나 가져와 정점을 복사하는 방식이 단순하면서도 효과적입니다.

guide/translations/ko-KR/src/memory/vma.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Vulkan Memory Allocator
22

3-
VMA has full CMake support, but it is also a single-header library that requires users to "instantiate" it in a single translation unit. Isolating that into a wrapper library to minimize warning pollution etc, we create our own `vma::vma` target that compiles this source file:
3+
VMA는 CMake를 완벽히 지원하지만, 단일 번역 단위에서 정의(instantiate)되어야 하는 단일 헤더 라이브러리이기도 합니다. 이를 관리하기 위해 고유한 `vma::vma` 타겟을 직접 생성하여 소스 파일을 컴파일하겠습니다.
44

55
```cpp
66
// vk_mem_alloc.cpp
@@ -9,7 +9,7 @@ VMA has full CMake support, but it is also a single-header library that requires
99
#include <vk_mem_alloc.h>
1010
```
1111

12-
Unlike VulkanHPP, VMA's interface is C only, thus we shall use our `Scoped` class template to wrap objects in RAII types. The first thing we need is a `VmaAllocator`, which is similar to a `vk::Device` or `GLFWwindow*`:
12+
VulkanHPP와는 달리 VMA는 C만을 지원합니다. 따라서 RAII 방식으로 관리하기 위해 `Scope`클래스 템플릿을 사용할 것입니다. 가장 먼저 필요한 것은 `VmaAllocator`으로, 이는 `vk::Device` 혹은 `GLFWwindow*`와 유사한 역할을 합니다.
1313

1414
```cpp
1515
// vma.hpp
@@ -53,7 +53,7 @@ auto vma::create_allocator(vk::Instance const instance,
5353
}
5454
```
5555
56-
`App` stores and creates a `vma::Allocator` object:
56+
`App``vma::Allocator` 객체를 생성하고 이를 보관합니다.
5757
5858
```cpp
5959
// ...

0 commit comments

Comments
 (0)