Commit 790abf03 by Tim Van Patten Committed by Commit Bot

Vulkan: Support program interface queries for inputs

Program interface queries are a generic way to query attributes of the program like uniforms, samplers, attributes, etc. This change supports those queries for program inputs. Bug: angleproject:3596 Test: dEQP-GLES31.functional.program_interface_query.* Test: ProgramInterfaceTest.cpp Change-Id: Ie904274f4efd87357256f559b69e148e8eda6119 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1775458Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Tim Van Patten <timvp@google.com>
parent d1c4a6d6
...@@ -321,7 +321,7 @@ class ProgramState final : angle::NonCopyable ...@@ -321,7 +321,7 @@ class ProgramState final : angle::NonCopyable
{ {
return mActiveUniformBlockBindings; return mActiveUniformBlockBindings;
} }
const std::vector<sh::ShaderVariable> &getAttributes() const { return mAttributes; } const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
const AttributesMask &getActiveAttribLocationsMask() const const AttributesMask &getActiveAttribLocationsMask() const
{ {
return mActiveAttribLocationsMask; return mActiveAttribLocationsMask;
...@@ -400,6 +400,7 @@ class ProgramState final : angle::NonCopyable ...@@ -400,6 +400,7 @@ class ProgramState final : angle::NonCopyable
{ {
return mActiveSamplerFormats[textureUnitIndex]; return mActiveSamplerFormats[textureUnitIndex];
} }
ShaderType getFirstAttachedShaderStageType() const;
private: private:
friend class MemoryProgramCache; friend class MemoryProgramCache;
...@@ -408,6 +409,7 @@ class ProgramState final : angle::NonCopyable ...@@ -408,6 +409,7 @@ class ProgramState final : angle::NonCopyable
void updateTransformFeedbackStrides(); void updateTransformFeedbackStrides();
void updateActiveSamplers(); void updateActiveSamplers();
void updateActiveImages(); void updateActiveImages();
void updateProgramInterfaceInputs();
// Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex); void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex);
...@@ -425,7 +427,8 @@ class ProgramState final : angle::NonCopyable ...@@ -425,7 +427,8 @@ class ProgramState final : angle::NonCopyable
// For faster iteration on the blocks currently being bound. // For faster iteration on the blocks currently being bound.
UniformBlockBindingMask mActiveUniformBlockBindings; UniformBlockBindingMask mActiveUniformBlockBindings;
std::vector<sh::ShaderVariable> mAttributes; // Vertex attributes, Fragment input varyings, etc.
std::vector<sh::ShaderVariable> mProgramInputs;
angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask; angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
unsigned int mMaxActiveAttribLocation; unsigned int mMaxActiveAttribLocation;
ComponentTypeMask mAttributesTypeMask; ComponentTypeMask mAttributesTypeMask;
...@@ -879,7 +882,10 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -879,7 +882,10 @@ class Program final : angle::NonCopyable, public LabeledObject
GLsizei bufSize, GLsizei bufSize,
GLsizei *length, GLsizei *length,
GLchar *name) const; GLchar *name) const;
const sh::ShaderVariable &getInputResource(GLuint index) const; const sh::ShaderVariable &getInputResource(size_t index) const;
GLuint getInputResourceMaxNameSize() const;
GLuint getInputResourceLocation(const GLchar *name) const;
const std::string getInputResourceName(GLuint index) const;
const sh::ShaderVariable &getOutputResource(GLuint index) const; const sh::ShaderVariable &getOutputResource(GLuint index) const;
const ProgramBindings &getAttributeBindings() const; const ProgramBindings &getAttributeBindings() const;
...@@ -936,6 +942,8 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -936,6 +942,8 @@ class Program final : angle::NonCopyable, public LabeledObject
// Writes a program's binary to the output memory buffer. // Writes a program's binary to the output memory buffer.
void serialize(const Context *context, angle::MemoryBuffer *binaryOut) const; void serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
int getArrayIndexFromName(const GLchar *name) const;
private: private:
struct LinkingState; struct LinkingState;
...@@ -1024,12 +1032,10 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -1024,12 +1032,10 @@ class Program final : angle::NonCopyable, public LabeledObject
GLenum nativeType, GLenum nativeType,
int components) const; int components) const;
template <typename T> void getResourceName(const std::string name,
void getResourceName(GLuint index,
const std::vector<T> &resources,
GLsizei bufSize, GLsizei bufSize,
GLsizei *length, GLsizei *length,
GLchar *name) const; GLchar *dest) const;
template <typename T> template <typename T>
GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const; GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const;
...@@ -1044,6 +1050,8 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -1044,6 +1050,8 @@ class Program final : angle::NonCopyable, public LabeledObject
void postResolveLink(const gl::Context *context); void postResolveLink(const gl::Context *context);
std::string stripArraySubscriptFromName(const GLchar *name) const;
ProgramState mState; ProgramState mState;
rx::ProgramImpl *mProgram; rx::ProgramImpl *mProgram;
......
...@@ -615,24 +615,32 @@ GLint GetCommonVariableProperty(const sh::ShaderVariable &var, GLenum prop) ...@@ -615,24 +615,32 @@ GLint GetCommonVariableProperty(const sh::ShaderVariable &var, GLenum prop)
GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop) GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop)
{ {
const auto &attribute = program->getInputResource(index); const sh::ShaderVariable &variable = program->getInputResource(index);
switch (prop) switch (prop)
{ {
case GL_TYPE: case GL_TYPE:
case GL_ARRAY_SIZE: case GL_ARRAY_SIZE:
return GetCommonVariableProperty(variable, prop);
case GL_NAME_LENGTH: case GL_NAME_LENGTH:
return GetCommonVariableProperty(attribute, prop); return clampCast<GLint>(program->getInputResourceName(index).size() + 1u);
case GL_LOCATION: case GL_LOCATION:
return program->getAttributeLocation(attribute.name); return variable.location;
// The query is targeted at the set of active input variables used by the first shader stage
// of program. If program contains multiple shader stages then input variables from any
// stage other than the first will not be enumerated. Since we found the variable to get
// this far, we know it exists in the first attached shader stage.
case GL_REFERENCED_BY_VERTEX_SHADER: case GL_REFERENCED_BY_VERTEX_SHADER:
return 1; return program->getState().getFirstAttachedShaderStageType() == ShaderType::Vertex;
case GL_REFERENCED_BY_FRAGMENT_SHADER: case GL_REFERENCED_BY_FRAGMENT_SHADER:
return program->getState().getFirstAttachedShaderStageType() == ShaderType::Fragment;
case GL_REFERENCED_BY_COMPUTE_SHADER: case GL_REFERENCED_BY_COMPUTE_SHADER:
return program->getState().getFirstAttachedShaderStageType() == ShaderType::Compute;
case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT: case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
return 0; return program->getState().getFirstAttachedShaderStageType() == ShaderType::Geometry;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -698,7 +706,7 @@ GLint QueryProgramInterfaceActiveResources(const Program *program, GLenum progra ...@@ -698,7 +706,7 @@ GLint QueryProgramInterfaceActiveResources(const Program *program, GLenum progra
switch (programInterface) switch (programInterface)
{ {
case GL_PROGRAM_INPUT: case GL_PROGRAM_INPUT:
return clampCast<GLint>(program->getAttributes().size()); return clampCast<GLint>(program->getState().getProgramInputs().size());
case GL_PROGRAM_OUTPUT: case GL_PROGRAM_OUTPUT:
return clampCast<GLint>(program->getState().getOutputVariables().size()); return clampCast<GLint>(program->getState().getOutputVariables().size());
...@@ -744,7 +752,7 @@ GLint QueryProgramInterfaceMaxNameLength(const Program *program, GLenum programI ...@@ -744,7 +752,7 @@ GLint QueryProgramInterfaceMaxNameLength(const Program *program, GLenum programI
switch (programInterface) switch (programInterface)
{ {
case GL_PROGRAM_INPUT: case GL_PROGRAM_INPUT:
maxNameLength = FindMaxSize(program->getAttributes(), &sh::ShaderVariable::name); maxNameLength = program->getInputResourceMaxNameSize();
break; break;
case GL_PROGRAM_OUTPUT: case GL_PROGRAM_OUTPUT:
...@@ -1707,7 +1715,7 @@ GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLe ...@@ -1707,7 +1715,7 @@ GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLe
GLint GetBufferVariableResourceProperty(const Program *program, GLuint index, const GLenum prop) GLint GetBufferVariableResourceProperty(const Program *program, GLuint index, const GLenum prop)
{ {
const auto &bufferVariable = program->getBufferVariableByIndex(index); const BufferVariable &bufferVariable = program->getBufferVariableByIndex(index);
switch (prop) switch (prop)
{ {
case GL_TYPE: case GL_TYPE:
...@@ -1836,7 +1844,7 @@ GLint QueryProgramResourceLocation(const Program *program, ...@@ -1836,7 +1844,7 @@ GLint QueryProgramResourceLocation(const Program *program,
switch (programInterface) switch (programInterface)
{ {
case GL_PROGRAM_INPUT: case GL_PROGRAM_INPUT:
return program->getAttributeLocation(name); return program->getInputResourceLocation(name);
case GL_PROGRAM_OUTPUT: case GL_PROGRAM_OUTPUT:
return program->getFragDataLocation(name); return program->getFragDataLocation(name);
...@@ -1861,10 +1869,17 @@ void QueryProgramResourceiv(const Program *program, ...@@ -1861,10 +1869,17 @@ void QueryProgramResourceiv(const Program *program,
{ {
if (!program->isLinked()) if (!program->isLinked())
{ {
if (length != nullptr) return;
{ }
*length = 0;
} if (length != nullptr)
{
*length = 0;
}
if (bufSize == 0)
{
// No room to write the results
return; return;
} }
......
...@@ -1557,7 +1557,7 @@ angle::Result ProgramD3D::getVertexExecutableForCachedInputLayout( ...@@ -1557,7 +1557,7 @@ angle::Result ProgramD3D::getVertexExecutableForCachedInputLayout(
// Generate new dynamic layout with attribute conversions // Generate new dynamic layout with attribute conversions
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout( std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, mState.getAttributes()); mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, mState.getProgramInputs());
// Generate new vertex executable // Generate new vertex executable
ShaderExecutableD3D *vertexExecutable = nullptr; ShaderExecutableD3D *vertexExecutable = nullptr;
......
...@@ -267,7 +267,7 @@ std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context, ...@@ -267,7 +267,7 @@ std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
} }
// Bind attribute locations to match the GL layer. // Bind attribute locations to match the GL layer.
for (const sh::ShaderVariable &attribute : mState.getAttributes()) for (const sh::ShaderVariable &attribute : mState.getProgramInputs())
{ {
if (!attribute.active || attribute.isBuiltIn()) if (!attribute.active || attribute.isBuiltIn())
{ {
......
...@@ -497,7 +497,7 @@ void AssignAttributeLocations(const gl::ProgramState &programState, ...@@ -497,7 +497,7 @@ void AssignAttributeLocations(const gl::ProgramState &programState,
// Parse attribute locations and replace them in the vertex shader. // Parse attribute locations and replace them in the vertex shader.
// See corresponding code in OutputVulkanGLSL.cpp. // See corresponding code in OutputVulkanGLSL.cpp.
for (const sh::ShaderVariable &attribute : programState.getAttributes()) for (const sh::ShaderVariable &attribute : programState.getProgramInputs())
{ {
// Warning: If we end up supporting ES 3.0 shaders and up, Program::linkAttributes is // Warning: If we end up supporting ES 3.0 shaders and up, Program::linkAttributes is
// going to bring us all attributes in this list instead of only the active ones. // going to bring us all attributes in this list instead of only the active ones.
......
...@@ -267,7 +267,8 @@ bool ValidateProgramResourceIndex(const Program *programObject, ...@@ -267,7 +267,8 @@ bool ValidateProgramResourceIndex(const Program *programObject,
switch (programInterface) switch (programInterface)
{ {
case GL_PROGRAM_INPUT: case GL_PROGRAM_INPUT:
return (index < static_cast<GLuint>(programObject->getActiveAttributeCount())); return (index <
static_cast<GLuint>(programObject->getState().getProgramInputs().size()));
case GL_PROGRAM_OUTPUT: case GL_PROGRAM_OUTPUT:
return (index < static_cast<GLuint>(programObject->getOutputResourceCount())); return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
......
...@@ -630,7 +630,6 @@ ...@@ -630,7 +630,6 @@
3520 VULKAN : dEQP-GLES31.functional.state_query.integer.max_uniform_locations* = FAIL 3520 VULKAN : dEQP-GLES31.functional.state_query.integer.max_uniform_locations* = FAIL
// Front-end query bugs: // Front-end query bugs:
3520 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_limited_query.resource_query = FAIL
3520 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.resource_list.compute.empty = FAIL 3520 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.resource_list.compute.empty = FAIL
3520 VULKAN : dEQP-GLES31.functional.program_interface_query.shader_storage_block.buffer_data_size.* = FAIL 3520 VULKAN : dEQP-GLES31.functional.program_interface_query.shader_storage_block.buffer_data_size.* = FAIL
...@@ -651,55 +650,15 @@ ...@@ -651,55 +650,15 @@
// SSBO and Image qualifiers: // SSBO and Image qualifiers:
3602 VULKAN : dEQP-GLES31.functional.synchronization.in_invocation.ssbo_alias_overwrite = FAIL 3602 VULKAN : dEQP-GLES31.functional.synchronization.in_invocation.ssbo_alias_overwrite = FAIL
// Struct referenced by:
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.compute.uniform_block.float_*struct* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.compute.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.separable_vertex.uniform_block.float_*struct* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.separable_vertex.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.vertex_fragment.uniform_block.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.vertex_fragment.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.vertex_fragment_only_vertex.uniform_block.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.vertex_fragment_only_vertex.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.vertex_fragment_only_fragment.uniform_block.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.vertex_fragment_only_fragment.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.compute.named_block.float_*struct* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.compute.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_vertex.named_block.float_*struct* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_vertex.named_block.float_array_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_vertex.named_block.float_struct_array = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_vertex.named_block.float_struct_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_vertex.named_block.float_unsized_struct_array = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_vertex.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.vertex_fragment.named_block.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.vertex_fragment.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.vertex_fragment_only_vertex.named_block.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.vertex_fragment_only_vertex.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.vertex_fragment_only_fragment.named_block.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.vertex_fragment_only_fragment.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.*random* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.separable_fragment.uniform_block.*struct* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.separable_fragment.block_array.float_struct = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.resource_list.separable_fragment.* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.array_size.separable_fragment.* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.location.separable_fragment.var* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.name_length.separable_fragment.var* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.type.separable_fragment.* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_fragment.named_block.float*struct* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.buffer_variable.referenced_by.separable_fragment.block_array.float_struct = FAIL
// Separate shader objects: // Separate shader objects:
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.referenced_by.referenced_by_separable_fragment = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_input.referenced_by.referenced_by_vertex_fragment = SKIP
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.resource_list.separable_vertex.* = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.resource_list.separable_vertex.* = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.array_size.separable_vertex.var* = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.array_size.separable_vertex.var* = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.location.separable_vertex.var* = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.location.separable_vertex.var* = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.name_length.separable_vertex.var* = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.name_length.separable_vertex.var* = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.referenced_by.referenced_by_separable_vertex = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.referenced_by.referenced_by_separable_vertex = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.referenced_by.referenced_by_vertex_fragment = SKIP
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.type.separable_vertex.basic_type.* = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.type.separable_vertex.basic_type.* = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.type.separable_vertex.array.* = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.type.separable_vertex.array.* = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.type.separable_vertex.struct.* = FAIL 3570 VULKAN : dEQP-GLES31.functional.program_interface_query.program_output.type.separable_vertex.struct.* = FAIL
3570 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.random.* = FAIL
// Block name matching failure: // Block name matching failure:
3459 VULKAN : dEQP-GLES31.functional.shaders.linkage.es31.shader_storage_block.mismatch_with_and_without_instance_name = FAIL 3459 VULKAN : dEQP-GLES31.functional.shaders.linkage.es31.shader_storage_block.mismatch_with_and_without_instance_name = FAIL
......
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