Support local resource array which don't have dynamic indexing. (#938)
This commit is contained in:
Родитель
fc52dbced0
Коммит
ba844c25fe
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче