Commit f3179a6a by Xinghua Cao Committed by Commit Bot

ES31: Implement bindImageTexture binds a single layer on D3D backend

Dynamically generate image2D variables' declaration and function definition in libANGLE. Bug: angleproject:1987 TEST=angle_end2end_tests.ComputeShaderTest.* Change-Id: Idacc756f7bd15f22eccb1d689e18e997f3e74159 Reviewed-on: https://chromium-review.googlesource.com/c/1142885 Commit-Queue: Xinghua Cao <xinghua.cao@intel.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 15460e36
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <array> #include <array>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -25,7 +26,7 @@ ...@@ -25,7 +26,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 203 #define ANGLE_SH_VERSION 204
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -628,6 +629,19 @@ bool GetUniformBlockRegister(const ShHandle handle, ...@@ -628,6 +629,19 @@ bool GetUniformBlockRegister(const ShHandle handle,
// Note that the map contains also registers of samplers that have been extracted from structs. // Note that the map contains also registers of samplers that have been extracted from structs.
const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle); const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle);
// Sampler, image and atomic counters share registers(t type and u type),
// GetReadonlyImage2DRegisterIndex and GetImage2DRegisterIndex return the first index into
// a range of reserved registers for image2D/iimage2D/uimage2D variables.
// Parameters: handle: Specifies the compiler
unsigned int GetReadonlyImage2DRegisterIndex(const ShHandle handle);
unsigned int GetImage2DRegisterIndex(const ShHandle handle);
// The method records these used function names related with image2D/iimage2D/uimage2D, these
// functions will be dynamically generated.
// Parameters:
// handle: Specifies the compiler
const std::set<std::string> *GetUsedImage2DFunctionNames(const ShHandle handle);
bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle); bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle);
bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle); bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle);
bool HasValidGeometryShaderMaxVertices(const ShHandle handle); bool HasValidGeometryShaderMaxVertices(const ShHandle handle);
......
...@@ -181,6 +181,7 @@ struct Uniform : public VariableWithLocation ...@@ -181,6 +181,7 @@ struct Uniform : public VariableWithLocation
bool operator!=(const Uniform &other) const { return !operator==(other); } bool operator!=(const Uniform &other) const { return !operator==(other); }
int binding; int binding;
GLenum imageUnitFormat;
int offset; int offset;
bool readonly; bool readonly;
bool writeonly; bool writeonly;
......
...@@ -443,6 +443,30 @@ bool IsImageType(GLenum type) ...@@ -443,6 +443,30 @@ bool IsImageType(GLenum type)
return false; return false;
} }
bool IsImage2DType(GLenum type)
{
switch (type)
{
case GL_IMAGE_2D:
case GL_INT_IMAGE_2D:
case GL_UNSIGNED_INT_IMAGE_2D:
return true;
case GL_IMAGE_3D:
case GL_INT_IMAGE_3D:
case GL_UNSIGNED_INT_IMAGE_3D:
case GL_IMAGE_2D_ARRAY:
case GL_INT_IMAGE_2D_ARRAY:
case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE:
return false;
default:
UNREACHABLE();
return false;
}
}
bool IsAtomicCounterType(GLenum type) bool IsAtomicCounterType(GLenum type)
{ {
return type == GL_UNSIGNED_INT_ATOMIC_COUNTER; return type == GL_UNSIGNED_INT_ATOMIC_COUNTER;
......
...@@ -38,6 +38,7 @@ int VariableRowCount(GLenum type); ...@@ -38,6 +38,7 @@ int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type); int VariableColumnCount(GLenum type);
bool IsSamplerType(GLenum type); bool IsSamplerType(GLenum type);
bool IsImageType(GLenum type); bool IsImageType(GLenum type);
bool IsImage2DType(GLenum type);
bool IsAtomicCounterType(GLenum type); bool IsAtomicCounterType(GLenum type);
bool IsOpaqueType(GLenum type); bool IsOpaqueType(GLenum type);
bool IsMatrixType(GLenum type); bool IsMatrixType(GLenum type);
......
...@@ -767,6 +767,8 @@ Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) ...@@ -767,6 +767,8 @@ Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable)
Uniform uniform; Uniform uniform;
setCommonVariableProperties(variable.getType(), variable.variable(), &uniform); setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
uniform.binding = variable.getType().getLayoutQualifier().binding; uniform.binding = variable.getType().getLayoutQualifier().binding;
uniform.imageUnitFormat =
GetImageInternalFormatType(variable.getType().getLayoutQualifier().imageInternalFormat);
uniform.location = variable.getType().getLayoutQualifier().location; uniform.location = variable.getType().getLayoutQualifier().location;
uniform.offset = variable.getType().getLayoutQualifier().offset; uniform.offset = variable.getType().getLayoutQualifier().offset;
uniform.readonly = variable.getType().getMemoryQualifier().readonly; uniform.readonly = variable.getType().getMemoryQualifier().readonly;
......
...@@ -334,6 +334,13 @@ void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out) ...@@ -334,6 +334,13 @@ void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out)
{ {
for (const ImageFunction &imageFunction : mUsesImage) for (const ImageFunction &imageFunction : mUsesImage)
{ {
// Skip to generate image2D functions here, dynamically generate these
// functions when linking, or after dispatch or draw.
if (IsImage2D(imageFunction.image))
{
mUsedImage2DFunctionNames.insert(imageFunction.name().data());
continue;
}
// Function header // Function header
out << imageFunction.getReturnType() << " " << imageFunction.name() << "("; out << imageFunction.getReturnType() << " " << imageFunction.name() << "(";
......
...@@ -31,6 +31,10 @@ class ImageFunctionHLSL final : angle::NonCopyable ...@@ -31,6 +31,10 @@ class ImageFunctionHLSL final : angle::NonCopyable
bool readonly); bool readonly);
void imageFunctionHeader(TInfoSinkBase &out); void imageFunctionHeader(TInfoSinkBase &out);
const std::set<std::string> &getUsedImage2DFunctionNames() const
{
return mUsedImage2DFunctionNames;
}
private: private:
struct ImageFunction struct ImageFunction
...@@ -84,6 +88,7 @@ class ImageFunctionHLSL final : angle::NonCopyable ...@@ -84,6 +88,7 @@ class ImageFunctionHLSL final : angle::NonCopyable
const ImmutableString &imageReference); const ImmutableString &imageReference);
using ImageFunctionSet = std::set<ImageFunction>; using ImageFunctionSet = std::set<ImageFunction>;
ImageFunctionSet mUsesImage; ImageFunctionSet mUsesImage;
std::set<std::string> mUsedImage2DFunctionNames;
}; };
} // namespace sh } // namespace sh
......
...@@ -35,6 +35,8 @@ namespace sh ...@@ -35,6 +35,8 @@ namespace sh
namespace namespace
{ {
constexpr const char kImage2DFunctionString[] = "// @@ IMAGE2D DECLARATION FUNCTION STRING @@";
TString ArrayHelperFunctionName(const char *prefix, const TType &type) TString ArrayHelperFunctionName(const char *prefix, const TType &type)
{ {
TStringStream fnName; TStringStream fnName;
...@@ -382,6 +384,21 @@ const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() c ...@@ -382,6 +384,21 @@ const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() c
return mResourcesHLSL->getUniformRegisterMap(); return mResourcesHLSL->getUniformRegisterMap();
} }
unsigned int OutputHLSL::getReadonlyImage2DRegisterIndex() const
{
return mResourcesHLSL->getReadonlyImage2DRegisterIndex();
}
unsigned int OutputHLSL::getImage2DRegisterIndex() const
{
return mResourcesHLSL->getImage2DRegisterIndex();
}
const std::set<std::string> &OutputHLSL::getUsedImage2DFunctionNames() const
{
return mImageFunctionHLSL->getUsedImage2DFunctionNames();
}
TString OutputHLSL::structInitializerString(int indent, TString OutputHLSL::structInitializerString(int indent,
const TType &type, const TType &type,
const TString &name) const const TString &name) const
...@@ -717,7 +734,7 @@ void OutputHLSL::header(TInfoSinkBase &out, ...@@ -717,7 +734,7 @@ void OutputHLSL::header(TInfoSinkBase &out,
if (mOutputType == SH_HLSL_4_1_OUTPUT) if (mOutputType == SH_HLSL_4_1_OUTPUT)
{ {
mResourcesHLSL->samplerMetadataUniforms(out, "c4"); mResourcesHLSL->samplerMetadataUniforms(out, 4);
} }
out << "};\n"; out << "};\n";
...@@ -829,7 +846,7 @@ void OutputHLSL::header(TInfoSinkBase &out, ...@@ -829,7 +846,7 @@ void OutputHLSL::header(TInfoSinkBase &out,
if (mOutputType == SH_HLSL_4_1_OUTPUT) if (mOutputType == SH_HLSL_4_1_OUTPUT)
{ {
mResourcesHLSL->samplerMetadataUniforms(out, "c4"); mResourcesHLSL->samplerMetadataUniforms(out, 4);
} }
out << "};\n" out << "};\n"
...@@ -865,9 +882,15 @@ void OutputHLSL::header(TInfoSinkBase &out, ...@@ -865,9 +882,15 @@ void OutputHLSL::header(TInfoSinkBase &out,
out << " uint3 gl_NumWorkGroups : packoffset(c0);\n"; out << " uint3 gl_NumWorkGroups : packoffset(c0);\n";
} }
ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT); ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT);
mResourcesHLSL->samplerMetadataUniforms(out, "c1"); unsigned int registerIndex = 1;
mResourcesHLSL->samplerMetadataUniforms(out, registerIndex);
// Sampler metadata struct must be two 4-vec, 32 bytes.
registerIndex += mResourcesHLSL->getSamplerCount() * 2;
mResourcesHLSL->imageMetadataUniforms(out, registerIndex);
out << "};\n"; out << "};\n";
out << kImage2DFunctionString << "\n";
std::ostringstream systemValueDeclaration; std::ostringstream systemValueDeclaration;
std::ostringstream glBuiltinInitialization; std::ostringstream glBuiltinInitialization;
......
...@@ -57,6 +57,9 @@ class OutputHLSL : public TIntermTraverser ...@@ -57,6 +57,9 @@ class OutputHLSL : public TIntermTraverser
const std::map<std::string, unsigned int> &getShaderStorageBlockRegisterMap() const; const std::map<std::string, unsigned int> &getShaderStorageBlockRegisterMap() const;
const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const; const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const;
const std::map<std::string, unsigned int> &getUniformRegisterMap() const; const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
unsigned int getReadonlyImage2DRegisterIndex() const;
unsigned int getImage2DRegisterIndex() const;
const std::set<std::string> &getUsedImage2DFunctionNames() const;
TInfoSinkBase &getInfoSink() TInfoSinkBase &getInfoSink()
{ {
......
...@@ -302,8 +302,7 @@ void ResourcesHLSL::outputHLSLImageUniformIndices(TInfoSinkBase &out, ...@@ -302,8 +302,7 @@ void ResourcesHLSL::outputHLSLImageUniformIndices(TInfoSinkBase &out,
void ResourcesHLSL::outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out, void ResourcesHLSL::outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out,
const HLSLTextureGroup textureGroup, const HLSLTextureGroup textureGroup,
const TVector<const TVariable *> &group, const TVector<const TVariable *> &group,
unsigned int *groupTextureRegisterIndex, unsigned int *groupTextureRegisterIndex)
unsigned int *imageUniformGroupIndex)
{ {
if (group.empty()) if (group.empty())
{ {
...@@ -311,23 +310,21 @@ void ResourcesHLSL::outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out, ...@@ -311,23 +310,21 @@ void ResourcesHLSL::outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out,
} }
unsigned int groupRegisterCount = 0; unsigned int groupRegisterCount = 0;
outputHLSLImageUniformIndices(out, group, *imageUniformGroupIndex, &groupRegisterCount); outputHLSLImageUniformIndices(out, group, *groupTextureRegisterIndex, &groupRegisterCount);
TString suffix = TextureGroupSuffix(textureGroup); TString suffix = TextureGroupSuffix(textureGroup);
out << "static const uint readonlyImageIndexOffset" << suffix << " = " out << "static const uint readonlyImageIndexOffset" << suffix << " = "
<< (*imageUniformGroupIndex) << ";\n"; << (*groupTextureRegisterIndex) << ";\n";
out << "uniform " << TextureString(textureGroup) << " readonlyImages" << suffix << "[" out << "uniform " << TextureString(textureGroup) << " readonlyImages" << suffix << "["
<< groupRegisterCount << "]" << groupRegisterCount << "]"
<< " : register(t" << (*groupTextureRegisterIndex) << ");\n"; << " : register(t" << (*groupTextureRegisterIndex) << ");\n";
*groupTextureRegisterIndex += groupRegisterCount; *groupTextureRegisterIndex += groupRegisterCount;
*imageUniformGroupIndex += groupRegisterCount;
} }
void ResourcesHLSL::outputHLSLImageUniformGroup(TInfoSinkBase &out, void ResourcesHLSL::outputHLSLImageUniformGroup(TInfoSinkBase &out,
const HLSLRWTextureGroup textureGroup, const HLSLRWTextureGroup textureGroup,
const TVector<const TVariable *> &group, const TVector<const TVariable *> &group,
unsigned int *groupTextureRegisterIndex, unsigned int *groupTextureRegisterIndex)
unsigned int *imageUniformGroupIndex)
{ {
if (group.empty()) if (group.empty())
{ {
...@@ -335,16 +332,15 @@ void ResourcesHLSL::outputHLSLImageUniformGroup(TInfoSinkBase &out, ...@@ -335,16 +332,15 @@ void ResourcesHLSL::outputHLSLImageUniformGroup(TInfoSinkBase &out,
} }
unsigned int groupRegisterCount = 0; unsigned int groupRegisterCount = 0;
outputHLSLImageUniformIndices(out, group, *imageUniformGroupIndex, &groupRegisterCount); outputHLSLImageUniformIndices(out, group, *groupTextureRegisterIndex, &groupRegisterCount);
TString suffix = RWTextureGroupSuffix(textureGroup); TString suffix = RWTextureGroupSuffix(textureGroup);
out << "static const uint imageIndexOffset" << suffix << " = " << (*imageUniformGroupIndex) out << "static const uint imageIndexOffset" << suffix << " = " << (*groupTextureRegisterIndex)
<< ";\n"; << ";\n";
out << "uniform " << RWTextureString(textureGroup) << " images" << suffix << "[" out << "uniform " << RWTextureString(textureGroup) << " images" << suffix << "["
<< groupRegisterCount << "]" << groupRegisterCount << "]"
<< " : register(u" << (*groupTextureRegisterIndex) << ");\n"; << " : register(u" << (*groupTextureRegisterIndex) << ");\n";
*groupTextureRegisterIndex += groupRegisterCount; *groupTextureRegisterIndex += groupRegisterCount;
*imageUniformGroupIndex += groupRegisterCount;
} }
void ResourcesHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out, void ResourcesHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
...@@ -411,6 +407,7 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -411,6 +407,7 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out,
TVector<TVector<const TVariable *>> groupedImageUniforms(HLSL_RWTEXTURE_MAX + 1); TVector<TVector<const TVariable *>> groupedImageUniforms(HLSL_RWTEXTURE_MAX + 1);
TUnorderedMap<int, unsigned int> assignedAtomicCounterBindings; TUnorderedMap<int, unsigned int> assignedAtomicCounterBindings;
unsigned int reservedReadonlyImageRegisterCount = 0, reservedImageRegisterCount = 0;
for (auto &uniformIt : referencedUniforms) for (auto &uniformIt : referencedUniforms)
{ {
// Output regular uniforms. Group sampler uniforms by type. // Output regular uniforms. Group sampler uniforms by type.
...@@ -429,6 +426,20 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -429,6 +426,20 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out,
} }
else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType())) else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType()))
{ {
if (IsImage2D(type.getBasicType()))
{
const Uniform *uniform = findUniformByName(variable.name());
if (type.getMemoryQualifier().readonly)
{
reservedReadonlyImageRegisterCount +=
HLSLVariableRegisterCount(*uniform, mOutputType);
}
else
{
reservedImageRegisterCount += HLSLVariableRegisterCount(*uniform, mOutputType);
}
continue;
}
if (type.getMemoryQualifier().readonly) if (type.getMemoryQualifier().readonly)
{ {
HLSLTextureGroup group = TextureGroup( HLSLTextureGroup group = TextureGroup(
...@@ -508,7 +519,6 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -508,7 +519,6 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out,
// Atomic counters and RW texture share the same resources. Therefore, RW texture need to // Atomic counters and RW texture share the same resources. Therefore, RW texture need to
// start counting after the last atomic counter. // start counting after the last atomic counter.
unsigned int groupRWTextureRegisterIndex = mUAVRegister; unsigned int groupRWTextureRegisterIndex = mUAVRegister;
unsigned int imageUniformGroupIndex = 0;
// TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case. // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case.
ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D); ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D);
for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId) for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
...@@ -519,23 +529,44 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -519,23 +529,44 @@ void ResourcesHLSL::uniformsHeader(TInfoSinkBase &out,
} }
mSamplerCount = groupTextureRegisterIndex; mSamplerCount = groupTextureRegisterIndex;
// Reserve t type register for readonly image2D variables.
mReadonlyImage2DRegisterIndex = mTextureRegister;
groupTextureRegisterIndex += reservedReadonlyImageRegisterCount;
mTextureRegister += reservedReadonlyImageRegisterCount;
for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId) for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
{ {
outputHLSLReadonlyImageUniformGroup( outputHLSLReadonlyImageUniformGroup(out, HLSLTextureGroup(groupId),
out, HLSLTextureGroup(groupId), groupedReadonlyImageUniforms[groupId], groupedReadonlyImageUniforms[groupId],
&groupTextureRegisterIndex, &imageUniformGroupIndex); &groupTextureRegisterIndex);
}
mReadonlyImageCount = groupTextureRegisterIndex - mReadonlyImage2DRegisterIndex;
if (mReadonlyImageCount)
{
out << "static const uint readonlyImageIndexStart = " << mReadonlyImage2DRegisterIndex
<< ";\n";
} }
// Reserve u type register for writable image2D variables.
mImage2DRegisterIndex = mUAVRegister;
groupRWTextureRegisterIndex += reservedImageRegisterCount;
mUAVRegister += reservedImageRegisterCount;
for (int groupId = HLSL_RWTEXTURE_MIN; groupId < HLSL_RWTEXTURE_MAX; ++groupId) for (int groupId = HLSL_RWTEXTURE_MIN; groupId < HLSL_RWTEXTURE_MAX; ++groupId)
{ {
outputHLSLImageUniformGroup(out, HLSLRWTextureGroup(groupId), outputHLSLImageUniformGroup(out, HLSLRWTextureGroup(groupId),
groupedImageUniforms[groupId], &groupRWTextureRegisterIndex, groupedImageUniforms[groupId],
&imageUniformGroupIndex); &groupRWTextureRegisterIndex);
}
mImageCount = groupRWTextureRegisterIndex - mImage2DRegisterIndex;
if (mImageCount)
{
out << "static const uint imageIndexStart = " << mImage2DRegisterIndex << ";\n";
} }
} }
} }
void ResourcesHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg) void ResourcesHLSL::samplerMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex)
{ {
// If mSamplerCount is 0 the shader doesn't use any textures for samplers. // If mSamplerCount is 0 the shader doesn't use any textures for samplers.
if (mSamplerCount > 0) if (mSamplerCount > 0)
...@@ -549,7 +580,31 @@ void ResourcesHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg) ...@@ -549,7 +580,31 @@ void ResourcesHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
" int4 intBorderColor;\n" " int4 intBorderColor;\n"
" };\n" " };\n"
" SamplerMetadata samplerMetadata[" " SamplerMetadata samplerMetadata["
<< mSamplerCount << "] : packoffset(" << reg << ");\n"; << mSamplerCount << "] : packoffset(c" << regIndex << ");\n";
}
}
void ResourcesHLSL::imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex)
{
if (mReadonlyImageCount > 0 || mImageCount > 0)
{
out << " struct ImageMetadata\n"
" {\n"
" int layer;\n"
" int3 padding;\n"
" };\n";
if (mReadonlyImageCount > 0)
{
out << " ImageMetadata readonlyImageMetadata[" << mReadonlyImageCount
<< "] : packoffset(c" << regIndex << ");\n";
}
if (mImageCount > 0)
{
out << " ImageMetadata imageMetadata[" << mImageCount << "] : packoffset(c"
<< regIndex + mReadonlyImageCount << ");\n";
}
} }
} }
......
...@@ -35,8 +35,9 @@ class ResourcesHLSL : angle::NonCopyable ...@@ -35,8 +35,9 @@ class ResourcesHLSL : angle::NonCopyable
TSymbolTable *symbolTable); TSymbolTable *symbolTable);
// Must be called after uniformsHeader // Must be called after uniformsHeader
void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg); void samplerMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex);
unsigned int getSamplerCount() const { return mSamplerCount; }
void imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex);
TString uniformBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks); TString uniformBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks);
TString shaderStorageBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks); TString shaderStorageBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks);
...@@ -58,6 +59,9 @@ class ResourcesHLSL : angle::NonCopyable ...@@ -58,6 +59,9 @@ class ResourcesHLSL : angle::NonCopyable
return mUniformRegisterMap; return mUniformRegisterMap;
} }
unsigned int getReadonlyImage2DRegisterIndex() const { return mReadonlyImage2DRegisterIndex; }
unsigned int getImage2DRegisterIndex() const { return mImage2DRegisterIndex; }
private: private:
TString uniformBlockString(const TInterfaceBlock &interfaceBlock, TString uniformBlockString(const TInterfaceBlock &interfaceBlock,
const TVariable *instanceVariable, const TVariable *instanceVariable,
...@@ -107,19 +111,19 @@ class ResourcesHLSL : angle::NonCopyable ...@@ -107,19 +111,19 @@ class ResourcesHLSL : angle::NonCopyable
void outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out, void outputHLSLReadonlyImageUniformGroup(TInfoSinkBase &out,
const HLSLTextureGroup textureGroup, const HLSLTextureGroup textureGroup,
const TVector<const TVariable *> &group, const TVector<const TVariable *> &group,
unsigned int *groupTextureRegisterIndex, unsigned int *groupTextureRegisterIndex);
unsigned int *imageUniformGroupIndex);
void outputHLSLImageUniformGroup(TInfoSinkBase &out, void outputHLSLImageUniformGroup(TInfoSinkBase &out,
const HLSLRWTextureGroup textureGroup, const HLSLRWTextureGroup textureGroup,
const TVector<const TVariable *> &group, const TVector<const TVariable *> &group,
unsigned int *groupTextureRegisterIndex, unsigned int *groupTextureRegisterIndex);
unsigned int *imageUniformGroupIndex);
unsigned int mUniformRegister; unsigned int mUniformRegister;
unsigned int mUniformBlockRegister; unsigned int mUniformBlockRegister;
unsigned int mTextureRegister; unsigned int mTextureRegister;
unsigned int mUAVRegister; unsigned int mUAVRegister;
unsigned int mSamplerCount; unsigned int mSamplerCount;
unsigned int mReadonlyImageCount;
unsigned int mImageCount;
StructureHLSL *mStructureHLSL; StructureHLSL *mStructureHLSL;
ShShaderOutput mOutputType; ShShaderOutput mOutputType;
...@@ -127,6 +131,8 @@ class ResourcesHLSL : angle::NonCopyable ...@@ -127,6 +131,8 @@ class ResourcesHLSL : angle::NonCopyable
std::map<std::string, unsigned int> mUniformBlockRegisterMap; std::map<std::string, unsigned int> mUniformBlockRegisterMap;
std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap; std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap;
std::map<std::string, unsigned int> mUniformRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap;
unsigned int mReadonlyImage2DRegisterIndex;
unsigned int mImage2DRegisterIndex;
}; };
} // namespace sh } // namespace sh
......
...@@ -554,6 +554,42 @@ const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle ...@@ -554,6 +554,42 @@ const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle
#endif // ANGLE_ENABLE_HLSL #endif // ANGLE_ENABLE_HLSL
} }
unsigned int GetReadonlyImage2DRegisterIndex(const ShHandle handle)
{
#ifdef ANGLE_ENABLE_HLSL
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
return translator->getReadonlyImage2DRegisterIndex();
#else
return 0;
#endif // ANGLE_ENABLE_HLSL
}
unsigned int GetImage2DRegisterIndex(const ShHandle handle)
{
#ifdef ANGLE_ENABLE_HLSL
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
return translator->getImage2DRegisterIndex();
#else
return 0;
#endif // ANGLE_ENABLE_HLSL
}
const std::set<std::string> *GetUsedImage2DFunctionNames(const ShHandle handle)
{
#ifdef ANGLE_ENABLE_HLSL
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
return translator->getUsedImage2DFunctionNames();
#else
return nullptr;
#endif // ANGLE_ENABLE_HLSL
}
bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle) bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle)
{ {
ASSERT(handle); ASSERT(handle);
......
...@@ -253,13 +253,16 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other, ...@@ -253,13 +253,16 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
return true; return true;
} }
Uniform::Uniform() : binding(-1), offset(-1), readonly(false), writeonly(false) {} Uniform::Uniform()
: binding(-1), imageUnitFormat(GL_NONE), offset(-1), readonly(false), writeonly(false)
{}
Uniform::~Uniform() {} Uniform::~Uniform() {}
Uniform::Uniform(const Uniform &other) Uniform::Uniform(const Uniform &other)
: VariableWithLocation(other), : VariableWithLocation(other),
binding(other.binding), binding(other.binding),
imageUnitFormat(other.imageUnitFormat),
offset(other.offset), offset(other.offset),
readonly(other.readonly), readonly(other.readonly),
writeonly(other.writeonly) writeonly(other.writeonly)
...@@ -269,6 +272,7 @@ Uniform &Uniform::operator=(const Uniform &other) ...@@ -269,6 +272,7 @@ Uniform &Uniform::operator=(const Uniform &other)
{ {
VariableWithLocation::operator=(other); VariableWithLocation::operator=(other);
binding = other.binding; binding = other.binding;
imageUnitFormat = other.imageUnitFormat;
offset = other.offset; offset = other.offset;
readonly = other.readonly; readonly = other.readonly;
writeonly = other.writeonly; writeonly = other.writeonly;
...@@ -278,7 +282,8 @@ Uniform &Uniform::operator=(const Uniform &other) ...@@ -278,7 +282,8 @@ Uniform &Uniform::operator=(const Uniform &other)
bool Uniform::operator==(const Uniform &other) const bool Uniform::operator==(const Uniform &other) const
{ {
return VariableWithLocation::operator==(other) && binding == other.binding && return VariableWithLocation::operator==(other) && binding == other.binding &&
offset == other.offset && readonly == other.readonly && writeonly == other.writeonly; imageUnitFormat == other.imageUnitFormat && offset == other.offset &&
readonly == other.readonly && writeonly == other.writeonly;
} }
bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
...@@ -289,6 +294,10 @@ bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const ...@@ -289,6 +294,10 @@ bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{ {
return false; return false;
} }
if (imageUnitFormat != other.imageUnitFormat)
{
return false;
}
if (location != -1 && other.location != -1 && location != other.location) if (location != -1 && other.location != -1 && location != other.location)
{ {
return false; return false;
......
...@@ -145,6 +145,9 @@ void TranslatorHLSL::translate(TIntermBlock *root, ...@@ -145,6 +145,9 @@ void TranslatorHLSL::translate(TIntermBlock *root,
mShaderStorageBlockRegisterMap = outputHLSL.getShaderStorageBlockRegisterMap(); mShaderStorageBlockRegisterMap = outputHLSL.getShaderStorageBlockRegisterMap();
mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap(); mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap();
mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
mReadonlyImage2DRegisterIndex = outputHLSL.getReadonlyImage2DRegisterIndex();
mImage2DRegisterIndex = outputHLSL.getImage2DRegisterIndex();
mUsedImage2DFunctionNames = outputHLSL.getUsedImage2DFunctionNames();
} }
bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll() bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll()
...@@ -181,4 +184,19 @@ const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap ...@@ -181,4 +184,19 @@ const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap
return &mUniformRegisterMap; return &mUniformRegisterMap;
} }
unsigned int TranslatorHLSL::getReadonlyImage2DRegisterIndex() const
{
return mReadonlyImage2DRegisterIndex;
}
unsigned int TranslatorHLSL::getImage2DRegisterIndex() const
{
return mImage2DRegisterIndex;
}
const std::set<std::string> *TranslatorHLSL::getUsedImage2DFunctionNames() const
{
return &mUsedImage2DFunctionNames;
}
} // namespace sh } // namespace sh
...@@ -25,6 +25,9 @@ class TranslatorHLSL : public TCompiler ...@@ -25,6 +25,9 @@ class TranslatorHLSL : public TCompiler
unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const; unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const;
const std::map<std::string, unsigned int> *getUniformRegisterMap() const; const std::map<std::string, unsigned int> *getUniformRegisterMap() const;
unsigned int getReadonlyImage2DRegisterIndex() const;
unsigned int getImage2DRegisterIndex() const;
const std::set<std::string> *getUsedImage2DFunctionNames() const;
protected: protected:
void translate(TIntermBlock *root, void translate(TIntermBlock *root,
...@@ -38,6 +41,9 @@ class TranslatorHLSL : public TCompiler ...@@ -38,6 +41,9 @@ class TranslatorHLSL : public TCompiler
std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap; std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap;
std::map<std::string, unsigned int> mUniformBlockRegisterMap; std::map<std::string, unsigned int> mUniformBlockRegisterMap;
std::map<std::string, unsigned int> mUniformRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap;
unsigned int mReadonlyImage2DRegisterIndex;
unsigned int mImage2DRegisterIndex;
std::set<std::string> mUsedImage2DFunctionNames;
}; };
} // namespace sh } // namespace sh
......
...@@ -812,7 +812,7 @@ const char *RWTextureTypeSuffix(const TBasicType type, ...@@ -812,7 +812,7 @@ const char *RWTextureTypeSuffix(const TBasicType type,
} }
default: default:
// All other types are identified by their group suffix // All other types are identified by their group suffix
return TextureGroupSuffix(type, imageInternalFormat); return RWTextureGroupSuffix(type, imageInternalFormat);
} }
#if !UNREACHABLE_IS_NORETURN #if !UNREACHABLE_IS_NORETURN
UNREACHABLE(); UNREACHABLE();
......
...@@ -778,4 +778,39 @@ bool IsInShaderStorageBlock(TIntermTyped *node) ...@@ -778,4 +778,39 @@ bool IsInShaderStorageBlock(TIntermTyped *node)
return type.getQualifier() == EvqBuffer; return type.getQualifier() == EvqBuffer;
} }
GLenum GetImageInternalFormatType(TLayoutImageInternalFormat iifq)
{
switch (iifq)
{
case EiifRGBA32F:
return GL_RGBA32F;
case EiifRGBA16F:
return GL_RGBA16F;
case EiifR32F:
return GL_R32F;
case EiifRGBA32UI:
return GL_RGBA32UI;
case EiifRGBA16UI:
return GL_RGBA16UI;
case EiifRGBA8UI:
return GL_RGBA8UI;
case EiifR32UI:
return GL_R32UI;
case EiifRGBA32I:
return GL_RGBA32I;
case EiifRGBA16I:
return GL_RGBA16I;
case EiifRGBA8I:
return GL_RGBA8I;
case EiifR32I:
return GL_R32I;
case EiifRGBA8:
return GL_RGBA8;
case EiifRGBA8_SNORM:
return GL_RGBA8_SNORM;
default:
return GL_NONE;
}
}
} // namespace sh } // namespace sh
...@@ -65,6 +65,8 @@ bool IsOutputHLSL(ShShaderOutput output); ...@@ -65,6 +65,8 @@ bool IsOutputHLSL(ShShaderOutput output);
bool IsOutputVulkan(ShShaderOutput output); bool IsOutputVulkan(ShShaderOutput output);
bool IsInShaderStorageBlock(TIntermTyped *node); bool IsInShaderStorageBlock(TIntermTyped *node);
GLenum GetImageInternalFormatType(TLayoutImageInternalFormat iifq);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_UTIL_H_ #endif // COMPILER_TRANSLATOR_UTIL_H_
...@@ -351,6 +351,8 @@ struct ImageUnit ...@@ -351,6 +351,8 @@ struct ImageUnit
GLenum format; GLenum format;
}; };
using ImageUnitTextureTypeMap = std::map<unsigned int, gl::TextureType>;
struct PixelStoreStateBase struct PixelStoreStateBase
{ {
GLint alignment = 4; GLint alignment = 4;
......
...@@ -28,27 +28,6 @@ namespace rx ...@@ -28,27 +28,6 @@ namespace rx
namespace namespace
{ {
// This class needs to match OutputHLSL::decorate
class DecorateVariable final : angle::NonCopyable
{
public:
explicit DecorateVariable(const std::string &str) : mName(str) {}
const std::string &getName() const { return mName; }
private:
const std::string &mName;
};
std::ostream &operator<<(std::ostream &o, const DecorateVariable &dv)
{
if (dv.getName().compare(0, 3, "gl_") != 0)
{
o << "_";
}
o << dv.getName();
return o;
}
const char *HLSLComponentTypeString(GLenum componentType) const char *HLSLComponentTypeString(GLenum componentType)
{ {
switch (componentType) switch (componentType)
...@@ -364,6 +343,25 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature( ...@@ -364,6 +343,25 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
return pixelHLSL; return pixelHLSL;
} }
std::string DynamicHLSL::generateComputeShaderForImage2DBindSignature(
const d3d::Context *context,
ProgramD3D &programD3D,
const gl::ProgramState &programData,
std::vector<sh::Uniform> &image2DUniforms,
const gl::ImageUnitTextureTypeMap &image2DBindLayout) const
{
std::string computeHLSL(
programData.getAttachedShader(ShaderType::Compute)->getTranslatedSource());
if (image2DUniforms.empty())
{
return computeHLSL;
}
return GenerateComputeShaderForImage2DBindSignature(context, programD3D, programData,
image2DUniforms, image2DBindLayout);
}
void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking, void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking,
const BuiltinInfo &builtins, const BuiltinInfo &builtins,
bool programUsesPointSize, bool programUsesPointSize,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "libANGLE/Program.h" #include "libANGLE/Program.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/DynamicImage2DHLSL.h"
#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h"
namespace sh namespace sh
...@@ -39,6 +40,27 @@ namespace rx ...@@ -39,6 +40,27 @@ namespace rx
class ProgramD3DMetadata; class ProgramD3DMetadata;
class ShaderD3D; class ShaderD3D;
// This class needs to match OutputHLSL::decorate
class DecorateVariable final : angle::NonCopyable
{
public:
explicit DecorateVariable(const std::string &str) : mName(str) {}
const std::string &getName() const { return mName; }
private:
const std::string &mName;
};
inline std::ostream &operator<<(std::ostream &o, const DecorateVariable &dv)
{
if (dv.getName().compare(0, 3, "gl_") != 0)
{
o << "_";
}
o << dv.getName();
return o;
}
struct PixelShaderOutputVariable struct PixelShaderOutputVariable
{ {
PixelShaderOutputVariable() {} PixelShaderOutputVariable() {}
...@@ -127,6 +149,12 @@ class DynamicHLSL : angle::NonCopyable ...@@ -127,6 +149,12 @@ class DynamicHLSL : angle::NonCopyable
const std::vector<PixelShaderOutputVariable> &outputVariables, const std::vector<PixelShaderOutputVariable> &outputVariables,
bool usesFragDepth, bool usesFragDepth,
const std::vector<GLenum> &outputLayout) const; const std::vector<GLenum> &outputLayout) const;
std::string generateComputeShaderForImage2DBindSignature(
const d3d::Context *context,
ProgramD3D &programD3D,
const gl::ProgramState &programData,
std::vector<sh::Uniform> &image2DUniforms,
const gl::ImageUnitTextureTypeMap &image2DBindLayout) const;
void generateShaderLinkHLSL(const gl::Caps &caps, void generateShaderLinkHLSL(const gl::Caps &caps,
const gl::ProgramState &programData, const gl::ProgramState &programData,
const ProgramD3DMetadata &programMetadata, const ProgramD3DMetadata &programMetadata,
......
//
// Copyright 2019 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.
//
// DynamicImage2DHLSL.h: Interface for link and run-time HLSL generation
//
#ifndef LIBANGLE_RENDERER_D3D_DYNAMICIMAGE2DHLSL_H_
#define LIBANGLE_RENDERER_D3D_DYNAMICIMAGE2DHLSL_H_
#include "common/angleutils.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace rx
{
std::string generateShaderForImage2DBindSignature(
const d3d::Context *context,
ProgramD3D &programD3D,
const gl::ProgramState &programData,
gl::ShaderType shaderType,
std::vector<sh::Uniform> &image2DUniforms,
const gl::ImageUnitTextureTypeMap &image2DBindLayout);
inline std::string GenerateComputeShaderForImage2DBindSignature(
const d3d::Context *context,
ProgramD3D &programD3D,
const gl::ProgramState &programData,
std::vector<sh::Uniform> &image2DUniforms,
const gl::ImageUnitTextureTypeMap &image2DBindLayout)
{
return generateShaderForImage2DBindSignature(context, programD3D, programData,
gl::ShaderType::Compute, image2DUniforms,
image2DBindLayout);
}
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
...@@ -53,6 +53,7 @@ struct D3DUniform : private angle::NonCopyable ...@@ -53,6 +53,7 @@ struct D3DUniform : private angle::NonCopyable
bool isSampler() const; bool isSampler() const;
bool isImage() const; bool isImage() const;
bool isImage2D() const;
bool isArray() const { return !arraySizes.empty(); } bool isArray() const { return !arraySizes.empty(); }
unsigned int getArraySizeProduct() const; unsigned int getArraySizeProduct() const;
bool isReferencedByShader(gl::ShaderType shaderType) const; bool isReferencedByShader(gl::ShaderType shaderType) const;
...@@ -198,7 +199,9 @@ class ProgramD3D : public ProgramImpl ...@@ -198,7 +199,9 @@ class ProgramD3D : public ProgramImpl
angle::Result getPixelExecutableForCachedOutputLayout(d3d::Context *context, angle::Result getPixelExecutableForCachedOutputLayout(d3d::Context *context,
ShaderExecutableD3D **outExectuable, ShaderExecutableD3D **outExectuable,
gl::InfoLog *infoLog); gl::InfoLog *infoLog);
angle::Result getComputeExecutable(ShaderExecutableD3D **outExecutable); angle::Result getComputeExecutableForImage2DBindLayout(d3d::Context *context,
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog);
std::unique_ptr<LinkEvent> link(const gl::Context *context, std::unique_ptr<LinkEvent> link(const gl::Context *context,
const gl::ProgramLinkedResources &resources, const gl::ProgramLinkedResources &resources,
gl::InfoLog &infoLog) override; gl::InfoLog &infoLog) override;
...@@ -285,6 +288,7 @@ class ProgramD3D : public ProgramImpl ...@@ -285,6 +288,7 @@ class ProgramD3D : public ProgramImpl
void updateCachedInputLayout(Serial associatedSerial, const gl::State &state); void updateCachedInputLayout(Serial associatedSerial, const gl::State &state);
void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer); void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer);
void updateCachedComputeImage2DBindLayout(const gl::Context *context);
bool isSamplerMappingDirty() { return mDirtySamplerMapping; } bool isSamplerMappingDirty() { return mDirtySamplerMapping; }
...@@ -292,6 +296,7 @@ class ProgramD3D : public ProgramImpl ...@@ -292,6 +296,7 @@ class ProgramD3D : public ProgramImpl
bool hasVertexExecutableForCachedInputLayout(); bool hasVertexExecutableForCachedInputLayout();
bool hasGeometryExecutableForPrimitiveType(gl::PrimitiveMode drawMode); bool hasGeometryExecutableForPrimitiveType(gl::PrimitiveMode drawMode);
bool hasPixelExecutableForCachedOutputLayout(); bool hasPixelExecutableForCachedOutputLayout();
bool hasComputeExecutableForCachedImage2DBindLayout();
bool anyShaderUniformsDirty() const { return mShaderUniformsDirty.any(); } bool anyShaderUniformsDirty() const { return mShaderUniformsDirty.any(); }
...@@ -309,6 +314,11 @@ class ProgramD3D : public ProgramImpl ...@@ -309,6 +314,11 @@ class ProgramD3D : public ProgramImpl
return mState.getLinkedShaderStages()[shaderType]; return mState.getLinkedShaderStages()[shaderType];
} }
void assignImage2DRegisters(unsigned int startImageIndex,
int startLogicalImageUnit,
bool readonly);
bool hasNamedUniform(const std::string &name);
private: private:
// These forward-declared tasks are used for multi-thread shader compiles. // These forward-declared tasks are used for multi-thread shader compiles.
class GetExecutableTask; class GetExecutableTask;
...@@ -371,6 +381,26 @@ class ProgramD3D : public ProgramImpl ...@@ -371,6 +381,26 @@ class ProgramD3D : public ProgramImpl
ShaderExecutableD3D *mShaderExecutable; ShaderExecutableD3D *mShaderExecutable;
}; };
class ComputeExecutable
{
public:
ComputeExecutable(const gl::ImageUnitTextureTypeMap &signature,
std::unique_ptr<ShaderExecutableD3D> shaderExecutable);
~ComputeExecutable();
bool matchesSignature(const gl::ImageUnitTextureTypeMap &signature) const
{
return mSignature == signature;
}
const gl::ImageUnitTextureTypeMap &signature() const { return mSignature; }
ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable.get(); }
private:
gl::ImageUnitTextureTypeMap mSignature;
std::unique_ptr<ShaderExecutableD3D> mShaderExecutable;
};
struct Sampler struct Sampler
{ {
Sampler(); Sampler();
...@@ -437,7 +467,6 @@ class ProgramD3D : public ProgramImpl ...@@ -437,7 +467,6 @@ class ProgramD3D : public ProgramImpl
void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings, void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings,
const BuiltinInfo &builtins); const BuiltinInfo &builtins);
D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location); D3DUniform *getD3DUniformFromLocation(GLint location);
const D3DUniform *getD3DUniformFromLocation(GLint location) const; const D3DUniform *getD3DUniformFromLocation(GLint location) const;
...@@ -449,8 +478,10 @@ class ProgramD3D : public ProgramImpl ...@@ -449,8 +478,10 @@ class ProgramD3D : public ProgramImpl
void updateCachedInputLayoutFromShader(); void updateCachedInputLayoutFromShader();
void updateCachedOutputLayoutFromShader(); void updateCachedOutputLayoutFromShader();
void updateCachedImage2DBindLayoutFromComputeShader();
void updateCachedVertexExecutableIndex(); void updateCachedVertexExecutableIndex();
void updateCachedPixelExecutableIndex(); void updateCachedPixelExecutableIndex();
void updateCachedComputeExecutableIndex();
void linkResources(const gl::ProgramLinkedResources &resources); void linkResources(const gl::ProgramLinkedResources &resources);
...@@ -461,7 +492,7 @@ class ProgramD3D : public ProgramImpl ...@@ -461,7 +492,7 @@ class ProgramD3D : public ProgramImpl
std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables; std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables;
angle::PackedEnumMap<gl::PrimitiveMode, std::unique_ptr<ShaderExecutableD3D>> angle::PackedEnumMap<gl::PrimitiveMode, std::unique_ptr<ShaderExecutableD3D>>
mGeometryExecutables; mGeometryExecutables;
std::unique_ptr<ShaderExecutableD3D> mComputeExecutable; std::vector<std::unique_ptr<ComputeExecutable>> mComputeExecutables;
gl::ShaderMap<std::string> mShaderHLSL; gl::ShaderMap<std::string> mShaderHLSL;
gl::ShaderMap<angle::CompilerWorkaroundsD3D> mShaderWorkarounds; gl::ShaderMap<angle::CompilerWorkaroundsD3D> mShaderWorkarounds;
...@@ -509,6 +540,10 @@ class ProgramD3D : public ProgramImpl ...@@ -509,6 +540,10 @@ class ProgramD3D : public ProgramImpl
std::vector<D3DInterfaceBlock> mD3DUniformBlocks; std::vector<D3DInterfaceBlock> mD3DUniformBlocks;
std::vector<D3DInterfaceBlock> mD3DShaderStorageBlocks; std::vector<D3DInterfaceBlock> mD3DShaderStorageBlocks;
std::vector<sh::Uniform> mImage2DUniforms;
gl::ImageUnitTextureTypeMap mComputeShaderImage2DBindLayoutCache;
Optional<size_t> mCachedComputeExecutableIndex;
gl::ShaderBitSet mShaderUniformsDirty; gl::ShaderBitSet mShaderUniformsDirty;
static unsigned int issueSerial(); static unsigned int issueSerial();
......
...@@ -144,6 +144,16 @@ ShShaderOutput ShaderD3D::getCompilerOutputType() const ...@@ -144,6 +144,16 @@ ShShaderOutput ShaderD3D::getCompilerOutputType() const
return mCompilerOutputType; return mCompilerOutputType;
} }
bool ShaderD3D::useImage2DFunction(const std::string &functionName) const
{
if (mUsedImage2DFunctionNames.empty())
{
return false;
}
return mUsedImage2DFunctionNames.find(functionName) != mUsedImage2DFunctionNames.end();
}
ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(const gl::Context *context, ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(const gl::Context *context,
std::stringstream *shaderSourceStream, std::stringstream *shaderSourceStream,
std::string *sourcePath) std::string *sourcePath)
...@@ -181,6 +191,13 @@ const std::map<std::string, unsigned int> &GetUniformRegisterMap( ...@@ -181,6 +191,13 @@ const std::map<std::string, unsigned int> &GetUniformRegisterMap(
return *uniformRegisterMap; return *uniformRegisterMap;
} }
const std::set<std::string> &GetUsedImage2DFunctionNames(
const std::set<std::string> *usedImage2DFunctionNames)
{
ASSERT(usedImage2DFunctionNames);
return *usedImage2DFunctionNames;
}
bool ShaderD3D::postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) bool ShaderD3D::postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog)
{ {
// TODO(jmadill): We shouldn't need to cache this. // TODO(jmadill): We shouldn't need to cache this.
...@@ -209,6 +226,10 @@ bool ShaderD3D::postTranslateCompile(gl::ShCompilerInstance *compiler, std::stri ...@@ -209,6 +226,10 @@ bool ShaderD3D::postTranslateCompile(gl::ShCompilerInstance *compiler, std::stri
ShHandle compilerHandle = compiler->getHandle(); ShHandle compilerHandle = compiler->getHandle();
mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle)); mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
mReadonlyImage2DRegisterIndex = sh::GetReadonlyImage2DRegisterIndex(compilerHandle);
mImage2DRegisterIndex = sh::GetImage2DRegisterIndex(compilerHandle);
mUsedImage2DFunctionNames =
GetUsedImage2DFunctionNames(sh::GetUsedImage2DFunctionNames(compilerHandle));
for (const sh::InterfaceBlock &interfaceBlock : mData.getUniformBlocks()) for (const sh::InterfaceBlock &interfaceBlock : mData.getUniformBlocks())
{ {
......
...@@ -56,6 +56,9 @@ class ShaderD3D : public ShaderImpl ...@@ -56,6 +56,9 @@ class ShaderD3D : public ShaderImpl
unsigned int getUniformBlockRegister(const std::string &blockName) const; unsigned int getUniformBlockRegister(const std::string &blockName) const;
unsigned int getShaderStorageBlockRegister(const std::string &blockName) const; unsigned int getShaderStorageBlockRegister(const std::string &blockName) const;
unsigned int getReadonlyImage2DRegisterIndex() const { return mReadonlyImage2DRegisterIndex; }
unsigned int getImage2DRegisterIndex() const { return mImage2DRegisterIndex; }
bool useImage2DFunction(const std::string &functionName) const;
void appendDebugInfo(const std::string &info) const { mDebugInfo += info; } void appendDebugInfo(const std::string &info) const { mDebugInfo += info; }
void generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const; void generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const;
...@@ -95,6 +98,9 @@ class ShaderD3D : public ShaderImpl ...@@ -95,6 +98,9 @@ class ShaderD3D : public ShaderImpl
std::map<std::string, unsigned int> mUniformRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap;
std::map<std::string, unsigned int> mUniformBlockRegisterMap; std::map<std::string, unsigned int> mUniformBlockRegisterMap;
std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap; std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap;
unsigned int mReadonlyImage2DRegisterIndex;
unsigned int mImage2DRegisterIndex;
std::set<std::string> mUsedImage2DFunctionNames;
ShCompileOptions mAdditionalOptions; ShCompileOptions mAdditionalOptions;
}; };
} // namespace rx } // namespace rx
......
...@@ -582,6 +582,44 @@ angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context * ...@@ -582,6 +582,44 @@ angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context)
{
const auto &glState = context->getState();
gl::Program *program = glState.getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
programD3D->updateCachedComputeImage2DBindLayout(context);
bool recompileCS = !programD3D->hasComputeExecutableForCachedImage2DBindLayout();
if (!recompileCS)
{
return angle::Result::Continue;
}
// Load the compiler if necessary and recompile the programs.
ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
gl::InfoLog infoLog;
ShaderExecutableD3D *computeExe = nullptr;
ANGLE_TRY(programD3D->getComputeExecutableForImage2DBindLayout(this, &computeExe, &infoLog));
if (!programD3D->hasComputeExecutableForCachedImage2DBindLayout())
{
ASSERT(infoLog.getLength() > 0);
ERR() << "Dynamic recompilation error log: " << infoLog.str();
ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable");
}
// Refresh the program cache entry.
if (mMemoryProgramCache)
{
mMemoryProgramCache->updateProgram(context, program);
}
return angle::Result::Continue;
}
angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers) angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{ {
return angle::Result::Continue; return angle::Result::Continue;
......
...@@ -153,7 +153,7 @@ class Context11 : public ContextD3D, public MultisampleTextureInitializer ...@@ -153,7 +153,7 @@ class Context11 : public ContextD3D, public MultisampleTextureInitializer
angle::Result triggerDrawCallProgramRecompilation(const gl::Context *context, angle::Result triggerDrawCallProgramRecompilation(const gl::Context *context,
gl::PrimitiveMode drawMode); gl::PrimitiveMode drawMode);
angle::Result triggerDispatchCallProgramRecompilation(const gl::Context *context);
angle::Result getIncompleteTexture(const gl::Context *context, angle::Result getIncompleteTexture(const gl::Context *context,
gl::TextureType type, gl::TextureType type,
gl::Texture **textureOut); gl::Texture **textureOut);
......
...@@ -262,6 +262,8 @@ void ShaderConstants11::init(const gl::Caps &caps) ...@@ -262,6 +262,8 @@ void ShaderConstants11::init(const gl::Caps &caps)
for (gl::ShaderType shaderType : gl::AllShaderTypes()) for (gl::ShaderType shaderType : gl::AllShaderTypes())
{ {
mShaderSamplerMetadata[shaderType].resize(caps.maxShaderTextureImageUnits[shaderType]); mShaderSamplerMetadata[shaderType].resize(caps.maxShaderTextureImageUnits[shaderType]);
mShaderReadonlyImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
mShaderImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
} }
} }
...@@ -290,7 +292,9 @@ size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const ...@@ -290,7 +292,9 @@ size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const
{ {
ASSERT(shaderType != gl::ShaderType::InvalidEnum); ASSERT(shaderType != gl::ShaderType::InvalidEnum);
return GetShaderConstantsStructSize(shaderType) + return GetShaderConstantsStructSize(shaderType) +
mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata); mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata) +
mShaderImageMetadata[shaderType].size() * sizeof(ImageMetadata) +
mShaderReadonlyImageMetadata[shaderType].size() * sizeof(ImageMetadata);
} }
void ShaderConstants11::markDirty() void ShaderConstants11::markDirty()
...@@ -398,6 +402,18 @@ bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data, ...@@ -398,6 +402,18 @@ bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data,
return dirty; return dirty;
} }
bool ShaderConstants11::updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit)
{
bool dirty = false;
if (data->layer != static_cast<int>(imageUnit.layer))
{
data->layer = static_cast<int>(imageUnit.layer);
dirty = true;
}
return dirty;
}
void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX, void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX,
GLuint numGroupsY, GLuint numGroupsY,
GLuint numGroupsZ) GLuint numGroupsZ)
...@@ -486,6 +502,27 @@ void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType, ...@@ -486,6 +502,27 @@ void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType,
} }
} }
void ShaderConstants11::onImageChange(gl::ShaderType shaderType,
unsigned int imageIndex,
const gl::ImageUnit &imageUnit)
{
ASSERT(shaderType != gl::ShaderType::InvalidEnum);
if (imageUnit.access == GL_READ_ONLY)
{
if (updateImageMetadata(&mShaderReadonlyImageMetadata[shaderType][imageIndex], imageUnit))
{
mNumActiveShaderReadonlyImages[shaderType] = 0;
}
}
else
{
if (updateImageMetadata(&mShaderImageMetadata[shaderType][imageIndex], imageUnit))
{
mNumActiveShaderImages[shaderType] = 0;
}
}
}
angle::Result ShaderConstants11::updateBuffer(const gl::Context *context, angle::Result ShaderConstants11::updateBuffer(const gl::Context *context,
Renderer11 *renderer, Renderer11 *renderer,
gl::ShaderType shaderType, gl::ShaderType shaderType,
...@@ -495,14 +532,28 @@ angle::Result ShaderConstants11::updateBuffer(const gl::Context *context, ...@@ -495,14 +532,28 @@ angle::Result ShaderConstants11::updateBuffer(const gl::Context *context,
// Re-upload the sampler meta-data if the current program uses more samplers // Re-upload the sampler meta-data if the current program uses more samplers
// than we previously uploaded. // than we previously uploaded.
const int numSamplers = programD3D.getUsedSamplerRange(shaderType).length(); const int numSamplers = programD3D.getUsedSamplerRange(shaderType).length();
const int numReadonlyImages = programD3D.getUsedImageRange(shaderType, true).length();
const int numImages = programD3D.getUsedImageRange(shaderType, false).length();
const bool dirty = const bool dirty = mShaderConstantsDirty[shaderType] ||
mShaderConstantsDirty[shaderType] || (mNumActiveShaderSamplers[shaderType] < numSamplers); (mNumActiveShaderSamplers[shaderType] < numSamplers) ||
(mNumActiveShaderReadonlyImages[shaderType] < numReadonlyImages) ||
(mNumActiveShaderImages[shaderType] < numImages);
const size_t dataSize = GetShaderConstantsStructSize(shaderType); const size_t dataSize = GetShaderConstantsStructSize(shaderType);
const uint8_t *samplerData = const uint8_t *samplerData =
reinterpret_cast<const uint8_t *>(mShaderSamplerMetadata[shaderType].data()); reinterpret_cast<const uint8_t *>(mShaderSamplerMetadata[shaderType].data());
const size_t samplerDataSize = sizeof(SamplerMetadata) * numSamplers;
const uint8_t *readonlyImageData =
reinterpret_cast<const uint8_t *>(mShaderReadonlyImageMetadata[shaderType].data());
const size_t readonlyImageDataSize = sizeof(ImageMetadata) * numReadonlyImages;
const uint8_t *imageData =
reinterpret_cast<const uint8_t *>(mShaderImageMetadata[shaderType].data());
const size_t imageDataSize = sizeof(ImageMetadata) * numImages;
mNumActiveShaderSamplers[shaderType] = numSamplers; mNumActiveShaderSamplers[shaderType] = numSamplers;
mNumActiveShaderReadonlyImages[shaderType] = numReadonlyImages;
mNumActiveShaderImages[shaderType] = numImages;
mShaderConstantsDirty.set(shaderType, false); mShaderConstantsDirty.set(shaderType, false);
const uint8_t *data = nullptr; const uint8_t *data = nullptr;
...@@ -538,6 +589,11 @@ angle::Result ShaderConstants11::updateBuffer(const gl::Context *context, ...@@ -538,6 +589,11 @@ angle::Result ShaderConstants11::updateBuffer(const gl::Context *context,
memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize, samplerData, memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize, samplerData,
sizeof(SamplerMetadata) * numSamplers); sizeof(SamplerMetadata) * numSamplers);
memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize, readonlyImageData,
readonlyImageDataSize);
memcpy(
static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize + readonlyImageDataSize,
imageData, imageDataSize);
renderer->getDeviceContext()->Unmap(driverConstantBuffer.get(), 0); renderer->getDeviceContext()->Unmap(driverConstantBuffer.get(), 0);
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2581,6 +2637,19 @@ angle::Result StateManager11::setTextureForSampler(const gl::Context *context, ...@@ -2581,6 +2637,19 @@ angle::Result StateManager11::setTextureForSampler(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result StateManager11::setImageState(const gl::Context *context,
gl::ShaderType type,
int index,
const gl::ImageUnit &imageUnit)
{
ASSERT(static_cast<unsigned int>(index) <
mRenderer->getNativeCaps().maxShaderImageUniforms[type]);
mShaderConstants.onImageChange(type, index, imageUnit);
return angle::Result::Continue;
}
// For each Direct3D sampler of either the pixel or vertex stage, // For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type, // looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive). // and sets the texture and its addressing/filtering state (or NULL when inactive).
...@@ -2640,6 +2709,12 @@ angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context, ...@@ -2640,6 +2709,12 @@ angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context,
mProgramD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps); mProgramD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps);
ASSERT(imageUnitIndex != -1); ASSERT(imageUnitIndex != -1);
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
if (!imageUnit.layered)
{
ANGLE_TRY(setImageState(context, gl::ShaderType::Compute,
readonlyImageIndex - readonlyImageRange.low(), imageUnit));
invalidateProgramUniforms();
}
ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, true, imageUnit)); ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, true, imageUnit));
} }
...@@ -2668,6 +2743,12 @@ angle::Result StateManager11::applyTexturesForUAVs(const gl::Context *context, ...@@ -2668,6 +2743,12 @@ angle::Result StateManager11::applyTexturesForUAVs(const gl::Context *context,
GLint imageUnitIndex = mProgramD3D->getImageMapping(shaderType, imageIndex, false, caps); GLint imageUnitIndex = mProgramD3D->getImageMapping(shaderType, imageIndex, false, caps);
ASSERT(imageUnitIndex != -1); ASSERT(imageUnitIndex != -1);
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex); const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
if (!imageUnit.layered)
{
ANGLE_TRY(setImageState(context, gl::ShaderType::Compute, imageIndex - imageRange.low(),
imageUnit));
invalidateProgramUniforms();
}
ANGLE_TRY(setTextureForImage(context, shaderType, imageIndex, false, imageUnit)); ANGLE_TRY(setTextureForImage(context, shaderType, imageIndex, false, imageUnit));
} }
...@@ -2797,10 +2878,21 @@ angle::Result StateManager11::syncProgram(const gl::Context *context, gl::Primit ...@@ -2797,10 +2878,21 @@ angle::Result StateManager11::syncProgram(const gl::Context *context, gl::Primit
angle::Result StateManager11::syncProgramForCompute(const gl::Context *context) angle::Result StateManager11::syncProgramForCompute(const gl::Context *context)
{ {
Context11 *context11 = GetImplAs<Context11>(context);
ANGLE_TRY(context11->triggerDispatchCallProgramRecompilation(context));
mProgramD3D->updateCachedComputeImage2DBindLayout(context);
// Binaries must be compiled before the sync.
ASSERT(mProgramD3D->hasComputeExecutableForCachedImage2DBindLayout());
ShaderExecutableD3D *computeExe = nullptr; ShaderExecutableD3D *computeExe = nullptr;
ANGLE_TRY(mProgramD3D->getComputeExecutable(&computeExe)); ANGLE_TRY(
ASSERT(computeExe != nullptr); mProgramD3D->getComputeExecutableForImage2DBindLayout(context11, &computeExe, nullptr));
setComputeShader(&GetAs<ShaderExecutable11>(computeExe)->getComputeShader());
const d3d11::ComputeShader *computeShader =
(computeExe ? &GetAs<ShaderExecutable11>(computeExe)->getComputeShader() : nullptr);
setComputeShader(computeShader);
// Explicitly clear the shaders dirty bit. // Explicitly clear the shaders dirty bit.
mInternalDirtyBits.reset(DIRTY_BIT_SHADERS); mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
......
...@@ -44,10 +44,14 @@ class ShaderConstants11 : angle::NonCopyable ...@@ -44,10 +44,14 @@ class ShaderConstants11 : angle::NonCopyable
const D3D11_VIEWPORT &dxViewport, const D3D11_VIEWPORT &dxViewport,
bool is9_3, bool is9_3,
bool presentPathFast); bool presentPathFast);
void onImageLayerChange(gl::ShaderType shaderType, unsigned int imageIndex, int layer);
void onSamplerChange(gl::ShaderType shaderType, void onSamplerChange(gl::ShaderType shaderType,
unsigned int samplerIndex, unsigned int samplerIndex,
const gl::Texture &texture, const gl::Texture &texture,
const gl::SamplerState &samplerState); const gl::SamplerState &samplerState);
void onImageChange(gl::ShaderType shaderType,
unsigned int imageIndex,
const gl::ImageUnit &imageUnit);
angle::Result updateBuffer(const gl::Context *context, angle::Result updateBuffer(const gl::Context *context,
Renderer11 *renderer, Renderer11 *renderer,
...@@ -127,6 +131,16 @@ class ShaderConstants11 : angle::NonCopyable ...@@ -127,6 +131,16 @@ class ShaderConstants11 : angle::NonCopyable
static_assert(sizeof(SamplerMetadata) == 32u, static_assert(sizeof(SamplerMetadata) == 32u,
"Sampler metadata struct must be two 4-vec --> 32 bytes."); "Sampler metadata struct must be two 4-vec --> 32 bytes.");
struct ImageMetadata
{
ImageMetadata() : layer(0), padding{0} {}
int layer;
int padding[3]; // This just pads the struct to 16 bytes
};
static_assert(sizeof(ImageMetadata) == 16u,
"Image metadata struct must be one 4-vec --> 16 bytes.");
static size_t GetShaderConstantsStructSize(gl::ShaderType shaderType); static size_t GetShaderConstantsStructSize(gl::ShaderType shaderType);
// Return true if dirty. // Return true if dirty.
...@@ -134,6 +148,9 @@ class ShaderConstants11 : angle::NonCopyable ...@@ -134,6 +148,9 @@ class ShaderConstants11 : angle::NonCopyable
const gl::Texture &texture, const gl::Texture &texture,
const gl::SamplerState &samplerState); const gl::SamplerState &samplerState);
// Return true if dirty.
bool updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit);
Vertex mVertex; Vertex mVertex;
Pixel mPixel; Pixel mPixel;
Compute mCompute; Compute mCompute;
...@@ -141,6 +158,10 @@ class ShaderConstants11 : angle::NonCopyable ...@@ -141,6 +158,10 @@ class ShaderConstants11 : angle::NonCopyable
gl::ShaderMap<std::vector<SamplerMetadata>> mShaderSamplerMetadata; gl::ShaderMap<std::vector<SamplerMetadata>> mShaderSamplerMetadata;
gl::ShaderMap<int> mNumActiveShaderSamplers; gl::ShaderMap<int> mNumActiveShaderSamplers;
gl::ShaderMap<std::vector<ImageMetadata>> mShaderReadonlyImageMetadata;
gl::ShaderMap<int> mNumActiveShaderReadonlyImages;
gl::ShaderMap<std::vector<ImageMetadata>> mShaderImageMetadata;
gl::ShaderMap<int> mNumActiveShaderImages;
}; };
class StateManager11 final : angle::NonCopyable class StateManager11 final : angle::NonCopyable
...@@ -313,6 +334,10 @@ class StateManager11 final : angle::NonCopyable ...@@ -313,6 +334,10 @@ class StateManager11 final : angle::NonCopyable
int index, int index,
gl::Texture *texture, gl::Texture *texture,
const gl::SamplerState &sampler); const gl::SamplerState &sampler);
angle::Result setImageState(const gl::Context *context,
gl::ShaderType type,
int index,
const gl::ImageUnit &imageUnit);
angle::Result setTextureForImage(const gl::Context *context, angle::Result setTextureForImage(const gl::Context *context,
gl::ShaderType type, gl::ShaderType type,
int index, int index,
...@@ -396,13 +421,15 @@ class StateManager11 final : angle::NonCopyable ...@@ -396,13 +421,15 @@ class StateManager11 final : angle::NonCopyable
DIRTY_BIT_RASTERIZER_STATE, DIRTY_BIT_RASTERIZER_STATE,
DIRTY_BIT_BLEND_STATE, DIRTY_BIT_BLEND_STATE,
DIRTY_BIT_DEPTH_STENCIL_STATE, DIRTY_BIT_DEPTH_STENCIL_STATE,
// DIRTY_BIT_SHADERS and DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE should be dealt before
// DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS for update image layers.
DIRTY_BIT_SHADERS,
DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE, DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE,
DIRTY_BIT_PROGRAM_UNIFORMS, DIRTY_BIT_PROGRAM_UNIFORMS,
DIRTY_BIT_DRIVER_UNIFORMS, DIRTY_BIT_DRIVER_UNIFORMS,
DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS, DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS,
DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS, DIRTY_BIT_PROGRAM_ATOMIC_COUNTER_BUFFERS,
DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS, DIRTY_BIT_PROGRAM_SHADER_STORAGE_BUFFERS,
DIRTY_BIT_SHADERS,
DIRTY_BIT_CURRENT_VALUE_ATTRIBS, DIRTY_BIT_CURRENT_VALUE_ATTRIBS,
DIRTY_BIT_TRANSFORM_FEEDBACK, DIRTY_BIT_TRANSFORM_FEEDBACK,
DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT, DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT,
......
...@@ -339,6 +339,8 @@ libangle_d3d_shared_sources = [ ...@@ -339,6 +339,8 @@ libangle_d3d_shared_sources = [
"src/libANGLE/renderer/d3d/DisplayD3D.h", "src/libANGLE/renderer/d3d/DisplayD3D.h",
"src/libANGLE/renderer/d3d/DynamicHLSL.cpp", "src/libANGLE/renderer/d3d/DynamicHLSL.cpp",
"src/libANGLE/renderer/d3d/DynamicHLSL.h", "src/libANGLE/renderer/d3d/DynamicHLSL.h",
"src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp",
"src/libANGLE/renderer/d3d/DynamicImage2DHLSL.h",
"src/libANGLE/renderer/d3d/EGLImageD3D.cpp", "src/libANGLE/renderer/d3d/EGLImageD3D.cpp",
"src/libANGLE/renderer/d3d/EGLImageD3D.h", "src/libANGLE/renderer/d3d/EGLImageD3D.h",
"src/libANGLE/renderer/d3d/formatutilsD3D.h", "src/libANGLE/renderer/d3d/formatutilsD3D.h",
......
...@@ -1096,8 +1096,6 @@ void main() ...@@ -1096,8 +1096,6 @@ void main()
// contents. // contents.
TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray) TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
{ {
ANGLE_SKIP_TEST_IF(IsD3D11());
GLTexture texture[2]; GLTexture texture[2];
GLFramebuffer framebuffer; GLFramebuffer framebuffer;
constexpr char kCS[] = R"(#version 310 es constexpr char kCS[] = R"(#version 310 es
...@@ -1165,7 +1163,6 @@ void main() ...@@ -1165,7 +1163,6 @@ void main()
// contents. // contents.
TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D) TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
{ {
ANGLE_SKIP_TEST_IF(IsD3D11());
GLTexture texture[2]; GLTexture texture[2];
GLFramebuffer framebuffer; GLFramebuffer framebuffer;
constexpr char kCS[] = R"(#version 310 es constexpr char kCS[] = R"(#version 310 es
...@@ -1233,8 +1230,6 @@ void main() ...@@ -1233,8 +1230,6 @@ void main()
// contents. // contents.
TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube) TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
{ {
ANGLE_SKIP_TEST_IF(IsD3D11());
GLTexture texture[2]; GLTexture texture[2];
GLFramebuffer framebuffer; GLFramebuffer framebuffer;
constexpr char kCS[] = R"(#version 310 es constexpr char kCS[] = R"(#version 310 es
...@@ -1313,6 +1308,109 @@ void main() ...@@ -1313,6 +1308,109 @@ void main()
} }
} }
// Test to bind kinds of texture types, bind either the entire texture
// level or a single layer or face of the face level.
TEST_P(ComputeShaderTest, BindImageTextureWithMixTextureTypes)
{
GLTexture texture[4];
GLFramebuffer framebuffer;
const char csSource[] =
R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
layout(r32ui, binding = 1) readonly uniform highp uimage2D uImage_2;
layout(r32ui, binding = 2) readonly uniform highp uimage3D uImage_3;
layout(r32ui, binding = 3) writeonly uniform highp uimage2D uImage_4;
void main()
{
uvec4 value_1 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
uvec4 value_2 = imageLoad(uImage_2, ivec2(gl_LocalInvocationID.xy));
uvec4 value_3 = imageLoad(uImage_3, ivec3(gl_LocalInvocationID.xyz));
imageStore(uImage_4, ivec2(gl_LocalInvocationID.xy), value_1 + value_2 + value_3);
})";
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
constexpr int kResultSize = kWidth * kHeight;
constexpr GLuint kInputValues2D[1] = {11};
constexpr GLuint KInputValues2DArray[2] = {23, 35};
constexpr GLuint KInputValues3D[2] = {102, 67};
constexpr GLuint KInputValuesCube[1] = {232};
constexpr GLuint expectedValue_1 = 148;
constexpr GLuint expectedValue_2 = 232;
GLuint outputValues[kResultSize];
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
kInputValues2D);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
GL_UNSIGNED_INT, KInputValues2DArray);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_3D, texture[2]);
glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
GL_UNSIGNED_INT, KInputValues3D);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_CUBE_MAP, texture[3]);
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
face++)
{
glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
KInputValuesCube);
}
EXPECT_GL_NO_ERROR();
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
glUseProgram(program.get());
glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glBindImageTexture(2, texture[2], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glBindImageTexture(3, texture[3], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glDispatchCompute(1, 1, 1);
EXPECT_GL_NO_ERROR();
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
glUseProgram(0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
for (GLenum face = 0; face < 6; face++)
{
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[3], 0);
EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR();
if (face == 4)
{
for (int i = 0; i < kResultSize; i++)
{
EXPECT_EQ(expectedValue_1, outputValues[i]);
}
}
else
{
for (int i = 0; i < kResultSize; i++)
{
EXPECT_EQ(expectedValue_2, outputValues[i]);
}
}
}
}
// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a // Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
// program which has not been linked successfully or which does not contain objects to form a // program which has not been linked successfully or which does not contain objects to form a
// compute shader. // compute shader.
......
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