Commit e895ced6 by Mohan Maiya Committed by Commit Bot

Vulkan: Add OES_shader_image_atomic support

Add support for shader builtins and enable the extension. Bug: angleproject:3578 Tests: dEQP-GLES31.functional.*image_atomic* Change-Id: Idd45b2ee62efe1474c6c5947c77da64ff2221bf6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2505540 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 4c5630d0
......@@ -26,7 +26,7 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 235
#define ANGLE_SH_VERSION 236
enum ShShaderSpec
{
......@@ -407,7 +407,7 @@ struct ShBuiltInResources
int EXT_texture_cube_map_array;
int EXT_shadow_samplers;
int OES_shader_multisample_interpolation;
int OES_shader_image_atomic;
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
// EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers
......
......@@ -357,6 +357,14 @@ struct FeaturesVk : FeatureSetBase
"and has the shaderFloat16 feature",
&members, "http://anglebug.com/4551"};
// Whether the VkDevice supports the VK_EXT_shader_atomic_flat extension and has the
// shaderImageFloat32Atomics feature
Feature supportsShaderImageFloat32Atomics = {
"shaderImageFloat32Atomics", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_EXT_shader_atomic_float extension and has the "
"shaderImageFloat32Atomics feature.",
&members, "http://anglebug.com/3578"};
// Some devices don't meet the limits required to perform mipmap generation using the built-in
// compute shader. On some other devices, VK_IMAGE_USAGE_STORAGE_BIT is detrimental to
// performance, making this solution impractical.
......
{
"src/compiler/translator/ImmutableString_ESSL_autogen.cpp":
"98168ea2a1d9bfa290c7e72e299955f8",
"bab94ae93917a40dd2f3184be08a4933",
"src/compiler/translator/ImmutableString_autogen.cpp":
"663daecf68294fa141be288ceb7f75f0",
"fa74ff3796c28e14bb617749987c94f8",
"src/compiler/translator/ParseContext_ESSL_autogen.h":
"b33dad2b5b23cc4a48b0a8183c536c21",
"fb36d587618dabfd828d7d5f645fa2e5",
"src/compiler/translator/ParseContext_complete_autogen.h":
"6113be5f4ebd8789901ef48a611a1e03",
"2db8d7d0efd13afdd4b971c89f785f7e",
"src/compiler/translator/SymbolTable_ESSL_autogen.cpp":
"96a8712eba5ae5245af83b082cbd5219",
"6a4ad24f5d85a39e797226cc9416df1d",
"src/compiler/translator/SymbolTable_autogen.cpp":
"51bdcd32bb37a2a1bbffa154f7427694",
"0ea25cc0c63638efa3f38923e796008b",
"src/compiler/translator/SymbolTable_autogen.h":
"2d8bed6ff5debc6546199a2add316a66",
"src/compiler/translator/builtin_function_declarations.txt":
"bd195be52e11bb993aa757acb3770b85",
"dfc73c66a0efbdc7543ed7a6fbd3f00c",
"src/compiler/translator/builtin_variables.json":
"98d347a6ed181eca3d89bfd73193d787",
"src/compiler/translator/gen_builtin_symbols.py":
"a538e53475983ae9643afd5b36056347",
"src/compiler/translator/tree_util/BuiltIn_ESSL_autogen.h":
"ad4b5fafc78f98b2bf0ff1f0516d6f4b",
"359670b3327789b173bb961e3c66a19f",
"src/compiler/translator/tree_util/BuiltIn_complete_autogen.h":
"7429fd6b4be0c23aba95fbbc66a40ad9",
"2ec6e29190e01f1731b3e3a18d6f0684",
"src/tests/compiler_tests/ImmutableString_test_ESSL_autogen.cpp":
"ade4d08598c35df6eb3a67a9eb45bad8",
"90bfc0010975c358a3a8d6336f9afb01",
"src/tests/compiler_tests/ImmutableString_test_autogen.cpp":
"424a9c61841fa9b5613fb94210272c30"
"7994b8d74b3f497da8e7b031a7f83e3d"
}
\ No newline at end of file
......@@ -1091,6 +1091,7 @@ void TCompiler::setResourceString()
<< ":EXT_texture_cube_map_array:" << mResources.EXT_texture_cube_map_array
<< ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers
<< ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation
<< ":OES_shader_image_atomic:" << mResources.OES_shader_image_atomic
<< ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset
<< ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset
<< ":MaxImageUnits:" << mResources.MaxImageUnits
......
......@@ -36,6 +36,7 @@
OP(OES_EGL_image_external) \
OP(OES_EGL_image_external_essl3) \
OP(OES_shader_multisample_interpolation) \
OP(OES_shader_image_atomic) \
OP(OES_standard_derivatives) \
OP(OES_texture_3D) \
OP(OES_texture_cube_map_array) \
......
......@@ -42,6 +42,7 @@ enum class TExtension : uint8_t
OES_EGL_image_external,
OES_EGL_image_external_essl3,
OES_shader_multisample_interpolation,
OES_shader_image_atomic,
OES_standard_derivatives,
OES_texture_3D,
OES_texture_cube_map_array,
......
......@@ -133,6 +133,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
{
extBehavior[TExtension::OES_shader_multisample_interpolation] = EBhUndefined;
}
if (resources.OES_shader_image_atomic)
{
extBehavior[TExtension::OES_shader_image_atomic] = EBhUndefined;
}
}
void ResetExtensionBehavior(const ShBuiltInResources &resources,
......
......@@ -6105,6 +6105,21 @@ void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *
GetImageArgumentToken(imageNode));
}
}
else if (BuiltInGroup::isImageAtomic(func))
{
if (memoryQualifier.readonly)
{
error(imageNode->getLine(),
"'imageAtomic' cannot be used with images qualified as 'readonly'",
GetImageArgumentToken(imageNode));
}
if (memoryQualifier.writeonly)
{
error(imageNode->getLine(),
"'imageAtomic' cannot be used with images qualified as 'writeonly'",
GetImageArgumentToken(imageNode));
}
}
}
}
......
......@@ -21,72 +21,77 @@ namespace BuiltInGroup
bool isTextureOffsetNoBias(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3110 && id <= 3179;
return id >= 3671 && id <= 3740;
}
bool isTextureOffsetBias(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3180 && id <= 3199;
return id >= 3741 && id <= 3760;
}
bool isTextureGatherOffsetsComp(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3237 && id <= 3249;
return id >= 3798 && id <= 3810;
}
bool isTextureGatherOffsetsNoComp(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3250 && id <= 3265;
return id >= 3811 && id <= 3826;
}
bool isTextureGatherOffsets(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3237 && id <= 3265;
return id >= 3798 && id <= 3826;
}
bool isTextureGatherOffsetComp(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3266 && id <= 3271;
return id >= 3827 && id <= 3832;
}
bool isTextureGatherOffsetNoComp(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3272 && id <= 3279;
return id >= 3833 && id <= 3840;
}
bool isTextureGatherOffset(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3266 && id <= 3279;
return id >= 3827 && id <= 3840;
}
bool isTextureGather(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3213 && id <= 3279;
return id >= 3774 && id <= 3840;
}
bool isInterpolationFS(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3292 && id <= 3315;
return id >= 3853 && id <= 3876;
}
bool isAtomicMemory(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3320 && id <= 3337;
return id >= 3881 && id <= 3898;
}
bool isImageLoad(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3368 && id <= 3382;
return id >= 3929 && id <= 3943;
}
bool isImageAtomic(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3944 && id <= 4522;
}
bool isImageStore(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3383 && id <= 3397;
return id >= 4523 && id <= 4537;
}
bool isImage(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 3338 && id <= 3397;
return id >= 3899 && id <= 4537;
}
} // namespace BuiltInGroup
......
......@@ -76,17 +76,22 @@ bool isAtomicMemory(const TFunction *func)
bool isImageLoad(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 2142 && id <= 2174;
return id >= 1578 && id <= 1613;
}
bool isImageAtomic(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 1614 && id <= 2735;
}
bool isImageStore(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 2175 && id <= 2207;
return id >= 2736 && id <= 2768;
}
bool isImage(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 1506 && id <= 2207;
return id >= 1506 && id <= 2768;
}
} // namespace BuiltInGroup
......
......@@ -180,8 +180,8 @@ void InitBuiltInResources(ShBuiltInResources *resources)
resources->EXT_texture_cube_map_array = 0;
resources->EXT_shadow_samplers = 0;
resources->OES_shader_multisample_interpolation = 0;
resources->NV_draw_buffers = 0;
resources->NV_draw_buffers = 0;
resources->OES_shader_image_atomic = 0;
resources->MaxClipDistances = 0;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1087,26 +1087,46 @@ GROUP BEGIN Image {"queryFunction": true}
DEFAULT METADATA {"glsl_level": "GLSL4_5_BUILTINS", "op": "CallBuiltInFunction"}
int imageSamples(readonly writeonly gimage2DMS);
int imageSamples(readonly writeonly gimage2DMSArray);
DEFAULT METADATA {"glsl_level": "GLSL4_2_BUILTINS", "op": "CallBuiltInFunction"}
uint imageAtomicAdd(IMAGE_PARAMS, uint);
int imageAtomicAdd(IMAGE_PARAMS, int);
uint imageAtomicMin(IMAGE_PARAMS, uint);
int imageAtomicMin(IMAGE_PARAMS, int);
uint imageAtomicMax(IMAGE_PARAMS, uint);
int imageAtomicMax(IMAGE_PARAMS, int);
uint imageAtomicAnd(IMAGE_PARAMS, uint);
int imageAtomicAnd(IMAGE_PARAMS, int);
uint imageAtomicOr(IMAGE_PARAMS, uint);
int imageAtomicOr(IMAGE_PARAMS, int);
uint imageAtomicXor(IMAGE_PARAMS, uint);
int imageAtomicXor(IMAGE_PARAMS, int);
uint imageAtomicExchange(IMAGE_PARAMS, uint);
int imageAtomicExchange(IMAGE_PARAMS, int);
DEFAULT METADATA {"glsl_level": "GLSL4_5_BUILTINS", "op": "CallBuiltInFunction"}
int imageAtomicExchange(IMAGE_PARAMS, float);
DEFAULT METADATA {"glsl_level": "GLSL4_2_BUILTINS", "op": "CallBuiltInFunction"}
uint imageAtomicCompSwap(IMAGE_PARAMS, uint, uint);
int imageAtomicCompSwap(IMAGE_PARAMS, int, int);
GROUP BEGIN Atomic {"queryFunction": true}
DEFAULT METADATA {"glsl_level": "GLSL4_2_BUILTINS", "op": "CallBuiltInFunction"}
uint imageAtomicAdd(IMAGE_PARAMS, uint);
int imageAtomicAdd(IMAGE_PARAMS, int);
uint imageAtomicMin(IMAGE_PARAMS, uint);
int imageAtomicMin(IMAGE_PARAMS, int);
uint imageAtomicMax(IMAGE_PARAMS, uint);
int imageAtomicMax(IMAGE_PARAMS, int);
uint imageAtomicAnd(IMAGE_PARAMS, uint);
int imageAtomicAnd(IMAGE_PARAMS, int);
uint imageAtomicOr(IMAGE_PARAMS, uint);
int imageAtomicOr(IMAGE_PARAMS, int);
uint imageAtomicXor(IMAGE_PARAMS, uint);
int imageAtomicXor(IMAGE_PARAMS, int);
uint imageAtomicExchange(IMAGE_PARAMS, uint);
int imageAtomicExchange(IMAGE_PARAMS, int);
DEFAULT METADATA {"glsl_level": "GLSL4_5_BUILTINS", "op": "CallBuiltInFunction"}
int imageAtomicExchange(IMAGE_PARAMS, float);
DEFAULT METADATA {"glsl_level": "GLSL4_2_BUILTINS", "op": "CallBuiltInFunction"}
uint imageAtomicCompSwap(IMAGE_PARAMS, uint, uint);
int imageAtomicCompSwap(IMAGE_PARAMS, int, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "op": "CallBuiltInFunction", "essl_extension": "OES_shader_image_atomic", "suffix": "Ext"}
uint imageAtomicAdd(readonly writeonly IMAGE_PARAMS, uint);
int imageAtomicAdd(readonly writeonly IMAGE_PARAMS, int);
uint imageAtomicMin(readonly writeonly IMAGE_PARAMS, uint);
int imageAtomicMin(readonly writeonly IMAGE_PARAMS, int);
uint imageAtomicMax(readonly writeonly IMAGE_PARAMS, uint);
int imageAtomicMax(readonly writeonly IMAGE_PARAMS, int);
uint imageAtomicAnd(readonly writeonly IMAGE_PARAMS, uint);
int imageAtomicAnd(readonly writeonly IMAGE_PARAMS, int);
uint imageAtomicOr(readonly writeonly IMAGE_PARAMS, uint);
int imageAtomicOr(readonly writeonly IMAGE_PARAMS, int);
uint imageAtomicXor(readonly writeonly IMAGE_PARAMS, uint);
int imageAtomicXor(readonly writeonly IMAGE_PARAMS, int);
uint imageAtomicExchange(readonly writeonly IMAGE_PARAMS, uint);
int imageAtomicExchange(readonly writeonly IMAGE_PARAMS, int);
int imageAtomicExchange(readonly writeonly IMAGE_PARAMS, float);
uint imageAtomicCompSwap(readonly writeonly IMAGE_PARAMS, uint, uint);
int imageAtomicCompSwap(readonly writeonly IMAGE_PARAMS, int, int);
GROUP END Atomic
GROUP END Image
GROUP BEGIN Noise
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1037,6 +1037,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_OES_texture_stencil8"] = enableableExtension(&Extensions::stencilIndex8);
map["GL_OES_sample_shading"] = enableableExtension(&Extensions::sampleShadingOES);
map["GL_OES_shader_multisample_interpolation"] = enableableExtension(&Extensions::multisampleInterpolationOES);
map["GL_OES_shader_image_atomic"] = enableableExtension(&Extensions::shaderImageAtomicOES);
map["GL_NV_robustness_video_memory_purge"] = esOnlyExtension(&Extensions::robustnessVideoMemoryPurgeNV);
map["GL_ANGLE_get_tex_level_parameter"] = enableableExtension(&Extensions::getTexLevelParameterANGLE);
// GLES1 extensions
......
......@@ -657,6 +657,9 @@ struct Extensions
// OES_shader_multisample_interpolation
bool multisampleInterpolationOES = false;
// GL_OES_shader_image_atomic
bool shaderImageAtomicOES = false;
// GL_NV_robustness_video_memory_purge
bool robustnessVideoMemoryPurgeNV = false;
......
......@@ -112,6 +112,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp
mResources.APPLE_clip_distance = extensions.clipDistanceAPPLE;
// OES_shader_multisample_interpolation
mResources.OES_shader_multisample_interpolation = extensions.multisampleInterpolationOES;
mResources.OES_shader_image_atomic = extensions.shaderImageAtomicOES;
// TODO: use shader precision caps to determine if high precision is supported?
mResources.FragmentPrecisionHigh = 1;
mResources.EXT_frag_depth = extensions.fragDepth;
......
......@@ -961,6 +961,10 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
mShaderFloat16Int8Features.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES;
mShaderAtomicFloatFeature = {};
mShaderAtomicFloatFeature.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT;
mDepthStencilResolveProperties = {};
mDepthStencilResolveProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
......@@ -1036,6 +1040,12 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
vk::AddToPNextChain(&deviceFeatures, &mShaderFloat16Int8Features);
}
// Query shader atomic float features
if (ExtensionFound(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, deviceExtensionNames))
{
vk::AddToPNextChain(&deviceFeatures, &mShaderAtomicFloatFeature);
}
// Query depth/stencil resolve properties
if (ExtensionFound(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, deviceExtensionNames))
{
......@@ -1080,6 +1090,7 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
mSubgroupProperties.pNext = nullptr;
mExternalMemoryHostProperties.pNext = nullptr;
mShaderFloat16Int8Features.pNext = nullptr;
mShaderAtomicFloatFeature.pNext = nullptr;
mDepthStencilResolveProperties.pNext = nullptr;
mSamplerYcbcrConversionFeatures.pNext = nullptr;
}
......@@ -1431,6 +1442,12 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
vk::AddToPNextChain(&createInfo, &mShaderFloat16Int8Features);
}
if (getFeatures().supportsShaderImageFloat32Atomics.enabled)
{
enabledDeviceExtensions.push_back(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME);
vk::AddToPNextChain(&createInfo, &mShaderAtomicFloatFeature);
}
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.flags = 0;
createInfo.queueCreateInfoCount = 1;
......@@ -1925,6 +1942,9 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat16,
mShaderFloat16Int8Features.shaderFloat16 == VK_TRUE);
ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderImageFloat32Atomics,
mShaderAtomicFloatFeature.shaderImageFloat32Atomics == VK_TRUE);
// The compute shader used to generate mipmaps uses a 256-wide workgroup. This path is only
// enabled on devices that meet this minimum requirement. Furthermore,
// VK_IMAGE_USAGE_STORAGE_BIT is detrimental to performance on many platforms, on which this
......
......@@ -356,6 +356,7 @@ class RendererVk : angle::NonCopyable
VkPhysicalDeviceSubgroupProperties mSubgroupProperties;
VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties;
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features;
VkPhysicalDeviceShaderAtomicFloatFeaturesEXT mShaderAtomicFloatFeature;
VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties;
VkExternalFenceProperties mExternalFenceProperties;
VkExternalSemaphoreProperties mExternalSemaphoreProperties;
......
......@@ -368,6 +368,11 @@ void RendererVk::ensureCapsInitialized() const
mNativeExtensions.multisampleInterpolationOES =
supportSampleRateShading && (mNativeCaps.maxInterpolationOffset >= 0.5);
mNativeExtensions.shaderImageAtomicOES =
((mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics == VK_TRUE) &&
(mPhysicalDeviceFeatures.fragmentStoresAndAtomics == VK_TRUE) &&
getFeatures().supportsShaderImageFloat32Atomics.enabled);
// https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html
mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
mNativeCaps.max3DTextureSize = LimitToInt(limitsVk.maxImageDimension3D);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
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