vk_shader_decompiler: Implement Layer output attribute
SPIR-V's Layer is GLSL's gl_Layer. It lets the application choose from a shader stage (vertex, tessellation or geometry) which framebuffer layer write the output fragments to.
This commit is contained in:
		| @@ -86,6 +86,7 @@ struct AttributeType { | |||||||
|  |  | ||||||
| struct VertexIndices { | struct VertexIndices { | ||||||
|     std::optional<u32> position; |     std::optional<u32> position; | ||||||
|  |     std::optional<u32> layer; | ||||||
|     std::optional<u32> viewport; |     std::optional<u32> viewport; | ||||||
|     std::optional<u32> point_size; |     std::optional<u32> point_size; | ||||||
|     std::optional<u32> clip_distances; |     std::optional<u32> clip_distances; | ||||||
| @@ -282,9 +283,11 @@ public: | |||||||
|         AddExtension("SPV_KHR_storage_buffer_storage_class"); |         AddExtension("SPV_KHR_storage_buffer_storage_class"); | ||||||
|         AddExtension("SPV_KHR_variable_pointers"); |         AddExtension("SPV_KHR_variable_pointers"); | ||||||
|  |  | ||||||
|         if (ir.UsesViewportIndex()) { |         if (ir.UsesLayer() || ir.UsesViewportIndex()) { | ||||||
|             AddCapability(spv::Capability::MultiViewport); |             if (ir.UsesViewportIndex()) { | ||||||
|             if (device.IsExtShaderViewportIndexLayerSupported()) { |                 AddCapability(spv::Capability::MultiViewport); | ||||||
|  |             } | ||||||
|  |             if (stage != ShaderType::Geometry && device.IsExtShaderViewportIndexLayerSupported()) { | ||||||
|                 AddExtension("SPV_EXT_shader_viewport_index_layer"); |                 AddExtension("SPV_EXT_shader_viewport_index_layer"); | ||||||
|                 AddCapability(spv::Capability::ShaderViewportIndexLayerEXT); |                 AddCapability(spv::Capability::ShaderViewportIndexLayerEXT); | ||||||
|             } |             } | ||||||
| @@ -920,13 +923,22 @@ private: | |||||||
|         VertexIndices indices; |         VertexIndices indices; | ||||||
|         indices.position = AddBuiltIn(t_float4, spv::BuiltIn::Position, "position"); |         indices.position = AddBuiltIn(t_float4, spv::BuiltIn::Position, "position"); | ||||||
|  |  | ||||||
|  |         if (ir.UsesLayer()) { | ||||||
|  |             if (stage != ShaderType::Vertex || device.IsExtShaderViewportIndexLayerSupported()) { | ||||||
|  |                 indices.layer = AddBuiltIn(t_int, spv::BuiltIn::Layer, "layer"); | ||||||
|  |             } else { | ||||||
|  |                 LOG_ERROR( | ||||||
|  |                     Render_Vulkan, | ||||||
|  |                     "Shader requires Layer but it's not supported on this stage with this device."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (ir.UsesViewportIndex()) { |         if (ir.UsesViewportIndex()) { | ||||||
|             if (stage != ShaderType::Vertex || device.IsExtShaderViewportIndexLayerSupported()) { |             if (stage != ShaderType::Vertex || device.IsExtShaderViewportIndexLayerSupported()) { | ||||||
|                 indices.viewport = AddBuiltIn(t_int, spv::BuiltIn::ViewportIndex, "viewport_index"); |                 indices.viewport = AddBuiltIn(t_int, spv::BuiltIn::ViewportIndex, "viewport_index"); | ||||||
|             } else { |             } else { | ||||||
|                 LOG_ERROR(Render_Vulkan, |                 LOG_ERROR(Render_Vulkan, "Shader requires ViewportIndex but it's not supported on " | ||||||
|                           "Shader requires ViewportIndex but it's not supported on this " |                                          "this stage with this device."); | ||||||
|                           "stage with this device."); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1285,6 +1297,13 @@ private: | |||||||
|                 } |                 } | ||||||
|                 case Attribute::Index::LayerViewportPointSize: |                 case Attribute::Index::LayerViewportPointSize: | ||||||
|                     switch (element) { |                     switch (element) { | ||||||
|  |                     case 1: { | ||||||
|  |                         if (!out_indices.layer) { | ||||||
|  |                             return {}; | ||||||
|  |                         } | ||||||
|  |                         const u32 index = out_indices.layer.value(); | ||||||
|  |                         return {AccessElement(t_out_int, out_vertex, index), Type::Int}; | ||||||
|  |                     } | ||||||
|                     case 2: { |                     case 2: { | ||||||
|                         if (!out_indices.viewport) { |                         if (!out_indices.viewport) { | ||||||
|                             return {}; |                             return {}; | ||||||
| @@ -1355,6 +1374,11 @@ private: | |||||||
|             UNIMPLEMENTED(); |             UNIMPLEMENTED(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (!target.id) { | ||||||
|  |             // On failure we return a nullptr target.id, skip these stores. | ||||||
|  |             return {}; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         OpStore(target.id, As(Visit(src), target.type)); |         OpStore(target.id, As(Visit(src), target.type)); | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user