mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
336 lines
8.9 KiB
C++
336 lines
8.9 KiB
C++
#ifndef OPENMW_COMPONENTS_FX_TECHNIQUE_H
|
|
#define OPENMW_COMPONENTS_FX_TECHNIQUE_H
|
|
|
|
#include <filesystem>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
#include <osg/BlendEquation>
|
|
#include <osg/BlendFunc>
|
|
#include <osg/FrameBufferObject>
|
|
#include <osg/Node>
|
|
#include <osg/Program>
|
|
#include <osg/Shader>
|
|
#include <osg/StateSet>
|
|
#include <osg/Texture2D>
|
|
#include <osg/Vec2f>
|
|
#include <osg/Vec3f>
|
|
#include <osg/Vec4f>
|
|
|
|
#include "lexer.hpp"
|
|
#include "pass.hpp"
|
|
#include "types.hpp"
|
|
|
|
namespace Resource
|
|
{
|
|
class ImageManager;
|
|
}
|
|
|
|
namespace VFS
|
|
{
|
|
class Manager;
|
|
}
|
|
|
|
namespace fx
|
|
{
|
|
using FlagsType = size_t;
|
|
|
|
struct DispatchNode
|
|
{
|
|
DispatchNode() = default;
|
|
|
|
DispatchNode(const DispatchNode& other, const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
|
|
: mHandle(other.mHandle)
|
|
, mFlags(other.mFlags)
|
|
, mRootStateSet(other.mRootStateSet)
|
|
{
|
|
mPasses.reserve(other.mPasses.size());
|
|
|
|
for (const auto& subpass : other.mPasses)
|
|
mPasses.emplace_back(subpass, copyOp);
|
|
}
|
|
|
|
struct SubPass
|
|
{
|
|
SubPass() = default;
|
|
|
|
osg::ref_ptr<osg::StateSet> mStateSet = new osg::StateSet;
|
|
osg::ref_ptr<osg::FrameBufferObject> mRenderTarget;
|
|
osg::ref_ptr<osg::Texture2D> mRenderTexture;
|
|
bool mResolve = false;
|
|
|
|
SubPass(const SubPass& other, const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
|
|
: mStateSet(new osg::StateSet(*other.mStateSet, copyOp))
|
|
, mResolve(other.mResolve)
|
|
{
|
|
if (other.mRenderTarget)
|
|
mRenderTarget = new osg::FrameBufferObject(*other.mRenderTarget, copyOp);
|
|
if (other.mRenderTexture)
|
|
mRenderTexture = new osg::Texture2D(*other.mRenderTexture, copyOp);
|
|
}
|
|
};
|
|
|
|
void compile()
|
|
{
|
|
for (auto rit = mPasses.rbegin(); rit != mPasses.rend(); ++rit)
|
|
{
|
|
if (!rit->mRenderTarget)
|
|
{
|
|
rit->mResolve = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// not safe to read/write in draw thread
|
|
std::shared_ptr<fx::Technique> mHandle = nullptr;
|
|
|
|
FlagsType mFlags = 0;
|
|
|
|
std::vector<SubPass> mPasses;
|
|
|
|
osg::ref_ptr<osg::StateSet> mRootStateSet = new osg::StateSet;
|
|
};
|
|
|
|
using DispatchArray = std::vector<DispatchNode>;
|
|
|
|
class Technique
|
|
{
|
|
public:
|
|
using PassList = std::vector<std::shared_ptr<Pass>>;
|
|
using TexList = std::vector<osg::ref_ptr<osg::Texture>>;
|
|
|
|
using UniformMap = std::vector<std::shared_ptr<Types::UniformBase>>;
|
|
using RenderTargetMap = std::unordered_map<std::string_view, Types::RenderTarget>;
|
|
|
|
inline static std::string sExt = ".omwfx";
|
|
inline static std::string sSubdir = "shaders";
|
|
|
|
enum class Status
|
|
{
|
|
Success,
|
|
Uncompiled,
|
|
File_Not_exists,
|
|
Parse_Error
|
|
};
|
|
|
|
static constexpr FlagsType Flag_Disable_Interiors = (1 << 0);
|
|
static constexpr FlagsType Flag_Disable_Exteriors = (1 << 1);
|
|
static constexpr FlagsType Flag_Disable_Underwater = (1 << 2);
|
|
static constexpr FlagsType Flag_Disable_Abovewater = (1 << 3);
|
|
static constexpr FlagsType Flag_Disable_SunGlare = (1 << 4);
|
|
static constexpr FlagsType Flag_Hidden = (1 << 5);
|
|
|
|
Technique(const VFS::Manager& vfs, Resource::ImageManager& imageManager, std::string name, int width,
|
|
int height, bool ubo, bool supportsNormals);
|
|
|
|
bool compile();
|
|
|
|
std::string getName() const;
|
|
|
|
std::string getFileName() const;
|
|
|
|
bool setLastModificationTime(std::filesystem::file_time_type timeStamp);
|
|
|
|
bool isValid() const { return mValid; }
|
|
|
|
bool getHDR() const { return mHDR; }
|
|
|
|
bool getNormals() const { return mNormals && mSupportsNormals; }
|
|
|
|
bool getLights() const { return mLights; }
|
|
|
|
const PassList& getPasses() { return mPasses; }
|
|
|
|
const TexList& getTextures() const { return mTextures; }
|
|
|
|
Status getStatus() const { return mStatus; }
|
|
|
|
std::string_view getAuthor() const { return mAuthor; }
|
|
|
|
std::string_view getDescription() const { return mDescription; }
|
|
|
|
std::string_view getVersion() const { return mVersion; }
|
|
|
|
int getGLSLVersion() const { return mGLSLVersion; }
|
|
|
|
std::string getGLSLProfile() const { return mGLSLProfile; }
|
|
|
|
const std::unordered_set<std::string>& getGLSLExtensions() const { return mGLSLExtensions; }
|
|
|
|
FlagsType getFlags() const { return mFlags; }
|
|
|
|
bool getHidden() const { return mFlags & Flag_Hidden; }
|
|
|
|
UniformMap& getUniformMap() { return mDefinedUniforms; }
|
|
|
|
RenderTargetMap& getRenderTargetsMap() { return mRenderTargets; }
|
|
|
|
std::string getLastError() const { return mLastError; }
|
|
|
|
UniformMap::iterator findUniform(const std::string& name);
|
|
|
|
bool getDynamic() const { return mDynamic; }
|
|
|
|
void setLocked(bool locked) { mLocked = locked; }
|
|
bool getLocked() const { return mLocked; }
|
|
|
|
private:
|
|
[[noreturn]] void error(const std::string& msg);
|
|
|
|
void clear();
|
|
|
|
std::string_view asLiteral() const;
|
|
|
|
template <class T>
|
|
void expect(const std::string& err = "");
|
|
|
|
template <class T, class T2>
|
|
void expect(const std::string& err = "");
|
|
|
|
template <class T>
|
|
bool isNext();
|
|
|
|
void parse(std::string&& buffer);
|
|
|
|
template <class SrcT, class T>
|
|
void parseUniform();
|
|
|
|
template <class T>
|
|
void parseSampler();
|
|
|
|
template <class T>
|
|
void parseBlock(bool named = true);
|
|
|
|
template <class T>
|
|
void parseBlockImp()
|
|
{
|
|
}
|
|
|
|
void parseBlockHeader();
|
|
|
|
bool parseBool();
|
|
|
|
std::string_view parseString();
|
|
|
|
float parseFloat();
|
|
|
|
int parseInteger();
|
|
|
|
int parseInternalFormat();
|
|
|
|
int parseSourceType();
|
|
|
|
int parseSourceFormat();
|
|
|
|
osg::BlendEquation::Equation parseBlendEquation();
|
|
|
|
osg::BlendFunc::BlendFuncMode parseBlendFuncMode();
|
|
|
|
osg::Texture::WrapMode parseWrapMode();
|
|
|
|
osg::Texture::InternalFormatMode parseCompression();
|
|
|
|
FlagsType parseFlags();
|
|
|
|
osg::Texture::FilterMode parseFilterMode();
|
|
|
|
template <class TDelimeter>
|
|
std::vector<std::string_view> parseLiteralList();
|
|
|
|
template <class OSGVec, class T>
|
|
OSGVec parseVec();
|
|
|
|
std::string getBlockWithLineDirective();
|
|
|
|
std::unique_ptr<Lexer::Lexer> mLexer;
|
|
Lexer::Token mToken;
|
|
|
|
std::string mShared;
|
|
std::string mName;
|
|
std::string mFileName;
|
|
std::string_view mBlockName;
|
|
std::string_view mAuthor;
|
|
std::string_view mDescription;
|
|
std::string_view mVersion;
|
|
|
|
std::unordered_set<std::string> mGLSLExtensions;
|
|
int mGLSLVersion;
|
|
std::string mGLSLProfile;
|
|
|
|
FlagsType mFlags;
|
|
|
|
Status mStatus;
|
|
|
|
bool mEnabled;
|
|
|
|
std::filesystem::file_time_type mLastModificationTime;
|
|
bool mValid;
|
|
bool mHDR;
|
|
bool mNormals;
|
|
bool mLights;
|
|
int mWidth;
|
|
int mHeight;
|
|
|
|
RenderTargetMap mRenderTargets;
|
|
|
|
TexList mTextures;
|
|
PassList mPasses;
|
|
|
|
std::unordered_map<std::string_view, std::shared_ptr<Pass>> mPassMap;
|
|
std::vector<std::string_view> mPassKeys;
|
|
|
|
Pass::Type mLastAppliedType;
|
|
|
|
UniformMap mDefinedUniforms;
|
|
|
|
const VFS::Manager& mVFS;
|
|
Resource::ImageManager& mImageManager;
|
|
bool mUBO;
|
|
bool mSupportsNormals;
|
|
|
|
std::string mBuffer;
|
|
|
|
std::string mLastError;
|
|
|
|
bool mDynamic = false;
|
|
bool mLocked = false;
|
|
};
|
|
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Shared>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Technique>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Render_Target>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Vertex>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Fragment>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Compute>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Sampler_1D>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Sampler_2D>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Sampler_3D>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Uniform_Bool>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Uniform_Float>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Uniform_Int>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Uniform_Vec2>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Uniform_Vec3>();
|
|
template <>
|
|
void Technique::parseBlockImp<Lexer::Uniform_Vec4>();
|
|
}
|
|
|
|
#endif
|