[spirv] Fix Memory Barrier mappings to SPIR-V. (#917)

This commit is contained in:
Ehsan 2017-12-18 14:07:45 -05:00 коммит произвёл GitHub
Родитель 9a502c0e10
Коммит 8c5a38ba22
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 87 добавлений и 24 удалений

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

@ -5473,24 +5473,66 @@ uint32_t SPIRVEmitter::processIntrinsicMemoryBarrier(const CallExpr *callExpr,
bool isDevice,
bool groupSync,
bool isAllBarrier) {
// Execution Barrier scope:
// Device = 1
// Workgroup = 2
// Memory Barrier scope:
// Device = 1
// Workgroup = 2
// Memory Semantics Barrier scope:
// WorkgroupMemory = 0x100 = 256
// CrossWorkgroupMemory = 0x200 = 512
// 'All Memory Barrier' must place barrier at several different levels, so
// several flags must be turned on:
// 0x10 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 = 0xFD0 = 4048.
const uint32_t memSemaMask = isAllBarrier ? 0xFD0 : isDevice ? 0x200 : 0x100;
const auto memSema = theBuilder.getConstantUint32(memSemaMask);
const auto memScope = isDevice ? theBuilder.getConstantUint32(1)
: theBuilder.getConstantUint32(2);
const auto execScope = groupSync ? memScope : 0;
theBuilder.createBarrier(execScope, memScope, memSema);
// * DeviceMemoryBarrier =
// OpMemoryBarrier (memScope=Device,
// sem=Image|Uniform|AcquireRelease)
//
// * DeviceMemoryBarrierWithGroupSync =
// OpControlBarrier(execScope = Workgroup,
// memScope=Device,
// sem=Image|Uniform|AcquireRelease)
const spv::MemorySemanticsMask deviceMemoryBarrierSema =
spv::MemorySemanticsMask::ImageMemory |
spv::MemorySemanticsMask::UniformMemory |
spv::MemorySemanticsMask::AcquireRelease;
// * GroupMemoryBarrier =
// OpMemoryBarrier (memScope=Workgroup,
// sem = Workgroup|AcquireRelease)
//
// * GroupMemoryBarrierWithGroupSync =
// OpControlBarrier (execScope = Workgroup,
// memScope = Workgroup,
// sem = Workgroup|AcquireRelease)
const spv::MemorySemanticsMask groupMemoryBarrierSema =
spv::MemorySemanticsMask::WorkgroupMemory |
spv::MemorySemanticsMask::AcquireRelease;
// * AllMemoryBarrier =
// OpMemoryBarrier(memScope = Device,
// sem = Image|Uniform|Workgroup|AcquireRelease)
//
// * AllMemoryBarrierWithGroupSync =
// OpControlBarrier(execScope = Workgroup,
// memScope = Device,
// sem = Image|Uniform|Workgroup|AcquireRelease)
const spv::MemorySemanticsMask allMemoryBarrierSema =
spv::MemorySemanticsMask::ImageMemory |
spv::MemorySemanticsMask::UniformMemory |
spv::MemorySemanticsMask::WorkgroupMemory |
spv::MemorySemanticsMask::AtomicCounterMemory |
spv::MemorySemanticsMask::AcquireRelease;
// Get <result-id> for execution scope.
// If present, execution scope is always Workgroup!
const uint32_t execScopeId =
groupSync ? theBuilder.getConstantUint32(
static_cast<uint32_t>(spv::Scope::Workgroup))
: 0;
// Get <result-id> for memory scope
const spv::Scope memScope =
(isDevice || isAllBarrier) ? spv::Scope::Device : spv::Scope::Workgroup;
const uint32_t memScopeId =
theBuilder.getConstantUint32(static_cast<uint32_t>(memScope));
// Get <result-id> for memory semantics
const auto memSemaMask = isAllBarrier ? allMemoryBarrierSema
: isDevice ? deviceMemoryBarrierSema
: groupMemoryBarrierSema;
const uint32_t memSema =
theBuilder.getConstantUint32(static_cast<uint32_t>(memSemaMask));
theBuilder.createBarrier(execScopeId, memScopeId, memSema);
return 0;
}

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

@ -1,6 +1,9 @@
// Run: %dxc -T cs_6_0 -E main
// Memory scope : Device = 0x1 = 1
// Semantics: ImageMemory | AtomicCounterMemory | UniformMemory | WorkgroupMemory | AcquireRelease = 0x800 | 0x400 | 0x40 | 0x100 | 0x8 = 3400
void main() {
// CHECK: OpMemoryBarrier %uint_1 %uint_4048
// CHECK: OpMemoryBarrier %uint_1 %uint_3400
AllMemoryBarrier();
}

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

@ -1,6 +1,10 @@
// Run: %dxc -T cs_6_0 -E main
// Execution scope : Workgroup = 0x2 = 2
// Memory scope : Device = 0x1 = 1
// Semantics: ImageMemory | AtomicCounterMemory | UniformMemory | WorkgroupMemory | AcquireRelease = 0x800 | 0x400 | 0x40 | 0x100 | 0x8 = 3400
void main() {
// CHECK: OpControlBarrier %uint_1 %uint_1 %uint_4048
// CHECK: OpControlBarrier %uint_2 %uint_1 %uint_3400
AllMemoryBarrierWithGroupSync();
}

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

@ -1,6 +1,9 @@
// Run: %dxc -T cs_6_0 -E main
// Memory scope : Device = 0x1 = 1
// Semantics: ImageMemory | UniformMemory | AcquireRelease = 0x800 | 0x40 | 0x8 = 2120
void main() {
// CHECK: OpMemoryBarrier %uint_1 %uint_512
// CHECK: OpMemoryBarrier %uint_1 %uint_2120
DeviceMemoryBarrier();
}

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

@ -1,6 +1,10 @@
// Run: %dxc -T cs_6_0 -E main
// Execution scope : Workgroup = 0x2 = 2
// Memory scope : Device = 0x1 = 1
// Semantics: ImageMemory | UniformMemory | AcquireRelease = 0x800 | 0x40 | 0x8 = 2120
void main() {
// CHECK: OpControlBarrier %uint_1 %uint_1 %uint_512
// CHECK: OpControlBarrier %uint_2 %uint_1 %uint_2120
DeviceMemoryBarrierWithGroupSync();
}

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

@ -1,6 +1,9 @@
// Run: %dxc -T cs_6_0 -E main
// Memory scope : Workgroup = 0x2 = 2
// Semantics: WorkgroupMemory | AcquireRelease = 0x100 | 0x8 = 264
void main() {
// CHECK: OpMemoryBarrier %uint_2 %uint_256
// CHECK: OpMemoryBarrier %uint_2 %uint_264
GroupMemoryBarrier();
}

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

@ -1,6 +1,10 @@
// Run: %dxc -T cs_6_0 -E main
// Execution scope : Workgroup = 0x2 = 2
// Memory scope : Workgroup = 0x2 = 2
// Semantics: WorkgroupMemory | AcquireRelease = 0x100 | 0x8 = 264
void main() {
// CHECK: OpControlBarrier %uint_2 %uint_2 %uint_256
// CHECK: OpControlBarrier %uint_2 %uint_2 %uint_264
GroupMemoryBarrierWithGroupSync();
}