Commit fcb6b5a5 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix precision transformation for geometry shaders

When a varying precision mismatch is present between two stages, the SPIR-V transformer transforms the following: in precision1 type1 inVar; out precision2 type2 outVar; void main() { f(inVar); outVar = g(); } to: in precision3 type1 inVarModified; out precision4 type2 outVarModified; precision1 type1 inVarTurnedPrivate; precision2 type2 outVarTurnedPrivate; void main() { // Input preamble inVarTurnedPrivate = inVarModified; f(inVarTurnedPrivate); outVarTurnedPrivate = g(); // Output preamble outVarModified = outVarTurnedPrivate; } This doesn't work for geometry shaders as they take the varying outputs on EmitVertex() as opposed to return from main. This change simply places the output preamble before every EmitVertex() instead of at the end of the shader, if it's a geometry shader. Bug: angleproject:5403 Change-Id: Ie395a3270c6903c54b49f64a26bc5297044cbaeb Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2561939 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ab9aae05
...@@ -1376,6 +1376,7 @@ class SpirvTransformer final : public SpirvTransformerBase ...@@ -1376,6 +1376,7 @@ class SpirvTransformer final : public SpirvTransformerBase
// transformed. If false is returned, the instruction should be copied as-is. // transformed. If false is returned, the instruction should be copied as-is.
bool transformAccessChain(const uint32_t *instruction, size_t wordCount); bool transformAccessChain(const uint32_t *instruction, size_t wordCount);
bool transformCapability(const uint32_t *instruction, size_t wordCount); bool transformCapability(const uint32_t *instruction, size_t wordCount);
bool transformEmitVertex(const uint32_t *instruction, size_t wordCount);
bool transformEntryPoint(const uint32_t *instruction, size_t wordCount); bool transformEntryPoint(const uint32_t *instruction, size_t wordCount);
bool transformDecorate(const uint32_t *instruction, size_t wordCount); bool transformDecorate(const uint32_t *instruction, size_t wordCount);
bool transformTypePointer(const uint32_t *instruction, size_t wordCount); bool transformTypePointer(const uint32_t *instruction, size_t wordCount);
...@@ -1385,6 +1386,7 @@ class SpirvTransformer final : public SpirvTransformerBase ...@@ -1385,6 +1386,7 @@ class SpirvTransformer final : public SpirvTransformerBase
// Helpers: // Helpers:
void writeInputPreamble(); void writeInputPreamble();
void writeOutputPrologue();
// Special flags: // Special flags:
bool mHasTransformFeedbackOutput; bool mHasTransformFeedbackOutput;
...@@ -1540,6 +1542,9 @@ void SpirvTransformer::transformInstruction() ...@@ -1540,6 +1542,9 @@ void SpirvTransformer::transformInstruction()
transformed = transformAccessChain(instruction, wordCount); transformed = transformAccessChain(instruction, wordCount);
break; break;
case spv::OpEmitVertex:
transformed = transformEmitVertex(instruction, wordCount);
break;
case spv::OpReturn: case spv::OpReturn:
transformed = transformReturn(instruction, wordCount); transformed = transformReturn(instruction, wordCount);
break; break;
...@@ -1627,6 +1632,29 @@ void SpirvTransformer::writeInputPreamble() ...@@ -1627,6 +1632,29 @@ void SpirvTransformer::writeInputPreamble()
} }
} }
// Called by transformInstruction to insert necessary instructions for casting varying
void SpirvTransformer::writeOutputPrologue()
{
for (uint32_t id = 0; id < mVariableInfoById.size(); id++)
{
const ShaderInterfaceVariableInfo *info = mVariableInfoById[id];
if (info && info->useRelaxedPrecision && info->activeStages[mShaderType] &&
info->varyingIsOutput)
{
ASSERT(mFixedVaryingTypeId[id] != 0);
// Build OpLoad instruction to load the highp value into a temporary
uint32_t tempVar = getNewId();
uint32_t tempVarType = mTypePointerTransformedId[mFixedVaryingTypeId[id]].typeID;
ASSERT(tempVarType != 0);
writeLoad(id, tempVarType, tempVar);
// Build OpStore instruction to cast the highp value to mediump for output
writeStore(mFixedVaryingId[id], tempVar);
}
}
}
void SpirvTransformer::visitName(const uint32_t *instruction) void SpirvTransformer::visitName(const uint32_t *instruction)
{ {
// We currently don't have any big-endian devices in the list of supported platforms. Literal // We currently don't have any big-endian devices in the list of supported platforms. Literal
...@@ -1939,6 +1967,17 @@ bool SpirvTransformer::transformCapability(const uint32_t *instruction, size_t w ...@@ -1939,6 +1967,17 @@ bool SpirvTransformer::transformCapability(const uint32_t *instruction, size_t w
return true; return true;
} }
bool SpirvTransformer::transformEmitVertex(const uint32_t *instruction, size_t wordCount)
{
// This is only possible in geometry shaders.
ASSERT(mShaderType == gl::ShaderType::Geometry);
// Write the temporary variables that hold varyings data before EmitVertex().
writeOutputPrologue();
return false;
}
bool SpirvTransformer::transformEntryPoint(const uint32_t *instruction, size_t wordCount) bool SpirvTransformer::transformEntryPoint(const uint32_t *instruction, size_t wordCount)
{ {
// Remove inactive varyings from the shader interface declaration. // Remove inactive varyings from the shader interface declaration.
...@@ -2075,25 +2114,16 @@ bool SpirvTransformer::transformReturn(const uint32_t *instruction, size_t wordC ...@@ -2075,25 +2114,16 @@ bool SpirvTransformer::transformReturn(const uint32_t *instruction, size_t wordC
return false; return false;
} }
for (uint32_t id = 0; id < mVariableInfoById.size(); id++) // For geometry shaders, this operations is done before every EmitVertex() instead.
// Additionally, this transformation (which affects output varyings) doesn't apply to fragment
// shaders.
if (mShaderType == gl::ShaderType::Geometry || mShaderType == gl::ShaderType::Fragment)
{ {
const ShaderInterfaceVariableInfo *info = mVariableInfoById[id]; return false;
if (info && info->useRelaxedPrecision && info->activeStages[mShaderType] && }
info->varyingIsOutput)
{
ASSERT(mFixedVaryingTypeId[id] != 0);
// Build OpLoad instruction to load the highp value into a temporary
uint32_t tempVar = getNewId();
uint32_t tempVarType = mTypePointerTransformedId[mFixedVaryingTypeId[id]].typeID;
ASSERT(tempVarType != 0);
writeLoad(id, tempVarType, tempVar); writeOutputPrologue();
// Build OpStore instruction to cast the highp value to mediump for output
writeStore(mFixedVaryingId[id], tempVar);
}
}
return false; return false;
} }
......
...@@ -187,11 +187,10 @@ ...@@ -187,11 +187,10 @@
3886 VULKAN : dEQP-GLES31.functional.image_load_store.3d.*layer = FAIL 3886 VULKAN : dEQP-GLES31.functional.image_load_store.3d.*layer = FAIL
// Geometry shader support: // Geometry shader support:
5403 VULKAN : dEQP-GLES31.functional.shaders.linkage.es31.geometry.varying.rules.output_different_precision = FAIL
5403 VULKAN : dEQP-GLES31.functional.geometry_shading.* = FAIL
3580 VULKAN : dEQP-GLES31.functional.shaders.linkage.es31.geometry.varying.types.float_struct = SKIP 3580 VULKAN : dEQP-GLES31.functional.shaders.linkage.es31.geometry.varying.types.float_struct = SKIP
5404 VULKAN : dEQP-GLES31.functional.geometry_shading.query.primitives_generated* = SKIP 5404 VULKAN : dEQP-GLES31.functional.geometry_shading.query.primitives_generated* = SKIP
5405 VULKAN : dEQP-GLES31.functional.geometry_shading.basic.*128 = FAIL 5405 VULKAN : dEQP-GLES31.functional.geometry_shading.basic.output_* = FAIL
5405 VULKAN : dEQP-GLES31.functional.geometry_shading.instanced.invocation_output_vary_by_* = FAIL
5406 VULKAN : dEQP-GLES31.functional.geometry_shading.input.*adjacency* = SKIP 5406 VULKAN : dEQP-GLES31.functional.geometry_shading.input.*adjacency* = SKIP
5407 VULKAN : dEQP-GLES31.functional.geometry_shading.layered.* = SKIP 5407 VULKAN : dEQP-GLES31.functional.geometry_shading.layered.* = SKIP
5407 VULKAN : dEQP-GLES31.functional.geometry_shading.instanced.invocation_per_layer* = SKIP 5407 VULKAN : dEQP-GLES31.functional.geometry_shading.instanced.invocation_per_layer* = SKIP
...@@ -209,6 +208,7 @@ ...@@ -209,6 +208,7 @@
5409 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.random.48 = FAIL 5409 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.random.48 = FAIL
5409 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.random.51 = FAIL 5409 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.random.51 = FAIL
5409 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.random.55 = FAIL 5409 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.random.55 = FAIL
5411 VULKAN : dEQP-GLES31.functional.geometry_shading.emit.*_emit_0_end_* = 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