Support local resource array which don't have dynamic indexing. (#938)

This commit is contained in:
Xiang Li 2017-12-19 15:29:11 -08:00 коммит произвёл GitHub
Родитель fc52dbced0
Коммит ba844c25fe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 129 добавлений и 47 удалений

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

@ -31,6 +31,7 @@ namespace dxilutil {
GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
llvm::Type *Ty, DxilTypeSystem &typeSys);
llvm::Type *GetArrayEltTy(llvm::Type *Ty);
bool HasDynamicIndexing(llvm::Value *V);
bool IsStaticGlobal(llvm::GlobalVariable *GV);
bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);

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

@ -101,3 +101,6 @@
// 0X80AA0018 - General internal error.
#define DXC_E_GENERAL_INTERNAL_ERROR DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0018))
// 0X80AA0019 - Abort compilation error.
#define DXC_E_ABORT_COMPILATION_ERROR DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0019))

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

@ -21,6 +21,7 @@
#include "dxc/HLSL/HLOperationLower.h"
#include "HLSignatureLower.h"
#include "dxc/HLSL/DxilUtil.h"
#include "dxc/Support/exception.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/IRBuilder.h"
@ -1626,7 +1627,14 @@ void DxilLegalizeResourceUsePass::PromoteLocalResource(Function &F) {
// Skip for unpromotable for lib.
if (!isAllocaPromotable(AI) && IsLib)
continue;
DXASSERT(isAllocaPromotable(AI), "otherwise, non-promotable resource array alloca found");
if (!isAllocaPromotable(AI)) {
static const StringRef kNonPromotableLocalResourceErrorMsg =
"non-promotable local resource found.";
F.getContext().emitError(kNonPromotableLocalResourceErrorMsg);
throw hlsl::Exception(DXC_E_ABORT_COMPILATION_ERROR,
kNonPromotableLocalResourceErrorMsg);
continue;
}
Allocas.push_back(AI);
}
}

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

@ -21,6 +21,8 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Constants.h"
using namespace llvm;
using namespace hlsl;
@ -38,6 +40,18 @@ Type *GetArrayEltTy(Type *Ty) {
return Ty;
}
bool HasDynamicIndexing(Value *V) {
for (auto User : V->users()) {
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) {
if (!isa<ConstantInt>(Idx))
return true;
}
}
}
return false;
}
unsigned
GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
llvm::Type *Ty,

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

@ -2570,7 +2570,9 @@ void SROA_Helper::RewriteForGEP(GEPOperator *GEP, IRBuilder<> &Builder) {
} else {
// End at array of basic type.
Type *Ty = GEP->getType()->getPointerElementType();
if (Ty->isVectorTy() || Ty->isStructTy() || Ty->isArrayTy()) {
if (Ty->isVectorTy() ||
(Ty->isStructTy() && !HLModule::IsHLSLObjectType(Ty)) ||
Ty->isArrayTy()) {
SmallVector<Value *, 8> NewArgs;
NewArgs.append(GEP->idx_begin(), GEP->idx_end());
@ -3225,32 +3227,41 @@ bool SROA_Helper::DoScalarReplacement(Value *V, std::vector<Value *> &Elts,
if (ElTy->isStructTy() &&
// Skip Matrix type.
!HLMatrixLower::IsMatrixType(ElTy)) {
// Skip HLSL object types.
if (HLModule::IsHLSLObjectType(ElTy)) {
return false;
}
// for array of struct
// split into arrays of struct elements
StructType *ElST = cast<StructType>(ElTy);
unsigned numTypes = ElST->getNumContainedTypes();
Elts.reserve(numTypes);
DxilStructAnnotation *SA = typeSys.GetStructAnnotation(ElST);
// Skip empty struct.
if (SA && SA->IsEmptyStruct())
return true;
for (int i = 0, e = numTypes; i != e; ++i) {
AllocaInst *NA = Builder.CreateAlloca(
CreateNestArrayTy(ElST->getContainedType(i), nestArrayTys), nullptr,
V->getName() + "." + Twine(i));
bool markPrecise = hasPrecise;
if (SA) {
DxilFieldAnnotation &FA = SA->GetFieldAnnotation(i);
markPrecise |= FA.IsPrecise();
if (!HLModule::IsHLSLObjectType(ElTy)) {
// for array of struct
// split into arrays of struct elements
StructType *ElST = cast<StructType>(ElTy);
unsigned numTypes = ElST->getNumContainedTypes();
Elts.reserve(numTypes);
DxilStructAnnotation *SA = typeSys.GetStructAnnotation(ElST);
// Skip empty struct.
if (SA && SA->IsEmptyStruct())
return true;
for (int i = 0, e = numTypes; i != e; ++i) {
AllocaInst *NA = Builder.CreateAlloca(
CreateNestArrayTy(ElST->getContainedType(i), nestArrayTys),
nullptr, V->getName() + "." + Twine(i));
bool markPrecise = hasPrecise;
if (SA) {
DxilFieldAnnotation &FA = SA->GetFieldAnnotation(i);
markPrecise |= FA.IsPrecise();
}
if (markPrecise)
HLModule::MarkPreciseAttributeWithMetadata(NA);
Elts.push_back(NA);
}
} else {
// For local resource array which not dynamic indexing,
// split it.
if (dxilutil::HasDynamicIndexing(V) ||
// Only support 1 dim split.
nestArrayTys.size() > 1)
return false;
for (int i = 0, e = AT->getNumElements(); i != e; ++i) {
AllocaInst *NA = Builder.CreateAlloca(ElTy, nullptr,
V->getName() + "." + Twine(i));
Elts.push_back(NA);
}
if (markPrecise)
HLModule::MarkPreciseAttributeWithMetadata(NA);
Elts.push_back(NA);
}
} else if (ElTy->isVectorTy()) {
// Skip vector if required.
@ -6727,15 +6738,7 @@ Constant *DynamicIndexingVectorToArray::lowerInitVal(Constant *InitVal, Type *Ne
}
bool DynamicIndexingVectorToArray::HasVectorDynamicIndexing(Value *V) {
for (auto User : V->users()) {
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) {
if (!isa<ConstantInt>(Idx))
return true;
}
}
}
return false;
return dxilutil::HasDynamicIndexing(V);
}
}

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

@ -0,0 +1,17 @@
// RUN: %dxc -T cs_6_0 -E main %s | FileCheck %s
// Make sure simple local resource array works.
// CHECK: main
RWByteAddressBuffer outputBuffer;
RWByteAddressBuffer outputBuffer2;
[numthreads(8, 8, 1)]
void main( uint2 id : SV_DispatchThreadID )
{
RWByteAddressBuffer buffer[2];
buffer[0] = outputBuffer;
buffer[1] = outputBuffer2;
buffer[0].Store(id.x, id.y);
buffer[1].Store(id.y, id.x);
}

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

@ -0,0 +1,16 @@
// RUN: %dxc -T cs_6_0 -E main %s | FileCheck %s
// Report error when cannot promote local resource.
// CHECK: non-promotable local resource found
RWByteAddressBuffer outputBuffer;
RWByteAddressBuffer outputBuffer2;
uint i;
[numthreads(8, 8, 1)]
void main( uint2 id : SV_DispatchThreadID )
{
RWByteAddressBuffer buffer[2];
buffer[0] = outputBuffer;
buffer[1] = outputBuffer2;
buffer[i].Store(id.y, id.x);
}

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

@ -534,16 +534,22 @@ namespace MainNs
string[] arguments = fileVars.Arguments;
if (isDxil)
{
var result = compiler.Compile(source, fileName, fileVars.Entry, fileVars.Target, arguments, arguments.Length, null, 0, library.CreateIncludeHandler());
if (result.GetStatus() == 0)
{
this.SelectedShaderBlob = result.GetResult();
this.DisassembleSelectedShaderBlob();
}
else
{
this.colorizationService.ClearColorization(this.DisassemblyTextBox);
this.DisassemblyTextBox.Text = GetStringFromBlob(result.GetErrors());
try
{
var result = compiler.Compile(source, fileName, fileVars.Entry, fileVars.Target, arguments, arguments.Length, null, 0, library.CreateIncludeHandler());
if (result.GetStatus() == 0)
{
this.SelectedShaderBlob = result.GetResult();
this.DisassembleSelectedShaderBlob();
}
else
{
this.colorizationService.ClearColorization(this.DisassemblyTextBox);
this.DisassemblyTextBox.Text = GetStringFromBlob(result.GetErrors());
}
} catch (Exception e)
{
DisassemblyTextBox.Text = e.ToString();
}
}
else

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

@ -566,8 +566,22 @@ public:
}
hr = S_OK;
} catch (std::bad_alloc &) {
hr = E_OUTOFMEMORY;
} catch (hlsl::Exception &e) {
_Analysis_assume_(DXC_FAILED(e.hr));
if (e.hr == DXC_E_ABORT_COMPILATION_ERROR) {
e.hr = S_OK;
CComPtr<IDxcBlobEncoding> pErrorBlob;
IFT(DxcCreateBlobWithEncodingOnHeapCopy(e.msg.c_str(), e.msg.size(),
CP_UTF8, &pErrorBlob));
IFT(DxcOperationResult::CreateFromResultErrorStatus(
nullptr, pErrorBlob, DXC_E_GENERAL_INTERNAL_ERROR, ppResult));
}
hr = e.hr;
} catch (...) {
hr = E_FAIL;
}
CATCH_CPP_ASSIGN_HRESULT();
Cleanup:
DxcEtw_DXCompilerCompile_Stop(hr);
return hr;