Android-x86
Fork
Donation

  • R/O
  • HTTP
  • SSH
  • HTTPS

external-swiftshader: Commit

external/swiftshader


Commit MetaInfo

Revision20220a0b0640436b659d0361a9d0789bc81d4177 (tree)
Time2020-04-14 18:43:47
AuthorNicolas Capens <capn@goog...>
CommiterNicolas Capens

Log Message

Reuse Store logic for Modf and Frexp output parameters

The Modf and Frexp instructions from the GLSL.std.450 extended SPIR-V
instruction set take a pointer argument to write one of their results
to. This makes them the only arithmetic instructions which need to know
how to explicitly access memory.

This change replaces the partial duplication of store logic with a call
to the underlying implementation of OpStore. To support storing
intermediate values not associated with SPIR-V objects, the Operand
class can now also wrap an independent Intermediate instance.

Bug: b/153641251
Change-Id: Iebab43640b45ed6c27a77576168481d1a27158b6
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43728
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>

Change Summary

Incremental Difference

--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -2431,6 +2431,13 @@ SpirvShader::Operand::Operand(const EmitState *state, const Object &object)
24312431 ASSERT(intermediate || (object.kind == SpirvShader::Object::Kind::Constant));
24322432 }
24332433
2434+SpirvShader::Operand::Operand(const Intermediate &value)
2435+ : constant(nullptr)
2436+ , intermediate(&value)
2437+ , componentCount(value.componentCount)
2438+{
2439+}
2440+
24342441 SpirvRoutine::SpirvRoutine(vk::PipelineLayout const *pipelineLayout)
24352442 : pipelineLayout(pipelineLayout)
24362443 {
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -992,6 +992,7 @@ private:
992992 {
993993 public:
994994 Operand(const SpirvShader *shader, const EmitState *state, SpirvShader::Object::ID objectId);
995+ Operand(const Intermediate &value);
995996
996997 RValue<SIMD::Float> Float(uint32_t i) const
997998 {
--- a/src/Pipeline/SpirvShaderGLSLstd450.cpp
+++ b/src/Pipeline/SpirvShaderGLSLstd450.cpp
@@ -354,24 +354,17 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
354354 {
355355 auto val = Operand(this, state, insn.word(5));
356356 auto ptrId = Object::ID(insn.word(6));
357- auto ptrTy = getType(getObject(ptrId));
358- auto ptr = GetPointerToData(ptrId, 0, state);
359- bool interleavedByLane = IsStorageInterleavedByLane(ptrTy.storageClass);
360- // TODO: GLSL modf() takes an output parameter and thus the pointer is assumed
361- // to be in bounds even for inactive lanes.
362- // - Clarify the SPIR-V spec.
363- // - Eliminate lane masking and assume interleaving.
364- auto robustness = OutOfBoundsBehavior::UndefinedBehavior;
357+
358+ Intermediate whole(type.componentCount);
365359
366360 for(auto i = 0u; i < type.componentCount; i++)
367361 {
368- SIMD::Float whole, frac;
369- std::tie(whole, frac) = Modf(val.Float(i));
370- dst.move(i, frac);
371- auto p = ptr + (i * sizeof(float));
372- if(interleavedByLane) { p = InterleaveByLane(p); }
373- p.Store(whole, robustness, state->activeLaneMask());
362+ auto wholeAndFrac = Modf(val.Float(i));
363+ dst.move(i, wholeAndFrac.second);
364+ whole.move(i, wholeAndFrac.first);
374365 }
366+
367+ Store(ptrId, whole, false, std::memory_order_relaxed, state);
375368 break;
376369 }
377370 case GLSLstd450ModfStruct:
@@ -380,10 +373,9 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
380373
381374 for(auto i = 0u; i < val.componentCount; i++)
382375 {
383- SIMD::Float whole, frac;
384- std::tie(whole, frac) = Modf(val.Float(i));
385- dst.move(i, frac);
386- dst.move(i + val.componentCount, whole);
376+ auto wholeAndFrac = Modf(val.Float(i));
377+ dst.move(i, wholeAndFrac.second);
378+ dst.move(val.componentCount + i, wholeAndFrac.first);
387379 }
388380 break;
389381 }
@@ -499,27 +491,17 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
499491 {
500492 auto val = Operand(this, state, insn.word(5));
501493 auto ptrId = Object::ID(insn.word(6));
502- auto ptrTy = getType(getObject(ptrId));
503- auto ptr = GetPointerToData(ptrId, 0, state);
504- bool interleavedByLane = IsStorageInterleavedByLane(ptrTy.storageClass);
505- // TODO: GLSL frexp() takes an output parameter and thus the pointer is assumed
506- // to be in bounds even for inactive lanes.
507- // - Clarify the SPIR-V spec.
508- // - Eliminate lane masking and assume interleaving.
509- auto robustness = OutOfBoundsBehavior::UndefinedBehavior;
494+
495+ Intermediate exp(type.componentCount);
510496
511497 for(auto i = 0u; i < type.componentCount; i++)
512498 {
513- SIMD::Float significand;
514- SIMD::Int exponent;
515- std::tie(significand, exponent) = Frexp(val.Float(i));
516-
517- dst.move(i, significand);
518-
519- auto p = ptr + (i * sizeof(float));
520- if(interleavedByLane) { p = InterleaveByLane(p); }
521- p.Store(exponent, robustness, state->activeLaneMask());
499+ auto significandAndExponent = Frexp(val.Float(i));
500+ dst.move(i, significandAndExponent.first);
501+ exp.move(i, significandAndExponent.second);
522502 }
503+
504+ Store(ptrId, exp, false, std::memory_order_relaxed, state);
523505 break;
524506 }
525507 case GLSLstd450FrexpStruct:
Show on old repository browser