blob: 38ab93a59401d0ea73d25b5562ba0a7141103da7 [file] [log] [blame] [edit]
//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Shader.h: Defines the abstract gl::Shader class and its concrete derived
// classes VertexShader and FragmentShader. Implements GL shader objects and
// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
// 3.8 page 84.
#ifndef LIBANGLE_SHADER_H_
#define LIBANGLE_SHADER_H_
#include <list>
#include <memory>
#include <string>
#include <vector>
#include <GLSLANG/ShaderLang.h>
#include "angle_gl.h"
#include "common/BinaryStream.h"
#include "common/CompiledShaderState.h"
#include "common/MemoryBuffer.h"
#include "common/Optional.h"
#include "common/angleutils.h"
#include "libANGLE/BlobCache.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Debug.h"
#include "libANGLE/angletypes.h"
namespace rx
{
class GLImplFactory;
class ShaderImpl;
class ShaderSh;
class WaitableCompileEvent;
} // namespace rx
namespace angle
{
class WaitableEvent;
class WorkerThreadPool;
} // namespace angle
namespace gl
{
class CompileTask;
class Context;
class ShaderProgramManager;
class State;
class BinaryInputStream;
class BinaryOutputStream;
// We defer the compile until link time, or until properties are queried.
enum class CompileStatus
{
NOT_COMPILED,
COMPILE_REQUESTED,
COMPILED,
};
class ShaderState final : angle::NonCopyable
{
public:
ShaderState(ShaderType shaderType);
~ShaderState();
const std::string &getLabel() const { return mLabel; }
const std::string &getSource() const { return mSource; }
bool isCompiledToBinary() const { return !mCompiledShaderState.compiledBinary.empty(); }
const std::string &getTranslatedSource() const { return mCompiledShaderState.translatedSource; }
const sh::BinaryBlob &getCompiledBinary() const { return mCompiledShaderState.compiledBinary; }
ShaderType getShaderType() const { return mCompiledShaderState.shaderType; }
int getShaderVersion() const { return mCompiledShaderState.shaderVersion; }
const std::vector<sh::ShaderVariable> &getInputVaryings() const
{
return mCompiledShaderState.inputVaryings;
}
const std::vector<sh::ShaderVariable> &getOutputVaryings() const
{
return mCompiledShaderState.outputVaryings;
}
const std::vector<sh::ShaderVariable> &getUniforms() const
{
return mCompiledShaderState.uniforms;
}
const std::vector<sh::InterfaceBlock> &getUniformBlocks() const
{
return mCompiledShaderState.uniformBlocks;
}
const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const
{
return mCompiledShaderState.shaderStorageBlocks;
}
const std::vector<sh::ShaderVariable> &getActiveAttributes() const
{
return mCompiledShaderState.activeAttributes;
}
const std::vector<sh::ShaderVariable> &getAllAttributes() const
{
return mCompiledShaderState.allAttributes;
}
const std::vector<sh::ShaderVariable> &getActiveOutputVariables() const
{
return mCompiledShaderState.activeOutputVariables;
}
bool compilePending() const { return mCompileStatus == CompileStatus::COMPILE_REQUESTED; }
const sh::WorkGroupSize &getLocalSize() const { return mCompiledShaderState.localSize; }
bool hasClipDistance() const { return mCompiledShaderState.hasClipDistance; }
bool hasDiscard() const { return mCompiledShaderState.hasDiscard; }
bool enablesPerSampleShading() const { return mCompiledShaderState.enablesPerSampleShading; }
rx::SpecConstUsageBits getSpecConstUsageBits() const
{
return mCompiledShaderState.specConstUsageBits;
}
int getNumViews() const { return mCompiledShaderState.numViews; }
Optional<PrimitiveMode> getGeometryShaderInputPrimitiveType() const
{
return mCompiledShaderState.geometryShaderInputPrimitiveType;
}
Optional<PrimitiveMode> getGeometryShaderOutputPrimitiveType() const
{
return mCompiledShaderState.geometryShaderOutputPrimitiveType;
}
Optional<GLint> getGeometryShaderMaxVertices() const
{
return mCompiledShaderState.geometryShaderMaxVertices;
}
Optional<GLint> getGeometryShaderInvocations() const
{
return mCompiledShaderState.geometryShaderInvocations;
}
CompileStatus getCompileStatus() const { return mCompileStatus; }
private:
friend class Shader;
std::string mLabel;
std::string mSource;
size_t mSourceHash = 0;
gl::CompiledShaderState mCompiledShaderState;
// Indicates if this shader has been successfully compiled
CompileStatus mCompileStatus = CompileStatus::NOT_COMPILED;
};
class Shader final : angle::NonCopyable, public LabeledObject
{
public:
Shader(ShaderProgramManager *manager,
rx::GLImplFactory *implFactory,
const gl::Limitations &rendererLimitations,
ShaderType type,
ShaderProgramID handle);
void onDestroy(const Context *context);
angle::Result setLabel(const Context *context, const std::string &label) override;
const std::string &getLabel() const override;
ShaderType getType() const { return mType; }
ShaderProgramID getHandle() const;
rx::ShaderImpl *getImplementation() const { return mImplementation.get(); }
void setSource(const Context *context,
GLsizei count,
const char *const *string,
const GLint *length);
int getInfoLogLength(const Context *context);
void getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog);
std::string getInfoLogString() const { return mInfoLog; }
int getSourceLength() const;
const std::string &getSourceString() const { return mState.getSource(); }
void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
int getTranslatedSourceLength(const Context *context);
int getTranslatedSourceWithDebugInfoLength(const Context *context);
const std::string &getTranslatedSource(const Context *context);
void getTranslatedSource(const Context *context,
GLsizei bufSize,
GLsizei *length,
char *buffer);
void getTranslatedSourceWithDebugInfo(const Context *context,
GLsizei bufSize,
GLsizei *length,
char *buffer);
const sh::BinaryBlob &getCompiledBinary(const Context *context);
size_t getSourceHash() const;
void compile(const Context *context);
bool isCompiled(const Context *context);
bool isCompleted();
void addRef();
void release(const Context *context);
unsigned int getRefCount() const;
bool isFlaggedForDeletion() const;
void flagForDeletion();
bool hasClipDistance() const { return mState.mCompiledShaderState.hasClipDistance; }
bool hasDiscard() const { return mState.mCompiledShaderState.hasDiscard; }
bool enablesPerSampleShading() const
{
return mState.mCompiledShaderState.enablesPerSampleShading;
}
BlendEquationBitSet getAdvancedBlendEquations() const
{
return mState.mCompiledShaderState.advancedBlendEquations;
}
rx::SpecConstUsageBits getSpecConstUsageBits() const
{
return mState.mCompiledShaderState.specConstUsageBits;
}
int getShaderVersion(const Context *context);
const std::vector<sh::ShaderVariable> &getInputVaryings(const Context *context);
const std::vector<sh::ShaderVariable> &getOutputVaryings(const Context *context);
const std::vector<sh::ShaderVariable> &getUniforms(const Context *context);
const std::vector<sh::InterfaceBlock> &getUniformBlocks(const Context *context);
const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks(const Context *context);
const std::vector<sh::ShaderVariable> &getActiveAttributes(const Context *context);
const std::vector<sh::ShaderVariable> &getAllAttributes(const Context *context);
const std::vector<sh::ShaderVariable> &getActiveOutputVariables(const Context *context);
// Returns mapped name of a transform feedback varying. The original name may contain array
// brackets with an index inside, which will get copied to the mapped name. The varying must be
// known to be declared in the shader.
std::string getTransformFeedbackVaryingMappedName(const Context *context,
const std::string &tfVaryingName);
const sh::WorkGroupSize &getWorkGroupSize(const Context *context);
int getNumViews(const Context *context);
Optional<PrimitiveMode> getGeometryShaderInputPrimitiveType(const Context *context);
Optional<PrimitiveMode> getGeometryShaderOutputPrimitiveType(const Context *context);
int getGeometryShaderInvocations(const Context *context);
Optional<GLint> getGeometryShaderMaxVertices(const Context *context);
int getTessControlShaderVertices(const Context *context);
GLenum getTessGenMode(const Context *context);
GLenum getTessGenSpacing(const Context *context);
GLenum getTessGenVertexOrder(const Context *context);
GLenum getTessGenPointMode(const Context *context);
const ShaderState &getState() const { return mState; }
GLuint getCurrentMaxComputeWorkGroupInvocations() const
{
return mCurrentMaxComputeWorkGroupInvocations;
}
unsigned int getMaxComputeSharedMemory() const { return mMaxComputeSharedMemory; }
bool hasBeenDeleted() const { return mDeleteStatus; }
// Block until compiling is finished and resolve it.
void resolveCompile(const Context *context);
// Writes a shader's binary to the output memory buffer.
angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
angle::Result deserialize(BinaryInputStream &stream);
// Load a binary from shader cache.
angle::Result loadBinary(const Context *context, const void *binary, GLsizei length);
// Load a binary from a glShaderBinary call.
angle::Result loadShaderBinary(const Context *context, const void *binary, GLsizei length);
void writeShaderKey(BinaryOutputStream *streamOut) const
{
ASSERT(streamOut && !mShaderHash.empty());
streamOut->writeBytes(mShaderHash.data(), egl::BlobCache::kKeyLength);
return;
}
private:
struct CompilingState;
~Shader() override;
static std::string joinShaderSources(GLsizei count,
const char *const *string,
const GLint *length);
static void GetSourceImpl(const std::string &source,
GLsizei bufSize,
GLsizei *length,
char *buffer);
angle::Result loadBinaryImpl(const Context *context,
const void *binary,
GLsizei length,
bool generatedWithOfflineCompiler);
// Compute a key to uniquely identify the shader object in memory caches.
void setShaderKey(const Context *context,
const ShCompileOptions &compileOptions,
const ShShaderOutput &outputType,
const ShBuiltInResources &resources);
ShaderState mState;
std::unique_ptr<rx::ShaderImpl> mImplementation;
const gl::Limitations mRendererLimitations;
const ShaderProgramID mHandle;
const ShaderType mType;
unsigned int mRefCount; // Number of program objects this shader is attached to
bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use
std::string mInfoLog;
// We keep a reference to the translator in order to defer compiles while preserving settings.
BindingPointer<Compiler> mBoundCompiler;
std::unique_ptr<CompilingState> mCompilingState;
egl::BlobCache::Key mShaderHash;
ShaderProgramManager *mResourceManager;
GLuint mCurrentMaxComputeWorkGroupInvocations;
unsigned int mMaxComputeSharedMemory;
};
const char *GetShaderTypeString(ShaderType type);
std::string GetShaderDumpFileDirectory();
std::string GetShaderDumpFileName(size_t shaderHash);
} // namespace gl
#endif // LIBANGLE_SHADER_H_