Permalink
Browse files

[escher] Implement tiled gaussian.

ES-67

Benchmark on Linux workstation:

32-bit float

[INFO:waterfall_demo.cc(329)] ---- Average frame rate: 32.4697
[INFO:waterfall_demo.cc(330)] ---- Total GPU memory: 1139291kB
[INFO:frame.cc(101)] ------------------------------------------------------
[INFO:frame.cc(103)] Timestamps for frame #200
[INFO:frame.cc(104)] total       |      since previous (all times in microseconds)
[INFO:frame.cc(106)] ------------------------------------------------------
[INFO:frame.cc(109)] 0   |      0       start of frame
[INFO:frame.cc(109)] 2986        |      2986    generated moment shadow map
[INFO:frame.cc(109)] 2987        |      1       transitioned layout to eGeneral
[INFO:frame.cc(109)] 7484        |      4497    applied 3x3 gaussian
[INFO:frame.cc(109)] 14777       |      7293    finished moment shadow map lighting pass
[INFO:frame.cc(109)] 14779       |      2       finished transition to presentation layout
[INFO:frame.cc(109)] 14780       |      1       end of frame
[INFO:frame.cc(112)] ------------------------------------------------------

16-bit float

[INFO:waterfall_demo.cc(329)] ---- Average frame rate: 60.9669
[INFO:waterfall_demo.cc(330)] ---- Total GPU memory: 698651kB
[INFO:frame.cc(101)] ------------------------------------------------------
[INFO:frame.cc(103)] Timestamps for frame #200
[INFO:frame.cc(104)] total       |      since previous (all times in microseconds)
[INFO:frame.cc(106)] ------------------------------------------------------
[INFO:frame.cc(109)] 0   |      0       start of frame
[INFO:frame.cc(109)] 1672        |      1672    generated moment shadow map
[INFO:frame.cc(109)] 1673        |      1       transitioned layout to eGeneral
[INFO:frame.cc(109)] 7391        |      5718    applied 3x3 gaussian
[INFO:frame.cc(109)] 13447       |      6056    finished moment shadow map lighting pass
[INFO:frame.cc(109)] 13448       |      1       finished transition to presentation layout
[INFO:frame.cc(109)] 13449       |      1       end of frame
[INFO:frame.cc(112)] ------------------------------------------------------

Change-Id: I96b276a11d31be57f5f5d990ca7322f565740f2b
  • Loading branch information...
misaka-10032 authored and CQ bot account: commit-bot@chromium.org committed Feb 25, 2018
1 parent 8f4889b commit 8185f23b3e10a11a6cbeb5ac80cfe48f42beeb64
@@ -103,6 +103,8 @@ source_set("escher") {
"impl/debug_print.cc",
"impl/descriptor_set_pool.cc",
"impl/descriptor_set_pool.h",
"impl/gaussian_3x3f.cc",
"impl/gaussian_3x3f.h",
"impl/glsl_compiler.cc",
"impl/glsl_compiler.h",
"impl/gpu_mem_slab.cc",
@@ -0,0 +1,103 @@
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lib/escher/impl/gaussian_3x3f.h"
#include "lib/escher/escher.h"
#include "lib/escher/impl/command_buffer.h"
#include "lib/escher/impl/image_cache.h"
#include "lib/escher/vk/buffer.h"
#include "lib/escher/vk/texture.h"
namespace {
constexpr uint32_t kGroupSizeX = 16;
constexpr uint32_t kGroupSizeY = 16;
constexpr char kShaderCode[] = R"GLSL(
#version 450
#extension GL_ARB_separate_shader_objects : enable
const vec3 kWeight = vec3(0.27901, 0.44198, 0.27901);
const int kGroupSizeX = 16;
const int kGroupSizeY = 16;
const int kInnerSizeX = 8;
const int kInnerSizeY = 1;
layout (local_size_x = kGroupSizeX/kInnerSizeX,
local_size_y = kGroupSizeY/kInnerSizeY) in;
layout(binding = 0, rgba32f) uniform image2D input_image;
layout(binding = 1, rgba32f) uniform image2D output_image;
shared vec4 tile[kGroupSizeY][kGroupSizeX];
vec4 tileLoad(ivec2 pos) {
ivec2 safe_pos = clamp(
pos, ivec2(0, 0), ivec2(kGroupSizeX-1, kGroupSizeY-1));
return tile[safe_pos.y][safe_pos.x];
}
void main() {
ivec2 global_anchor = ivec2(gl_GlobalInvocationID.x * kInnerSizeX,
gl_GlobalInvocationID.y * kInnerSizeY);
ivec2 local_anchor = ivec2(gl_LocalInvocationID.x * kInnerSizeX,
gl_LocalInvocationID.y * kInnerSizeY);
for (int dy = 0; dy < kInnerSizeY; dy++) {
for (int dx = 0; dx < kInnerSizeX; dx++) {
ivec2 global_pos = ivec2(global_anchor.x+dx, global_anchor.y+dy);
ivec2 local_pos = ivec2(local_anchor.x+dx, local_anchor.y+dy);
vec4 left = imageLoad(input_image, ivec2(global_pos.x-1, global_pos.y));
vec4 mid = imageLoad(input_image, global_pos);
vec4 right = imageLoad(input_image, ivec2(global_pos.x+1, global_pos.y));
tile[local_pos.y][local_pos.x] =
kWeight.x * left + kWeight.y * mid + kWeight.z * right;
}
}
// Guarantees `tile` is computed.
barrier();
// Guarantees `tile` is coherent across threads.
groupMemoryBarrier();
for (int dy = 0; dy < kInnerSizeY; dy++) {
for (int dx = 0; dx < kInnerSizeX; dx++) {
ivec2 global_pos = ivec2(global_anchor.x+dx, global_anchor.y+dy);
ivec2 local_pos = ivec2(local_anchor.x+dx, local_anchor.y+dy);
vec4 top = tileLoad(ivec2(local_pos.x, local_pos.y-1));
vec4 mid = tileLoad(local_pos);
vec4 bottom = tileLoad(ivec2(local_pos.x, local_pos.y+1));
vec4 result =
kWeight.x * top + kWeight.y * mid + kWeight.z * bottom;
imageStore(output_image, global_pos, result);
}
}
}
)GLSL";
} // namespace
namespace escher {
namespace impl {
Gaussian3x3f::Gaussian3x3f(Escher* escher) : escher_(escher) {}
void Gaussian3x3f::Apply(CommandBuffer* command_buffer,
const TexturePtr& input,
const TexturePtr& output) {
if (!kernel_) {
kernel_ = std::make_unique<ComputeShader>(
escher_,
std::vector<vk::ImageLayout>{
vk::ImageLayout::eGeneral,
vk::ImageLayout::eGeneral},
std::vector<vk::DescriptorType>{},
/* push_constants_size= */ 0, kShaderCode);
}
kernel_->Dispatch(
{input, output}, {}, command_buffer,
(input->width() + kGroupSizeX - 1) / kGroupSizeX,
(input->height() + kGroupSizeY - 1) / kGroupSizeY,
/* z= */ 1, /* push_constants= */ nullptr);
}
} // namespace impl
} // namespace escher
@@ -0,0 +1,37 @@
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <memory>
#include "lib/escher/forward_declarations.h"
#include "lib/escher/impl/compute_shader.h"
#include "lib/fxl/macros.h"
#include "vulkan/vulkan.hpp"
namespace escher {
namespace impl {
// A helper class that wraps up a compute shader for Gaussian blur on images
// with vk::Format::eR32G32B32A32Sfloat.
// TODO(SCN-619): Investigate the performance issue.
class Gaussian3x3f {
public:
explicit Gaussian3x3f(Escher* escher);
// Apply two-pass gaussian on the input texture, and render into the output
// texture. Mipmap is not supported. Assumes the image layout is
// vk::ImageLayout::eGeneral.
void Apply(CommandBuffer* command_buffer,
const TexturePtr& input,
const TexturePtr& output);
Escher* escher_;
std::unique_ptr<ComputeShader> kernel_;
FXL_DISALLOW_COPY_AND_ASSIGN(Gaussian3x3f);
};
} // namespace impl
} // namespace escher
@@ -4,13 +4,33 @@
#include "lib/escher/renderer/moment_shadow_map_renderer.h"
#include "lib/escher/escher.h"
#include "lib/escher/impl/image_cache.h"
#include "lib/escher/impl/model_moment_shadow_map_pass.h"
#include "lib/escher/impl/vulkan_utils.h"
#include "lib/escher/renderer/moment_shadow_map.h"
#include "lib/escher/scene/camera.h"
#include "lib/escher/scene/stage.h"
namespace {
// Create an image of the same size and format as the input.
escher::ImagePtr CreateSimilarImage(escher::Escher* escher,
escher::impl::CommandBuffer* command_buffer,
const escher::ImagePtr& input) {
escher::ImageInfo info;
info.format = input->format();
info.width = input->width();
info.height = input->height();
info.sample_count = 1;
info.usage = vk::ImageUsageFlagBits::eSampled |
vk::ImageUsageFlagBits::eStorage;
auto output = escher->image_cache()->NewImage(info);
command_buffer->TransitionImageLayout(
output, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral);
return output;
}
} // namespace
namespace escher {
MomentShadowMapRendererPtr MomentShadowMapRenderer::New(
@@ -42,7 +62,8 @@ MomentShadowMapRenderer::MomentShadowMapRenderer(
depth_format,
model_data,
model_renderer,
model_render_pass) {}
model_render_pass),
gaussian3x3f_(escher) {}
ShadowMapPtr MomentShadowMapRenderer::GenerateDirectionalShadowMap(
const FramePtr& frame,
@@ -63,9 +84,23 @@ ShadowMapPtr MomentShadowMapRenderer::GenerateDirectionalShadowMap(
DrawShadowPass(
command_buffer, shadow_stage, model, camera, color_image, depth_image);
frame->AddTimestamp("generated moment shadow map");
// TODO(ES-67): Apply Gaussian blur on color_image.
command_buffer->TransitionImageLayout(
color_image, vk::ImageLayout::eColorAttachmentOptimal,
vk::ImageLayout::eGeneral);
frame->AddTimestamp("transitioned layout to eGeneral");
auto input_texture = fxl::MakeRefCounted<Texture>(
escher()->resource_recycler(), color_image, vk::Filter::eNearest);
auto blurred_image = CreateSimilarImage(
escher(), command_buffer, color_image);
auto output_texture = fxl::MakeRefCounted<Texture>(
escher()->resource_recycler(), blurred_image, vk::Filter::eNearest);
gaussian3x3f_.Apply(command_buffer, input_texture, output_texture);
frame->AddTimestamp("applied 3x3 gaussian");
return SubmitPartialFrameAndBuildShadowMap<MomentShadowMap>(
frame, camera, color_image, light_color);
frame, camera, blurred_image, light_color);
}
} // namespace escher
@@ -4,6 +4,7 @@
#pragma once
#include "lib/escher/impl/gaussian_3x3f.h"
#include "lib/escher/renderer/shadow_map_renderer.h"
namespace escher {
@@ -35,6 +36,8 @@ class MomentShadowMapRenderer final : public ShadowMapRenderer {
const impl::ModelRenderPassPtr& model_render_pass);
private:
impl::Gaussian3x3f gaussian3x3f_;
FRIEND_MAKE_REF_COUNTED(MomentShadowMapRenderer);
FRIEND_REF_COUNTED_THREAD_SAFE(MomentShadowMapRenderer);
FXL_DISALLOW_COPY_AND_ASSIGN(MomentShadowMapRenderer);
@@ -96,7 +96,8 @@ ImagePtr ShadowMapRenderer::GetTransitionedColorImage(
info.sample_count = 1;
info.usage = vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eSampled |
vk::ImageUsageFlagBits::eTransferSrc;
vk::ImageUsageFlagBits::eTransferSrc |
vk::ImageUsageFlagBits::eStorage;
auto color_image = escher()->image_cache()->NewImage(info);
command_buffer->TransitionImageLayout(
color_image, vk::ImageLayout::eUndefined,

0 comments on commit 8185f23

Please sign in to comment.