Support space-only resource register annotations (#2163)

This change adds support for : register(spaceN), where a space is specified but no register, such that the resource allocator runs on the given space.

For backwards compatibility, -auto-binding-space applies to resources without register bindings but not to those with an explicit register assignment like : register(t0) - those always go in space 0. To support this, I had to add state to represent "unspecified space". In the UnusualAnnotation, it's a Optional<uint32_t>. In the DxilResource, it's UINT_MAX, like we do for unspecified registers.
This commit is contained in:
Tristan Labelle 2019-05-09 12:15:05 -07:00 коммит произвёл GitHub
Родитель f89e3b7150
Коммит 17624a864b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
24 изменённых файлов: 242 добавлений и 213 удалений

Просмотреть файл

@ -168,22 +168,21 @@ private:
}
// Allocate unallocated resources
const unsigned space = AutoBindingSpace;
typename SpacesAllocator<unsigned, T>::Allocator &alloc0 = SAlloc.Get(space);
typename SpacesAllocator<unsigned, T>::Allocator &reservedAlloc0 = ReservedRegisters.Get(space);
for (auto &res : resourceList) {
if (res->IsAllocated())
continue;
DXASSERT(res->GetSpaceID() == 0,
"otherwise non-zero space has no user register assignment");
unsigned space = res->GetSpaceID();
if (space == UINT_MAX) space = AutoBindingSpace;
typename SpacesAllocator<unsigned, T>::Allocator& alloc = SAlloc.Get(space);
typename SpacesAllocator<unsigned, T>::Allocator& reservedAlloc = ReservedRegisters.Get(space);
unsigned reg = 0;
unsigned end = 0;
bool allocateSpaceFound = false;
if (res->IsUnbounded()) {
if (alloc0.GetUnbounded() != nullptr) {
const T *unbounded = alloc0.GetUnbounded();
if (alloc.GetUnbounded() != nullptr) {
const T *unbounded = alloc.GetUnbounded();
Ctx.emitError(Twine("more than one unbounded resource (") +
unbounded->GetGlobalName() + Twine(" and ") +
res->GetGlobalName() + Twine(") in space ") +
@ -191,26 +190,26 @@ private:
continue;
}
if (reservedAlloc0.FindForUnbounded(reg)) {
if (reservedAlloc.FindForUnbounded(reg)) {
end = UINT_MAX;
allocateSpaceFound = true;
}
}
else if (reservedAlloc0.Find(res->GetRangeSize(), reg)) {
else if (reservedAlloc.Find(res->GetRangeSize(), reg)) {
end = reg + res->GetRangeSize() - 1;
allocateSpaceFound = true;
}
if (allocateSpaceFound) {
bool success = reservedAlloc0.Insert(res.get(), reg, end) == nullptr;
bool success = reservedAlloc.Insert(res.get(), reg, end) == nullptr;
DXASSERT_NOMSG(success);
success = alloc0.Insert(res.get(), reg, end) == nullptr;
success = alloc.Insert(res.get(), reg, end) == nullptr;
DXASSERT_NOMSG(success);
if (res->IsUnbounded()) {
alloc0.SetUnbounded(res.get());
reservedAlloc0.SetUnbounded(res.get());
alloc.SetUnbounded(res.get());
reservedAlloc.SetUnbounded(res.get());
}
res->SetLowerBound(reg);

Просмотреть файл

@ -22,6 +22,7 @@
#include "dxc/DXIL/DxilConstants.h"
#include "dxc/Support/WinAdapter.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/Optional.h"
namespace clang {
class ASTContext;
@ -201,6 +202,7 @@ private:
public:
UnusualAnnotation(UnusualAnnotationKind kind) : Kind(kind), Loc() { }
UnusualAnnotation(UnusualAnnotationKind kind, clang::SourceLocation loc) : Kind(kind), Loc(loc) { }
UnusualAnnotation(const UnusualAnnotation& other) : Kind(other.Kind), Loc(other.Loc) {}
UnusualAnnotationKind getKind() const { return Kind; }
UnusualAnnotation* CopyToASTContext(clang::ASTContext& Context);
@ -215,35 +217,22 @@ public:
struct RegisterAssignment : public UnusualAnnotation
{
/// <summary>Initializes a new RegisterAssignment in invalid state.</summary>
RegisterAssignment() : UnusualAnnotation(UA_RegisterAssignment),
ShaderProfile(), IsValid(false),
RegisterType(0), RegisterNumber(0), RegisterSpace(0), RegisterOffset(0)
{
}
RegisterAssignment(const RegisterAssignment& other) : UnusualAnnotation(UA_RegisterAssignment, other.Loc),
ShaderProfile(other.ShaderProfile),
IsValid(other.IsValid),
RegisterType(other.RegisterType),
RegisterNumber(other.RegisterNumber),
RegisterSpace(other.RegisterSpace),
RegisterOffset(other.RegisterOffset)
{
}
RegisterAssignment() : UnusualAnnotation(UA_RegisterAssignment) { }
llvm::StringRef ShaderProfile;
bool IsValid;
char RegisterType; // 'x' means only space is assigned from the source code
uint32_t RegisterNumber;
uint32_t RegisterSpace;
uint32_t RegisterOffset;
bool IsValid = false;
char RegisterType = 0; // Lower-case letter, 0 if not explicitly set
uint32_t RegisterNumber = 0; // Iff RegisterType != 0
llvm::Optional<uint32_t> RegisterSpace; // Set only if explicit "spaceN" syntax
uint32_t RegisterOffset = 0;
void setIsValid(bool value) {
IsValid = value;
}
void setAsSpaceOnly() { RegisterType = 'x'; }
bool isSpaceOnly() const { return RegisterType == 'x'; }
bool isSpaceOnly() const {
return RegisterType == 0 && RegisterSpace.hasValue();
}
static bool classof(const UnusualAnnotation *UA) {
return UA->getKind() == UA_RegisterAssignment;

Просмотреть файл

@ -1002,8 +1002,6 @@ def err_hlsl_unsupported_register_noninteger : Error<
"register subcomponent is not an integral constant">;
def err_hlsl_unsupported_register_type : Error<
"register type is unsupported - available types are 'b', 'c', 'i', 's', 't', 'u'">;
def err_hlsl_missing_register_type_and_number : Error<
"missing register type and number">;
def err_hlsl_unsupported_space_number : Error<
"space number should be an integral numeric string">;
def err_hlsl_modifier_after_type : Error<

Просмотреть файл

@ -7530,10 +7530,6 @@ def err_hlsl_unsupported_lvalue_cast_op : Error<
"cannot truncate lvalue vector/matrix">;
def err_hlsl_unsupported_buffer_packoffset : Error<
"packoffset is only allowed within a constant buffer, not on the constant buffer declaration">;
def err_hlsl_unsupported_cbuffer_register : Error<
"invalid register specification, expected 'b' binding">;
def err_hlsl_unsupported_tbuffer_register : Error<
"invalid register specification, expected 't' binding">;
def err_hlsl_unsupported_buffer_slot_target_specific : Error<
"user defined constant buffer slots cannot be target specific">;
def err_hlsl_unsupported_builtin_op: Error<

Просмотреть файл

@ -1021,13 +1021,19 @@ void ASTDumper::dumpHLSLUnusualAnnotations(const ArrayRef<hlsl::UnusualAnnotatio
OS << " register(";
if (!registerAssignment->ShaderProfile.empty())
OS << registerAssignment->ShaderProfile << ", ";
if (!registerAssignment->RegisterType)
OS << "invalid";
else
OS << std::string(&(registerAssignment->RegisterType), 1);
OS << registerAssignment->RegisterNumber + registerAssignment->RegisterOffset;
if (registerAssignment->RegisterSpace)
OS << ", space" << registerAssignment->RegisterSpace;
bool needsComma = false;
if (!registerAssignment->isSpaceOnly()) {
if (!registerAssignment->RegisterType)
OS << "invalid";
else
OS << StringRef(&registerAssignment->RegisterType, 1);
OS << registerAssignment->RegisterNumber + registerAssignment->RegisterOffset;
needsComma = true;
}
if (registerAssignment->RegisterSpace.hasValue()) {
if (needsComma) OS << ", ";
OS << "space" << registerAssignment->RegisterSpace.getValue();
}
OS << ")";
if (!registerAssignment->IsValid)
OS << " invalid";

Просмотреть файл

@ -2337,12 +2337,43 @@ namespace {
}
}
static void InitFromUnusualAnnotations(DxilResourceBase &Resource, NamedDecl &Decl) {
for (hlsl::UnusualAnnotation* It : Decl.getUnusualAnnotations()) {
switch (It->getKind()) {
case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
hlsl::RegisterAssignment* RegAssign = cast<hlsl::RegisterAssignment>(It);
if (RegAssign->RegisterType) {
Resource.SetLowerBound(RegAssign->RegisterNumber);
// For backcompat, don't auto-assign the register space if there's an
// explicit register type.
Resource.SetSpaceID(RegAssign->RegisterSpace.getValueOr(0));
}
else {
Resource.SetSpaceID(RegAssign->RegisterSpace.getValueOr(UINT_MAX));
}
break;
}
case hlsl::UnusualAnnotation::UA_SemanticDecl:
// Ignore Semantics
break;
case hlsl::UnusualAnnotation::UA_ConstantPacking:
// Should be handled by front-end
llvm_unreachable("packoffset on resource");
break;
default:
llvm_unreachable("unknown UnusualAnnotation on resource");
break;
}
}
}
uint32_t CGMSHLSLRuntime::AddSampler(VarDecl *samplerDecl) {
llvm::GlobalVariable *val =
cast<llvm::GlobalVariable>(CGM.GetAddrOfGlobalVar(samplerDecl));
unique_ptr<DxilSampler> hlslRes(new DxilSampler);
hlslRes->SetLowerBound(UINT_MAX);
hlslRes->SetSpaceID(UINT_MAX);
hlslRes->SetGlobalSymbol(val);
hlslRes->SetGlobalName(samplerDecl->getName());
@ -2356,27 +2387,7 @@ uint32_t CGMSHLSLRuntime::AddSampler(VarDecl *samplerDecl) {
DxilSampler::SamplerKind kind = KeywordToSamplerKind(RT->getDecl()->getName());
hlslRes->SetSamplerKind(kind);
for (hlsl::UnusualAnnotation *it : samplerDecl->getUnusualAnnotations()) {
switch (it->getKind()) {
case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
hlsl::RegisterAssignment *ra = cast<hlsl::RegisterAssignment>(it);
hlslRes->SetLowerBound(ra->RegisterNumber);
hlslRes->SetSpaceID(ra->RegisterSpace);
break;
}
case hlsl::UnusualAnnotation::UA_SemanticDecl:
// Ignore Semantics
break;
case hlsl::UnusualAnnotation::UA_ConstantPacking:
// Should be handled by front-end
llvm_unreachable("packoffset on sampler");
break;
default:
llvm_unreachable("unknown UnusualAnnotation on sampler");
break;
}
}
InitFromUnusualAnnotations(*hlslRes, *samplerDecl);
hlslRes->SetID(m_pHLModule->GetSamplers().size());
return m_pHLModule->AddSampler(std::move(hlslRes));
@ -2732,6 +2743,7 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
unique_ptr<HLResource> hlslRes(new HLResource);
hlslRes->SetLowerBound(UINT_MAX);
hlslRes->SetSpaceID(UINT_MAX);
hlslRes->SetGlobalSymbol(val);
hlslRes->SetGlobalName(decl->getName());
@ -2740,27 +2752,7 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
GetResourceDeclElemTypeAndRangeSize(CGM, *m_pHLModule, *decl,
VarTy, rangeSize);
hlslRes->SetRangeSize(rangeSize);
for (hlsl::UnusualAnnotation *it : decl->getUnusualAnnotations()) {
switch (it->getKind()) {
case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
hlsl::RegisterAssignment *ra = cast<hlsl::RegisterAssignment>(it);
hlslRes->SetLowerBound(ra->RegisterNumber);
hlslRes->SetSpaceID(ra->RegisterSpace);
break;
}
case hlsl::UnusualAnnotation::UA_SemanticDecl:
// Ignore Semantics
break;
case hlsl::UnusualAnnotation::UA_ConstantPacking:
// Should be handled by front-end
llvm_unreachable("packoffset on uav/srv");
break;
default:
llvm_unreachable("unknown UnusualAnnotation on uav/srv");
break;
}
}
InitFromUnusualAnnotations(*hlslRes, *decl);
if (decl->hasAttr<HLSLGloballyCoherentAttr>()) {
hlslRes->SetGloballyCoherent(true);
@ -2853,6 +2845,13 @@ void CGMSHLSLRuntime::AddConstant(VarDecl *constDecl, HLCBuffer &CB) {
case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
if (isGlobalCB) {
RegisterAssignment *ra = cast<RegisterAssignment>(it);
if (ra->RegisterSpace.hasValue()) {
DiagnosticsEngine& Diags = CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"register space cannot be specified on global constants.");
Diags.Report(it->Loc, DiagID);
}
offset = ra->RegisterNumber << 2;
// Change to byte.
offset <<= 2;
@ -2868,6 +2867,7 @@ void CGMSHLSLRuntime::AddConstant(VarDecl *constDecl, HLCBuffer &CB) {
std::unique_ptr<DxilResourceBase> pHlslConst = llvm::make_unique<DxilResourceBase>(DXIL::ResourceClass::Invalid);
pHlslConst->SetLowerBound(UINT_MAX);
pHlslConst->SetSpaceID(0);
pHlslConst->SetGlobalSymbol(cast<llvm::GlobalVariable>(constVal));
pHlslConst->SetGlobalName(constDecl->getName());
@ -2913,6 +2913,7 @@ uint32_t CGMSHLSLRuntime::AddCBuffer(HLSLBufferDecl *D) {
// setup the CB
CB->SetGlobalSymbol(nullptr);
CB->SetGlobalName(D->getNameAsString());
CB->SetSpaceID(UINT_MAX);
CB->SetLowerBound(UINT_MAX);
if (!D->isCBuffer()) {
CB->SetKind(DXIL::ResourceKind::TBuffer);
@ -2921,24 +2922,7 @@ uint32_t CGMSHLSLRuntime::AddCBuffer(HLSLBufferDecl *D) {
// the global variable will only used once by the createHandle?
// SetHandle(llvm::Value *pHandle);
for (hlsl::UnusualAnnotation *it : D->getUnusualAnnotations()) {
switch (it->getKind()) {
case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
hlsl::RegisterAssignment *ra = cast<hlsl::RegisterAssignment>(it);
uint32_t regNum = ra->RegisterNumber;
uint32_t regSpace = ra->RegisterSpace;
CB->SetSpaceID(regSpace);
CB->SetLowerBound(regNum);
break;
}
case hlsl::UnusualAnnotation::UA_SemanticDecl:
// skip semantic on constant buffer
break;
case hlsl::UnusualAnnotation::UA_ConstantPacking:
llvm_unreachable("no packoffset on constant buffer");
break;
}
}
InitFromUnusualAnnotations(*CB, *D);
// Add constant
if (D->isConstantBufferView()) {

Просмотреть файл

@ -214,9 +214,12 @@ static void ParseRegisterNumberForHLSL(_In_z_ const char *name,
DXASSERT_NOMSG(registerNumber != nullptr);
DXASSERT_NOMSG(diagId != nullptr);
if (*name != 'b' && *name != 'c' && *name != 'i' && *name != 's' &&
*name != 't' && *name != 'u' && *name != 'B' && *name != 'C' &&
*name != 'I' && *name != 'S' && *name != 'T' && *name != 'U') {
char firstLetter = name[0];
if (firstLetter >= 'A' && firstLetter <= 'Z')
firstLetter += 'a' - 'A';
StringRef validExplicitRegisterTypes("bcistu");
if (validExplicitRegisterTypes.find(firstLetter) == StringRef::npos) {
*diagId = diag::err_hlsl_unsupported_register_type;
*registerType = 0;
*registerNumber = 0;
@ -226,7 +229,7 @@ static void ParseRegisterNumberForHLSL(_In_z_ const char *name,
*registerType = *name;
++name;
// It's valid to omit the register name.
// It's valid to omit the register number.
if (*name) {
char *nameEnd;
unsigned long num;
@ -393,20 +396,11 @@ bool Parser::MaybeParseHLSLAttributes(std::vector<hlsl::UnusualAnnotation *> &ta
DXASSERT(Tok.is(tok::identifier), "otherwise previous code should have failed");
unsigned diagId;
// SPIRV Change Starts
bool hasOnlySpace = false;
identifierText = Tok.getIdentifierInfo()->getName().data();
if (strncmp(identifierText, "space", strlen("space")) == 0) {
if (!getLangOpts().SPIRV) {
Diag(Tok.getLocation(),
diag::err_hlsl_missing_register_type_and_number);
SkipUntil(tok::r_paren, StopAtSemi); // skip through )
return true;
}
hasOnlySpace = true;
} else {
// SPIRV Change Ends
ParseRegisterNumberForHLSL(
Tok.getIdentifierInfo()->getName().data(), &r.RegisterType, &r.RegisterNumber, &diagId);
if (diagId == 0) {
@ -461,22 +455,19 @@ bool Parser::MaybeParseHLSLAttributes(std::vector<hlsl::UnusualAnnotation *> &ta
return true;
}
}
// SPIRV Change Starts
}
if (hasOnlySpace) {
ParseSpaceForHLSL(Tok.getIdentifierInfo()->getName().data(), &r.RegisterSpace, &diagId);
unsigned RegisterSpaceValue = 0;
ParseSpaceForHLSL(Tok.getIdentifierInfo()->getName().data(), &RegisterSpaceValue, &diagId);
if (diagId != 0) {
Diag(Tok.getLocation(), diagId);
r.setIsValid(false);
} else {
r.setAsSpaceOnly();
r.RegisterSpace = RegisterSpaceValue;
r.setIsValid(true);
}
ConsumeToken(); // consume identifier
} else {
// SPIRV Change Ends
if (Tok.is(tok::comma)) {
ConsumeToken(); // consume comma
if (!Tok.is(tok::identifier)) {
@ -484,15 +475,18 @@ bool Parser::MaybeParseHLSLAttributes(std::vector<hlsl::UnusualAnnotation *> &ta
SkipUntil(tok::r_paren, StopAtSemi); // skip through )
return true;
}
ParseSpaceForHLSL(Tok.getIdentifierInfo()->getName().data(), &r.RegisterSpace, &diagId);
unsigned RegisterSpaceVal = 0;
ParseSpaceForHLSL(Tok.getIdentifierInfo()->getName().data(), &RegisterSpaceVal, &diagId);
if (diagId != 0) {
Diag(Tok.getLocation(), diagId);
r.setIsValid(false);
}
else {
r.RegisterSpace = RegisterSpaceVal;
}
ConsumeToken(); // consume identifier
}
} // SPIRV Change
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected)) {
SkipUntil(tok::r_paren, StopAtSemi); // skip through )

Просмотреть файл

@ -107,15 +107,13 @@ Decl *Parser::ParseConstBuffer(unsigned Context, SourceLocation &DeclEnd,
ArrayRef<hlsl::UnusualAnnotation*> annotations = namedDecl->getUnusualAnnotations();
for (hlsl::UnusualAnnotation* annotation : annotations) {
if (const auto *regAssignment = dyn_cast<hlsl::RegisterAssignment>(annotation)) {
// SPIRV Change Starts - skip the check if space-only for SPIR-V
if (getLangOpts().SPIRV && regAssignment->isSpaceOnly())
if (regAssignment->isSpaceOnly())
continue;
// SPIRV Change Ends
if (isCBuffer && regAssignment->RegisterType != 'b' && regAssignment->RegisterType != 'B') {
Diag(namedDecl->getLocation(), diag::err_hlsl_unsupported_cbuffer_register);
Diag(namedDecl->getLocation(), diag::err_hlsl_incorrect_bind_semantic) << "'b'";
}
else if (!isCBuffer && regAssignment->RegisterType != 't' && regAssignment->RegisterType != 'T') {
Diag(namedDecl->getLocation(), diag::err_hlsl_unsupported_tbuffer_register);
Diag(namedDecl->getLocation(), diag::err_hlsl_incorrect_bind_semantic) << "'t'";
}
}
}

Просмотреть файл

@ -1334,7 +1334,7 @@ public:
bool getSetBinding(const hlsl::RegisterAssignment *regAttr, int *setNo,
int *bindNo) const {
std::ostringstream iss;
iss << regAttr->RegisterSpace << regAttr->RegisterType
iss << regAttr->RegisterSpace.getValueOr(0) << regAttr->RegisterType
<< regAttr->RegisterNumber;
auto found = mapping.find(iss.str());
@ -1450,7 +1450,7 @@ bool DeclResultIdMapper::decorateResourceBindings() {
if (const auto *vkBinding = var.getBinding())
set = vkBinding->getSet();
else if (const auto *reg = var.getRegister())
set = reg->RegisterSpace;
set = reg->RegisterSpace.getValueOr(0);
tryToDecorate(var.getSpirvInstr(), set, vkCBinding->getBinding());
}
@ -1476,7 +1476,7 @@ bool DeclResultIdMapper::decorateResourceBindings() {
if (reg->isSpaceOnly())
continue;
const uint32_t set = reg->RegisterSpace;
const uint32_t set = reg->RegisterSpace.getValueOr(0);
uint32_t binding = reg->RegisterNumber;
switch (reg->RegisterType) {
case 'b':
@ -1509,7 +1509,7 @@ bool DeclResultIdMapper::decorateResourceBindings() {
if (const auto *vkBinding = var.getBinding())
set = vkBinding->getSet();
else if (const auto *reg = var.getRegister())
set = reg->RegisterSpace;
set = reg->RegisterSpace.getValueOr(0);
spvBuilder.decorateDSetBinding(var.getSpirvInstr(), set,
bindingSet.useNextBinding(set));
@ -1517,7 +1517,7 @@ bool DeclResultIdMapper::decorateResourceBindings() {
} else if (!var.getBinding()) {
const auto *reg = var.getRegister();
if (reg && reg->isSpaceOnly()) {
const uint32_t set = reg->RegisterSpace;
const uint32_t set = reg->RegisterSpace.getValueOr(0);
spvBuilder.decorateDSetBinding(var.getSpirvInstr(), set,
bindingSet.useNextBinding(set));
} else if (!reg) {

Просмотреть файл

@ -9501,10 +9501,12 @@ void hlsl::DiagnoseRegisterType(
clang::QualType type,
char registerType)
{
// SPIRV Change Starts - skip the check if space-only for SPIR-V
if (self->getLangOpts().SPIRV && registerType == 'x')
// Register type can be zero if only a register space was provided.
if (registerType == 0)
return;
// SPIRV Change Ends
if (registerType >= 'A' && registerType <= 'Z')
registerType = registerType + ('a' - 'A');
HLSLExternalSource* source = HLSLExternalSource::FromSema(self);
ArBasicKind element = source->GetTypeElementKind(type);
@ -9535,8 +9537,7 @@ void hlsl::DiagnoseRegisterType(
case AR_BASIC_MIN16INT:
case AR_BASIC_MIN16UINT:
expected = "'b', 'c', or 'i'";
isValid = registerType == 'b' || registerType == 'c' || registerType == 'i' ||
registerType == 'B' || registerType == 'C' || registerType == 'I';
isValid = registerType == 'b' || registerType == 'c' || registerType == 'i';
break;
case AR_OBJECT_TEXTURE1D:
@ -9549,8 +9550,7 @@ void hlsl::DiagnoseRegisterType(
case AR_OBJECT_TEXTURE2DMS:
case AR_OBJECT_TEXTURE2DMS_ARRAY:
expected = "'t' or 's'";
isValid = registerType == 't' || registerType == 's' ||
registerType == 'T' || registerType == 'S';
isValid = registerType == 't' || registerType == 's';
break;
case AR_OBJECT_SAMPLER:
@ -9560,13 +9560,12 @@ void hlsl::DiagnoseRegisterType(
case AR_OBJECT_SAMPLERCUBE:
case AR_OBJECT_SAMPLERCOMPARISON:
expected = "'s' or 't'";
isValid = registerType == 's' || registerType == 't' ||
registerType == 'S' || registerType == 'T';
isValid = registerType == 's' || registerType == 't';
break;
case AR_OBJECT_BUFFER:
expected = "'t'";
isValid = registerType == 't' || registerType == 'T';
isValid = registerType == 't';
break;
case AR_OBJECT_POINTSTREAM:
@ -9589,13 +9588,13 @@ void hlsl::DiagnoseRegisterType(
case AR_OBJECT_RWTEXTURE3D:
case AR_OBJECT_RWBUFFER:
expected = "'u'";
isValid = registerType == 'u' || registerType == 'U';
isValid = registerType == 'u';
break;
case AR_OBJECT_BYTEADDRESS_BUFFER:
case AR_OBJECT_STRUCTURED_BUFFER:
expected = "'t'";
isValid = registerType == 't' || registerType == 'T';
isValid = registerType == 't';
break;
case AR_OBJECT_CONSUME_STRUCTURED_BUFFER:
@ -9605,16 +9604,16 @@ void hlsl::DiagnoseRegisterType(
case AR_OBJECT_RWSTRUCTURED_BUFFER_CONSUME:
case AR_OBJECT_APPEND_STRUCTURED_BUFFER:
expected = "'u'";
isValid = registerType == 'u' || registerType == 'U';
isValid = registerType == 'u';
break;
case AR_OBJECT_CONSTANT_BUFFER:
expected = "'b'";
isValid = registerType == 'b' || registerType == 'B';
isValid = registerType == 'b';
break;
case AR_OBJECT_TEXTURE_BUFFER:
expected = "'t'";
isValid = registerType == 't' || registerType == 'T';
isValid = registerType == 't';
break;
case AR_OBJECT_ROVBUFFER:
@ -9626,7 +9625,7 @@ void hlsl::DiagnoseRegisterType(
case AR_OBJECT_ROVTEXTURE2D_ARRAY:
case AR_OBJECT_ROVTEXTURE3D:
expected = "'u'";
isValid = registerType == 'u' || registerType == 'U';
isValid = registerType == 'u';
break;
case AR_OBJECT_LEGACY_EFFECT: // Used for all unsupported but ignored legacy effect types
@ -9638,12 +9637,9 @@ void hlsl::DiagnoseRegisterType(
// fxc is inconsistent as to when it reports an error and when it ignores invalid bind semantics, so emit
// a warning instead.
if (!isValid)
{
if (isWarning)
self->Diag(loc, diag::warn_hlsl_incorrect_bind_semantic) << expected;
else
self->Diag(loc, diag::err_hlsl_incorrect_bind_semantic) << expected;
if (!isValid) {
unsigned DiagID = isWarning ? diag::warn_hlsl_incorrect_bind_semantic : diag::err_hlsl_incorrect_bind_semantic;
self->Diag(loc, DiagID) << expected;
}
}
@ -11175,14 +11171,11 @@ Decl* Sema::ActOnStartHLSLBuffer(
case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
hlsl::RegisterAssignment* registerAssignment = cast<hlsl::RegisterAssignment>(*unusualIter);
// SPIRV Change Starts - skip the check if space-only for SPIR-V
if (getLangOpts().SPIRV && registerAssignment->isSpaceOnly())
if (registerAssignment->isSpaceOnly())
continue;
// SPIRV Change Ends
if (registerAssignment->RegisterType != expectedRegisterType && registerAssignment->RegisterType != toupper(expectedRegisterType)) {
Diag(registerAssignment->Loc, cbuffer ? diag::err_hlsl_unsupported_cbuffer_register :
diag::err_hlsl_unsupported_tbuffer_register);
Diag(registerAssignment->Loc, diag::err_hlsl_incorrect_bind_semantic) << (cbuffer ? "'b'" : "'t'");
} else if (registerAssignment->ShaderProfile.size() > 0) {
Diag(registerAssignment->Loc, diag::err_hlsl_unsupported_buffer_slot_target_specific);
}

Просмотреть файл

@ -0,0 +1,17 @@
// RUN: %dxc -E main -T vs_6_0 -auto-binding-space 1 %s | FileCheck %s
// Test that auto-binding-space affects only resources with no
// explicit register nor space binding.
// CHECK: buf_a texture f32 buf T0 t0,space1 1
// CHECK: buf_b texture f32 buf T1 t1 1
// CHECK: buf_c texture f32 buf T2 t0,space2 1
// CHECK: buf_d texture f32 buf T3 t2,space3 1
Buffer buf_a;
Buffer buf_b : register(t1);
Buffer buf_c : register(space2);
Buffer buf_d : register(t2,space3);
float main() : OUT {
return buf_a[0] + buf_b[0] + buf_c[0] + buf_d[0];
}

Просмотреть файл

@ -0,0 +1,17 @@
// RUN: %dxc -T lib_6_3 %s | FileCheck %s
// Test that auto-binding-space affects only resources with no
// explicit register nor space binding.
// CHECK: buf_a texture f32 buf T0t4294967295,space4294967295 1
// CHECK: buf_b texture f32 buf T1 t1 1
// CHECK: buf_c texture f32 buf T2t4294967295,space2 1
// CHECK: buf_d texture f32 buf T3 t2,space3 1
Buffer buf_a;
Buffer buf_b : register(t1);
Buffer buf_c : register(space2);
Buffer buf_d : register(t2,space3);
export float foo() {
return buf_a[0] + buf_b[0] + buf_c[0] + buf_d[0];
}

Просмотреть файл

@ -0,0 +1,16 @@
// RUN: %dxc -E main -T vs_6_0 %s | FileCheck %s
// Test resource allocation with space-only register annotations.
// CHECK-DAG: buf_s0_a texture f32 buf T0 t0 1
// CHECK-DAG: buf_s1_a texture f32 buf T1 t0,space1 1
// CHECK-DAG: buf_s0_b texture f32 buf T2 t1 1
// CHECK-DAG: buf_s1_b texture f32 buf T3 t1,space1 1
Buffer buf_s0_a;
Buffer buf_s1_a : register(space1);
Buffer buf_s0_b;
Buffer buf_s1_b : register(space1);
float main() : OUT {
return buf_s0_a[0] + buf_s1_a[0] + buf_s0_b[0] + buf_s1_b[0];
}

Просмотреть файл

@ -0,0 +1,46 @@
// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
struct S { float val; };
// Constant buffers, space cb
// CHECK-DAG: ; cb cbuffer NA NA CB0 cb0,space1 1
// CHECK-DAG: ; cb2 cbuffer NA NA CB1 cb1,space1 1
cbuffer cb : register(space1) { float cb_val; }
ConstantBuffer<S> cb2 : register(space1);
// Samplers, space s
// CHECK-DAG: ; s sampler NA NA S0 s0,space2 1
SamplerState s : register(space2);
// SRVs, space t
// CHECK-DAG: ; buf texture f32 buf T0 t0,space3 1
// CHECK-DAG: ; tex texture f32 1d T1 t1,space3 1
// CHECK-DAG: ; sbuf texture struct r/o T2 t2,space3 1
// CHECK-DAG: ; babuf texture byte r/o T3 t3,space3 1
// CHECK-DAG: ; tb texture u32 tbuffer T4 t4,space3 1
// CHECK-DAG: ; tb2 texture u32 tbuffer T5 t5,space3 1
Buffer<float> buf : register(space3);
Texture1D<float> tex : register(space3);
StructuredBuffer<float> sbuf : register(space3);
ByteAddressBuffer babuf : register(space3);
tbuffer tb : register(space3) { float tb_val; }
TextureBuffer<S> tb2 : register(space3);
// UAVs, space u
// CHECK-DAG: ; rwsbuf UAV struct r/w U0 u0,space4 1
// CHECK-DAG: ; appbuf UAV struct r/w+cnt U1 u1,space4 1
// CHECK-DAG: ; conbuf UAV struct r/w+cnt U2 u2,space4 1
// CHECK-DAG: ; rwbabuf UAV byte r/w U3 u3,space4 1
RWStructuredBuffer<float> rwsbuf : register(space4);
AppendStructuredBuffer<float> appbuf : register(space4);
ConsumeStructuredBuffer<float> conbuf : register(space4);
RWByteAddressBuffer rwbabuf : register(space4);
// Use all resources so they get allocated
float main() : SV_Target {
appbuf.Append(0);
return cb_val + cb2.val
+ buf[0] + tex[0] + sbuf[0] + babuf.Load<float>(0) + tb_val + tb2.val
+ rwsbuf[0] + conbuf.Consume() + rwbabuf.Load<float>(0)
+ tex.Sample(s, 0);
}

Просмотреть файл

@ -0,0 +1,8 @@
// RUN: %dxc -E main -T vs_6_0 %s | FileCheck %s
// Test space-only register annotations with shader type specifier.
// CHECK: buf texture u32 buf T0 t0,space2 1
Buffer<uint> buf : register(ps, space1) : register(vs, space2);
uint main() : OUT { return buf[0]; }

Просмотреть файл

@ -0,0 +1,11 @@
// RUN: %dxc -T vs_6_0 -E main %s | FileCheck %s
// Test that register annotations on globals constants affect the offset.
// CHECK: ; int x; ; Offset: 16
// CHECK: ; int y; ; Offset: 0
int x : register(c1);
int y : register(c0);
int2 main() : OUT { return int2(x, y); }

Просмотреть файл

@ -1,36 +0,0 @@
// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
// CHECK: :4:40: error: missing register type and number
Buffer<float4> MyBuffer : register(space1);
// CHECK: :6:40: error: missing register type and number
Texture2D<float4> MyTexture : register(space1);
// CHECK: :9:30: error: missing register type and number
cbuffer MyCbuffer : register(space2) {
float4 CB_a;
}
// CHECK: :14:30: error: missing register type and number
tbuffer MyTbuffer : register(space2) {
float4 TB_a;
}
struct S { float4 val; };
// CHECK: :21:41: error: missing register type and number
ConstantBuffer<S> MyCbuffer2 : register(space3);
// CHECK: :23:41: error: missing register type and number
TextureBuffer<S> MyTbuffer2 : register(space3);
// CHECK: :26:50: error: missing register type and number
StructuredBuffer<S> MySbuffer1 : register(space4);
// CHECK: :28:50: error: missing register type and number
RWStructuredBuffer<S> MySbuffer2 : register(space4);
// CHECK: :30:50: error: missing register type and number
AppendStructuredBuffer<S> MySbuffer3 : register(space4);
// CHECK: :32:50: error: missing register type and number
ConsumeStructuredBuffer<S> MySbuffer4 : register(space4);
float4 main() : SV_Target {
return MyBuffer[0];
}

Просмотреть файл

@ -1031,7 +1031,7 @@ static void Ref1_CheckBinding_b_buf(D3D12_SHADER_INPUT_BIND_DESC &resDesc) {
VERIFY_ARE_EQUAL(resDesc.Type, D3D_SIT_UAV_RWBYTEADDRESS);
// not explicitly bound:
VERIFY_ARE_EQUAL(resDesc.BindPoint, 4294967295);
VERIFY_ARE_EQUAL(resDesc.Space, 0);
VERIFY_ARE_EQUAL(resDesc.Space, 4294967295);
VERIFY_ARE_EQUAL(resDesc.BindCount, 1);
}

Просмотреть файл

@ -256,8 +256,6 @@ public:
TEST_METHOD(WhenMissingPayloadThenFail)
TEST_METHOD(ShaderFunctionReturnTypeVoid)
TEST_METHOD(SpaceOnlyRegisterFail)
TEST_METHOD(WhenDisassembleInvalidBlobThenFail)
dxc::DxcDllSupport m_dllSupport;
@ -3055,10 +3053,6 @@ float4 main(uint vid : SV_ViewID, float3 In[31] : INPUT) : SV_Target \
/*bRegex*/true);
}
TEST_F(ValidationTest, SpaceOnlyRegisterFail) {
TestCheck(L"..\\CodeGenHLSL\\space-only-register.hlsl");
}
// Regression test for a double-delete when failing to parse bitcode.
TEST_F(ValidationTest, WhenDisassembleInvalidBlobThenFail) {
if (!m_dllSupport.IsEnabled()) {
@ -3075,7 +3069,6 @@ TEST_F(ValidationTest, WhenDisassembleInvalidBlobThenFail) {
VERIFY_FAILED(pCompiler->Disassemble(pInvalidBitcode, &pDisassembly));
}
TEST_F(ValidationTest, GSMainMissingAttributeFail) {
TestCheck(L"..\\CodeGenHLSL\\attributes-gs-no-inout-main.hlsl");
}
@ -3194,8 +3187,8 @@ TEST_F(ValidationTest, ResCounter) {
RewriteAssemblyCheckMsg(
"RWStructuredBuffer<float4> buf; export float GetCounter() {return buf.IncrementCounter();}",
"lib_6_3",
{ "!\"buf\", i32 0, i32 -1, i32 1, i32 12, i1 false, i1 true, i1 false, !" },
{ "!\"buf\", i32 0, i32 -1, i32 1, i32 12, i1 false, i1 false, i1 false, !" },
{ "!\"buf\", i32 -1, i32 -1, i32 1, i32 12, i1 false, i1 true, i1 false, !" },
{ "!\"buf\", i32 -1, i32 -1, i32 1, i32 12, i1 false, i1 false, i1 false, !" },
"BufferUpdateCounter valid only when HasCounter is true",
true);
}