blob: dcaa142fc2a5e0d45ddf7e8fcaac14bb7f30ff2d [file] [log] [blame]
//
// Copyright 2021 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.
//
// Header for the shared ShaderInterfaceVariableInfoMap class, used by both the
// Direct-to-Metal and Metal-SPIRV backends
#ifndef LIBANGLE_RENDERER_SHADERINTERFACEVARIABLEINFOMAP_H_
#define LIBANGLE_RENDERER_SHADERINTERFACEVARIABLEINFOMAP_H_
#include "common/FastVector.h"
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/renderer_utils.h"
#include <functional>
#include <stdio.h>
namespace rx
{
enum class ShaderVariableType
{
AtomicCounter,
Attribute,
DefaultUniform,
DriverUniform,
FramebufferFetch,
Image,
Output,
SecondaryOutput,
ShaderStorageBuffer,
Texture,
TransformFeedback,
UniformBuffer,
Varying,
EnumCount,
};
struct TypeAndIndex
{
ShaderVariableType variableType;
uint32_t index;
};
class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
{
public:
using VariableInfoArray = std::vector<ShaderInterfaceVariableInfo>;
using VariableTypeToInfoMap = angle::PackedEnumMap<ShaderVariableType, VariableInfoArray>;
using NameToTypeAndIndexMap = angle::HashMap<std::string, TypeAndIndex>;
static constexpr size_t kResourceFastMapMax = 32;
using ResourceIndexMap = angle::FastMap<uint32_t, kResourceFastMapMax>;
using VariableTypeToIndexMap = angle::PackedEnumMap<ShaderVariableType, ResourceIndexMap>;
ShaderInterfaceVariableInfoMap();
~ShaderInterfaceVariableInfoMap();
void clear();
void load(const gl::ShaderMap<VariableTypeToInfoMap> &data,
const gl::ShaderMap<NameToTypeAndIndexMap> &nameToTypeAndIndexMap,
const gl::ShaderMap<VariableTypeToIndexMap> &indexedResourceIndexMap);
ShaderInterfaceVariableInfo &add(gl::ShaderType shaderType,
ShaderVariableType variableType,
const std::string &variableName);
void markAsDuplicate(gl::ShaderType shaderType,
ShaderVariableType variableType,
const std::string &variableName);
ShaderInterfaceVariableInfo &addOrGet(gl::ShaderType shaderType,
ShaderVariableType variableType,
const std::string &variableName);
void setActiveStages(gl::ShaderType shaderType,
ShaderVariableType variableType,
const std::string &variableName,
gl::ShaderBitSet activeStages);
ShaderInterfaceVariableInfo &getMutable(gl::ShaderType shaderType,
ShaderVariableType variableType,
const std::string &variableName);
const ShaderInterfaceVariableInfo &getDefaultUniformInfo(gl::ShaderType shaderType) const;
const ShaderInterfaceVariableInfo &getIndexedVariableInfo(gl::ShaderType shaderType,
ShaderVariableType variableType,
uint32_t variableIndex) const;
bool hasAtomicCounterInfo(gl::ShaderType shaderType) const;
const ShaderInterfaceVariableInfo &getAtomicCounterInfo(gl::ShaderType shaderType) const;
const ShaderInterfaceVariableInfo &getFramebufferFetchInfo(gl::ShaderType shaderType) const;
#if ANGLE_ENABLE_METAL_SPIRV
bool hasTransformFeedbackInfo(gl::ShaderType shaderType, uint32_t bufferIndex) const;
#endif
const ShaderInterfaceVariableInfo &getTransformFeedbackInfo(gl::ShaderType shaderType,
uint32_t bufferIndex) const;
uint32_t getDefaultUniformBinding(gl::ShaderType shaderType) const;
uint32_t getXfbBufferBinding(uint32_t xfbBufferIndex) const;
uint32_t getAtomicCounterBufferBinding(gl::ShaderType shaderType,
uint32_t atomicCounterBufferIndex) const;
bool hasVariable(gl::ShaderType shaderType, const std::string &variableName) const;
const ShaderInterfaceVariableInfo &getVariableByName(gl::ShaderType shaderType,
const std::string &variableName) const;
void mapIndexedResourceByName(gl::ShaderType shaderType,
ShaderVariableType variableType,
uint32_t resourceIndex,
const std::string &variableName);
void mapIndexedResource(gl::ShaderType shaderType,
ShaderVariableType variableType,
uint32_t resourceIndex,
uint32_t variableIndex);
const VariableInfoArray &getAttributes() const;
const gl::ShaderMap<VariableTypeToInfoMap> &getData() const;
const gl::ShaderMap<NameToTypeAndIndexMap> &getNameToTypeAndIndexMap() const;
const gl::ShaderMap<VariableTypeToIndexMap> &getIndexedResourceMap() const;
private:
gl::ShaderMap<VariableTypeToInfoMap> mData;
gl::ShaderMap<NameToTypeAndIndexMap> mNameToTypeAndIndexMap;
gl::ShaderMap<VariableTypeToIndexMap> mIndexedResourceIndexMap;
};
ANGLE_INLINE const ShaderInterfaceVariableInfo &
ShaderInterfaceVariableInfoMap::getDefaultUniformInfo(gl::ShaderType shaderType) const
{
ASSERT(mData[shaderType][ShaderVariableType::DefaultUniform].size() == 1);
return mData[shaderType][ShaderVariableType::DefaultUniform][0];
}
ANGLE_INLINE const ShaderInterfaceVariableInfo &
ShaderInterfaceVariableInfoMap::getIndexedVariableInfo(gl::ShaderType shaderType,
ShaderVariableType variableType,
uint32_t resourceIndex) const
{
ASSERT(resourceIndex < mIndexedResourceIndexMap[shaderType][variableType].size());
uint32_t variableIndex = mIndexedResourceIndexMap[shaderType][variableType][resourceIndex];
ASSERT(variableIndex < mData[shaderType][variableType].size());
return mData[shaderType][variableType][variableIndex];
}
ANGLE_INLINE bool ShaderInterfaceVariableInfoMap::hasAtomicCounterInfo(
gl::ShaderType shaderType) const
{
return !mData[shaderType][ShaderVariableType::AtomicCounter].empty();
}
ANGLE_INLINE const ShaderInterfaceVariableInfo &
ShaderInterfaceVariableInfoMap::getAtomicCounterInfo(gl::ShaderType shaderType) const
{
ASSERT(mData[shaderType][ShaderVariableType::AtomicCounter].size() == 1);
return mData[shaderType][ShaderVariableType::AtomicCounter][0];
}
ANGLE_INLINE const ShaderInterfaceVariableInfo &
ShaderInterfaceVariableInfoMap::getFramebufferFetchInfo(gl::ShaderType shaderType) const
{
ASSERT(!mData[shaderType][ShaderVariableType::FramebufferFetch].empty());
return mData[shaderType][ShaderVariableType::FramebufferFetch][0];
}
ANGLE_INLINE const ShaderInterfaceVariableInfo &
ShaderInterfaceVariableInfoMap::getTransformFeedbackInfo(gl::ShaderType shaderType,
uint32_t bufferIndex) const
{
ASSERT(bufferIndex < mData[shaderType][ShaderVariableType::TransformFeedback].size());
return mData[shaderType][ShaderVariableType::TransformFeedback][bufferIndex];
}
ANGLE_INLINE uint32_t
ShaderInterfaceVariableInfoMap::getDefaultUniformBinding(gl::ShaderType shaderType) const
{
return getDefaultUniformInfo(shaderType).binding;
}
ANGLE_INLINE uint32_t
ShaderInterfaceVariableInfoMap::getXfbBufferBinding(uint32_t xfbBufferIndex) const
{
// Note: we only use this method for transform feedback emulation. And emulation only supports
// XFB in the vertex shader.
return getTransformFeedbackInfo(gl::ShaderType::Vertex, xfbBufferIndex).binding;
}
ANGLE_INLINE uint32_t ShaderInterfaceVariableInfoMap::getAtomicCounterBufferBinding(
gl::ShaderType shaderType,
uint32_t atomicCounterBufferIndex) const
{
ASSERT(hasAtomicCounterInfo(shaderType));
return getAtomicCounterInfo(shaderType).binding + atomicCounterBufferIndex;
}
} // namespace rx
#endif // LIBANGLE_RENDERER_SHADERINTERFACEVARIABLEINFOMAP_H_