331 lines
11 KiB
Objective-C
331 lines
11 KiB
Objective-C
//
|
|
// Copyright Contributors to the MaterialX Project
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
#ifndef MATERIALX_MSLPROGRAM_H
|
|
#define MATERIALX_MSLPROGRAM_H
|
|
|
|
/// @file
|
|
/// MSL Program interfaces
|
|
|
|
#include <MaterialXRenderMsl/Export.h>
|
|
|
|
#include <MaterialXRender/Camera.h>
|
|
#include <MaterialXRender/GeometryHandler.h>
|
|
#include <MaterialXRender/ImageHandler.h>
|
|
#include <MaterialXRender/LightHandler.h>
|
|
|
|
#include <MaterialXGenShader/Shader.h>
|
|
|
|
#import <Metal/Metal.h>
|
|
|
|
MATERIALX_NAMESPACE_BEGIN
|
|
|
|
// Shared pointer to a MslProgram
|
|
using MslProgramPtr = std::shared_ptr<class MslProgram>;
|
|
using MetalFramebufferPtr = std::shared_ptr<class MetalFramebuffer>;
|
|
|
|
/// @class MslProgram
|
|
/// A class representing an executable MSL program.
|
|
///
|
|
/// There are two main interfaces which can be used. One which takes in a HwShader and one which
|
|
/// allows for explicit setting of shader stage code.
|
|
class MX_RENDERMSL_API MslProgram
|
|
{
|
|
public:
|
|
/// Create a MSL program instance
|
|
static MslProgramPtr create()
|
|
{
|
|
return MslProgramPtr(new MslProgram());
|
|
}
|
|
|
|
/// Destructor
|
|
virtual ~MslProgram();
|
|
|
|
/// @name Shader code setup
|
|
/// @{
|
|
|
|
/// Set up code stages to validate based on an input hardware shader.
|
|
/// @param shader Hardware shader to use
|
|
void setStages(ShaderPtr shader);
|
|
|
|
/// Set the code stages based on a list of stage strings.
|
|
/// Refer to the ordering of stages as defined by a HwShader.
|
|
/// @param stage Name of the shader stage.
|
|
/// @param sourceCode Source code of the shader stage.
|
|
void addStage(const string& stage, const string& sourceCode);
|
|
|
|
/// Get source code string for a given stage.
|
|
/// @return Shader stage string. String is empty if not found.
|
|
const string& getStageSourceCode(const string& stage) const;
|
|
|
|
/// Clear out any existing stages
|
|
void clearStages();
|
|
|
|
/// Return the shader, if any, used to generate this program.
|
|
ShaderPtr getShader() const
|
|
{
|
|
return _shader;
|
|
}
|
|
|
|
/// @}
|
|
/// @name Program validation and introspection
|
|
/// @{
|
|
|
|
/// Create the pipeline state object from stages specified
|
|
/// @param device MetalDevice that pipeline state object is being created on.
|
|
/// @param framebuffer specifies information about output frame buffer.
|
|
/// An exception is thrown if the program cannot be created.
|
|
/// The exception will contain a list of program creation errors.
|
|
/// @return Pipeline State Object identifier.
|
|
id<MTLRenderPipelineState> build(id<MTLDevice> device, MetalFramebufferPtr frameBuffer);
|
|
|
|
/// Structure to hold information about program inputs.
|
|
/// The structure is populated by directly scanning the program so may not contain
|
|
/// some inputs listed on any associated HwShader as those inputs may have been
|
|
/// optimized out if they are unused.
|
|
struct MX_RENDERMSL_API Input
|
|
{
|
|
static MTLDataType INVALID_METAL_TYPE;
|
|
|
|
/// Program location. -1 means an invalid location
|
|
int location;
|
|
/// Metal type of the input.
|
|
MTLDataType resourceType;
|
|
/// Size.
|
|
int size;
|
|
/// Input type string. Will only be non-empty if initialized stages with a HwShader
|
|
string typeString;
|
|
/// Input value. Will only be non-empty if initialized stages with a HwShader and a value was set during
|
|
/// shader generation.
|
|
MaterialX::ConstValuePtr value;
|
|
/// Is this a constant
|
|
bool isConstant;
|
|
/// Element path (if any)
|
|
string path;
|
|
/// Unit
|
|
string unit;
|
|
/// Colorspace
|
|
string colorspace;
|
|
|
|
/// Program input constructor
|
|
Input(int inputLocation, MTLDataType inputType, int inputSize, const string& inputPath) :
|
|
location(inputLocation),
|
|
resourceType(inputType),
|
|
size(inputSize),
|
|
isConstant(false),
|
|
path(inputPath)
|
|
{
|
|
}
|
|
};
|
|
/// Program input structure shared pointer type
|
|
using InputPtr = std::shared_ptr<Input>;
|
|
/// Program input shaded pointer map type
|
|
using InputMap = std::unordered_map<string, InputPtr>;
|
|
|
|
/// Get list of program input uniforms.
|
|
/// The program must have been created successfully first.
|
|
/// An exception is thrown if the parsing of the program for uniforms cannot be performed.
|
|
/// @return Program uniforms list.
|
|
const InputMap& getUniformsList();
|
|
|
|
/// Get list of program input attributes.
|
|
/// The program must have been created successfully first.
|
|
/// An exception is thrown if the parsing of the program for attribute cannot be performed.
|
|
/// @return Program attributes list.
|
|
const InputMap& getAttributesList();
|
|
|
|
/// Find the locations in the program which starts with a given variable name
|
|
/// @param variable Variable to search for
|
|
/// @param variableList List of program inputs to search
|
|
/// @param foundList Returned list of found program inputs. Empty if none found.
|
|
/// @param exactMatch Search for exact variable name match.
|
|
void findInputs(const string& variable,
|
|
const InputMap& variableList,
|
|
InputMap& foundList,
|
|
bool exactMatch);
|
|
|
|
/// @}
|
|
/// @name Program activation
|
|
/// @{
|
|
|
|
/// Bind the pipeline state object to the command encoder.
|
|
/// @param renderCmdEncoder encoder that binds the pipeline state object.
|
|
/// @return False if failed
|
|
bool bind(id<MTLRenderCommandEncoder> renderCmdEncoder);
|
|
|
|
/// Bind inputs
|
|
/// @param renderCmdEncoder encoder that inputs will be bound to.
|
|
/// @param cam Camera object use to view the object
|
|
/// @param geometryHandler
|
|
/// @param imageHandler
|
|
/// @param lightHandler
|
|
/// @return void - No return value
|
|
void prepareUsedResources(id<MTLRenderCommandEncoder> renderCmdEncoder,
|
|
CameraPtr cam,
|
|
GeometryHandlerPtr geometryHandler,
|
|
ImageHandlerPtr imageHandler,
|
|
LightHandlerPtr lightHandler);
|
|
|
|
/// Return true if a uniform with the given name is present.
|
|
bool hasUniform(const string& name);
|
|
|
|
/// Bind a value to the uniform with the given name.
|
|
void bindUniform(const string& name, ConstValuePtr value, bool errorIfMissing = true);
|
|
|
|
/// Bind attribute buffers to attribute inputs.
|
|
/// A hardware buffer of the given attribute type is created and bound to the program locations
|
|
/// for the input attribute.
|
|
/// @param renderCmdEncoder Metal Render Command Encoder that the attribute being bind to
|
|
/// @param inputs Attribute inputs to bind to
|
|
/// @param mesh Mesh containing streams to bind
|
|
void bindAttribute(id<MTLRenderCommandEncoder> renderCmdEncoder,
|
|
const MslProgram::InputMap& inputs,
|
|
MeshPtr mesh);
|
|
|
|
/// Bind input geometry partition (indexing)
|
|
void bindPartition(MeshPartitionPtr partition);
|
|
|
|
/// Bind input geometry streams
|
|
void bindMesh(id<MTLRenderCommandEncoder> renderCmdEncoder, MeshPtr mesh);
|
|
|
|
/// Queries the index buffer assigned to a mesh partition
|
|
id<MTLBuffer> getIndexBuffer(MeshPartitionPtr mesh)
|
|
{
|
|
if (_indexBufferIds.find(mesh) != _indexBufferIds.end())
|
|
return _indexBufferIds[mesh];
|
|
return nil;
|
|
}
|
|
|
|
/// Unbind any bound geometry
|
|
void unbindGeometry();
|
|
|
|
/// Bind any input textures
|
|
void bindTextures(id<MTLRenderCommandEncoder> renderCmdEncoder,
|
|
LightHandlerPtr lightHandler,
|
|
ImageHandlerPtr imageHandler);
|
|
|
|
void bindTexture(ImageHandlerPtr imageHandler,
|
|
string shaderTextureName,
|
|
ImagePtr imagePtr,
|
|
ImageSamplingProperties samplingProperties);
|
|
|
|
/// Bind lighting
|
|
void bindLighting(LightHandlerPtr lightHandler, ImageHandlerPtr imageHandler);
|
|
|
|
/// Bind view information
|
|
void bindViewInformation(CameraPtr camera);
|
|
|
|
/// Bind time and frame
|
|
void bindTimeAndFrame(float time = 1.0f, float frame = 1.0f);
|
|
|
|
/// @}
|
|
/// @name Utilities
|
|
/// @{
|
|
|
|
/// Returns if alpha blending is enabled.
|
|
bool isTransparent() const { return _alphaBlendingEnabled; }
|
|
|
|
/// Specify textures bound to this program shouldn't be mip mapped.
|
|
void setEnableMipMaps(bool enableMipMapping) { _enableMipMapping = enableMipMapping; }
|
|
|
|
/// Print all uniforms to the given stream.
|
|
void printUniforms(std::ostream& outputStream);
|
|
|
|
/// Print all attributes to the given stream.
|
|
void printAttributes(std::ostream& outputStream);
|
|
|
|
/// @}
|
|
|
|
public:
|
|
static unsigned int UNDEFINED_METAL_RESOURCE_ID;
|
|
static int UNDEFINED_METAL_PROGRAM_LOCATION;
|
|
|
|
protected:
|
|
MslProgram();
|
|
|
|
// Update a list of program input uniforms
|
|
const InputMap& updateUniformsList();
|
|
|
|
// Update a list of program input attributes
|
|
const InputMap& updateAttributesList();
|
|
|
|
// Clear out any cached input lists
|
|
void clearInputLists();
|
|
|
|
// Utility to find a uniform value in an uniform list.
|
|
// If uniform cannot be found a null pointer will be return.
|
|
ConstValuePtr findUniformValue(const string& uniformName, const InputMap& uniformList);
|
|
|
|
// Bind an individual texture to a program uniform location
|
|
ImagePtr bindTexture(id<MTLRenderCommandEncoder> renderCmdEncoder,
|
|
unsigned int uniformLocation,
|
|
const FilePath& filePath,
|
|
ImageSamplingProperties samplingProperties,
|
|
ImageHandlerPtr imageHandler);
|
|
|
|
// Bind an individual texture to a program uniform location
|
|
ImagePtr bindTexture(id<MTLRenderCommandEncoder> renderCmdEncoder,
|
|
unsigned int uniformLocation,
|
|
ImagePtr imagePtr,
|
|
ImageHandlerPtr imageHandler);
|
|
|
|
void bindUniformBuffers(id<MTLRenderCommandEncoder> renderCmdEncoder,
|
|
LightHandlerPtr lightHandler,
|
|
CameraPtr camera);
|
|
|
|
// Delete any currently created pso
|
|
void reset();
|
|
|
|
// Utility to map a MaterialX type to an METAL type
|
|
static MTLDataType mapTypeToMetalType(TypeDesc type);
|
|
|
|
private:
|
|
// Stages used to create program
|
|
// Map of stage name and its source code
|
|
StringMap _stages;
|
|
|
|
// Generated pipeline state object. A non-zero number indicates a valid shader program.
|
|
id<MTLRenderPipelineState> _pso = nil;
|
|
MTLRenderPipelineReflection* _psoReflection = nil;
|
|
|
|
// List of program input uniforms
|
|
InputMap _uniformList;
|
|
std::unordered_map<std::string, std::string> _globalUniformNameList;
|
|
// List of program input attributes
|
|
InputMap _attributeList;
|
|
|
|
std::unordered_map<std::string, ImagePtr> _explicitBoundImages;
|
|
|
|
// Hardware shader (if any) used for program creation
|
|
ShaderPtr _shader;
|
|
|
|
// Attribute buffer resource handles
|
|
// for each attribute identifier in the program
|
|
std::unordered_map<string, id<MTLBuffer>> _attributeBufferIds;
|
|
|
|
// Attribute indexing buffer handle
|
|
std::map<MeshPartitionPtr, id<MTLBuffer>> _indexBufferIds;
|
|
|
|
// Program texture map
|
|
std::unordered_map<string, unsigned int> _programTextures;
|
|
|
|
// Metal Device Object
|
|
id<MTLDevice> _device = nil;
|
|
|
|
// Currently bound mesh
|
|
MeshPtr _boundMesh = nullptr;
|
|
|
|
bool _alphaBlendingEnabled = false;
|
|
|
|
float _time = 0.0f;
|
|
float _frame = 0.0f;
|
|
|
|
bool _enableMipMapping = true;
|
|
};
|
|
|
|
MATERIALX_NAMESPACE_END
|
|
|
|
#endif
|