Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension allows multiple same OpTypePointer types #783

Closed
wants to merge 4 commits into from

Conversation

atgoo
Copy link

@atgoo atgoo commented Aug 29, 2017

SPV_KHR_variable_pointers allows OpTypePointer to declare multiple
identical types

#781

SPV_KHR_variable_pointers allows OpTypePointer to declare multiple
identical types if they have different declarations.

KhronosGroup#781
Copy link
Collaborator

@dneto0 dneto0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick turnaround.
I think it's not quite right in its internals, and I think some of the tests are incorrect.

@@ -238,4 +238,57 @@ OpMemoryModel Physical32 OpenCL
Not(HasSubstr(GetErrorString(SpvOpTypeVoid))));
}

TEST_F(ValidateTypeUnique, PointerTypesSameArrayStrideNoExtension) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test name is misleading to me: The array strides here are different, but the test name is ....SameArrayStride...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CopyPaste

const auto result = decoration_params.emplace(decoration.dec_type(),
&decoration.params());
(void)result;
assert(result.second);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you should assert here? There's nothing wrong with redundant decorations, except that it wastes space.
I don't think the storage behind id_decorations has unique'd it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth saying you're assuming that a single decoration enum can only be set once per target ID.
It think that's true currently, and is likely to be true always. But I don't recall a SPIR-V validation rule about that. (Perhaps an oversight.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will assume that decorations are not unique, but only use the last one.

@@ -425,6 +426,22 @@ bool ValidationState_t::RegisterUniqueTypeDeclaration(
key.insert(key.end(), inst.words + words_begin, inst.words + words_end);
}

if (inst.opcode == SpvOpTypePointer &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to have a comment describing the rule you're enforcing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

CompileSuccessfully(str.c_str());
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr(GetErrorString(SpvOpTypePointer)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused. The validation succeeds, but generates an error string?

Does this test even pass?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It logs a warning but returns SPV_SUCCESS.

@@ -49,7 +49,7 @@ spv_result_t TypeUniquePass(ValidationState_t& _,
// return _.diag(SPV_ERROR_INVALID_DATA)
return _.diag(SPV_SUCCESS)
<< "Duplicate non-aggregate type declarations are not allowed."
<< " Opcode: " << inst->opcode;
<< " Opcode: " << spvOpcodeString(SpvOp(inst->opcode));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an improvement. But in actual practice I've found having the ID generated by this instruction is easier to work with. It pinpoints the exact instruction at fault.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

OpCapability Shader
OpCapability Linkage
OpMemoryModel Logical GLSL450
OpDecorate %ptr1 ArrayStride 4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe you just have a typo here?

Copy link
Author

@atgoo atgoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready for review.

const auto result = decoration_params.emplace(decoration.dec_type(),
&decoration.params());
(void)result;
assert(result.second);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will assume that decorations are not unique, but only use the last one.

@@ -425,6 +426,22 @@ bool ValidationState_t::RegisterUniqueTypeDeclaration(
key.insert(key.end(), inst.words + words_begin, inst.words + words_end);
}

if (inst.opcode == SpvOpTypePointer &&
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -49,7 +49,7 @@ spv_result_t TypeUniquePass(ValidationState_t& _,
// return _.diag(SPV_ERROR_INVALID_DATA)
return _.diag(SPV_SUCCESS)
<< "Duplicate non-aggregate type declarations are not allowed."
<< " Opcode: " << inst->opcode;
<< " Opcode: " << spvOpcodeString(SpvOp(inst->opcode));
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -238,4 +238,57 @@ OpMemoryModel Physical32 OpenCL
Not(HasSubstr(GetErrorString(SpvOpTypeVoid))));
}

TEST_F(ValidateTypeUnique, PointerTypesSameArrayStrideNoExtension) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CopyPaste

CompileSuccessfully(str.c_str());
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr(GetErrorString(SpvOpTypePointer)));
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It logs a warning but returns SPV_SUCCESS.

Copy link
Collaborator

@dneto0 dneto0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule should be more relaxed than what you implemented.

for (const auto& kv : decoration_params) {
// Append decoration data to the key, sorted by decoration type.
// Use magic number to separate unrelated chunks of data.
const uint32_t kMagicSeparator = 0xffff9296;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low level comment: This magic number mechanism is fragile. Better to push a kv.second.size() then its contents.

(But really we should not care about duplication of decorations.)

@@ -425,6 +426,25 @@ bool ValidationState_t::RegisterUniqueTypeDeclaration(
key.insert(key.end(), inst.words + words_begin, inst.words + words_end);
}

// If module has extension SPV_KHR_variable_pointers, then OpTypePointer
// is allowed to create identical types so long as their decorations differ.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking again, this is not the rule.
The SPV_KHR_variable_pointers extension says

Pointer types are also allowed to have multiple id's for the same opcode and operands, to allow for differing ArrayStride Array Stride decoration values.

Also, in that paragraph, "non-aggregate types" will then generally be "non-aggregate non-pointer types."

From 2.8 in the SPIR-V spec:

It is valid to declare multiple aggregate type s having the same opcode and operands. This is to allow multiple instances of aggregate types with the same structure to be decorated differently. (Different decorations are not required; two different aggregate type ids are allowed to have identical declarations and decorations, and will still be two different types.)

That means the validator should allow distinct OpTypePointer with the same operands, and with the same decorations.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think all this new code boils down to:

if (inst.opcode == SpvOpTypePointer && HasExtension....) return true;

Even better: put the check up in the callee, along with the aggregate types. That is, modify TypeUniquePass to do the pointer-and-has-extension check.

@atgoo
Copy link
Author

atgoo commented Aug 31, 2017

Ready for review.

Copy link
Collaborator

@dneto0 dneto0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from being correct, this is even cleaner.
LGTM, and thanks.

@dneto0
Copy link
Collaborator

dneto0 commented Sep 1, 2017

Hmm. Except that the commit message was inaccurate. I'll fix it on the rebase.

@dneto0
Copy link
Collaborator

dneto0 commented Sep 1, 2017

Rebased, squashed, and pushed into master as 725284c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants