blob: 61806511851b7622408c63942cf29a8456c5c55d [file] [log] [blame]
// 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.
#ifndef SRC_UI_LIB_ESCHER_VK_SHADER_PROGRAM_H_
#define SRC_UI_LIB_ESCHER_VK_SHADER_PROGRAM_H_
#include "src/ui/lib/escher/resources/resource.h"
#include "src/ui/lib/escher/util/enum_cast.h"
#include "src/ui/lib/escher/util/enum_count.h"
#include "src/ui/lib/escher/util/hash.h"
#include "src/ui/lib/escher/util/hash_map.h"
#include "src/ui/lib/escher/vk/sampler.h"
#include "src/ui/lib/escher/vk/shader_module.h"
namespace escher {
class ResourceRecycler;
class ShaderProgram;
using ShaderProgramPtr = fxl::RefPtr<ShaderProgram>;
// ShaderProgram encapsulates a set of ShaderModules, which are used to generate
// vk::Pipelines. This is done in collaboration with CommandBuffer; different
// pipelines may be required depending on the current CommandBuffer state.
// ShaderProgram listens for changes in the ShaderModules; whenever new SPIR-V
// is available, all existing pipelines are invalidated and will be lazily
// regenerated upon demand.
class ShaderProgram : public Resource, private ShaderModuleListener {
public:
static const ResourceTypeInfo kTypeInfo;
const ResourceTypeInfo& type_info() const override { return kTypeInfo; }
// Graphics program.
static ShaderProgramPtr NewGraphics(
ResourceRecycler* resource_recycler,
std::vector<ShaderModulePtr> shader_modules);
// Compute program.
static ShaderProgramPtr NewCompute(ResourceRecycler* resource_recycler,
ShaderModulePtr shader_module);
~ShaderProgram() override;
// NOTE: The following public methods are called by the CommandBuffer
// implementation, and are not useful to Escher clients.
// Return the pipeline layout for this program, operating with the optional
// immutable sampler passed in (pass the null vk::Sampler handle to opt-out).
//
// TODO(ES-202): This code-flow assumes that ShaderPrograms source from, at
// most, a single sampler. This is a blocking bug for implementing, e.g.,
// ES-159.
PipelineLayout* ObtainPipelineLayout(const SamplerPtr& immutable_sampler);
// Return the module corresponding to the specified shader stage, or nullptr
// if the program has no shader for that stage (e.g. many graphics programs
// will not have a geometry shader).
const ShaderModulePtr& GetModuleForStage(ShaderStage stage) const;
// Simple HashMap lookup and insertion.
vk::Pipeline FindPipeline(Hash hash) const;
void StashPipeline(Hash hash, vk::Pipeline pipeline);
private:
// Called by NewGraphics() and NewCompute(), respectively.
ShaderProgram(ResourceRecycler* resource_recycler,
std::vector<ShaderModulePtr> shader_modules);
ShaderProgram(ResourceRecycler* resource_recycler,
ShaderModulePtr shader_module);
// Used by ClearCurrentPipelineLayout() and ClearPipelineStash() as an easy
// way to have the ResourceRecycler keep the obsolete pipelines alive until
// safe to destroy them.
explicit ShaderProgram(ResourceManager* owner);
void OnShaderModuleUpdated(ShaderModule* shader_module) override;
void ClearPipelineLayout();
void ClearPipelineStash();
std::array<ShaderModulePtr, EnumCount<ShaderStage>()> shader_modules_;
// TODO(ES-201): These are effectively strong references to vk::Pipelines --
// it is assumed that this object will be responsible for deleting them when
// they go out of scope. During normal execution (e.g., without a shader
// refresh) this cache is never cleared.
HashMap<Hash, vk::Pipeline> graphics_pipelines_;
PipelineLayoutPtr pipeline_layout_;
};
// Inline function definitions.
inline const ShaderModulePtr& ShaderProgram::GetModuleForStage(
ShaderStage stage) const {
FXL_DCHECK(stage != ShaderStage::kEnumCount);
return shader_modules_[EnumCast(stage)];
}
inline vk::Pipeline ShaderProgram::FindPipeline(Hash hash) const {
auto it = graphics_pipelines_.find(hash);
return it != graphics_pipelines_.end() ? it->second : vk::Pipeline();
}
inline void ShaderProgram::StashPipeline(Hash hash, vk::Pipeline pipeline) {
FXL_DCHECK(!FindPipeline(hash));
graphics_pipelines_[hash] = pipeline;
}
} // namespace escher
#endif // SRC_UI_LIB_ESCHER_VK_SHADER_PROGRAM_H_