From 5d93616e0316aba5241b3f25a3298672a9becedb Mon Sep 17 00:00:00 2001 From: redstrate <54911369+redstrate@users.noreply.github.com> Date: Tue, 22 Sep 2020 16:09:25 -0400 Subject: [PATCH] Add functions to dispatch compute workloads --- engine/gfx/metal/src/gfx_metal.mm | 53 +++++++++++++++++++-- engine/gfx/metal/src/gfx_metal_pipeline.hpp | 2 + engine/gfx/public/gfx_commandbuffer.hpp | 44 +++++++++++++---- engine/renderer/src/dofpass.cpp | 2 +- engine/renderer/src/gaussianhelper.cpp | 2 +- engine/renderer/src/imguipass.cpp | 2 +- engine/renderer/src/renderer.cpp | 20 ++++---- engine/renderer/src/scenecapture.cpp | 8 ++-- engine/renderer/src/shadowpass.cpp | 12 ++--- engine/renderer/src/smaapass.cpp | 4 +- shaders/histogram.comp.glsl | 9 +++- tools/common/src/commoneditor.cpp | 4 +- tools/common/src/debugpass.cpp | 10 ++-- 13 files changed, 127 insertions(+), 45 deletions(-) diff --git a/engine/gfx/metal/src/gfx_metal.mm b/engine/gfx/metal/src/gfx_metal.mm index d4d89c1..fc6848e 100755 --- a/engine/gfx/metal/src/gfx_metal.mm +++ b/engine/gfx/metal/src/gfx_metal.mm @@ -673,6 +673,15 @@ GFXPipeline* GFXMetal::create_compute_pipeline(const GFXComputePipelineCreateInf MTLComputePipelineDescriptor* pipelineDescriptor = [MTLComputePipelineDescriptor new]; pipelineDescriptor.computeFunction = computeFunc; + if(debug_enabled) { + pipelineDescriptor.label = [NSString stringWithFormat:@"%s", info.label.data()]; + pipeline->label = info.label; + } + + pipeline->compute_handle = [device newComputePipelineStateWithDescriptor:pipelineDescriptor error:&error]; + if(!pipeline->handle) + NSLog(@"%@", error.debugDescription); + [computeLibrary release]; return pipeline; @@ -707,6 +716,7 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const int window) { id commandBuffer = [command_queue commandBuffer]; id renderEncoder = nil; + id computeEncoder = nil; id blitEncoder = nil; GFXMetalRenderPass* currentRenderPass = nullptr; @@ -720,6 +730,7 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const int window) { enum class CurrentEncoder { None, Render, + Compute, Blit } current_encoder = CurrentEncoder::None; @@ -728,10 +739,14 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const int window) { if(renderEncoder != nil) [renderEncoder endEncoding]; + if(computeEncoder != nil) + [computeEncoder endEncoding]; + if(blitEncoder != nil) [blitEncoder endEncoding]; renderEncoder = nil; + computeEncoder = nil; blitEncoder = nil; } @@ -777,6 +792,11 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const int window) { [descriptor release]; } break; + case CurrentEncoder::Compute: + { + computeEncoder = [commandBuffer computeCommandEncoder]; + } + break; case CurrentEncoder::Blit: { blitEncoder = [commandBuffer blitCommandEncoder]; @@ -806,23 +826,33 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const int window) { needEncoder(CurrentEncoder::Render, true); } break; - case GFXCommandType::SetPipeline: + case GFXCommandType::SetGraphicsPipeline: { needEncoder(CurrentEncoder::Render); - [renderEncoder setRenderPipelineState:((GFXMetalPipeline*)command.data.set_pipeline.pipeline)->handle]; + [renderEncoder setRenderPipelineState:((GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline)->handle]; - currentPipeline = (GFXMetalPipeline*)command.data.set_pipeline.pipeline; + currentPipeline = (GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline; [renderEncoder setDepthStencilState:currentPipeline->depthStencil]; - [renderEncoder setCullMode:((GFXMetalPipeline*)command.data.set_pipeline.pipeline)->cullMode]; - [renderEncoder setFrontFacingWinding:toWinding(((GFXMetalPipeline*)command.data.set_pipeline.pipeline)->winding_mode)]; + [renderEncoder setCullMode:((GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline)->cullMode]; + [renderEncoder setFrontFacingWinding:toWinding(((GFXMetalPipeline*)command.data.set_graphics_pipeline.pipeline)->winding_mode)]; if(currentPipeline->renderWire) [renderEncoder setTriangleFillMode:MTLTriangleFillModeLines]; else [renderEncoder setTriangleFillMode:MTLTriangleFillModeFill]; + } + break; + case GFXCommandType::SetComputePipeline: + { + needEncoder(CurrentEncoder::Compute); + + currentPipeline = (GFXMetalPipeline*)command.data.set_compute_pipeline.pipeline; + + [computeEncoder setComputePipelineState:((GFXMetalPipeline*)command.data.set_compute_pipeline.pipeline)->compute_handle]; + } break; case GFXCommandType::SetVertexBuffer: @@ -1034,6 +1064,19 @@ void GFXMetal::submit(GFXCommandBuffer* command_buffer, const int window) { } } break; + case GFXCommandType::Dispatch: { + needEncoder(CurrentEncoder::Compute); + + NSUInteger threadGroupSize = currentPipeline->compute_handle.maxTotalThreadsPerThreadgroup; + + MTLSize threadgroupSize = MTLSizeMake(std::min(threadGroupSize, + (NSUInteger)command.data.dispatch.group_count_x), + std::min(threadGroupSize, (NSUInteger)command.data.dispatch.group_count_y), + std::min(threadGroupSize, (NSUInteger)command.data.dispatch.group_count_z)); + + [computeEncoder dispatchThreads:MTLSizeMake(command.data.dispatch.group_count_x, command.data.dispatch.group_count_y, command.data.dispatch.group_count_z) threadsPerThreadgroup:threadgroupSize]; + } + break; } } diff --git a/engine/gfx/metal/src/gfx_metal_pipeline.hpp b/engine/gfx/metal/src/gfx_metal_pipeline.hpp index df2e9d0..a09e040 100755 --- a/engine/gfx/metal/src/gfx_metal_pipeline.hpp +++ b/engine/gfx/metal/src/gfx_metal_pipeline.hpp @@ -9,6 +9,8 @@ public: std::string label; id handle = nil; + id compute_handle = nil; + id depthStencil = nil; MTLPrimitiveType primitiveType; diff --git a/engine/gfx/public/gfx_commandbuffer.hpp b/engine/gfx/public/gfx_commandbuffer.hpp index b6cefcd..93870ec 100755 --- a/engine/gfx/public/gfx_commandbuffer.hpp +++ b/engine/gfx/public/gfx_commandbuffer.hpp @@ -41,7 +41,8 @@ enum class IndexType : int { enum class GFXCommandType { Invalid, SetRenderPass, - SetPipeline, + SetGraphicsPipeline, + SetComputePipeline, SetVertexBuffer, SetIndexBuffer, SetPushConstant, @@ -58,7 +59,8 @@ enum class GFXCommandType { SetDepthBias, PushGroup, PopGroup, - InsertLabel + InsertLabel, + Dispatch }; struct GFXDrawCommand { @@ -67,11 +69,13 @@ struct GFXDrawCommand { struct CommandData { GFXRenderPassBeginInfo set_render_pass; - struct SetPipelineData { - SetPipelineData() {} - + struct SetGraphicsPipelineData { GFXPipeline* pipeline = nullptr; - } set_pipeline; + } set_graphics_pipeline; + + struct SetComputePipelineData { + GFXPipeline* pipeline = nullptr; + } set_compute_pipeline; struct SetVertexData { GFXBuffer* buffer = nullptr; @@ -153,6 +157,10 @@ struct GFXDrawCommand { struct InsertLabelData { std::string_view name; } insert_label; + + struct DispatchData { + uint32_t group_count_x, group_count_y, group_count_z; + } dispatch; } data; }; @@ -166,10 +174,18 @@ public: commands.push_back(command); } - void set_pipeline(GFXPipeline* pipeline) { + void set_graphics_pipeline(GFXPipeline* pipeline) { GFXDrawCommand command; - command.type = GFXCommandType::SetPipeline; - command.data.set_pipeline.pipeline = pipeline; + command.type = GFXCommandType::SetGraphicsPipeline; + command.data.set_graphics_pipeline.pipeline = pipeline; + + commands.push_back(command); + } + + void set_compute_pipeline(GFXPipeline* pipeline) { + GFXDrawCommand command; + command.type = GFXCommandType::SetComputePipeline; + command.data.set_compute_pipeline.pipeline = pipeline; commands.push_back(command); } @@ -334,5 +350,15 @@ public: commands.push_back(command); } + void dispatch(const uint32_t group_count_x, const uint32_t group_count_y, const uint32_t group_count_z) { + GFXDrawCommand command; + command.type = GFXCommandType::Dispatch; + command.data.dispatch.group_count_x = group_count_x; + command.data.dispatch.group_count_y = group_count_y; + command.data.dispatch.group_count_z = group_count_z; + + commands.push_back(command); + } + std::vector commands; }; diff --git a/engine/renderer/src/dofpass.cpp b/engine/renderer/src/dofpass.cpp index 250e64f..942c039 100755 --- a/engine/renderer/src/dofpass.cpp +++ b/engine/renderer/src/dofpass.cpp @@ -35,7 +35,7 @@ DoFPass::DoFPass(GFX* gfx, Renderer* renderer) : renderer(renderer) { } void DoFPass::render(GFXCommandBuffer* command_buffer, Scene&) { - command_buffer->set_pipeline(pipeline); + command_buffer->set_graphics_pipeline(pipeline); command_buffer->bind_texture(renderer->offscreenColorTexture, 0); command_buffer->bind_texture(renderer->offscreenDepthTexture, 1); diff --git a/engine/renderer/src/gaussianhelper.cpp b/engine/renderer/src/gaussianhelper.cpp index b3727c2..16a88f4 100755 --- a/engine/renderer/src/gaussianhelper.cpp +++ b/engine/renderer/src/gaussianhelper.cpp @@ -64,7 +64,7 @@ GFXTexture* GaussianHelper::render(GFXCommandBuffer* commandBuffer, GFXTexture* commandBuffer->set_render_pass(info); - commandBuffer->set_pipeline(pipeline); + commandBuffer->set_graphics_pipeline(pipeline); commandBuffer->memory_barrier(); diff --git a/engine/renderer/src/imguipass.cpp b/engine/renderer/src/imguipass.cpp index 90ab5fb..965a13c 100755 --- a/engine/renderer/src/imguipass.cpp +++ b/engine/renderer/src/imguipass.cpp @@ -97,7 +97,7 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, const int index) { update_buffers(*draw_data); - command_buffer->set_pipeline(pipeline); + command_buffer->set_graphics_pipeline(pipeline); command_buffer->set_vertex_buffer(vertex_buffer, 0, 0); command_buffer->set_index_buffer(index_buffer, IndexType::UINT16); diff --git a/engine/renderer/src/renderer.cpp b/engine/renderer/src/renderer.cpp index b997c3b..30f1eea 100755 --- a/engine/renderer/src/renderer.cpp +++ b/engine/renderer/src/renderer.cpp @@ -206,6 +206,10 @@ void Renderer::stopSceneBlur() { void Renderer::render(Scene* scene, int index) { GFXCommandBuffer* commandbuffer = engine->get_gfx()->acquire_command_buffer(); + commandbuffer->set_compute_pipeline(histogram_pipeline); + + commandbuffer->dispatch(1, 1, 1); + const auto extent = get_extent(); const auto render_extent = get_render_extent(); @@ -286,7 +290,7 @@ void Renderer::render(Scene* scene, int index) { commandbuffer->push_group("Post Processing"); - commandbuffer->set_pipeline(viewport_mode ? renderToViewportPipeline : postPipeline); + commandbuffer->set_graphics_pipeline(viewport_mode ? renderToViewportPipeline : postPipeline); commandbuffer->bind_texture(offscreenColorTexture, 1); commandbuffer->bind_texture(offscreenBackTexture, 2); commandbuffer->bind_texture(smaaPass->blend_texture, 3); @@ -447,7 +451,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene.get(obj), part))) continue; - command_buffer->set_pipeline(mesh.mesh->bones.empty() ? mesh.materials[material_index]->static_pipeline : mesh.materials[material_index]->skinned_pipeline); + command_buffer->set_graphics_pipeline(mesh.mesh->bones.empty() ? mesh.materials[material_index]->static_pipeline : mesh.materials[material_index]->skinned_pipeline); if(!mesh.mesh->bones.empty()) command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128); @@ -493,7 +497,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj pc.sun_position_fov = Vector4(scene.get(obj).get_world_position(), radians(camera.fov)); } - command_buffer->set_pipeline(skyPipeline); + command_buffer->set_graphics_pipeline(skyPipeline); command_buffer->set_push_constant(&pc, sizeof(SkyPushConstant)); @@ -602,10 +606,10 @@ void Renderer::render_screen(GFXCommandBuffer *commandbuffer, ui::Screen* screen pc.screenSize = windowSize; if(options.render_world) { - commandbuffer->set_pipeline(worldGeneralPipeline); + commandbuffer->set_graphics_pipeline(worldGeneralPipeline); pc.mvp = options.mvp; } else { - commandbuffer->set_pipeline(generalPipeline); + commandbuffer->set_graphics_pipeline(generalPipeline); } commandbuffer->set_push_constant(&pc, sizeof(UIPushConstant)); @@ -618,10 +622,10 @@ void Renderer::render_screen(GFXCommandBuffer *commandbuffer, ui::Screen* screen pc.screenSize = windowSize; if(options.render_world) { - commandbuffer->set_pipeline(worldTextPipeline); + commandbuffer->set_graphics_pipeline(worldTextPipeline); pc.mvp = options.mvp; } else { - commandbuffer->set_pipeline(textPipeline); + commandbuffer->set_graphics_pipeline(textPipeline); } commandbuffer->set_push_constant(&pc, sizeof(UIPushConstant)); @@ -983,7 +987,7 @@ void Renderer::createBRDF() { command_buffer->set_render_pass(beginInfo); - command_buffer->set_pipeline(brdfPipeline); + command_buffer->set_graphics_pipeline(brdfPipeline); Viewport viewport = {}; viewport.width = brdf_resolution; diff --git a/engine/renderer/src/scenecapture.cpp b/engine/renderer/src/scenecapture.cpp index 51a358b..b83efc7 100755 --- a/engine/renderer/src/scenecapture.cpp +++ b/engine/renderer/src/scenecapture.cpp @@ -253,7 +253,7 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) { if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene->get(obj), part))) continue; - command_buffer->set_pipeline( mesh.materials[material_index]->capture_pipeline); + command_buffer->set_graphics_pipeline(mesh.materials[material_index]->capture_pipeline); command_buffer->set_push_constant(&pc, sizeof(PushConstant)); @@ -286,7 +286,7 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) { pc.sun_position_fov = Vector4(scene->get(obj).get_world_position(), radians(90.0f)); } - command_buffer->set_pipeline(skyPipeline); + command_buffer->set_graphics_pipeline(skyPipeline); command_buffer->set_push_constant(&pc, sizeof(SkyPushConstant)); @@ -322,7 +322,7 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) { command_buffer->set_vertex_buffer(cubeMesh->position_buffer, 0, 0); command_buffer->set_index_buffer(cubeMesh->index_buffer, IndexType::UINT32); - command_buffer->set_pipeline(irradiancePipeline); + command_buffer->set_graphics_pipeline(irradiancePipeline); command_buffer->bind_texture(environmentCube, 2); command_buffer->set_push_constant(&mvp, sizeof(Matrix4x4)); @@ -362,7 +362,7 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) { pc.mvp = projection * sceneTransforms[face]; pc.roughness = ((float)mip) / (float)(mipLevels - 1); - command_buffer->set_pipeline(prefilterPipeline); + command_buffer->set_graphics_pipeline(prefilterPipeline); command_buffer->bind_texture(environmentCube, 2); command_buffer->set_push_constant(&pc, sizeof(PushConstant)); diff --git a/engine/renderer/src/shadowpass.cpp b/engine/renderer/src/shadowpass.cpp index 80b257b..6bafcd2 100755 --- a/engine/renderer/src/shadowpass.cpp +++ b/engine/renderer/src/shadowpass.cpp @@ -126,13 +126,13 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c if(mesh.mesh->bones.empty()) { switch(type) { case Light::Type::Sun: - command_buffer->set_pipeline(static_sun_pipeline); + command_buffer->set_graphics_pipeline(static_sun_pipeline); break; case Light::Type::Spot: - command_buffer->set_pipeline(static_spot_pipeline); + command_buffer->set_graphics_pipeline(static_spot_pipeline); break; case Light::Type::Point: - command_buffer->set_pipeline(static_point_pipeline); + command_buffer->set_graphics_pipeline(static_point_pipeline); break; } @@ -148,13 +148,13 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c } else { switch(type) { case Light::Type::Sun: - command_buffer->set_pipeline(skinned_sun_pipeline); + command_buffer->set_graphics_pipeline(skinned_sun_pipeline); break; case Light::Type::Spot: - command_buffer->set_pipeline(skinned_spot_pipeline); + command_buffer->set_graphics_pipeline(skinned_spot_pipeline); break; case Light::Type::Point: - command_buffer->set_pipeline(skinned_point_pipeline); + command_buffer->set_graphics_pipeline(skinned_point_pipeline); break; } diff --git a/engine/renderer/src/smaapass.cpp b/engine/renderer/src/smaapass.cpp index e64ab14..1e2149d 100755 --- a/engine/renderer/src/smaapass.cpp +++ b/engine/renderer/src/smaapass.cpp @@ -43,7 +43,7 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer) { command_buffer->set_viewport(viewport); - command_buffer->set_pipeline(edge_pipeline); + command_buffer->set_graphics_pipeline(edge_pipeline); command_buffer->set_push_constant(&pc, sizeof(PushConstant)); command_buffer->bind_texture(renderer->offscreenColorTexture, 0); // color @@ -57,7 +57,7 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer) { beginInfo.framebuffer = blend_framebuffer; command_buffer->set_render_pass(beginInfo); - command_buffer->set_pipeline(blend_pipeline); + command_buffer->set_graphics_pipeline(blend_pipeline); command_buffer->set_push_constant(&pc, sizeof(PushConstant)); command_buffer->bind_texture(edge_texture, 0); diff --git a/shaders/histogram.comp.glsl b/shaders/histogram.comp.glsl index bd51952..a773306 100755 --- a/shaders/histogram.comp.glsl +++ b/shaders/histogram.comp.glsl @@ -1,3 +1,10 @@ +layout(local_size_x = 16, local_size_y = 16) in; + +layout(rgba32f, binding = 0) uniform image2D hdr_image; + +shared uint histogram_shared[256]; + void main() { - + histogram_shared[gl_LocalInvocationIndex] = 1; + groupMemoryBarrier(); } diff --git a/tools/common/src/commoneditor.cpp b/tools/common/src/commoneditor.cpp index 08ab910..3eb5ae9 100755 --- a/tools/common/src/commoneditor.cpp +++ b/tools/common/src/commoneditor.cpp @@ -893,7 +893,7 @@ GFXTexture* CommonEditor::get_texture_preview(Texture& texture) { command_buffer->set_viewport(viewport); - command_buffer->set_pipeline(renderer->renderToUnormTexturePipeline); + command_buffer->set_graphics_pipeline(renderer->renderToUnormTexturePipeline); command_buffer->bind_texture(texture.handle, 1); command_buffer->bind_texture(renderer->dummyTexture, 2); @@ -1010,7 +1010,7 @@ GFXTexture* CommonEditor::generate_common_preview(Scene& scene, const Vector3 ca command_buffer->set_viewport(viewport); - command_buffer->set_pipeline(renderer->renderToUnormTexturePipeline); + command_buffer->set_graphics_pipeline(renderer->renderToUnormTexturePipeline); command_buffer->bind_texture(offscreen_color_texture, 1); command_buffer->bind_texture(renderer->dummyTexture, 2); diff --git a/tools/common/src/debugpass.cpp b/tools/common/src/debugpass.cpp index 1b9ea91..6a24b77 100755 --- a/tools/common/src/debugpass.cpp +++ b/tools/common/src/debugpass.cpp @@ -239,7 +239,7 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { Matrix4x4 vp = camera.perspective * camera.view; - commandBuffer->set_pipeline(primitive_pipeline); + commandBuffer->set_graphics_pipeline(primitive_pipeline); struct DebugPrimitive { Vector3 position, size; @@ -338,7 +338,7 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { commandBuffer->draw_indexed(cubeMesh->num_indices, 0, 0); } - commandBuffer->set_pipeline(billboard_pipeline); + commandBuffer->set_graphics_pipeline(billboard_pipeline); // draw primitives for(auto& bill : billboards) { @@ -355,7 +355,7 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { commandBuffer->draw_indexed(4, 0, 0); } - commandBuffer->set_pipeline(arrow_pipeline); + commandBuffer->set_graphics_pipeline(arrow_pipeline); // draw handles for selected object; if(selected_object != NullObject && engine->get_scene()->has(selected_object)) { @@ -386,7 +386,7 @@ void DebugPass::render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) { commandBuffer->set_render_pass(info); if(selected_object != NullObject && engine->get_scene()->has(selected_object)) { - commandBuffer->set_pipeline(sobelPipeline); + commandBuffer->set_graphics_pipeline(sobelPipeline); auto renderable = engine->get_scene()->get(selected_object); @@ -496,7 +496,7 @@ void DebugPass::get_selected_object(int x, int y, std::functionset_viewport(viewport); - commandBuffer->set_pipeline(selectPipeline); + commandBuffer->set_graphics_pipeline(selectPipeline); for(auto [i, object] : utility::enumerate(selectable_objects)) { AssetPtr mesh;