From 29a7427f1e38b53f89f6c9ac9453d9262cea2011 Mon Sep 17 00:00:00 2001 From: Matthew Netsch Date: Fri, 4 Oct 2019 11:46:04 -0400 Subject: [PATCH] Account for VS executing more than once when atomics are used. Components: Vulkan Affects: dEQP-VK.glsl.opaque_type_indexing.atomic_counter.* dEQP-VK.glsl.atomic_operations.* Change-Id: I15eabf9b47af204fd13370efdc323af141b6b11b --- .../shaderexecutor/vktAtomicOperationTests.cpp | 15 ++++- .../shaderexecutor/vktOpaqueTypeIndexingTests.cpp | 68 +++++++++++++--------- 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/external/vulkancts/modules/vulkan/shaderexecutor/vktAtomicOperationTests.cpp b/external/vulkancts/modules/vulkan/shaderexecutor/vktAtomicOperationTests.cpp index 8e46111..24c8940 100644 --- a/external/vulkancts/modules/vulkan/shaderexecutor/vktAtomicOperationTests.cpp +++ b/external/vulkancts/modules/vulkan/shaderexecutor/vktAtomicOperationTests.cpp @@ -216,6 +216,7 @@ public: T input[NUM_ELEMENTS]; T compare[NUM_ELEMENTS]; T output[NUM_ELEMENTS]; + T invocationHitCount[NUM_ELEMENTS]; deInt32 index; }; @@ -247,6 +248,7 @@ public: { m_ptr->input[i] = static_cast(rnd.getUint64()); m_ptr->output[i] = pattern; + m_ptr->invocationHitCount[i] = 0; } m_ptr->index = 0; @@ -675,6 +677,7 @@ void AtomicOperationCase::createShaderSpec (void) " ${DATATYPE} inputValues[${N}];\n" " ${DATATYPE} compareValues[${N}];\n" " ${DATATYPE} outputValues[${N}];\n" + " ${DATATYPE} invocationHitCount[${N}];\n" " int index;\n" "} buf;\n"); @@ -694,14 +697,22 @@ void AtomicOperationCase::createShaderSpec (void) specializations["N"] = de::toString((int)NUM_ELEMENTS); specializations["COMPARE_ARG"] = m_atomicOp == ATOMIC_OP_COMP_SWAP ? "buf.compareValues[idx], " : ""; - const tcu::StringTemplate shaderTemplateSrc( + const tcu::StringTemplate nonVertexShaderTemplateSrc( "int idx = atomicAdd(buf.index, 1);\n" "buf.outputValues[idx] = ${ATOMICOP}(buf.inoutValues[idx % (${N}/2)], ${COMPARE_ARG}buf.inputValues[idx]);\n"); + const tcu::StringTemplate vertexShaderTemplateSrc( + "int idx = gl_VertexIndex;\n" + "if (atomicAdd(buf.invocationHitCount[idx], 1) == 0)\n" + "{\n" + " buf.outputValues[idx] = ${ATOMICOP}(buf.inoutValues[idx % (${N}/2)], ${COMPARE_ARG}buf.inputValues[idx]);\n" + "}\n"); + m_shaderSpec.outputs.push_back(Symbol("outData", glu::VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP))); m_shaderSpec.globalDeclarations = shaderTemplateGlobal.specialize(specializations); - m_shaderSpec.source = shaderTemplateSrc.specialize(specializations); m_shaderSpec.glslVersion = glu::GLSL_VERSION_450; + m_shaderSpec.source = m_shaderType == glu::SHADERTYPE_VERTEX ? + vertexShaderTemplateSrc.specialize(specializations) : nonVertexShaderTemplateSrc.specialize(specializations); } void addAtomicOperationTests (tcu::TestCaseGroup* atomicOperationTestsGroup) diff --git a/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp b/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp index d1f54ff..dfe8fe9 100644 --- a/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp +++ b/external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp @@ -1694,11 +1694,12 @@ tcu::TestStatus AtomicCounterIndexingCaseInstance::iterate (void) } { - tcu::TestLog& log = m_context.getTestContext().getLog(); - tcu::TestStatus testResult = tcu::TestStatus::pass("Pass"); - std::vector numHits (numCounters, 0); // Number of hits per counter. - std::vector counterValues (numCounters); - std::vector > counterMasks (numCounters); + tcu::TestLog& log = m_context.getTestContext().getLog(); + tcu::TestStatus testResult = tcu::TestStatus::pass("Pass"); + std::vector numHits (numCounters, 0); // Number of hits per counter. + std::vector counterValues (numCounters); + std::vector > resultValueHitCountMaps (numCounters); + for (int opNdx = 0; opNdx < numOps; opNdx++) numHits[m_opIndices[opNdx]] += 1; @@ -1717,24 +1718,32 @@ tcu::TestStatus AtomicCounterIndexingCaseInstance::iterate (void) const deUint32 refCount = (deUint32)(numHits[counterNdx]*numInvocations); const deUint32 resCount = counterValues[counterNdx]; - if (refCount != resCount) + bool foundInvalidCtrValue = false; + + if(resCount < refCount) + { + log << tcu::TestLog::Message << "ERROR: atomic counter " << counterNdx << " has value " << resCount + << ", expected value greater than or equal to " << refCount + << tcu::TestLog::EndMessage; + + foundInvalidCtrValue = true; + } + else if (refCount == 0 && resCount != 0) { log << tcu::TestLog::Message << "ERROR: atomic counter " << counterNdx << " has value " << resCount << ", expected " << refCount << tcu::TestLog::EndMessage; + foundInvalidCtrValue = true; + } + + if (foundInvalidCtrValue == true) + { if (testResult.getCode() == QP_TEST_RESULT_PASS) testResult = tcu::TestStatus::fail("Invalid atomic counter value"); } } - // Allocate bitmasks - one bit per each valid result value - for (int counterNdx = 0; counterNdx < numCounters; counterNdx++) - { - const int counterValue = numHits[counterNdx]*numInvocations; - counterMasks[counterNdx].resize(counterValue, false); - } - // Verify result values from shaders for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++) { @@ -1742,11 +1751,14 @@ tcu::TestStatus AtomicCounterIndexingCaseInstance::iterate (void) { const int counterNdx = m_opIndices[opNdx]; const deUint32 resValue = outValues[opNdx*numInvocations + invocationNdx]; - const bool rangeOk = de::inBounds(resValue, 0u, (deUint32)counterMasks[counterNdx].size()); - const bool notSeen = rangeOk && !counterMasks[counterNdx][resValue]; - const bool isOk = rangeOk && notSeen; + const bool rangeOk = de::inBounds(resValue, 0u, counterValues[counterNdx]); + + if (resultValueHitCountMaps[counterNdx].count(resValue) == 0) + resultValueHitCountMaps[counterNdx][resValue] = 1; + else + resultValueHitCountMaps[counterNdx][resValue] += 1; - if (!isOk) + if (!rangeOk) { log << tcu::TestLog::Message << "ERROR: at invocation " << invocationNdx << ", op " << opNdx << ": got invalid result value " @@ -1756,21 +1768,23 @@ tcu::TestStatus AtomicCounterIndexingCaseInstance::iterate (void) if (testResult.getCode() == QP_TEST_RESULT_PASS) testResult = tcu::TestStatus::fail("Invalid result value"); } - else - { - // Mark as used - no other invocation should see this value from same counter. - counterMasks[counterNdx][resValue] = true; - } } } - if (testResult.getCode() == QP_TEST_RESULT_PASS) + for (int ctrIdx = 0; ctrIdx < numCounters; ctrIdx++) { - // Consistency check - all masks should be 1 now - for (int counterNdx = 0; counterNdx < numCounters; counterNdx++) + std::map::iterator hitCountItr; + for (hitCountItr = resultValueHitCountMaps[ctrIdx].begin(); hitCountItr != resultValueHitCountMaps[ctrIdx].end(); hitCountItr++) { - for (std::vector::const_iterator i = counterMasks[counterNdx].begin(); i != counterMasks[counterNdx].end(); i++) - TCU_CHECK_INTERNAL(*i); + if(hitCountItr->second > 1) + { + log << tcu::TestLog::Message << "ERROR: Duplicate result value from counter " << ctrIdx << "." + <<" Value " << hitCountItr->first << " found " << hitCountItr->second << " times." + << tcu::TestLog::EndMessage; + + if (testResult.getCode() == QP_TEST_RESULT_PASS) + testResult = tcu::TestStatus::fail("Invalid result value"); + } } } -- 2.7.4