Commit 711b7a12 by Xinghua Cao Committed by Commit Bot

ES31: Support images in the compiler on D3D backend.

BUG=angleproject:1987 TEST=angle_end2end_tests Change-Id: I83f5f9ffda7e676a8f98b963d1f1c50e9463faf4 Reviewed-on: https://chromium-review.googlesource.com/706247 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 7478ce7f
...@@ -226,6 +226,8 @@ ...@@ -226,6 +226,8 @@
'compiler/translator/StructureHLSL.h', 'compiler/translator/StructureHLSL.h',
'compiler/translator/TextureFunctionHLSL.cpp', 'compiler/translator/TextureFunctionHLSL.cpp',
'compiler/translator/TextureFunctionHLSL.h', 'compiler/translator/TextureFunctionHLSL.h',
'compiler/translator/ImageFunctionHLSL.cpp',
'compiler/translator/ImageFunctionHLSL.h',
'compiler/translator/TranslatorHLSL.cpp', 'compiler/translator/TranslatorHLSL.cpp',
'compiler/translator/TranslatorHLSL.h', 'compiler/translator/TranslatorHLSL.h',
'compiler/translator/UnfoldShortCircuitToIf.cpp', 'compiler/translator/UnfoldShortCircuitToIf.cpp',
......
...@@ -477,6 +477,106 @@ inline bool IsShadowSampler(TBasicType type) ...@@ -477,6 +477,106 @@ inline bool IsShadowSampler(TBasicType type)
return false; return false;
} }
inline bool IsImage2D(TBasicType type)
{
switch (type)
{
case EbtImage2D:
case EbtIImage2D:
case EbtUImage2D:
return true;
case EbtImage3D:
case EbtIImage3D:
case EbtUImage3D:
case EbtImage2DArray:
case EbtIImage2DArray:
case EbtUImage2DArray:
case EbtImageCube:
case EbtIImageCube:
case EbtUImageCube:
return false;
default:
assert(!IsImage(type));
}
return false;
}
inline bool IsImage3D(TBasicType type)
{
switch (type)
{
case EbtImage3D:
case EbtIImage3D:
case EbtUImage3D:
return true;
case EbtImage2D:
case EbtIImage2D:
case EbtUImage2D:
case EbtImage2DArray:
case EbtIImage2DArray:
case EbtUImage2DArray:
case EbtImageCube:
case EbtIImageCube:
case EbtUImageCube:
return false;
default:
assert(!IsImage(type));
}
return false;
}
inline bool IsImage2DArray(TBasicType type)
{
switch (type)
{
case EbtImage2DArray:
case EbtIImage2DArray:
case EbtUImage2DArray:
return true;
case EbtImage2D:
case EbtIImage2D:
case EbtUImage2D:
case EbtImage3D:
case EbtIImage3D:
case EbtUImage3D:
case EbtImageCube:
case EbtIImageCube:
case EbtUImageCube:
return false;
default:
assert(!IsImage(type));
}
return false;
}
inline bool IsImageCube(TBasicType type)
{
switch (type)
{
case EbtImageCube:
case EbtIImageCube:
case EbtUImageCube:
return true;
case EbtImage2D:
case EbtIImage2D:
case EbtUImage2D:
case EbtImage3D:
case EbtIImage3D:
case EbtUImage3D:
case EbtImage2DArray:
case EbtIImage2DArray:
case EbtUImage2DArray:
return false;
default:
assert(!IsImage(type));
}
return false;
}
inline bool IsInteger(TBasicType type) inline bool IsInteger(TBasicType type)
{ {
return type == EbtInt || type == EbtUInt; return type == EbtInt || type == EbtUInt;
......
//
// Copyright (c) 2017 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.
//
// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output.
//
#include "compiler/translator/ImageFunctionHLSL.h"
#include "compiler/translator/UtilsHLSL.h"
namespace sh
{
// static
void ImageFunctionHLSL::OutputImageFunctionArgumentList(
TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction)
{
if (imageFunction.readonly)
{
out << TextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex";
}
else
{
out << RWTextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex";
}
if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD ||
imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
{
switch (imageFunction.image)
{
case EbtImage2D:
case EbtIImage2D:
case EbtUImage2D:
out << ", int2 p";
break;
case EbtImage3D:
case EbtIImage3D:
case EbtUImage3D:
case EbtImageCube:
case EbtIImageCube:
case EbtUImageCube:
case EbtImage2DArray:
case EbtIImage2DArray:
case EbtUImage2DArray:
out << ", int3 p";
break;
default:
UNREACHABLE();
}
if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
{
switch (imageFunction.image)
{
case EbtImage2D:
case EbtImage3D:
case EbtImageCube:
case EbtImage2DArray:
out << ", float4 data";
break;
case EbtIImage2D:
case EbtIImage3D:
case EbtIImageCube:
case EbtIImage2DArray:
out << ", int4 data";
break;
case EbtUImage2D:
case EbtUImage3D:
case EbtUImageCube:
case EbtUImage2DArray:
out << ", uint4 data";
break;
default:
UNREACHABLE();
}
}
}
}
// static
void ImageFunctionHLSL::OutputImageSizeFunctionBody(
TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction,
const TString &imageReference)
{
if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
IsImageCube(imageFunction.image))
{
// "depth" stores either the number of layers in an array texture or 3D depth
out << " uint width; uint height; uint depth;\n"
<< " " << imageReference << ".GetDimensions(width, height, depth);\n";
}
else if (IsImage2D(imageFunction.image))
{
out << " uint width; uint height;\n"
<< " " << imageReference << ".GetDimensions(width, height);\n";
}
else
UNREACHABLE();
if (strcmp(imageFunction.getReturnType(), "int3") == 0)
{
out << " return int3(width, height, depth);\n";
}
else
{
out << " return int2(width, height);\n";
}
}
// static
void ImageFunctionHLSL::OutputImageLoadFunctionBody(
TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction,
const TString &imageReference)
{
if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
IsImageCube(imageFunction.image))
{
out << " return " << imageReference << "[uint3(p.x, p.y, p.z)];\n";
}
else if (IsImage2D(imageFunction.image))
{
out << " return " << imageReference << "[uint2(p.x, p.y)];\n";
}
else
UNREACHABLE();
}
// static
void ImageFunctionHLSL::OutputImageStoreFunctionBody(
TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction,
const TString &imageReference)
{
if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image))
{
out << " " << imageReference << "[p] = data;\n";
}
else
UNREACHABLE();
}
TString ImageFunctionHLSL::ImageFunction::name() const
{
TString name = "gl_image";
if (readonly)
{
name += TextureTypeSuffix(image, imageInternalFormat);
}
else
{
name += RWTextureTypeSuffix(image, imageInternalFormat);
}
switch (method)
{
case Method::SIZE:
name += "Size";
break;
case Method::LOAD:
name += "Load";
break;
case Method::STORE:
name += "Store";
break;
default:
UNREACHABLE();
}
return name;
}
const char *ImageFunctionHLSL::ImageFunction::getReturnType() const
{
if (method == ImageFunction::Method::SIZE)
{
switch (image)
{
case EbtImage2D:
case EbtIImage2D:
case EbtUImage2D:
case EbtImageCube:
case EbtIImageCube:
case EbtUImageCube:
return "int2";
case EbtImage3D:
case EbtIImage3D:
case EbtUImage3D:
case EbtImage2DArray:
case EbtIImage2DArray:
case EbtUImage2DArray:
return "int3";
default:
UNREACHABLE();
}
}
else if (method == ImageFunction::Method::LOAD)
{
switch (image)
{
case EbtImage2D:
case EbtImage3D:
case EbtImageCube:
case EbtImage2DArray:
return "float4";
case EbtIImage2D:
case EbtIImage3D:
case EbtIImageCube:
case EbtIImage2DArray:
return "int4";
case EbtUImage2D:
case EbtUImage3D:
case EbtUImageCube:
case EbtUImage2DArray:
return "uint4";
default:
UNREACHABLE();
}
}
else if (method == ImageFunction::Method::STORE)
{
return "void";
}
else
{
UNREACHABLE();
}
return "";
}
bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const
{
return std::tie(image, imageInternalFormat, readonly, method) <
std::tie(rhs.image, rhs.imageInternalFormat, rhs.readonly, rhs.method);
}
TString ImageFunctionHLSL::useImageFunction(const TString &name,
const TBasicType &type,
TLayoutImageInternalFormat imageInternalFormat,
bool readonly)
{
ASSERT(IsImage(type));
ImageFunction imageFunction;
imageFunction.image = type;
imageFunction.imageInternalFormat = imageInternalFormat;
imageFunction.readonly = readonly;
if (name == "imageSize")
{
imageFunction.method = ImageFunction::Method::SIZE;
}
else if (name == "imageLoad")
{
imageFunction.method = ImageFunction::Method::LOAD;
}
else if (name == "imageStore")
{
imageFunction.method = ImageFunction::Method::STORE;
}
else
UNREACHABLE();
mUsesImage.insert(imageFunction);
return imageFunction.name();
}
void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out)
{
for (const ImageFunction &imageFunction : mUsesImage)
{
// Function header
out << imageFunction.getReturnType() << " " << imageFunction.name() << "(";
OutputImageFunctionArgumentList(out, imageFunction);
out << ")\n"
"{\n";
TString imageReference("tex");
if (imageFunction.method == ImageFunction::Method::SIZE)
{
OutputImageSizeFunctionBody(out, imageFunction, imageReference);
}
else if (imageFunction.method == ImageFunction::Method::LOAD)
{
OutputImageLoadFunctionBody(out, imageFunction, imageReference);
}
else
{
OutputImageStoreFunctionBody(out, imageFunction, imageReference);
}
out << "}\n"
"\n";
}
}
} // namespace sh
//
// Copyright (c) 2017 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.
//
// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output.
//
#ifndef COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_
#define COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_
#include <set>
#include "GLSLANG/ShaderLang.h"
#include "compiler/translator/BaseTypes.h"
#include "compiler/translator/Common.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/Types.h"
namespace sh
{
class ImageFunctionHLSL final : angle::NonCopyable
{
public:
// Returns the name of the image function implementation to caller.
// The name that's passed in is the name of the GLSL image function that it should implement.
TString useImageFunction(const TString &name,
const TBasicType &type,
TLayoutImageInternalFormat imageInternalFormat,
bool readonly);
void imageFunctionHeader(TInfoSinkBase &out);
private:
struct ImageFunction
{
// See ESSL 3.10.4 section 8.12 for reference about what the different methods below do.
enum class Method
{
SIZE,
LOAD,
STORE
};
TString name() const;
bool operator<(const ImageFunction &rhs) const;
const char *getReturnType() const;
TBasicType image;
TLayoutImageInternalFormat imageInternalFormat;
bool readonly;
Method method;
};
static void OutputImageFunctionArgumentList(
TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction);
static void OutputImageSizeFunctionBody(TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction,
const TString &imageReference);
static void OutputImageLoadFunctionBody(TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction,
const TString &imageReference);
static void OutputImageStoreFunctionBody(TInfoSinkBase &out,
const ImageFunctionHLSL::ImageFunction &imageFunction,
const TString &imageReference);
using ImageFunctionSet = std::set<ImageFunction>;
ImageFunctionSet mUsesImage;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_
...@@ -556,6 +556,11 @@ class TFunctionSymbolInfo ...@@ -556,6 +556,11 @@ class TFunctionSymbolInfo
void setId(const TSymbolUniqueId &functionId); void setId(const TSymbolUniqueId &functionId);
const TSymbolUniqueId &getId() const; const TSymbolUniqueId &getId() const;
bool isImageFunction() const
{
return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore";
}
private: private:
TName mName; TName mName;
TSymbolUniqueId *mId; TSymbolUniqueId *mId;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" #include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/FlagStd140Structs.h" #include "compiler/translator/FlagStd140Structs.h"
#include "compiler/translator/ImageFunctionHLSL.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/NodeSearch.h" #include "compiler/translator/NodeSearch.h"
#include "compiler/translator/RemoveSwitchFallThrough.h" #include "compiler/translator/RemoveSwitchFallThrough.h"
...@@ -165,8 +166,9 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, ...@@ -165,8 +166,9 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
mExcessiveLoopIndex = nullptr; mExcessiveLoopIndex = nullptr;
mStructureHLSL = new StructureHLSL; mStructureHLSL = new StructureHLSL;
mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms); mUniformHLSL = new UniformHLSL(shaderType, mStructureHLSL, outputType, uniforms);
mTextureFunctionHLSL = new TextureFunctionHLSL; mTextureFunctionHLSL = new TextureFunctionHLSL;
mImageFunctionHLSL = new ImageFunctionHLSL;
if (mOutputType == SH_HLSL_3_0_OUTPUT) if (mOutputType == SH_HLSL_3_0_OUTPUT)
{ {
...@@ -186,6 +188,7 @@ OutputHLSL::~OutputHLSL() ...@@ -186,6 +188,7 @@ OutputHLSL::~OutputHLSL()
SafeDelete(mStructureHLSL); SafeDelete(mStructureHLSL);
SafeDelete(mUniformHLSL); SafeDelete(mUniformHLSL);
SafeDelete(mTextureFunctionHLSL); SafeDelete(mTextureFunctionHLSL);
SafeDelete(mImageFunctionHLSL);
for (auto &eqFunction : mStructEqualityFunctions) for (auto &eqFunction : mStructEqualityFunctions)
{ {
SafeDelete(eqFunction); SafeDelete(eqFunction);
...@@ -731,6 +734,7 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built ...@@ -731,6 +734,7 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
bool getDimensionsIgnoresBaseLevel = bool getDimensionsIgnoresBaseLevel =
(mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0; (mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0;
mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel); mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel);
mImageFunctionHLSL->imageFunctionHeader(out);
if (mUsesFragCoord) if (mUsesFragCoord)
{ {
...@@ -1865,6 +1869,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1865,6 +1869,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
// AST, such as precision emulation functions. // AST, such as precision emulation functions.
out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "("; out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
} }
else if (node->getFunctionSymbolInfo()->isImageFunction())
{
TString name = node->getFunctionSymbolInfo()->getName();
TType type = (*arguments)[0]->getAsTyped()->getType();
TString imageFunctionName = mImageFunctionHLSL->useImageFunction(
name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat,
type.getMemoryQualifier().readonly);
out << imageFunctionName << "(";
}
else else
{ {
const TString &name = node->getFunctionSymbolInfo()->getName(); const TString &name = node->getFunctionSymbolInfo()->getName();
......
...@@ -23,6 +23,7 @@ namespace sh ...@@ -23,6 +23,7 @@ namespace sh
class StructureHLSL; class StructureHLSL;
class TextureFunctionHLSL; class TextureFunctionHLSL;
class TSymbolTable; class TSymbolTable;
class ImageFunctionHLSL;
class UnfoldShortCircuit; class UnfoldShortCircuit;
class UniformHLSL; class UniformHLSL;
...@@ -164,6 +165,7 @@ class OutputHLSL : public TIntermTraverser ...@@ -164,6 +165,7 @@ class OutputHLSL : public TIntermTraverser
StructureHLSL *mStructureHLSL; StructureHLSL *mStructureHLSL;
UniformHLSL *mUniformHLSL; UniformHLSL *mUniformHLSL;
TextureFunctionHLSL *mTextureFunctionHLSL; TextureFunctionHLSL *mTextureFunctionHLSL;
ImageFunctionHLSL *mImageFunctionHLSL;
// Parameters determining what goes in the header output // Parameters determining what goes in the header output
bool mUsesFragColor; bool mUsesFragColor;
......
...@@ -92,12 +92,16 @@ void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out, ...@@ -92,12 +92,16 @@ void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out,
} // anonymous namespace } // anonymous namespace
UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, UniformHLSL::UniformHLSL(sh::GLenum shaderType,
StructureHLSL *structureHLSL,
ShShaderOutput outputType, ShShaderOutput outputType,
const std::vector<Uniform> &uniforms) const std::vector<Uniform> &uniforms)
: mUniformRegister(0), : mUniformRegister(0),
mUniformBlockRegister(0), mUniformBlockRegister(0),
mSamplerRegister(0), mTextureRegister(0),
mRWTextureRegister(0),
mSamplerCount(0),
mShaderType(shaderType),
mStructureHLSL(structureHLSL), mStructureHLSL(structureHLSL),
mOutputType(outputType), mOutputType(outputType),
mUniforms(uniforms) mUniforms(uniforms)
...@@ -131,19 +135,36 @@ unsigned int UniformHLSL::assignUniformRegister(const TType &type, ...@@ -131,19 +135,36 @@ unsigned int UniformHLSL::assignUniformRegister(const TType &type,
const TString &name, const TString &name,
unsigned int *outRegisterCount) unsigned int *outRegisterCount)
{ {
unsigned int registerIndex = unsigned int registerIndex;
(IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
const Uniform *uniform = findUniformByName(name); const Uniform *uniform = findUniformByName(name);
ASSERT(uniform); ASSERT(uniform);
if (IsSampler(type.getBasicType()) ||
(IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly))
{
registerIndex = mTextureRegister;
}
else if (IsImage(type.getBasicType()))
{
registerIndex = mRWTextureRegister;
}
else
{
registerIndex = mUniformRegister;
}
mUniformRegisterMap[uniform->name] = registerIndex; mUniformRegisterMap[uniform->name] = registerIndex;
unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
if (gl::IsSamplerType(uniform->type)) if (IsSampler(type.getBasicType()) ||
(IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly))
{ {
mSamplerRegister += registerCount; mTextureRegister += registerCount;
}
else if (IsImage(type.getBasicType()))
{
mRWTextureRegister += registerCount;
} }
else else
{ {
...@@ -162,10 +183,10 @@ unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type ...@@ -162,10 +183,10 @@ unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type
{ {
// Sampler that is a field of a uniform structure. // Sampler that is a field of a uniform structure.
ASSERT(IsSampler(type.getBasicType())); ASSERT(IsSampler(type.getBasicType()));
unsigned int registerIndex = mSamplerRegister; unsigned int registerIndex = mTextureRegister;
mUniformRegisterMap[std::string(name.c_str())] = registerIndex; mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u; unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u;
mSamplerRegister += registerCount; mTextureRegister += registerCount;
if (outRegisterCount) if (outRegisterCount)
{ {
*outRegisterCount = registerCount; *outRegisterCount = registerCount;
...@@ -175,7 +196,7 @@ unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type ...@@ -175,7 +196,7 @@ unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type
void UniformHLSL::outputHLSLSamplerUniformGroup( void UniformHLSL::outputHLSLSamplerUniformGroup(
TInfoSinkBase &out, TInfoSinkBase &out,
const HLSLTextureSamplerGroup textureGroup, const HLSLTextureGroup textureGroup,
const TVector<const TIntermSymbol *> &group, const TVector<const TIntermSymbol *> &group,
const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames, const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
unsigned int *groupTextureRegisterIndex) unsigned int *groupTextureRegisterIndex)
...@@ -251,6 +272,46 @@ void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, ...@@ -251,6 +272,46 @@ void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
<< str(registerIndex) << ");\n"; << str(registerIndex) << ");\n";
} }
void UniformHLSL::outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const unsigned int registerIndex)
{
// TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
// Texture2DArray. Translate this variable to HLSL Texture3D object or HLSL Texture2DArray
// object, or create a temporary Texture2D to save content of the layer and bind the
// temporary Texture2D to image2D variable.
out << "uniform "
<< TextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) << " "
<< DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t"
<< str(registerIndex) << ");\n";
return;
}
void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const unsigned int registerIndex)
{
// TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
// Texture2DArray. Translate this variable to HLSL RWTexture3D object or HLSL RWTexture2DArray
// object, or create a temporary Texture2D to save content of the layer and bind the
// temporary Texture2D to image2D variable.
if (mShaderType == GL_COMPUTE_SHADER)
{
out << "uniform "
<< RWTextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat)
<< " " << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(u"
<< str(registerIndex) << ");\n";
}
else
{
// TODO(xinghua.cao@intel.com): Support images in vertex shader and fragment shader,
// which are needed to sync binding value when linking program.
}
return;
}
void UniformHLSL::outputUniform(TInfoSinkBase &out, void UniformHLSL::outputUniform(TInfoSinkBase &out,
const TType &type, const TType &type,
const TName &name, const TName &name,
...@@ -290,6 +351,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -290,6 +351,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
// HLSL sampler type, enumerated in HLSLTextureSamplerGroup. // HLSL sampler type, enumerated in HLSLTextureSamplerGroup.
TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1); TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1);
TMap<const TIntermSymbol *, TString> samplerInStructSymbolsToAPINames; TMap<const TIntermSymbol *, TString> samplerInStructSymbolsToAPINames;
TVector<const TIntermSymbol *> imageUniformsHLSL41Output;
for (auto &uniformIt : referencedUniforms) for (auto &uniformIt : referencedUniforms)
{ {
// Output regular uniforms. Group sampler uniforms by type. // Output regular uniforms. Group sampler uniforms by type.
...@@ -299,7 +361,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -299,7 +361,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType())) if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
{ {
HLSLTextureSamplerGroup group = TextureGroup(type.getBasicType()); HLSLTextureGroup group = TextureGroup(type.getBasicType());
groupedSamplerUniforms[group].push_back(&uniform); groupedSamplerUniforms[group].push_back(&uniform);
} }
else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType())) else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
...@@ -307,6 +369,10 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -307,6 +369,10 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr); unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex); outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex);
} }
else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType()))
{
imageUniformsHLSL41Output.push_back(&uniform);
}
else else
{ {
if (type.isStructureContainingSamplers()) if (type.isStructureContainingSamplers())
...@@ -325,7 +391,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -325,7 +391,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
if (outputType == SH_HLSL_4_1_OUTPUT) if (outputType == SH_HLSL_4_1_OUTPUT)
{ {
HLSLTextureSamplerGroup group = TextureGroup(samplerType.getBasicType()); HLSLTextureGroup group = TextureGroup(samplerType.getBasicType());
groupedSamplerUniforms[group].push_back(sampler); groupedSamplerUniforms[group].push_back(sampler);
samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler]; samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler];
} }
...@@ -357,16 +423,32 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -357,16 +423,32 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId) for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
{ {
outputHLSLSamplerUniformGroup( outputHLSLSamplerUniformGroup(
out, HLSLTextureSamplerGroup(groupId), groupedSamplerUniforms[groupId], out, HLSLTextureGroup(groupId), groupedSamplerUniforms[groupId],
samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex); samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex);
} }
mSamplerCount = groupTextureRegisterIndex;
for (const TIntermSymbol *image : imageUniformsHLSL41Output)
{
const TType &type = image->getType();
const TName &name = image->getName();
unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
if (type.getMemoryQualifier().readonly)
{
outputHLSL4_1_FL11Texture(out, type, name, registerIndex);
}
else
{
outputHLSL4_1_FL11RWTexture(out, type, name, registerIndex);
}
}
} }
} }
void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg) void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
{ {
// If mSamplerRegister is 0 the shader doesn't use any textures. // If mSamplerCount is 0 the shader doesn't use any textures for samplers.
if (mSamplerRegister > 0) if (mSamplerCount > 0)
{ {
out << " struct SamplerMetadata\n" out << " struct SamplerMetadata\n"
" {\n" " {\n"
...@@ -376,7 +458,7 @@ void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg) ...@@ -376,7 +458,7 @@ void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
" int padding;\n" " int padding;\n"
" };\n" " };\n"
" SamplerMetadata samplerMetadata[" " SamplerMetadata samplerMetadata["
<< mSamplerRegister << "] : packoffset(" << reg << ");\n"; << mSamplerCount << "] : packoffset(" << reg << ");\n";
} }
} }
......
...@@ -21,7 +21,8 @@ class TSymbolTable; ...@@ -21,7 +21,8 @@ class TSymbolTable;
class UniformHLSL : angle::NonCopyable class UniformHLSL : angle::NonCopyable
{ {
public: public:
UniformHLSL(StructureHLSL *structureHLSL, UniformHLSL(sh::GLenum shaderType,
StructureHLSL *structureHLSL,
ShShaderOutput outputType, ShShaderOutput outputType,
const std::vector<Uniform> &uniforms); const std::vector<Uniform> &uniforms);
...@@ -63,7 +64,14 @@ class UniformHLSL : angle::NonCopyable ...@@ -63,7 +64,14 @@ class UniformHLSL : angle::NonCopyable
const TType &type, const TType &type,
const TName &name, const TName &name,
const unsigned int registerIndex); const unsigned int registerIndex);
void outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const unsigned int registerIndex);
void outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const unsigned int registerIndex);
void outputUniform(TInfoSinkBase &out, void outputUniform(TInfoSinkBase &out,
const TType &type, const TType &type,
const TName &name, const TName &name,
...@@ -79,14 +87,17 @@ class UniformHLSL : angle::NonCopyable ...@@ -79,14 +87,17 @@ class UniformHLSL : angle::NonCopyable
void outputHLSLSamplerUniformGroup( void outputHLSLSamplerUniformGroup(
TInfoSinkBase &out, TInfoSinkBase &out,
const HLSLTextureSamplerGroup textureGroup, const HLSLTextureGroup textureGroup,
const TVector<const TIntermSymbol *> &group, const TVector<const TIntermSymbol *> &group,
const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames, const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
unsigned int *groupTextureRegisterIndex); unsigned int *groupTextureRegisterIndex);
unsigned int mUniformRegister; unsigned int mUniformRegister;
unsigned int mUniformBlockRegister; unsigned int mUniformBlockRegister;
unsigned int mSamplerRegister; unsigned int mTextureRegister;
unsigned int mRWTextureRegister;
unsigned int mSamplerCount;
sh::GLenum mShaderType;
StructureHLSL *mStructureHLSL; StructureHLSL *mStructureHLSL;
ShShaderOutput mOutputType; ShShaderOutput mOutputType;
......
...@@ -27,7 +27,7 @@ TString SamplerString(const TBasicType type) ...@@ -27,7 +27,7 @@ TString SamplerString(const TBasicType type)
} }
} }
TString SamplerString(HLSLTextureSamplerGroup type) TString SamplerString(HLSLTextureGroup type)
{ {
if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END) if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END)
{ {
...@@ -39,7 +39,8 @@ TString SamplerString(HLSLTextureSamplerGroup type) ...@@ -39,7 +39,8 @@ TString SamplerString(HLSLTextureSamplerGroup type)
} }
} }
HLSLTextureSamplerGroup TextureGroup(const TBasicType type) HLSLTextureGroup TextureGroup(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{ {
switch (type) switch (type)
{ {
...@@ -81,24 +82,170 @@ HLSLTextureSamplerGroup TextureGroup(const TBasicType type) ...@@ -81,24 +82,170 @@ HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
return HLSL_TEXTURE_CUBE_COMPARISON; return HLSL_TEXTURE_CUBE_COMPARISON;
case EbtSampler2DArrayShadow: case EbtSampler2DArrayShadow:
return HLSL_TEXTURE_2D_ARRAY_COMPARISON; return HLSL_TEXTURE_2D_ARRAY_COMPARISON;
case EbtImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_TEXTURE_2D;
case EiifRGBA8:
return HLSL_TEXTURE_2D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_TEXTURE_2D_SNORM;
default:
UNREACHABLE();
}
}
case EbtIImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_TEXTURE_2D_INT4;
default:
UNREACHABLE();
}
}
case EbtUImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_TEXTURE_2D_UINT4;
default:
UNREACHABLE();
}
}
case EbtImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_TEXTURE_3D;
case EiifRGBA8:
return HLSL_TEXTURE_3D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_TEXTURE_3D_SNORM;
default:
UNREACHABLE();
}
}
case EbtIImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_TEXTURE_3D_INT4;
default:
UNREACHABLE();
}
}
case EbtUImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_TEXTURE_3D_UINT4;
default:
UNREACHABLE();
}
}
case EbtImage2DArray:
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_TEXTURE_2D_ARRAY;
case EiifRGBA8:
return HLSL_TEXTURE_2D_ARRAY_UNORN;
case EiifRGBA8_SNORM:
return HLSL_TEXTURE_2D_ARRAY_SNORM;
default:
UNREACHABLE();
}
}
case EbtIImage2DArray:
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_TEXTURE_2D_ARRAY_INT4;
default:
UNREACHABLE();
}
}
case EbtUImage2DArray:
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_TEXTURE_2D_ARRAY_UINT4;
default:
UNREACHABLE();
}
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
return HLSL_TEXTURE_UNKNOWN; return HLSL_TEXTURE_UNKNOWN;
} }
TString TextureString(const HLSLTextureSamplerGroup type) TString TextureString(const HLSLTextureGroup textureGroup)
{ {
switch (type) switch (textureGroup)
{ {
case HLSL_TEXTURE_2D: case HLSL_TEXTURE_2D:
return "Texture2D"; return "Texture2D<float4>";
case HLSL_TEXTURE_CUBE: case HLSL_TEXTURE_CUBE:
return "TextureCube"; return "TextureCube<float4>";
case HLSL_TEXTURE_2D_ARRAY: case HLSL_TEXTURE_2D_ARRAY:
return "Texture2DArray"; return "Texture2DArray<float4>";
case HLSL_TEXTURE_3D: case HLSL_TEXTURE_3D:
return "Texture3D"; return "Texture3D<float4>";
case HLSL_TEXTURE_2D_UNORM:
return "Texture2D<unorm float4>";
case HLSL_TEXTURE_CUBE_UNORM:
return "TextureCube<unorm float4>";
case HLSL_TEXTURE_2D_ARRAY_UNORN:
return "Texture2DArray<unorm float4>";
case HLSL_TEXTURE_3D_UNORM:
return "Texture3D<unorm float4>";
case HLSL_TEXTURE_2D_SNORM:
return "Texture2D<snorm float4>";
case HLSL_TEXTURE_CUBE_SNORM:
return "TextureCube<snorm float4>";
case HLSL_TEXTURE_2D_ARRAY_SNORM:
return "Texture2DArray<snorm float4>";
case HLSL_TEXTURE_3D_SNORM:
return "Texture3D<snorm float4>";
case HLSL_TEXTURE_2D_MS: case HLSL_TEXTURE_2D_MS:
return "Texture2DMS<float4>"; return "Texture2DMS<float4>";
case HLSL_TEXTURE_2D_INT4: case HLSL_TEXTURE_2D_INT4:
...@@ -127,15 +274,15 @@ TString TextureString(const HLSLTextureSamplerGroup type) ...@@ -127,15 +274,15 @@ TString TextureString(const HLSLTextureSamplerGroup type)
UNREACHABLE(); UNREACHABLE();
} }
return "<unknown texture type>"; return "<unknown read texture type>";
} }
TString TextureString(const TBasicType type) TString TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{ {
return TextureString(TextureGroup(type)); return TextureString(TextureGroup(type, imageInternalFormat));
} }
TString TextureGroupSuffix(const HLSLTextureSamplerGroup type) TString TextureGroupSuffix(const HLSLTextureGroup type)
{ {
switch (type) switch (type)
{ {
...@@ -147,6 +294,22 @@ TString TextureGroupSuffix(const HLSLTextureSamplerGroup type) ...@@ -147,6 +294,22 @@ TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
return "2DArray"; return "2DArray";
case HLSL_TEXTURE_3D: case HLSL_TEXTURE_3D:
return "3D"; return "3D";
case HLSL_TEXTURE_2D_UNORM:
return "2D_unorm_float4_";
case HLSL_TEXTURE_CUBE_UNORM:
return "Cube_unorm_float4_";
case HLSL_TEXTURE_2D_ARRAY_UNORN:
return "2DArray_unorm_float4_";
case HLSL_TEXTURE_3D_UNORM:
return "3D_unorm_float4_";
case HLSL_TEXTURE_2D_SNORM:
return "2D_snorm_float4_";
case HLSL_TEXTURE_CUBE_SNORM:
return "Cube_snorm_float4_";
case HLSL_TEXTURE_2D_ARRAY_SNORM:
return "2DArray_snorm_float4_";
case HLSL_TEXTURE_3D_SNORM:
return "3D_snorm_float4_";
case HLSL_TEXTURE_2D_MS: case HLSL_TEXTURE_2D_MS:
return "2DMS"; return "2DMS";
case HLSL_TEXTURE_2D_INT4: case HLSL_TEXTURE_2D_INT4:
...@@ -178,12 +341,12 @@ TString TextureGroupSuffix(const HLSLTextureSamplerGroup type) ...@@ -178,12 +341,12 @@ TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
return "<unknown texture type>"; return "<unknown texture type>";
} }
TString TextureGroupSuffix(const TBasicType type) TString TextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{ {
return TextureGroupSuffix(TextureGroup(type)); return TextureGroupSuffix(TextureGroup(type, imageInternalFormat));
} }
TString TextureTypeSuffix(const TBasicType type) TString TextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{ {
switch (type) switch (type)
{ {
...@@ -193,9 +356,337 @@ TString TextureTypeSuffix(const TBasicType type) ...@@ -193,9 +356,337 @@ TString TextureTypeSuffix(const TBasicType type)
return "Cube_uint4_"; return "Cube_uint4_";
case EbtSamplerExternalOES: case EbtSamplerExternalOES:
return "_External"; return "_External";
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return "Cube_float4_";
case EiifRGBA8:
return "Cube_unorm_float4_";
case EiifRGBA8_SNORM:
return "Cube_snorm_float4_";
default:
UNREACHABLE();
}
}
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return "Cube_int4_";
default:
UNREACHABLE();
}
}
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return "Cube_uint4_";
default:
UNREACHABLE();
}
}
default:
// All other types are identified by their group suffix
return TextureGroupSuffix(type, imageInternalFormat);
}
}
HLSLRWTextureGroup RWTextureGroup(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat)
{
switch (type)
{
case EbtImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_RWTEXTURE_2D_FLOAT4;
case EiifRGBA8:
return HLSL_RWTEXTURE_2D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_RWTEXTURE_2D_SNORM;
default:
UNREACHABLE();
}
}
case EbtIImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_RWTEXTURE_2D_INT4;
default:
UNREACHABLE();
}
}
case EbtUImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_RWTEXTURE_2D_UINT4;
default:
UNREACHABLE();
}
}
case EbtImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_RWTEXTURE_3D_FLOAT4;
case EiifRGBA8:
return HLSL_RWTEXTURE_3D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_RWTEXTURE_3D_SNORM;
default:
UNREACHABLE();
}
}
case EbtIImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_RWTEXTURE_3D_INT4;
default:
UNREACHABLE();
}
}
case EbtUImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_RWTEXTURE_3D_UINT4;
default:
UNREACHABLE();
}
}
case EbtImage2DArray:
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_RWTEXTURE_2D_ARRAY_FLOAT4;
case EiifRGBA8:
return HLSL_RWTEXTURE_2D_ARRAY_UNORN;
case EiifRGBA8_SNORM:
return HLSL_RWTEXTURE_2D_ARRAY_SNORM;
default:
UNREACHABLE();
}
}
case EbtIImage2DArray:
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_RWTEXTURE_2D_ARRAY_INT4;
default:
UNREACHABLE();
}
}
case EbtUImage2DArray:
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_RWTEXTURE_2D_ARRAY_UINT4;
default:
UNREACHABLE();
}
}
default:
UNREACHABLE();
}
return HLSL_RWTEXTURE_UNKNOWN;
}
TString RWTextureString(const HLSLRWTextureGroup RWTextureGroup)
{
switch (RWTextureGroup)
{
case HLSL_RWTEXTURE_2D_FLOAT4:
return "RWTexture2D<float4>";
case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4:
return "RWTexture2DArray<float4>";
case HLSL_RWTEXTURE_3D_FLOAT4:
return "RWTexture3D<float4>";
case HLSL_RWTEXTURE_2D_UNORM:
return "RWTexture2D<unorm float4>";
case HLSL_RWTEXTURE_2D_ARRAY_UNORN:
return "RWTexture2DArray<unorm float4>";
case HLSL_RWTEXTURE_3D_UNORM:
return "RWTexture3D<unorm float4>";
case HLSL_RWTEXTURE_2D_SNORM:
return "RWTexture2D<snorm float4>";
case HLSL_RWTEXTURE_2D_ARRAY_SNORM:
return "RWTexture2DArray<snorm float4>";
case HLSL_RWTEXTURE_3D_SNORM:
return "RWTexture3D<snorm float4>";
case HLSL_RWTEXTURE_2D_UINT4:
return "RWTexture2D<uint4>";
case HLSL_RWTEXTURE_2D_ARRAY_UINT4:
return "RWTexture2DArray<uint4>";
case HLSL_RWTEXTURE_3D_UINT4:
return "RWTexture3D<uint4>";
case HLSL_RWTEXTURE_2D_INT4:
return "RWTexture2D<int4>";
case HLSL_RWTEXTURE_2D_ARRAY_INT4:
return "RWTexture2DArray<int4>";
case HLSL_RWTEXTURE_3D_INT4:
return "RWTexture3D<int4>";
default:
UNREACHABLE();
}
return "<unknown read and write texture type>";
}
TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
return RWTextureString(RWTextureGroup(type, imageInternalFormat));
}
TString RWTextureGroupSuffix(const HLSLRWTextureGroup type)
{
switch (type)
{
case HLSL_RWTEXTURE_2D_FLOAT4:
return "RW2D_float4_";
case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4:
return "RW2DArray_float4_";
case HLSL_RWTEXTURE_3D_FLOAT4:
return "RW3D_float4_";
case HLSL_RWTEXTURE_2D_UNORM:
return "RW2D_unorm_float4_";
case HLSL_RWTEXTURE_2D_ARRAY_UNORN:
return "RW2DArray_unorm_float4_";
case HLSL_RWTEXTURE_3D_UNORM:
return "RW3D_unorm_float4_";
case HLSL_RWTEXTURE_2D_SNORM:
return "RW2D_snorm_float4_";
case HLSL_RWTEXTURE_2D_ARRAY_SNORM:
return "RW2DArray_snorm_float4_";
case HLSL_RWTEXTURE_3D_SNORM:
return "RW3D_snorm_float4_";
case HLSL_RWTEXTURE_2D_UINT4:
return "RW2D_uint4_";
case HLSL_RWTEXTURE_2D_ARRAY_UINT4:
return "RW2DArray_uint4_";
case HLSL_RWTEXTURE_3D_UINT4:
return "RW3D_uint4_";
case HLSL_RWTEXTURE_2D_INT4:
return "RW2D_int4_";
case HLSL_RWTEXTURE_2D_ARRAY_INT4:
return "RW2DArray_int4_";
case HLSL_RWTEXTURE_3D_INT4:
return "RW3D_int4_";
default:
UNREACHABLE();
}
return "<unknown read and write resource>";
}
TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
return RWTextureGroupSuffix(RWTextureGroup(type, imageInternalFormat));
}
TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
switch (type)
{
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return "RWCube_float4_";
case EiifRGBA8:
return "RWCube_unorm_float4_";
case EiifRGBA8_SNORM:
return "RWCube_unorm_float4_";
default:
UNREACHABLE();
}
}
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return "RWCube_int4_";
default:
UNREACHABLE();
}
}
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return "RWCube_uint4_";
default:
UNREACHABLE();
}
}
default: default:
// All other types are identified by their group suffix // All other types are identified by their group suffix
return TextureGroupSuffix(type); return TextureGroupSuffix(type, imageInternalFormat);
} }
} }
......
...@@ -21,16 +21,24 @@ class TName; ...@@ -21,16 +21,24 @@ class TName;
namespace sh namespace sh
{ {
// Unique combinations of HLSL Texture type and HLSL Sampler type. // HLSL Texture type for GLSL sampler type and readonly image type.
enum HLSLTextureSamplerGroup enum HLSLTextureGroup
{ {
// Regular samplers // read resources
HLSL_TEXTURE_2D, HLSL_TEXTURE_2D,
HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D, HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D,
HLSL_TEXTURE_CUBE, HLSL_TEXTURE_CUBE,
HLSL_TEXTURE_2D_ARRAY, HLSL_TEXTURE_2D_ARRAY,
HLSL_TEXTURE_3D, HLSL_TEXTURE_3D,
HLSL_TEXTURE_2D_UNORM,
HLSL_TEXTURE_CUBE_UNORM,
HLSL_TEXTURE_2D_ARRAY_UNORN,
HLSL_TEXTURE_3D_UNORM,
HLSL_TEXTURE_2D_SNORM,
HLSL_TEXTURE_CUBE_SNORM,
HLSL_TEXTURE_2D_ARRAY_SNORM,
HLSL_TEXTURE_3D_SNORM,
HLSL_TEXTURE_2D_MS, HLSL_TEXTURE_2D_MS,
HLSL_TEXTURE_2D_INT4, HLSL_TEXTURE_2D_INT4,
HLSL_TEXTURE_3D_INT4, HLSL_TEXTURE_3D_INT4,
...@@ -54,14 +62,52 @@ enum HLSLTextureSamplerGroup ...@@ -54,14 +62,52 @@ enum HLSLTextureSamplerGroup
HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN
}; };
HLSLTextureSamplerGroup TextureGroup(const TBasicType type); // HLSL RWTexture type for GLSL read and write image type.
TString TextureString(const HLSLTextureSamplerGroup type); enum HLSLRWTextureGroup
TString TextureString(const TBasicType type); {
TString TextureGroupSuffix(const HLSLTextureSamplerGroup type); // read/write resource
TString TextureGroupSuffix(const TBasicType type); HLSL_RWTEXTURE_2D_FLOAT4,
TString TextureTypeSuffix(const TBasicType type); HLSL_RWTEXTURE_MIN = HLSL_RWTEXTURE_2D_FLOAT4,
HLSL_RWTEXTURE_2D_ARRAY_FLOAT4,
HLSL_RWTEXTURE_3D_FLOAT4,
HLSL_RWTEXTURE_2D_UNORM,
HLSL_RWTEXTURE_2D_ARRAY_UNORN,
HLSL_RWTEXTURE_3D_UNORM,
HLSL_RWTEXTURE_2D_SNORM,
HLSL_RWTEXTURE_2D_ARRAY_SNORM,
HLSL_RWTEXTURE_3D_SNORM,
HLSL_RWTEXTURE_2D_UINT4,
HLSL_RWTEXTURE_2D_ARRAY_UINT4,
HLSL_RWTEXTURE_3D_UINT4,
HLSL_RWTEXTURE_2D_INT4,
HLSL_RWTEXTURE_2D_ARRAY_INT4,
HLSL_RWTEXTURE_3D_INT4,
HLSL_RWTEXTURE_UNKNOWN,
HLSL_RWTEXTURE_MAX = HLSL_RWTEXTURE_UNKNOWN
};
HLSLTextureGroup TextureGroup(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
TString TextureString(const HLSLTextureGroup textureGroup);
TString TextureString(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
TString TextureGroupSuffix(const HLSLTextureGroup type);
TString TextureGroupSuffix(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
TString TextureTypeSuffix(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
HLSLRWTextureGroup RWTextureGroup(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat);
TString RWTextureString(const HLSLRWTextureGroup textureGroup);
TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
TString RWTextureGroupSuffix(const HLSLRWTextureGroup type);
TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
TString SamplerString(const TBasicType type); TString SamplerString(const TBasicType type);
TString SamplerString(HLSLTextureSamplerGroup type); TString SamplerString(HLSLTextureGroup type);
// Adds a prefix to user-defined names to avoid naming clashes. // Adds a prefix to user-defined names to avoid naming clashes.
TString Decorate(const TString &string); TString Decorate(const TString &string);
TString DecorateVariableIfNeeded(const TName &name); TString DecorateVariableIfNeeded(const TName &name);
......
...@@ -921,6 +921,34 @@ size_t GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel) ...@@ -921,6 +921,34 @@ size_t GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)
} }
} }
size_t GetMaximumImageUnits(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
case D3D_FEATURE_LEVEL_11_1:
case D3D_FEATURE_LEVEL_11_0:
// TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using
// the minimum requirement for GLES 3.1.
return 4;
default:
return 0;
}
}
size_t GetMaximumComputeImageUniforms(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
case D3D_FEATURE_LEVEL_11_1:
case D3D_FEATURE_LEVEL_11_0:
// TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using
// the minimum requirement for GLES 3.1.
return 4;
default:
return 0;
}
}
int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
{ {
switch (featureLevel) switch (featureLevel)
...@@ -1344,6 +1372,9 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons ...@@ -1344,6 +1372,9 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
static_cast<GLuint>(GetMaximumComputeUniformBlocks(featureLevel)); static_cast<GLuint>(GetMaximumComputeUniformBlocks(featureLevel));
caps->maxComputeTextureImageUnits = caps->maxComputeTextureImageUnits =
static_cast<GLuint>(GetMaximumComputeTextureUnits(featureLevel)); static_cast<GLuint>(GetMaximumComputeTextureUnits(featureLevel));
caps->maxImageUnits = static_cast<GLuint>(GetMaximumImageUnits(featureLevel));
caps->maxComputeImageUniforms =
static_cast<GLuint>(GetMaximumComputeImageUniforms(featureLevel));
// Aggregate shader limits // Aggregate shader limits
caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
1442 D3D11 : dEQP-GLES31.functional.vertex_attribute_binding.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.vertex_attribute_binding.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.texture.gather.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.texture.gather.* = SKIP
// TODO(xinghua.cao@intel.com): FAIL expectation instead of SKIP should be sufficient for OpenGL, but the
// test expectations parser doesn't support having FAIL for GL and SKIP for D3D with the same test filter.
1442 OPENGL D3D11 : dEQP-GLES31.functional.image_load_store.* = SKIP
// D3D11 Failing Tests // D3D11 Failing Tests
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_framebuffer_width_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_framebuffer_width_* = FAIL
...@@ -44,7 +47,6 @@ ...@@ -44,7 +47,6 @@
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_shared_memory_size_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_shared_memory_size_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_atomic_counter_buffers_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_atomic_counter_buffers_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_atomic_counters_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_atomic_counters_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_image_uniforms_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_shader_storage_blocks_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_compute_shader_storage_blocks_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_atomic_counter_buffer_bindings_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_atomic_counter_buffer_bindings_* = FAIL
1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_atomic_counter_buffer_size_* = FAIL 1442 D3D11 : dEQP-GLES31.functional.state_query.integer.max_atomic_counter_buffer_size_* = FAIL
...@@ -1207,7 +1209,6 @@ ...@@ -1207,7 +1209,6 @@
1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.22 = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.22 = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.37 = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.37 = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.38 = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.ubo.random.all_shared_buffer.38 = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.image_load_store.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.atomic_counter.* = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.atomic_counter.* = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_2d = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_2d = FAIL
1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_2d_array = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_2d_array = FAIL
......
...@@ -366,6 +366,66 @@ TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier) ...@@ -366,6 +366,66 @@ TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
} }
} }
// imageLoad functions
TEST_P(ComputeShaderTest, ImageLoad)
{
const std::string csSource =
"#version 310 es\n"
"layout(local_size_x=8) in;\n"
"layout(rgba8) uniform highp readonly image2D mImage2DInput;\n"
"layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;\n"
"layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;\n"
"void main()\n"
"{\n"
" vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));\n"
" ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));\n"
" uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));\n"
"}\n";
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
EXPECT_GL_NO_ERROR();
}
// imageStore functions
TEST_P(ComputeShaderTest, ImageStore)
{
const std::string csSource =
"#version 310 es\n"
"layout(local_size_x=8) in;\n"
"layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;\n"
"layout(r32f) uniform highp writeonly image3D mImage3DOutput;\n"
"layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;\n"
"void main()\n"
"{\n"
" imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));\n"
" imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));\n"
" imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));\n"
"}\n";
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
EXPECT_GL_NO_ERROR();
}
// imageSize functions
TEST_P(ComputeShaderTest, ImageSize)
{
const std::string csSource =
"#version 310 es\n"
"layout(local_size_x=8) in;\n"
"layout(rgba8) uniform highp readonly imageCube mImageCubeInput;\n"
"layout(r32i) uniform highp readonly iimage2D mImage2DInput;\n"
"layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;\n"
"void main()\n"
"{\n"
" ivec2 sizeCube = imageSize(mImageCubeInput);\n"
" ivec2 size2D = imageSize(mImage2DInput);\n"
" ivec3 size2DArray = imageSize(mImage2DArrayInput);\n"
"}\n";
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
EXPECT_GL_NO_ERROR();
}
// Check that it is not possible to create a compute shader when the context does not support ES // Check that it is not possible to create a compute shader when the context does not support ES
// 3.10 // 3.10
TEST_P(ComputeShaderTestES3, NotSupported) TEST_P(ComputeShaderTestES3, NotSupported)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment