Commit a0159c03 by Jaedon Lee Committed by Commit Bot

Vulkan: Implement basic geometry shader feature

Enable the default behavior of the geometry shader Bug: angleproject:3571 Test: dEQP-GLES31.functional.geometry_shading.input.basic_primitive.points dEQP-GLES31.functional.geometry_shading.input.basic_primitive.lines dEQP-GLES31.functional.geometry_shading.input.basic_primitive.line_loop dEQP-GLES31.functional.geometry_shading.input.basic_primitive.line_strip dEQP-GLES31.functional.geometry_shading.input.basic_primitive.triangles dEQP-GLES31.functional.geometry_shading.input.basic_primitive.triangle_strip dEQP-GLES31.functional.geometry_shading.input.basic_primitive.triangle_fan Change-Id: I65708d19bbfe6a0ad8ca392a1d6b3609b1410ef4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1793753 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent f8bb9087
......@@ -158,6 +158,7 @@ Samsung Electronics, Inc.
Kyeongmin Kim
Minkyu Jeong
Mohan Maiya
Sangwon Park
Arm Ltd.
Fei Yang
......@@ -920,6 +920,14 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
return false;
}
}
else if (getShaderType() == GL_GEOMETRY_SHADER)
{
AddANGLEPositionVarying(root, &getSymbolTable());
WriteGeometryShaderLayoutQualifiers(
sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
}
else
{
ASSERT(getShaderType() == GL_COMPUTE_SHADER);
......
......@@ -1382,7 +1382,8 @@ angle::Result Program::link(const Context *context)
unlink();
// Re-link shaders after the unlink call.
ASSERT(linkValidateShaders(mInfoLog));
bool result = linkValidateShaders(mInfoLog);
ASSERT(result);
std::unique_ptr<ProgramLinkedResources> resources;
if (mState.mAttachedShaders[ShaderType::Compute])
......@@ -4043,7 +4044,7 @@ bool Program::linkValidateGlobalNames(InfoLog &infoLog) const
uniformBlockFieldMap[field.name];
for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
{
const sh::InterfaceBlock *prevUniformBlock = prevBlockFieldPair.first;
const sh::InterfaceBlock *prevUniformBlock = prevBlockFieldPair.first;
const sh::ShaderVariable *prevUniformBlockField = prevBlockFieldPair.second;
if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
......@@ -4139,21 +4140,18 @@ ProgramMergedVaryings Program::getMergedVaryings() const
{
ProgramMergedVaryings merged;
Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
if (vertexShader)
{
for (const sh::ShaderVariable &varying : vertexShader->getOutputVaryings())
{
merged[varying.name].vertex = &varying;
}
}
Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
if (fragmentShader)
for (Shader *shader : mState.mAttachedShaders)
{
for (const sh::ShaderVariable &varying : fragmentShader->getInputVaryings())
if (shader)
{
merged[varying.name].fragment = &varying;
for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
{
merged[varying.name].frontShader = &varying;
}
for (const sh::ShaderVariable &varying : shader->getInputVaryings())
{
merged[varying.name].backShader = &varying;
}
}
}
......
......@@ -544,10 +544,10 @@ class ProgramBindings final : angle::NonCopyable
struct ProgramVaryingRef
{
const sh::ShaderVariable *get() const { return vertex ? vertex : fragment; }
const sh::ShaderVariable *get() const { return frontShader ? frontShader : backShader; }
const sh::ShaderVariable *vertex = nullptr;
const sh::ShaderVariable *fragment = nullptr;
const sh::ShaderVariable *frontShader = nullptr;
const sh::ShaderVariable *backShader = nullptr;
};
using ProgramMergedVaryings = std::map<std::string, ProgramVaryingRef>;
......
......@@ -472,7 +472,7 @@ void Shader::resolveCompile()
{
mState.mAllAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
// TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
mState.mActiveOutputVariables =
......@@ -610,7 +610,8 @@ const std::vector<sh::ShaderVariable> &Shader::getActiveOutputVariables()
std::string Shader::getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName)
{
// TODO(jiawei.shao@intel.com): support transform feedback on geometry shader.
ASSERT(mState.getShaderType() == ShaderType::Vertex);
ASSERT(mState.getShaderType() == ShaderType::Vertex ||
mState.getShaderType() == ShaderType::Geometry);
const auto &varyings = getOutputVaryings();
auto bracketPos = tfVaryingName.find("[");
if (bracketPos != std::string::npos)
......
......@@ -287,8 +287,8 @@ bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
for (const auto &ref : mergedVaryings)
{
const sh::ShaderVariable *input = ref.second.vertex;
const sh::ShaderVariable *output = ref.second.fragment;
const sh::ShaderVariable *input = ref.second.frontShader;
const sh::ShaderVariable *output = ref.second.backShader;
// Only pack statically used varyings that have a matched input or output, plus special
// builtins. Note that we pack all statically used user-defined varyings even if they are
......@@ -313,7 +313,7 @@ bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
// variable is taken from the fragment shader.
if (varying->isStruct())
{
ASSERT(!varying->isArray());
ASSERT(!(varying->isArray() && varying == input));
for (GLuint fieldIndex = 0; fieldIndex < varying->fields.size(); ++fieldIndex)
{
const sh::ShaderVariable &field = varying->fields[fieldIndex];
......@@ -406,7 +406,6 @@ bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
const std::vector<PackedVarying> &packedVaryings)
{
// "Variables are packed into the registers one at a time so that they each occupy a contiguous
// subrectangle. No splitting of variables is permitted."
for (const PackedVarying &packedVarying : packedVaryings)
......
......@@ -229,8 +229,11 @@ std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
std::vector<std::string> transformFeedbackVaryingMappedNames;
for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
{
gl::ShaderType tfShaderType = mState.hasLinkedShaderStage(gl::ShaderType::Geometry)
? gl::ShaderType::Geometry
: gl::ShaderType::Vertex;
std::string tfVaryingMappedName =
mState.getAttachedShader(gl::ShaderType::Vertex)
mState.getAttachedShader(tfShaderType)
->getTransformFeedbackVaryingMappedName(tfVarying);
transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
}
......
......@@ -102,6 +102,7 @@ class IntermediateShaderSource final : angle::NonCopyable
void init(const std::string &source);
bool empty() const { return mTokens.empty(); }
bool findTokenName(const std::string &name);
// Find @@ LAYOUT-name(extra, args) @@ and replace it with:
//
// layout(specifier, extra, args)
......@@ -280,6 +281,18 @@ void IntermediateShaderSource::init(const std::string &source)
}
}
bool IntermediateShaderSource::findTokenName(const std::string &name)
{
for (Token &block : mTokens)
{
if (block.text == name)
{
return true;
}
}
return false;
}
void IntermediateShaderSource::insertLayoutSpecifier(const std::string &name,
const std::string &specifier)
{
......@@ -567,7 +580,8 @@ void AssignOutputLocations(const gl::ProgramState &programState,
}
}
void AssignVaryingLocations(const gl::ProgramLinkedResources &resources,
void AssignVaryingLocations(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources,
IntermediateShaderSource *outStageSource,
IntermediateShaderSource *inStageSource)
{
......@@ -607,6 +621,16 @@ void AssignVaryingLocations(const gl::ProgramLinkedResources &resources,
const std::string &name =
varying.isStructField() ? varying.parentStructName : varying.varying->name;
// Varings are from 3 stage of shader sources
// To match pair of (out - in) qualifier, varying should be in the pair of shader source
if (!outStageSource->findTokenName(name) || !inStageSource->findTokenName(name))
{
// Pair can be unmatching at transform feedback case,
// But it requires qualifier.
if (!varying.vertexOnly)
continue;
}
outStageSource->insertLayoutSpecifier(name, locationString);
inStageSource->insertLayoutSpecifier(name, locationString);
......@@ -939,18 +963,29 @@ void GlslangWrapper::GetShaderSource(bool useOldRewriteStructSamplers,
IntermediateShaderSource *vertexSource = &intermediateSources[gl::ShaderType::Vertex];
IntermediateShaderSource *fragmentSource = &intermediateSources[gl::ShaderType::Fragment];
IntermediateShaderSource *geometrySource = &intermediateSources[gl::ShaderType::Geometry];
if (!vertexSource->empty())
if (!geometrySource->empty())
{
AssignOutputLocations(programState, fragmentSource);
AssignVaryingLocations(programState, resources, geometrySource, fragmentSource);
if (!vertexSource->empty())
{
AssignAttributeLocations(programState, vertexSource);
AssignVaryingLocations(programState, resources, vertexSource, geometrySource);
}
}
else if (!vertexSource->empty())
{
AssignAttributeLocations(programState, vertexSource);
AssignOutputLocations(programState, fragmentSource);
AssignVaryingLocations(resources, vertexSource, fragmentSource);
AssignVaryingLocations(programState, resources, vertexSource, fragmentSource);
}
else if (!fragmentSource->empty())
{
AssignAttributeLocations(programState, fragmentSource);
AssignOutputLocations(programState, fragmentSource);
AssignVaryingLocations(resources, vertexSource, fragmentSource);
AssignVaryingLocations(programState, resources, vertexSource, fragmentSource);
}
AssignUniformBindings(&intermediateSources);
AssignTextureBindings(useOldRewriteStructSamplers, programState, &intermediateSources);
......@@ -1005,6 +1040,14 @@ angle::Result GlslangWrapper::GetShaderCode(vk::Context *context,
kVersionDefine, kLineRasterDefine),
VK_ERROR_INVALID_SHADER_NV);
if (!shaderSources[gl::ShaderType::Geometry].empty())
{
ANGLE_VK_CHECK(context,
angle::ReplaceSubstring(&patchedSources[gl::ShaderType::Geometry],
kVersionDefine, kLineRasterDefine),
VK_ERROR_INVALID_SHADER_NV);
}
return GetShaderCodeImpl(context, glCaps, patchedSources, shaderCodeOut);
}
else
......
......@@ -1013,6 +1013,7 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics;
enabledFeatures.features.fragmentStoresAndAtomics =
mPhysicalDeviceFeatures.fragmentStoresAndAtomics;
enabledFeatures.features.geometryShader = mPhysicalDeviceFeatures.geometryShader;
if (!vk::CommandBuffer::ExecutesInline())
{
enabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
......
......@@ -182,6 +182,19 @@ void UnpackBlendAttachmentState(const vk::PackedColorBlendAttachmentState &packe
stateOut->alphaBlendOp = static_cast<VkBlendOp>(packedState.alphaBlendOp);
}
void SetPipelineShaderStageInfo(const VkStructureType type,
const VkShaderStageFlagBits stage,
const VkShaderModule module,
VkPipelineShaderStageCreateInfo *shaderStage)
{
shaderStage->sType = type;
shaderStage->flags = 0;
shaderStage->stage = stage;
shaderStage->module = module;
shaderStage->pName = "main";
shaderStage->pSpecializationInfo = nullptr;
}
angle::Result InitializeRenderPassFromDesc(vk::Context *context,
const RenderPassDesc &desc,
const AttachmentOpsArray &ops,
......@@ -601,9 +614,10 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
const gl::ComponentTypeMask &programAttribsTypeMask,
const ShaderModule *vertexModule,
const ShaderModule *fragmentModule,
const ShaderModule *geometryModule,
Pipeline *pipelineOut) const
{
angle::FixedVector<VkPipelineShaderStageCreateInfo, 2> shaderStages;
angle::FixedVector<VkPipelineShaderStageCreateInfo, 3> shaderStages;
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {};
VkPipelineViewportStateCreateInfo viewportState = {};
......@@ -618,25 +632,27 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
// Vertex shader is always expected to be present.
ASSERT(vertexModule != nullptr);
VkPipelineShaderStageCreateInfo vertexStage = {};
vertexStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertexStage.flags = 0;
vertexStage.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertexStage.module = vertexModule->getHandle();
vertexStage.pName = "main";
vertexStage.pSpecializationInfo = nullptr;
SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
VK_SHADER_STAGE_VERTEX_BIT, vertexModule->getHandle(), &vertexStage);
shaderStages.push_back(vertexStage);
if (geometryModule)
{
VkPipelineShaderStageCreateInfo geometryStage = {};
SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
VK_SHADER_STAGE_GEOMETRY_BIT, geometryModule->getHandle(),
&geometryStage);
shaderStages.push_back(geometryStage);
}
// Fragment shader is optional.
// anglebug.com/3509 - Don't compile the fragment shader if rasterizationDiscardEnable = true
if (fragmentModule && !mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable)
{
VkPipelineShaderStageCreateInfo fragmentStage = {};
fragmentStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragmentStage.flags = 0;
fragmentStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragmentStage.module = fragmentModule->getHandle();
fragmentStage.pName = "main";
fragmentStage.pSpecializationInfo = nullptr;
SetPipelineShaderStageInfo(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
VK_SHADER_STAGE_FRAGMENT_BIT, fragmentModule->getHandle(),
&fragmentStage);
shaderStages.push_back(fragmentStage);
}
......@@ -1494,7 +1510,7 @@ void PipelineLayoutDesc::updatePushConstantRange(gl::ShaderType shaderType,
uint32_t size)
{
ASSERT(shaderType == gl::ShaderType::Vertex || shaderType == gl::ShaderType::Fragment ||
shaderType == gl::ShaderType::Compute);
shaderType == gl::ShaderType::Geometry || shaderType == gl::ShaderType::Compute);
PackedPushConstantRange &packed = mPushConstantRanges[shaderType];
packed.offset = offset;
packed.size = size;
......@@ -1705,6 +1721,7 @@ angle::Result GraphicsPipelineCache::insertPipeline(
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule,
const vk::ShaderModule *geometryModule,
const vk::GraphicsPipelineDesc &desc,
const vk::GraphicsPipelineDesc **descPtrOut,
vk::PipelineHelper **pipelineOut)
......@@ -1718,7 +1735,7 @@ angle::Result GraphicsPipelineCache::insertPipeline(
ANGLE_TRY(desc.initializePipeline(contextVk, pipelineCacheVk, compatibleRenderPass,
pipelineLayout, activeAttribLocationsMask,
programAttribsTypeMask, vertexModule, fragmentModule,
&newPipeline));
geometryModule, &newPipeline));
}
// The Serial will be updated outside of this query.
......
......@@ -364,6 +364,7 @@ class GraphicsPipelineDesc final
const gl::ComponentTypeMask &programAttribsTypeMask,
const ShaderModule *vertexModule,
const ShaderModule *fragmentModule,
const ShaderModule *geometryModule,
Pipeline *pipelineOut) const;
// Vertex input state. For ES 3.1 this should be separated into binding and attribute.
......@@ -828,6 +829,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule,
const vk::ShaderModule *geometryModule,
const vk::GraphicsPipelineDesc &desc,
const vk::GraphicsPipelineDesc **descPtrOut,
vk::PipelineHelper **pipelineOut)
......@@ -842,7 +844,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
return insertPipeline(contextVk, pipelineCacheVk, compatibleRenderPass, pipelineLayout,
activeAttribLocationsMask, programAttribsTypeMask, vertexModule,
fragmentModule, desc, descPtrOut, pipelineOut);
fragmentModule, geometryModule, desc, descPtrOut, pipelineOut);
}
private:
......@@ -854,6 +856,7 @@ class GraphicsPipelineCache final : angle::NonCopyable
const gl::ComponentTypeMask &programAttribsTypeMask,
const vk::ShaderModule *vertexModule,
const vk::ShaderModule *fragmentModule,
const vk::ShaderModule *geometryModule,
const vk::GraphicsPipelineDesc &desc,
const vk::GraphicsPipelineDesc **descPtrOut,
vk::PipelineHelper **pipelineOut);
......@@ -919,10 +922,10 @@ constexpr uint32_t kDriverUniformsDescriptorSetIndex = 3;
// Only 1 driver uniform binding is used.
constexpr uint32_t kReservedDriverUniformBindingCount = 1;
// There is 1 default uniform binding used per stage. Currently, a maxium of two stages are
// There is 1 default uniform binding used per stage. Currently, a maxium of three stages are
// supported.
constexpr uint32_t kReservedPerStageDefaultUniformBindingCount = 1;
constexpr uint32_t kReservedDefaultUniformBindingCount = 2;
constexpr uint32_t kReservedDefaultUniformBindingCount = 3;
// Binding index start for transform feedback buffers:
constexpr uint32_t kXfbBindingIndexStart = kReservedDefaultUniformBindingCount;
} // namespace rx
......
......@@ -430,6 +430,25 @@ void RendererVk::ensureCapsInitialized() const
// Enable GL_NV_pixel_buffer_object extension.
mNativeExtensions.pixelBufferObject = true;
// Geometry shader is optional.
if (mPhysicalDeviceFeatures.geometryShader)
{
// TODO : Remove below comment when http://anglebug.com/3571 will be completed
// mNativeExtensions.geometryShader = true;
mNativeCaps.maxFramebufferLayers = limitsVk.maxFramebufferLayers;
mNativeCaps.layerProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
mNativeCaps.maxGeometryInputComponents = limitsVk.maxGeometryInputComponents;
mNativeCaps.maxGeometryOutputComponents = limitsVk.maxGeometryOutputComponents;
mNativeCaps.maxGeometryOutputVertices = limitsVk.maxGeometryOutputVertices;
mNativeCaps.maxGeometryTotalOutputComponents = limitsVk.maxGeometryTotalOutputComponents;
mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Geometry] =
mNativeCaps.maxCombinedShaderOutputResources;
mNativeCaps.maxShaderAtomicCounterBuffers[gl::ShaderType::Geometry] =
maxCombinedAtomicCounterBuffers;
mNativeCaps.maxGeometryShaderInvocations = limitsVk.maxGeometryShaderInvocations;
}
}
namespace egl_vk
......
......@@ -1030,11 +1030,14 @@ class ShaderProgramHelper : angle::NonCopyable
ShaderModule *fragmentShader = mShaders[gl::ShaderType::Fragment].valid()
? &mShaders[gl::ShaderType::Fragment].get().get()
: nullptr;
ShaderModule *geometryShader = mShaders[gl::ShaderType::Geometry].valid()
? &mShaders[gl::ShaderType::Geometry].get().get()
: nullptr;
return mGraphicsPipelines.getPipeline(contextVk, pipelineCache, *compatibleRenderPass,
pipelineLayout, activeAttribLocationsMask,
programAttribsTypeMask, vertexShader, fragmentShader,
pipelineDesc, descPtrOut, pipelineOut);
return mGraphicsPipelines.getPipeline(
contextVk, pipelineCache, *compatibleRenderPass, pipelineLayout,
activeAttribLocationsMask, programAttribsTypeMask, vertexShader, fragmentShader,
geometryShader, pipelineDesc, descPtrOut, pipelineOut);
}
angle::Result getComputePipeline(Context *context,
......
......@@ -666,4 +666,4 @@
3886 VULKAN : dEQP-GLES31.functional.image_load_store.3d.*layer = FAIL
// Inactive SSBOs with flexible array member (about 20% of these tests are affected):
3714 VULKAN : dEQP-GLES31.functional.ssbo.layout.random.* = FAIL
3714 VULKAN : dEQP-GLES31.functional.ssbo.layout.random.* = FAIL
\ No newline at end of file
......@@ -92,8 +92,8 @@ void VulkanPipelineCachePerfTest::step()
{
for (const auto &hit : mCacheHits)
{
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, hit, &desc,
&result);
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, nullptr, hit,
&desc, &result);
}
}
......@@ -101,8 +101,8 @@ void VulkanPipelineCachePerfTest::step()
++missCount, ++mMissIndex)
{
const auto &miss = mCacheMisses[mMissIndex];
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, miss, &desc,
&result);
(void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, nullptr, miss,
&desc, &result);
}
}
......
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