spirv: Guard against typeless image reads on unsupported devices
This commit is contained in:
		| @@ -238,11 +238,13 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | ||||
|             ctx.AddCapability(spv::Capability::SubgroupVoteKHR); | ||||
|         } | ||||
|     } | ||||
|     if (info.uses_typeless_image_reads && profile.support_typeless_image_loads) { | ||||
|         ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat); | ||||
|     } | ||||
|     // TODO: Track this usage | ||||
|     ctx.AddCapability(spv::Capability::ImageGatherExtended); | ||||
|     ctx.AddCapability(spv::Capability::ImageQuery); | ||||
|     ctx.AddCapability(spv::Capability::SampledBuffer); | ||||
|     ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat); | ||||
| } | ||||
| } // Anonymous namespace | ||||
|  | ||||
|   | ||||
| @@ -388,6 +388,10 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I | ||||
|  | ||||
| Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { | ||||
|     const auto info{inst->Flags<IR::TextureInstInfo>()}; | ||||
|     if (info.image_format == ImageFormat::Typeless && !ctx.profile.support_typeless_image_loads) { | ||||
|         // LOG_WARNING(..., "Typeless image read not supported by host"); | ||||
|         return ctx.ConstantNull(ctx.U32[4]); | ||||
|     } | ||||
|     return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4], | ||||
|                 Image(ctx, index, info), coords, std::nullopt, std::span<const Id>{}); | ||||
| } | ||||
|   | ||||
| @@ -421,6 +421,13 @@ void VisitUsages(Info& info, IR::Inst& inst) { | ||||
|             inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr; | ||||
|         break; | ||||
|     } | ||||
|     case IR::Opcode::ImageRead: { | ||||
|         const auto flags{inst.Flags<IR::TextureInstInfo>()}; | ||||
|         info.uses_typeless_image_reads |= flags.image_format == ImageFormat::Typeless; | ||||
|         info.uses_sparse_residency |= | ||||
|             inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr; | ||||
|         break; | ||||
|     } | ||||
|     case IR::Opcode::SubgroupEqMask: | ||||
|     case IR::Opcode::SubgroupLtMask: | ||||
|     case IR::Opcode::SubgroupLeMask: | ||||
|   | ||||
| @@ -36,6 +36,7 @@ struct Profile { | ||||
|     bool support_explicit_workgroup_layout{}; | ||||
|     bool support_vote{}; | ||||
|     bool support_viewport_index_layer_non_geometry{}; | ||||
|     bool support_typeless_image_loads{}; | ||||
|     bool warp_size_potentially_larger_than_guest{}; | ||||
|  | ||||
|     // FClamp is broken and OpFMax + OpFMin should be used instead | ||||
|   | ||||
| @@ -127,6 +127,7 @@ struct Info { | ||||
|     bool uses_subgroup_vote{}; | ||||
|     bool uses_subgroup_mask{}; | ||||
|     bool uses_fswzadd{}; | ||||
|     bool uses_typeless_image_reads{}; | ||||
|  | ||||
|     IR::Type used_constant_buffer_types{}; | ||||
|  | ||||
|   | ||||
| @@ -635,6 +635,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_, | ||||
|         .support_vote = true, | ||||
|         .support_viewport_index_layer_non_geometry = | ||||
|             device.IsExtShaderViewportIndexLayerSupported(), | ||||
|         .support_typeless_image_loads = device.IsFormatlessImageLoadSupported(), | ||||
|         .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), | ||||
|         .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR, | ||||
|         .generic_input_types{}, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user