Skip to content

Commit f7c916f

Browse files
committed
Code optimization for indirect drawing
1 parent b91dd70 commit f7c916f

File tree

3 files changed

+133
-117
lines changed

3 files changed

+133
-117
lines changed

chapter-20/src/main/java/org/lwjglb/engine/graph/Render.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public void resize(int width, int height) {
7979
public void setupData(Scene scene) {
8080
renderBuffers.loadStaticModels(scene);
8181
renderBuffers.loadAnimatedModels(scene);
82-
sceneRender.setupMaterialsUniform(scene.getTextureCache(), scene.getMaterialCache());
82+
sceneRender.setupData(scene);
83+
shadowRender.setupData(scene);
8384
List<Model> modelList = new ArrayList<>(scene.getModelMap().values());
8485
modelList.forEach(m -> m.getMeshDataList().clear());
8586
}

chapter-20/src/main/java/org/lwjglb/engine/graph/SceneRender.java

Lines changed: 67 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public class SceneRender {
1717
private static final int MAX_MATERIALS = 20;
1818
private static final int MAX_TEXTURES = 16;
1919
private ShaderProgram shaderProgram;
20+
private int staticDrawCount;
21+
private int staticRenderBufferHandle;
2022
private UniformsMap uniformsMap;
2123

2224
public SceneRender() {
@@ -27,47 +29,9 @@ public SceneRender() {
2729
createUniforms();
2830
}
2931

30-
private ByteBuffer buildStaticCommandBuffer(List<Model> modelList, Map<String, Integer> entitiesIdxMap) {
31-
int numMeshes = 0;
32-
for (Model model : modelList) {
33-
numMeshes += model.getMeshDrawDataList().size();
34-
}
35-
36-
int firstIndex = 0;
37-
int baseInstance = 0;
38-
int drawElement = 0;
39-
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
40-
for (Model model : modelList) {
41-
List<Entity> entities = model.getEntitiesList();
42-
int numEntities = entities.size();
43-
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
44-
// count
45-
commandBuffer.putInt(meshDrawData.vertices());
46-
// instanceCount
47-
commandBuffer.putInt(numEntities);
48-
commandBuffer.putInt(firstIndex);
49-
// baseVertex
50-
commandBuffer.putInt(meshDrawData.offset());
51-
commandBuffer.putInt(baseInstance);
52-
53-
firstIndex += meshDrawData.vertices();
54-
baseInstance += entities.size();
55-
56-
for (Entity entity : entities) {
57-
String name = "drawElements[" + drawElement + "]";
58-
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
59-
uniformsMap.setUniform(name + ".materialIdx", meshDrawData.materialIdx());
60-
drawElement++;
61-
}
62-
}
63-
}
64-
commandBuffer.flip();
65-
66-
return commandBuffer;
67-
}
68-
6932
public void cleanup() {
7033
shaderProgram.cleanup();
34+
glDeleteBuffers(staticRenderBufferHandle);
7135
}
7236

7337
private void createUniforms() {
@@ -99,7 +63,7 @@ private void createUniforms() {
9963
}
10064
}
10165

102-
public void render(Scene scene, RenderBuffers globalBuffer, GBuffer gBuffer) {
66+
public void render(Scene scene, RenderBuffers renderBuffers, GBuffer gBuffer) {
10367
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gBuffer.getGBufferId());
10468
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10569
glViewport(0, 0, gBuffer.getWidth(), gBuffer.getHeight());
@@ -123,38 +87,28 @@ public void render(Scene scene, RenderBuffers globalBuffer, GBuffer gBuffer) {
12387
texture.bind();
12488
}
12589

126-
Map<String, Integer> entitiesIdxMap = new HashMap<>();
12790
int entityIdx = 0;
12891
for (Model model : scene.getModelMap().values()) {
12992
List<Entity> entities = model.getEntitiesList();
13093
for (Entity entity : entities) {
131-
entitiesIdxMap.put(entity.getId(), entityIdx);
13294
uniformsMap.setUniform("modelMatrices[" + entityIdx + "]", entity.getModelMatrix());
13395
entityIdx++;
13496
}
13597
}
13698

137-
renderStaticMeshes(scene, globalBuffer, entitiesIdxMap);
99+
// Static meshes
100+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, staticRenderBufferHandle);
101+
glBindVertexArray(renderBuffers.getStaticVaoId());
102+
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, staticDrawCount, 0);
103+
glBindVertexArray(0);
138104

139105
glEnable(GL_BLEND);
140106
shaderProgram.unbind();
141107
}
142108

143-
private void renderStaticMeshes(Scene scene, RenderBuffers globalBuffer, Map<String, Integer> entitiesIdxMap) {
144-
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> !m.isAnimated()).toList();
145-
146-
ByteBuffer commandBuffer = buildStaticCommandBuffer(modelList, entitiesIdxMap);
147-
int drawCount = commandBuffer.remaining() / COMMAND_SIZE;
148-
int bufferHandle = glGenBuffers();
149-
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, bufferHandle);
150-
glBufferData(GL_DRAW_INDIRECT_BUFFER, commandBuffer, GL_DYNAMIC_DRAW);
151-
152-
glBindVertexArray(globalBuffer.getStaticVaoId());
153-
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, drawCount, 0);
154-
glBindVertexArray(0);
155-
156-
MemoryUtil.memFree(commandBuffer);
157-
glDeleteBuffers(bufferHandle);
109+
public void setupData(Scene scene) {
110+
setupStaticCommandBuffer(scene);
111+
setupMaterialsUniform(scene.getTextureCache(), scene.getMaterialCache());
158112
}
159113

160114
public void setupMaterialsUniform(TextureCache textureCache, MaterialCache materialCache) {
@@ -189,4 +143,59 @@ public void setupMaterialsUniform(TextureCache textureCache, MaterialCache mater
189143
}
190144
shaderProgram.unbind();
191145
}
146+
147+
private void setupStaticCommandBuffer(Scene scene) {
148+
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> !m.isAnimated()).toList();
149+
Map<String, Integer> entitiesIdxMap = new HashMap<>();
150+
int entityIdx = 0;
151+
int numMeshes = 0;
152+
for (Model model : scene.getModelMap().values()) {
153+
numMeshes += model.getMeshDrawDataList().size();
154+
List<Entity> entities = model.getEntitiesList();
155+
for (Entity entity : entities) {
156+
entitiesIdxMap.put(entity.getId(), entityIdx);
157+
entityIdx++;
158+
}
159+
}
160+
161+
int firstIndex = 0;
162+
int baseInstance = 0;
163+
int drawElement = 0;
164+
shaderProgram.bind();
165+
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
166+
for (Model model : modelList) {
167+
List<Entity> entities = model.getEntitiesList();
168+
int numEntities = entities.size();
169+
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
170+
// count
171+
commandBuffer.putInt(meshDrawData.vertices());
172+
// instanceCount
173+
commandBuffer.putInt(numEntities);
174+
commandBuffer.putInt(firstIndex);
175+
// baseVertex
176+
commandBuffer.putInt(meshDrawData.offset());
177+
commandBuffer.putInt(baseInstance);
178+
179+
firstIndex += meshDrawData.vertices();
180+
baseInstance += entities.size();
181+
182+
for (Entity entity : entities) {
183+
String name = "drawElements[" + drawElement + "]";
184+
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
185+
uniformsMap.setUniform(name + ".materialIdx", meshDrawData.materialIdx());
186+
drawElement++;
187+
}
188+
}
189+
}
190+
commandBuffer.flip();
191+
shaderProgram.unbind();
192+
193+
staticDrawCount = commandBuffer.remaining() / COMMAND_SIZE;
194+
195+
staticRenderBufferHandle = glGenBuffers();
196+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, staticRenderBufferHandle);
197+
glBufferData(GL_DRAW_INDIRECT_BUFFER, commandBuffer, GL_DYNAMIC_DRAW);
198+
199+
MemoryUtil.memFree(commandBuffer);
200+
}
192201
}

chapter-20/src/main/java/org/lwjglb/engine/graph/ShadowRender.java

Lines changed: 64 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public class ShadowRender {
1616
private ArrayList<CascadeShadow> cascadeShadows;
1717
private ShaderProgram shaderProgram;
1818
private ShadowBuffer shadowBuffer;
19+
private int staticDrawCount;
20+
private int staticRenderBufferHandle;
1921
private UniformsMap uniformsMap;
2022

2123
public ShadowRender() {
@@ -34,47 +36,10 @@ public ShadowRender() {
3436
createUniforms();
3537
}
3638

37-
private ByteBuffer buildStaticCommandBuffer(List<Model> modelList, Map<String, Integer> entitiesIdxMap) {
38-
int numMeshes = 0;
39-
for (Model model : modelList) {
40-
numMeshes += model.getMeshDrawDataList().size();
41-
}
42-
43-
int firstIndex = 0;
44-
int baseInstance = 0;
45-
int drawElement = 0;
46-
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
47-
for (Model model : modelList) {
48-
List<Entity> entities = model.getEntitiesList();
49-
int numEntities = entities.size();
50-
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
51-
// count
52-
commandBuffer.putInt(meshDrawData.vertices());
53-
// instanceCount
54-
commandBuffer.putInt(numEntities);
55-
commandBuffer.putInt(firstIndex);
56-
// baseVertex
57-
commandBuffer.putInt(meshDrawData.offset());
58-
commandBuffer.putInt(baseInstance);
59-
60-
firstIndex += meshDrawData.vertices();
61-
baseInstance += entities.size();
62-
63-
for (Entity entity : entities) {
64-
String name = "drawElements[" + drawElement + "]";
65-
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
66-
drawElement++;
67-
}
68-
}
69-
}
70-
commandBuffer.flip();
71-
72-
return commandBuffer;
73-
}
74-
7539
public void cleanup() {
7640
shaderProgram.cleanup();
7741
shadowBuffer.cleanup();
42+
glDeleteBuffers(staticRenderBufferHandle);
7843
}
7944

8045
private void createUniforms() {
@@ -99,20 +64,18 @@ public ShadowBuffer getShadowBuffer() {
9964
return shadowBuffer;
10065
}
10166

102-
public void render(Scene scene, RenderBuffers globalBuffer) {
67+
public void render(Scene scene, RenderBuffers renderBuffers) {
10368
CascadeShadow.updateCascadeShadows(cascadeShadows, scene);
10469

10570
glBindFramebuffer(GL_FRAMEBUFFER, shadowBuffer.getDepthMapFBO());
10671
glViewport(0, 0, ShadowBuffer.SHADOW_MAP_WIDTH, ShadowBuffer.SHADOW_MAP_HEIGHT);
10772

10873
shaderProgram.bind();
10974

110-
Map<String, Integer> entitiesIdxMap = new HashMap<>();
11175
int entityIdx = 0;
11276
for (Model model : scene.getModelMap().values()) {
11377
List<Entity> entities = model.getEntitiesList();
11478
for (Entity entity : entities) {
115-
entitiesIdxMap.put(entity.getId(), entityIdx);
11679
uniformsMap.setUniform("modelMatrices[" + entityIdx + "]", entity.getModelMatrix());
11780
entityIdx++;
11881
}
@@ -123,35 +86,78 @@ public void render(Scene scene, RenderBuffers globalBuffer) {
12386
glClear(GL_DEPTH_BUFFER_BIT);
12487
}
12588

126-
renderStaticMeshes(scene, globalBuffer, entitiesIdxMap);
89+
// Static meshes
90+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, staticRenderBufferHandle);
91+
glBindVertexArray(renderBuffers.getStaticVaoId());
92+
for (int i = 0; i < CascadeShadow.SHADOW_MAP_CASCADE_COUNT; i++) {
93+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowBuffer.getDepthMapTexture().getIds()[i], 0);
94+
95+
CascadeShadow shadowCascade = cascadeShadows.get(i);
96+
uniformsMap.setUniform("projViewMatrix", shadowCascade.getProjViewMatrix());
97+
98+
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, staticDrawCount, 0);
99+
}
100+
glBindVertexArray(0);
127101

128102
shaderProgram.unbind();
129103
glBindFramebuffer(GL_FRAMEBUFFER, 0);
130104
}
131105

132-
private void renderStaticMeshes(Scene scene, RenderBuffers renderBuffers, Map<String, Integer> entitiesIdxMap) {
133-
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> !m.isAnimated()).toList();
134-
135-
ByteBuffer commandBuffer = buildStaticCommandBuffer(modelList, entitiesIdxMap);
136-
int drawCount = commandBuffer.remaining() / COMMAND_SIZE;
137-
int bufferHandle = glGenBuffers();
138-
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, bufferHandle);
139-
glBufferData(GL_DRAW_INDIRECT_BUFFER, commandBuffer, GL_DYNAMIC_DRAW);
106+
public void setupData(Scene scene) {
107+
setupStaticCommandBuffer(scene);
108+
}
140109

141-
glBindVertexArray(renderBuffers.getStaticVaoId());
110+
private void setupStaticCommandBuffer(Scene scene) {
111+
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> !m.isAnimated()).toList();
112+
Map<String, Integer> entitiesIdxMap = new HashMap<>();
113+
int entityIdx = 0;
114+
int numMeshes = 0;
115+
for (Model model : scene.getModelMap().values()) {
116+
List<Entity> entities = model.getEntitiesList();
117+
numMeshes += model.getMeshDrawDataList().size();
118+
for (Entity entity : entities) {
119+
entitiesIdxMap.put(entity.getId(), entityIdx);
120+
entityIdx++;
121+
}
122+
}
142123

143-
for (int i = 0; i < CascadeShadow.SHADOW_MAP_CASCADE_COUNT; i++) {
144-
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowBuffer.getDepthMapTexture().getIds()[i], 0);
124+
int firstIndex = 0;
125+
int baseInstance = 0;
126+
int drawElement = 0;
127+
shaderProgram.bind();
128+
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
129+
for (Model model : modelList) {
130+
List<Entity> entities = model.getEntitiesList();
131+
int numEntities = entities.size();
132+
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
133+
// count
134+
commandBuffer.putInt(meshDrawData.vertices());
135+
// instanceCount
136+
commandBuffer.putInt(numEntities);
137+
commandBuffer.putInt(firstIndex);
138+
// baseVertex
139+
commandBuffer.putInt(meshDrawData.offset());
140+
commandBuffer.putInt(baseInstance);
145141

146-
CascadeShadow shadowCascade = cascadeShadows.get(i);
147-
uniformsMap.setUniform("projViewMatrix", shadowCascade.getProjViewMatrix());
142+
firstIndex += meshDrawData.vertices();
143+
baseInstance += entities.size();
148144

149-
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, drawCount, 0);
145+
for (Entity entity : entities) {
146+
String name = "drawElements[" + drawElement + "]";
147+
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
148+
drawElement++;
149+
}
150+
}
150151
}
152+
commandBuffer.flip();
153+
shaderProgram.unbind();
151154

152-
glBindVertexArray(0);
155+
staticDrawCount = commandBuffer.remaining() / COMMAND_SIZE;
156+
157+
staticRenderBufferHandle = glGenBuffers();
158+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, staticRenderBufferHandle);
159+
glBufferData(GL_DRAW_INDIRECT_BUFFER, commandBuffer, GL_DYNAMIC_DRAW);
153160

154161
MemoryUtil.memFree(commandBuffer);
155-
glDeleteBuffers(bufferHandle);
156162
}
157163
}

0 commit comments

Comments
 (0)