Commit 26143fdd by Xinghua Cao Committed by Commit Bot

ES31: Support bindImageTexture on Texture2D for compute shaders on D3D

BUG=angleproject:1987 TEST=angle_end2end_tests Change-Id: I3b0afb441a41dbd7f204b1d1bba7884c8d203ce1 Reviewed-on: https://chromium-review.googlesource.com/749004 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 10d41397
......@@ -25,7 +25,7 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 193
#define ANGLE_SH_VERSION 194
enum ShShaderSpec
{
......
......@@ -170,6 +170,8 @@ struct Uniform : public VariableWithLocation
int binding;
int offset;
bool readonly;
bool writeonly;
// Decide whether two uniforms are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
......
......@@ -93,7 +93,7 @@ struct UniformTypeInfo final : angle::NonCopyable
{
constexpr UniformTypeInfo(GLenum type,
GLenum componentType,
GLenum samplerTextureType,
GLenum textureType,
GLenum transposedMatrixType,
GLenum boolVectorType,
int rowCount,
......@@ -107,7 +107,7 @@ struct UniformTypeInfo final : angle::NonCopyable
bool isImageType)
: type(type),
componentType(componentType),
samplerTextureType(samplerTextureType),
textureType(textureType),
transposedMatrixType(transposedMatrixType),
boolVectorType(boolVectorType),
rowCount(rowCount),
......@@ -124,7 +124,7 @@ struct UniformTypeInfo final : angle::NonCopyable
GLenum type;
GLenum componentType;
GLenum samplerTextureType;
GLenum textureType;
GLenum transposedMatrixType;
GLenum boolVectorType;
int rowCount;
......
......@@ -697,6 +697,8 @@ Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable)
uniform.binding = variable.getType().getLayoutQualifier().binding;
uniform.location = variable.getType().getLayoutQualifier().location;
uniform.offset = variable.getType().getLayoutQualifier().offset;
uniform.readonly = variable.getType().getMemoryQualifier().readonly;
uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
return uniform;
}
......
......@@ -245,7 +245,8 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
return true;
}
Uniform::Uniform() : binding(-1), offset(-1)
Uniform::Uniform() : binding(-1), offset(-1), readonly(false), writeonly(false)
{
}
......@@ -254,7 +255,11 @@ Uniform::~Uniform()
}
Uniform::Uniform(const Uniform &other)
: VariableWithLocation(other), binding(other.binding), offset(other.offset)
: VariableWithLocation(other),
binding(other.binding),
offset(other.offset),
readonly(other.readonly),
writeonly(other.writeonly)
{
}
......@@ -263,13 +268,15 @@ Uniform &Uniform::operator=(const Uniform &other)
VariableWithLocation::operator=(other);
binding = other.binding;
offset = other.offset;
readonly = other.readonly;
writeonly = other.writeonly;
return *this;
}
bool Uniform::operator==(const Uniform &other) const
{
return VariableWithLocation::operator==(other) && binding == other.binding &&
offset == other.offset;
offset == other.offset && readonly == other.readonly && writeonly == other.writeonly;
}
bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
......@@ -288,6 +295,10 @@ bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{
return false;
}
if (readonly != other.readonly || writeonly != other.writeonly)
{
return false;
}
return VariableWithLocation::isSameVariableAtLinkTime(other, true, true);
}
......
......@@ -17,6 +17,7 @@
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "platform/WorkaroundsD3D.h"
namespace rx
......@@ -31,22 +32,29 @@ class ShaderExecutableD3D;
#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
#endif
enum class HLSLRegisterType : uint8_t
{
None = 0,
Texture = 1,
UnorderedAccessView = 2
};
// Helper struct representing a single shader uniform
// TODO(jmadill): Make uniform blocks shared between all programs, so we don't need separate
// register indices.
struct D3DUniform : private angle::NonCopyable
{
D3DUniform(GLenum type,
HLSLRegisterType reg,
const std::string &nameIn,
const std::vector<unsigned int> &arraySizesIn,
bool defaultBlock);
~D3DUniform();
bool isSampler() const;
bool isImage() const;
bool isArray() const { return !arraySizes.empty(); }
unsigned int getArraySizeProduct() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
bool isReferencedByComputeShader() const;
......@@ -65,6 +73,7 @@ struct D3DUniform : private angle::NonCopyable
uint8_t *csData;
// Register information.
HLSLRegisterType regType;
unsigned int vsRegisterIndex;
unsigned int psRegisterIndex;
unsigned int csRegisterIndex;
......@@ -175,6 +184,13 @@ class ProgramD3D : public ProgramImpl
SamplerMapping updateSamplerMapping();
GLint getImageMapping(gl::ShaderType type,
unsigned int imageIndex,
bool readonly,
const gl::Caps &caps) const;
GLuint getUsedImageRange(gl::ShaderType type, bool readonly) const;
GLenum getImageTextureType(gl::ShaderType type, unsigned int imageIndex, bool readonly) const;
bool usesPointSize() const { return mUsesPointSize; }
bool usesPointSpriteEmulation() const;
bool usesGeometryShader(GLenum drawMode) const;
......@@ -368,6 +384,13 @@ class ProgramD3D : public ProgramImpl
GLenum textureType;
};
struct Image
{
Image();
bool active;
GLint logicalImageUnit;
};
typedef std::map<std::string, D3DUniform *> D3DUniformMap;
void defineUniformsAndAssignRegisters(const gl::Context *context);
......@@ -377,22 +400,26 @@ class ProgramD3D : public ProgramImpl
void defineStructUniformFields(GLenum shaderType,
const std::vector<sh::ShaderVariable> &fields,
const std::string &namePrefix,
const HLSLRegisterType regType,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void defineArrayOfStructsUniformFields(GLenum shaderType,
const sh::ShaderVariable &uniform,
unsigned int arrayNestingIndex,
const std::string &prefix,
const HLSLRegisterType regType,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void defineArrayUniformElements(GLenum shaderType,
const sh::ShaderVariable &uniform,
const std::string &fullName,
const HLSLRegisterType regType,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void defineUniform(GLenum shaderType,
const sh::ShaderVariable &uniform,
const std::string &fullName,
const HLSLRegisterType regType,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void assignAllSamplerRegisters();
......@@ -404,6 +431,14 @@ class ProgramD3D : public ProgramImpl
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
void assignAllImageRegisters();
void assignImageRegisters(size_t uniformIndex);
static void AssignImages(unsigned int startImageIndex,
int startLogicalImageUnit,
unsigned int imageCount,
std::vector<Image> &outImages,
GLuint *outUsedRange);
template <typename DestT>
void getUniformInternal(GLint location, DestT *dataOut) const;
......@@ -491,6 +526,11 @@ class ProgramD3D : public ProgramImpl
GLuint mUsedComputeSamplerRange;
bool mDirtySamplerMapping;
std::vector<Image> mImagesCS;
std::vector<Image> mReadonlyImagesCS;
GLuint mUsedComputeImageRange;
GLuint mUsedComputeReadonlyImageRange;
// Cache for pixel shader output layout to save reallocations.
std::vector<GLenum> mPixelShaderOutputLayoutCache;
Optional<size_t> mCachedPixelExecutableIndex;
......@@ -507,6 +547,7 @@ class ProgramD3D : public ProgramImpl
std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms;
std::map<std::string, int> mImageBindingMap;
std::vector<D3DUniformBlock> mD3DUniformBlocks;
bool mVertexUniformsDirty;
......
......@@ -211,6 +211,14 @@ HRESULT CreateResource(ID3D11Device *device,
}
HRESULT CreateResource(ID3D11Device *device,
const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc,
ID3D11Resource *resource,
ID3D11UnorderedAccessView **resourceOut)
{
return device->CreateUnorderedAccessView(resource, desc, resourceOut);
}
HRESULT CreateResource(ID3D11Device *device,
const D3D11_TEXTURE2D_DESC *desc,
const D3D11_SUBRESOURCE_DATA *initData,
ID3D11Texture2D **texture)
......
......@@ -60,6 +60,8 @@ using ShaderData = WrappedArray<uint8_t>;
OP(NAME, SamplerState, ID3D11SamplerState, D3D11_SAMPLER_DESC, void) \
OP(NAME, ShaderResourceView, ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, \
ID3D11Resource) \
OP(NAME, UnorderedAccessView, ID3D11UnorderedAccessView, D3D11_UNORDERED_ACCESS_VIEW_DESC, \
ID3D11Resource) \
OP(NAME, Texture2D, ID3D11Texture2D, D3D11_TEXTURE2D_DESC, const D3D11_SUBRESOURCE_DATA) \
OP(NAME, Texture3D, ID3D11Texture3D, D3D11_TEXTURE3D_DESC, const D3D11_SUBRESOURCE_DATA) \
OP(NAME, VertexShader, ID3D11VertexShader, ShaderData, void)
......@@ -357,6 +359,7 @@ namespace d3d11
ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS)
using SharedSRV = SharedResource11<ID3D11ShaderResourceView>;
using SharedUAV = SharedResource11<ID3D11UnorderedAccessView>;
} // namespace d3d11
#undef ANGLE_RESOURCE_TYPE_CLASS
......
......@@ -295,6 +295,10 @@ class StateManager11 final : angle::NonCopyable
void setShaderResourceInternal(gl::ShaderType shaderType,
UINT resourceSlot,
const SRVType *srv);
template <typename UAVType>
void setUnorderedAccessViewInternal(gl::ShaderType shaderType,
UINT resourceSlot,
const UAVType *uav);
bool unsetConflictingView(ID3D11View *view);
bool unsetConflictingSRVs(gl::ShaderType shaderType,
......@@ -324,6 +328,7 @@ class StateManager11 final : angle::NonCopyable
gl::Error syncTextures(const gl::Context *context);
gl::Error applyTextures(const gl::Context *context, gl::ShaderType shaderType);
gl::Error syncTexturesForCompute(const gl::Context *context);
gl::Error setSamplerState(const gl::Context *context,
gl::ShaderType type,
......@@ -334,9 +339,15 @@ class StateManager11 final : angle::NonCopyable
gl::ShaderType type,
int index,
gl::Texture *texture);
gl::Error setTextureForImage(const gl::Context *context,
gl::ShaderType type,
int index,
bool readonly,
const gl::ImageUnit &imageUnit);
// Faster than calling setTexture a jillion times
gl::Error clearTextures(gl::ShaderType shaderType, size_t rangeStart, size_t rangeEnd);
gl::Error clearSRVs(gl::ShaderType shaderType, size_t rangeStart, size_t rangeEnd);
gl::Error clearUAVs(gl::ShaderType shaderType, size_t rangeStart, size_t rangeEnd);
void handleMultiviewDrawFramebufferChange(const gl::Context *context);
gl::Error syncCurrentValueAttribs(const gl::State &glState);
......@@ -432,42 +443,50 @@ class StateManager11 final : angle::NonCopyable
std::set<Query11 *> mCurrentQueries;
// Currently applied textures
struct SRVRecord
template <typename DescType>
struct ViewRecord
{
uintptr_t srv;
uintptr_t view;
uintptr_t resource;
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
DescType desc;
};
// A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV
// A cache of current Views that also tracks the highest 'used' (non-NULL) View.
// We might want to investigate a more robust approach that is also fast when there's
// a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will
// waste time on SRVs 1-6.)
class SRVCache : angle::NonCopyable
// a large gap between used Views (e.g. if View 0 and 7 are non-NULL, this approach will
// waste time on Views 1-6.)
template <typename ViewType, typename DescType>
class ViewCache : angle::NonCopyable
{
public:
SRVCache();
~SRVCache();
ViewCache();
~ViewCache();
void initialize(size_t size) { mCurrentSRVs.resize(size); }
void initialize(size_t size) { mCurrentViews.resize(size); }
size_t size() const { return mCurrentSRVs.size(); }
size_t highestUsed() const { return mHighestUsedSRV; }
size_t size() const { return mCurrentViews.size(); }
size_t highestUsed() const { return mHighestUsedView; }
const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; }
const ViewRecord<DescType> &operator[](size_t index) const { return mCurrentViews[index]; }
void clear();
void update(size_t resourceIndex, ID3D11ShaderResourceView *srv);
void update(size_t resourceIndex, ViewType *view);
private:
std::vector<SRVRecord> mCurrentSRVs;
size_t mHighestUsedSRV;
std::vector<ViewRecord<DescType>> mCurrentViews;
size_t mHighestUsedView;
};
using SRVCache = ViewCache<ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC>;
using UAVCache = ViewCache<ID3D11UnorderedAccessView, D3D11_UNORDERED_ACCESS_VIEW_DESC>;
SRVCache mCurVertexSRVs;
SRVCache mCurPixelSRVs;
SRVCache mCurComputeSRVs;
UAVCache mCurComputeUAVs;
SRVCache *getSRVCache(gl::ShaderType shaderType);
// A block of NULL pointers, cached so we don't re-allocate every draw call
std::vector<ID3D11ShaderResourceView *> mNullSRVs;
std::vector<ID3D11UnorderedAccessView *> mNullUAVs;
// Current translations of "Current-Value" data - owned by Context, not VertexArray.
gl::AttributesMask mDirtyCurrentValueAttribs;
......
......@@ -87,7 +87,7 @@ def get_swizzle_format_id(internal_format, angle_format):
# The format itself can be used for swizzles if it can be accessed as a render target and
# sampled and the bit count for all 4 channels is the same.
if "rtvFormat" in angle_format and "srvFormat" in angle_format and not channels_different and len(angle_format['channels']) == 4:
if "rtvFormat" in angle_format and "srvFormat" in angle_format and "uavFormat" in angle_format and not channels_different and len(angle_format['channels']) == 4:
return angle_format["glInternalFormat"] if "glInternalFormat" in angle_format else internal_format
b = int(math.ceil(float(max_component_bits) / 8) * 8)
......@@ -144,6 +144,7 @@ format_entry_template = """{space}{{
{space} angle::Format::ID::{formatName},
{space} {texFormat},
{space} {srvFormat},
{space} {uavFormat},
{space} {rtvFormat},
{space} {dsvFormat},
{space} {blitSRVFormat},
......@@ -159,6 +160,7 @@ split_format_entry_template = """{space} {condition}
{space} angle::Format::ID::{formatName},
{space} {texFormat},
{space} {srvFormat},
{space} {uavFormat},
{space} {rtvFormat},
{space} {dsvFormat},
{space} {blitSRVFormat},
......@@ -178,6 +180,7 @@ def json_to_table_data(internal_format, format_name, prefix, json):
"formatName": format_name,
"texFormat": "DXGI_FORMAT_UNKNOWN",
"srvFormat": "DXGI_FORMAT_UNKNOWN",
"uavFormat": "DXGI_FORMAT_UNKNOWN",
"rtvFormat": "DXGI_FORMAT_UNKNOWN",
"dsvFormat": "DXGI_FORMAT_UNKNOWN",
"condition": prefix,
......
......@@ -52,6 +52,9 @@ static constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f,
0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}};
// TODO(xinghua.cao@intel.com): Get a more accurate limit.
static D3D_FEATURE_LEVEL kMinimumFeatureLevelForES31 = D3D_FEATURE_LEVEL_11_0;
// Helper functor for querying DXGI support. Saves passing the parameters repeatedly.
class DXGISupportHelper : angle::NonCopyable
{
......@@ -1208,6 +1211,11 @@ gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
}
}
D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31()
{
return kMinimumFeatureLevelForES31;
}
unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
......
......@@ -73,6 +73,8 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31();
} // namespace d3d11_gl
namespace d3d11
......
......@@ -14,6 +14,7 @@
"R8G8B8A8_UNORM": {
"texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
"srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
"uavFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
"rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
"channels": "rgba",
"componentType": "unorm",
......@@ -32,6 +33,7 @@
"R16G16B16A16_FLOAT": {
"texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
"srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
"uavFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
"rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
"channels": "rgba",
"componentType": "float",
......@@ -41,6 +43,7 @@
"R32G32B32A32_FLOAT": {
"texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
"srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
"uavFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
"rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
"channels": "rgba",
"componentType": "float",
......@@ -204,6 +207,7 @@
"R32_FLOAT": {
"texFormat": "DXGI_FORMAT_R32_FLOAT",
"srvFormat": "DXGI_FORMAT_R32_FLOAT",
"uavFormat": "DXGI_FORMAT_R32_FLOAT",
"rtvFormat": "DXGI_FORMAT_R32_FLOAT",
"channels": "r",
"componentType": "float",
......@@ -213,6 +217,7 @@
"R32_SINT": {
"texFormat": "DXGI_FORMAT_R32_SINT",
"srvFormat": "DXGI_FORMAT_R32_SINT",
"uavFormat": "DXGI_FORMAT_R32_SINT",
"rtvFormat": "DXGI_FORMAT_R32_SINT",
"channels": "r",
"componentType": "int",
......@@ -222,6 +227,7 @@
"R32_UINT": {
"texFormat": "DXGI_FORMAT_R32_UINT",
"srvFormat": "DXGI_FORMAT_R32_UINT",
"uavFormat": "DXGI_FORMAT_R32_UINT",
"rtvFormat": "DXGI_FORMAT_R32_UINT",
"channels": "r",
"componentType": "uint",
......@@ -373,6 +379,7 @@
"R16G16B16A16_SINT": {
"texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
"srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
"uavFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
"rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
"channels": "rgba",
"componentType": "int",
......@@ -382,6 +389,7 @@
"R16G16B16A16_UINT": {
"texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
"srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
"uavFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
"rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
"channels": "rgba",
"componentType": "uint",
......@@ -391,6 +399,7 @@
"R32G32B32A32_SINT": {
"texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
"srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
"uavFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
"rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
"channels": "rgba",
"componentType": "int",
......@@ -400,6 +409,7 @@
"R32G32B32A32_UINT": {
"texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
"srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
"uavFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
"rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
"channels": "rgba",
"componentType": "uint",
......@@ -438,6 +448,7 @@
"R8G8B8A8_UINT": {
"texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
"srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
"uavFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
"rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
"channels": "rgba",
"componentType": "uint",
......@@ -447,6 +458,7 @@
"R8G8B8A8_SNORM": {
"texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
"srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
"uavFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
"channels": "rgba",
"componentType": "snorm",
"bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
......
......@@ -37,6 +37,7 @@ struct Format final : private angle::NonCopyable
angle::Format::ID formatID,
DXGI_FORMAT texFormat,
DXGI_FORMAT srvFormat,
DXGI_FORMAT uavFormat,
DXGI_FORMAT rtvFormat,
DXGI_FORMAT dsvFormat,
DXGI_FORMAT blitSRVFormat,
......@@ -54,6 +55,7 @@ struct Format final : private angle::NonCopyable
DXGI_FORMAT texFormat;
DXGI_FORMAT srvFormat;
DXGI_FORMAT uavFormat;
DXGI_FORMAT rtvFormat;
DXGI_FORMAT dsvFormat;
......@@ -69,6 +71,7 @@ constexpr Format::Format()
formatID(angle::Format::ID::NONE),
texFormat(DXGI_FORMAT_UNKNOWN),
srvFormat(DXGI_FORMAT_UNKNOWN),
uavFormat(DXGI_FORMAT_UNKNOWN),
rtvFormat(DXGI_FORMAT_UNKNOWN),
dsvFormat(DXGI_FORMAT_UNKNOWN),
blitSRVFormat(DXGI_FORMAT_UNKNOWN),
......@@ -81,6 +84,7 @@ constexpr Format::Format(GLenum internalFormat,
angle::Format::ID formatID,
DXGI_FORMAT texFormat,
DXGI_FORMAT srvFormat,
DXGI_FORMAT uavFormat,
DXGI_FORMAT rtvFormat,
DXGI_FORMAT dsvFormat,
DXGI_FORMAT blitSRVFormat,
......@@ -90,6 +94,7 @@ constexpr Format::Format(GLenum internalFormat,
formatID(formatID),
texFormat(texFormat),
srvFormat(srvFormat),
uavFormat(uavFormat),
rtvFormat(rtvFormat),
dsvFormat(dsvFormat),
blitSRVFormat(blitSRVFormat),
......
......@@ -346,8 +346,6 @@ TEST_P(ComputeShaderTest, DispatchCompute)
// Use image uniform to write texture in compute shader, and verify the content is expected.
TEST_P(ComputeShaderTest, BindImageTexture)
{
ANGLE_SKIP_TEST_IF(IsD3D11());
GLTexture mTexture[2];
GLFramebuffer mFramebuffer;
const std::string csSource =
......@@ -528,6 +526,88 @@ TEST_P(ComputeShaderTest, ImageSize)
EXPECT_GL_NO_ERROR();
}
// Use image uniform to read and write textures in compute shader, and verify the contents.
TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
{
GLTexture texture[2];
GLFramebuffer framebuffer;
const std::string csSource =
R"(#version 310 es
layout(local_size_x=4, local_size_y=2, local_size_z=1) in;
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
void main()
{
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
})";
constexpr int kWidth = 4, kHeight = 2;
constexpr GLuint kInputValues[2][8] = {{200, 200, 200, 200, 200, 200, 200, 200},
{100, 100, 100, 100, 100, 100, 100, 100}};
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,
kInputValues[0]);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
kInputValues[1]);
EXPECT_GL_NO_ERROR();
glUseProgram(0);
GLuint outputValues[8];
constexpr GLuint expectedValue_1 = 200;
constexpr GLuint expectedValue_2 = 100;
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
for (int i = 0; i < kWidth * kHeight; i++)
{
EXPECT_EQ(expectedValue_1, outputValues[i]);
}
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
for (int i = 0; i < kWidth * kHeight; i++)
{
EXPECT_EQ(expectedValue_2, outputValues[i]);
}
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
glUseProgram(program.get());
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glDispatchCompute(1, 1, 1);
EXPECT_GL_NO_ERROR();
glUseProgram(0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR();
for (int i = 0; i < kWidth * kHeight; i++)
{
EXPECT_EQ(expectedValue_1, outputValues[i]);
}
}
// Check that it is not possible to create a compute shader when the context does not support ES
// 3.10
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