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;
......
...@@ -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