Files
FlaxEngine/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.VS.h
2020-12-07 23:40:54 +01:00

156 lines
4.8 KiB
C++

// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
#pragma once
#include "ShaderFunctionReader.h"
#include "ShaderProcessing.h"
#include "Engine/Graphics/Shaders/Config.h"
#if COMPILE_WITH_SHADER_COMPILER
namespace ShaderProcessing
{
/// <summary>
/// Vertex Shaders reader
/// </summary>
class VertexShaderFunctionReader : public ShaderFunctionReader<VertexShaderMeta>
{
class InputLayoutReader : public ITokenReader
{
protected:
VertexShaderFunctionReader* _parent;
Token _startToken;
public:
InputLayoutReader(VertexShaderFunctionReader* parent)
: _parent(parent)
, _startToken("META_VS_IN_ELEMENT")
{
}
public:
// [ITokenReader]
bool CheckStartToken(const Token& token) override
{
return token == _startToken;
}
void Process(IShaderParser* parser, Reader& text) override
{
VertexShaderMeta::InputElement element;
Token token;
auto& current = _parent->_current;
// Semantic type
text.ReadToken(&token);
element.Type = ParseInputType(token);
// Semantic index
text.ReadToken(&token);
if (StringUtils::Parse(token.Start, token.Length, &element.Index))
{
parser->OnError(TEXT("Cannot parse token."));
return;
}
// Element format
text.ReadToken(&token);
element.Format = ParsePixelFormat(token);
if (element.Format == PixelFormat::Unknown)
{
parser->OnError(String::Format(TEXT("Unknown input data format \'{0}\' for the Vertex Shader."), String(token.ToString())));
return;
}
// Input slot
text.ReadToken(&token);
if (StringUtils::Parse(token.Start, token.Length, &element.InputSlot))
{
parser->OnError(TEXT("Cannot parse token."));
return;
}
// Aligned byte offset
text.ReadToken(&token);
if (token == "ALIGN")
{
element.AlignedByteOffset = INPUT_LAYOUT_ELEMENT_ALIGN;
}
else if (StringUtils::Parse(token.Start, token.Length, &element.AlignedByteOffset))
{
parser->OnError(TEXT("Cannot parse token."));
return;
}
// Input slot class
text.ReadToken(&token);
if (token == "PER_VERTEX")
{
element.InputSlotClass = INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA;
}
else if (token == "PER_INSTANCE")
{
element.InputSlotClass = INPUT_LAYOUT_ELEMENT_PER_INSTANCE_DATA;
}
else
{
parser->OnError(String::Format(TEXT("Invalid input slot class type \'{0}\'."), String(token.ToString())));
return;
}
// Instance data step rate
text.ReadToken(&token);
if (StringUtils::Parse(token.Start, token.Length, &element.InstanceDataStepRate))
{
parser->OnError(TEXT("Cannot parse token."));
return;
}
// Visible state
text.ReadToken(&token);
element.VisibleFlag = token.ToString();
current.InputLayout.Add(element);
}
};
DECLARE_SHADER_META_READER_HEADER("META_VS", VS);
VertexShaderFunctionReader()
{
_childReaders.Add(New<InputLayoutReader>(this));
}
~VertexShaderFunctionReader()
{
}
void OnParseBefore(IShaderParser* parser, Reader& text) override
{
// Clear current meta
_current.InputLayout.Clear();
// Base
ShaderFunctionReader::OnParseBefore(parser, text);
}
void OnParseAfter(IShaderParser* parser, Reader& text) override
{
// Check if errors in specified input layout
if (_current.InputLayout.Count() > VERTEX_SHADER_MAX_INPUT_ELEMENTS)
{
parser->OnError(String::Format(TEXT("Vertex Shader \'{0}\' has too many input layout elements specified. Maximum allowed amount is {1}."), String(_current.Name), VERTEX_SHADER_MAX_INPUT_ELEMENTS));
return;
}
// Base
ShaderFunctionReader::OnParseAfter(parser, text);
}
};
}
#endif