-
Notifications
You must be signed in to change notification settings - Fork 14
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
BF4, BF Hardline, DA:I, Plants vs. Zombies: Garden Warfare / Frostbite 3 Engine #10
Comments
Thanks for the report, I haven't tried any games other than Star Swarm. Fortunately the |
No, thanks to you for this amazing project. Keep up the good work :-) |
Did you try to launch BF4 from wine? It doesn't detect Mantle API at all because I think, the client tries to find amdmantle64.dll first instead of mantle64.dll. |
I tried it on windows 10 without wine. To make games be able to detect mantle using Nvidia, you have to move amdmantle64.dll and mantleaxl64.dll into the executable folder, and then paste GRVK's dlls, in this case mantle64.dll. You can get those dlls downloading the Adrenaline 19.4.3 driver drom AMD. |
I hope there will be at least some explanation of function parameters from such libraries (there is a ton of parameters for this function for example), so we could implement these functions to avoid using proprietary libraries. |
@xatornet can you restrict this issue for Frostbite games, and create separate issues for UE3 and other engines? |
Well, considering it's possible to select Mantle backend in bf4 now, does the game even work with it (at least in-menu)? |
It looks like this with some additional hacks. I get a crash after the
|
Interesting, might look into it as well. I think it's probably due to UPD: object type is really |
@Cherser-s correct, I'm handling that and using windowed mode, but it still crashes. |
Wait, did you already implemented the code, which is handling these 3 features? Can you push it at least to another branch, so I can look into it? I've implemented it partially myself though. Also, do you handle ""present"" queue flags info as well? |
Hm weird, it doesn't initialize on my machine at all, it doesn't get past |
@Cherser-s That's because BF4 checks the driver version. I pushed a fix earlier today, I'll post another branch tomorrow so you can take a look |
Yeah I got those commits, and managed to reproduce the same problem as well. Interesting, that crash happens much later, perhaps during the game initialization, as there are no calls at all to Mantle libraries. It's really weird that the game (the code in executable that is) itself crashes. |
v0.4.0 has the same problem on DA:I Here's grvk.log: |
I have patches for this that I haven't posted yet. |
I'll be looking for those on later releases |
For me, DA:I is working just fine (Windows 10, Radeon RX 570) with the versions 0.2.0 (about 30h of gameplay without any issues) and 0.3.0, although it seems that multisampling is not working in 0.2.0. However, with the newest version I get === GRVK 0.4.0 === and the game crashes silently. |
@Osyfe there's no way the game actually runs on Mantle with 0.2.0, it's most likely falling back to DX11 at boot. |
Oh, interesting. Is there a way to check which API actually is used by an application? |
Confirm this, in the case if either there isn't mantleaxl64.dll present, or API version isn't supported by the client (as in case with FB3 games), then the game just fallbacks to using D3D11.
Hmmm, also have to implement more UAV operations. Interesting, how it doesn't crash after calling WSI functions here... |
Try applying this patch to the latest commit from master branch to avoid those errors in shader translation:
P.S.: I think the UAV atomics should be typed. |
I still get the same error. |
Ah damn it, it seems that I assume the wrong opcode |
Ok, I have added this missing instruction handling, please try it out. I also added dump handling for these instructions. diff --git a/src/amdilc/amdilc_compiler.c b/src/amdilc/amdilc_compiler.c
index 52e8e97..b549301 100644
--- a/src/amdilc/amdilc_compiler.c
+++ b/src/amdilc/amdilc_compiler.c
@@ -1078,6 +1078,41 @@ static void emitTypedUav(
addResource(compiler, &resource);
}
+static void emitRawSrv(
+ IlcCompiler* compiler,
+ const Instruction* instr)
+{
+ uint16_t id = GET_BITS(instr->control, 0, 13);
+
+ IlcSpvId arrayId = ilcSpvPutRuntimeArrayType(compiler->module, compiler->floatId, true);
+ IlcSpvId structId = ilcSpvPutStructType(compiler->module, 1, &arrayId);
+ IlcSpvId pointerId = ilcSpvPutPointerType(compiler->module, SpvStorageClassStorageBuffer,
+ structId);
+ IlcSpvId resourceId = ilcSpvPutVariable(compiler->module, pointerId,
+ SpvStorageClassStorageBuffer);
+
+ IlcSpvWord arrayStride = sizeof(float);
+ IlcSpvWord memberOffset = 0;
+ ilcSpvPutDecoration(compiler->module, arrayId, SpvDecorationArrayStride, 1, &arrayStride);
+ ilcSpvPutDecoration(compiler->module, structId, SpvDecorationBlock, 0, NULL);
+ ilcSpvPutMemberDecoration(compiler->module, structId, 0, SpvDecorationOffset, 1, &memberOffset);
+ ilcSpvPutDecoration(compiler->module, resourceId, SpvDecorationNonWritable, 0, NULL);
+
+ ilcSpvPutName(compiler->module, arrayId, "rawSrv");
+ emitBinding(compiler, resourceId, ILC_BASE_RESOURCE_ID + id, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
+
+ const IlcResource resource = {
+ .id = resourceId,
+ .typeId = arrayId,
+ .texelTypeId = compiler->floatId,
+ .ilId = id,
+ .ilType = IL_USAGE_PIXTEX_UNKNOWN,
+ .strideId = 0,
+ };
+
+ addResource(compiler, &resource);
+}
+
static void emitStructuredSrv(
IlcCompiler* compiler,
const Instruction* instr)
@@ -2125,13 +2160,38 @@ static void emitUavAtomicOp(
IlcSpvId src1Id = loadSource(compiler, &instr->srcs[1], COMP_MASK_XYZW, vecTypeId);
IlcSpvId valueId = emitVectorTrim(compiler, src1Id, vecTypeId, COMP_INDEX_X, 1);
- if (instr->opcode == IL_OP_UAV_ADD || instr->opcode == IL_OP_UAV_READ_ADD) {
- readId = ilcSpvPutAtomicOp(compiler->module, SpvOpAtomicIAdd, resource->texelTypeId,
- texelPtrId, scopeId, semanticsId, valueId);
- } else {
+ IlcSpvWord operation;
+ switch (instr->opcode) {
+ case IL_OP_UAV_ADD:
+ case IL_OP_UAV_READ_ADD:
+ operation = SpvOpAtomicIAdd;
+ break;
+ case IL_OP_UAV_MAX:
+ case IL_OP_UAV_READ_MAX:
+ operation = SpvOpAtomicSMax;
+ break;
+ case IL_OP_UAV_MIN:
+ case IL_OP_UAV_READ_MIN:
+ operation = SpvOpAtomicSMin;
+ break;
+ case IL_OP_UAV_OR:
+ case IL_OP_UAV_READ_OR:
+ operation = SpvOpAtomicOr;
+ break;
+ case IL_OP_UAV_AND:
+ case IL_OP_UAV_READ_AND:
+ operation = SpvOpAtomicAnd;
+ break;
+ case IL_OP_UAV_XOR:
+ case IL_OP_UAV_READ_XOR:
+ operation = SpvOpAtomicXor;
+ break;
+ default:
assert(false);
+ break;
}
-
+ readId = ilcSpvPutAtomicOp(compiler->module, operation, resource->texelTypeId,
+ texelPtrId, scopeId, semanticsId, valueId);
if (instr->dstCount > 0) {
IlcSpvId resId = emitVectorGrow(compiler, readId, resource->texelTypeId, 1);
storeDestination(compiler, &instr->dsts[0], resId, vecTypeId);
@@ -2202,6 +2262,65 @@ static void emitStructuredSrvLoad(
storeDestination(compiler, dst, loadId, compiler->float4Id);
}
+static void emitRawSrvLoad(
+ IlcCompiler* compiler,
+ const Instruction* instr)
+{
+ uint8_t ilResourceId = GET_BITS(instr->control, 0, 7);
+ bool indexedResourceId = GET_BIT(instr->control, 12);
+
+ if (indexedResourceId) {
+ LOGW("unhandled indexed resource ID\n");
+ }
+
+ const IlcResource* resource = findResource(compiler, ilResourceId);
+ const Destination* dst = &instr->dsts[0];
+
+ if (resource == NULL) {
+ LOGE("resource %d not found\n", ilResourceId);
+ return;
+ }
+
+ IlcSpvId srcId = loadSource(compiler, &instr->srcs[0], COMP_MASK_XYZW, compiler->int4Id);
+ IlcSpvId byteAddrId = emitVectorTrim(compiler, srcId, compiler->int4Id, COMP_INDEX_X, 1);
+
+ const IlcSpvId divIds[] = {
+ byteAddrId, ilcSpvPutConstant(compiler->module, compiler->intId, 4)
+ };
+ IlcSpvId wordAddrId = ilcSpvPutAlu(compiler->module, SpvOpSDiv, compiler->intId, 2, divIds);
+
+ // Read up to four components based on the destination mask
+ IlcSpvId zeroId = ilcSpvPutConstant(compiler->module, compiler->intId, ZERO_LITERAL);
+ IlcSpvId oneId = ilcSpvPutConstant(compiler->module, compiler->intId, 1);
+ IlcSpvId ptrTypeId = ilcSpvPutPointerType(compiler->module, SpvStorageClassStorageBuffer,
+ resource->texelTypeId);
+ IlcSpvId fZeroId = ilcSpvPutConstant(compiler->module, compiler->floatId, ZERO_LITERAL);
+ IlcSpvWord constituents[] = { fZeroId, fZeroId, fZeroId, fZeroId };
+
+ for (unsigned i = 0; i < 4; i++) {
+ if (dst->component[i] == IL_MODCOMP_NOWRITE) {
+ break;
+ }
+
+ if (i > 0) {
+ // Increment address
+ const IlcSpvId incrementIds[] = { wordAddrId, oneId };
+ wordAddrId = ilcSpvPutAlu(compiler->module, SpvOpIAdd, compiler->intId,
+ 2, incrementIds);
+ }
+
+ const IlcSpvId indexIds[] = { zeroId, wordAddrId };
+ IlcSpvId ptrId = ilcSpvPutAccessChain(compiler->module, ptrTypeId, resource->id,
+ 2, indexIds);
+ constituents[i] = ilcSpvPutLoad(compiler->module, resource->texelTypeId, ptrId);
+ }
+
+ IlcSpvId loadId = ilcSpvPutCompositeConstruct(compiler->module, compiler->float4Id,
+ 4, constituents);
+ storeDestination(compiler, dst, loadId, compiler->float4Id);
+}
+
+
static void emitImplicitInput(
IlcCompiler* compiler,
SpvBuiltIn spvBuiltIn,
@@ -2407,6 +2526,16 @@ static void emitInstr(
break;
case IL_OP_UAV_ADD:
case IL_OP_UAV_READ_ADD:
+ case IL_OP_UAV_MAX:
+ case IL_OP_UAV_READ_MAX:
+ case IL_OP_UAV_MIN:
+ case IL_OP_UAV_READ_MIN:
+ case IL_OP_UAV_AND:
+ case IL_OP_UAV_READ_AND:
+ case IL_OP_UAV_OR:
+ case IL_OP_UAV_READ_OR:
+ case IL_OP_UAV_XOR:
+ case IL_OP_UAV_READ_XOR:
emitUavAtomicOp(compiler, instr);
break;
case IL_OP_DCL_STRUCT_SRV:
@@ -2415,6 +2544,12 @@ static void emitInstr(
case IL_OP_SRV_STRUCT_LOAD:
emitStructuredSrvLoad(compiler, instr);
break;
+ case IL_OP_DCL_RAW_SRV:
+ emitRawSrv(compiler, instr);
+ break;
+ case IL_OP_SRV_RAW_LOAD:
+ emitRawSrvLoad(compiler, instr);
+ break;
case IL_DCL_STRUCT_LDS:
emitStructuredLds(compiler, instr);
break;
diff --git a/src/amdilc/amdilc_decoder.c b/src/amdilc/amdilc_decoder.c
index 309fb1e..10ff8c4 100644
--- a/src/amdilc/amdilc_decoder.c
+++ b/src/amdilc/amdilc_decoder.c
@@ -99,8 +99,20 @@ static const OpcodeInfo mOpcodeInfos[IL_OP_LAST] = {
[IL_OP_UAV_STORE] = { IL_OP_UAV_STORE, 0, 2, 0, false },
[IL_OP_UAV_ADD] = { IL_OP_UAV_ADD, 0, 2, 0, false },
[IL_OP_UAV_READ_ADD] = { IL_OP_UAV_READ_ADD, 1, 2, 0, false },
+ [IL_OP_UAV_MAX] = { IL_OP_UAV_MAX, 0, 2, 0, false },
+ [IL_OP_UAV_READ_MAX] = { IL_OP_UAV_READ_MAX, 1, 2, 0, false },
+ [IL_OP_UAV_MIN] = { IL_OP_UAV_MIN, 0, 2, 0, false },
+ [IL_OP_UAV_READ_MIN] = { IL_OP_UAV_READ_MIN, 1, 2, 0, false },
+ [IL_OP_UAV_AND] = { IL_OP_UAV_AND, 0, 2, 0, false },
+ [IL_OP_UAV_READ_AND] = { IL_OP_UAV_READ_AND, 1, 2, 0, false },
+ [IL_OP_UAV_OR] = { IL_OP_UAV_OR, 0, 2, 0, false },
+ [IL_OP_UAV_READ_OR] = { IL_OP_UAV_READ_OR, 1, 2, 0, false },
+ [IL_OP_UAV_XOR] = { IL_OP_UAV_XOR, 0, 2, 0, false },
+ [IL_OP_UAV_READ_XOR] = { IL_OP_UAV_READ_XOR, 1, 2, 0, false },
[IL_OP_DCL_STRUCT_SRV] = { IL_OP_DCL_STRUCT_SRV, 0, 0, 1, false },
[IL_OP_SRV_STRUCT_LOAD] = { IL_OP_SRV_STRUCT_LOAD, 1, 1, 0, false },
+ [IL_OP_DCL_RAW_SRV] = { IL_OP_DCL_RAW_SRV, 0, 0, 0, false },
+ [IL_OP_SRV_RAW_LOAD] = { IL_OP_SRV_RAW_LOAD, 1, 1, 0, false },
[IL_DCL_STRUCT_LDS] = { IL_DCL_STRUCT_LDS, 0, 0, 2, false },
[IL_OP_U_BIT_EXTRACT] = { IL_OP_U_BIT_EXTRACT, 1, 3, 0, false },
[IL_OP_U_BIT_INSERT] = { IL_OP_U_BIT_INSERT, 1, 4, 0, false },
diff --git a/src/amdilc/amdilc_dump.c b/src/amdilc/amdilc_dump.c
index 6d2d173..28827ce 100644
--- a/src/amdilc/amdilc_dump.c
+++ b/src/amdilc/amdilc_dump.c
@@ -721,6 +721,36 @@ static void dumpInstruction(
case IL_OP_UAV_READ_ADD:
fprintf(file, "uav_read_add_id(%u)", GET_BITS(instr->control, 0, 13));
break;
+ case IL_OP_UAV_MAX:
+ fprintf(file, "uav_max_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_READ_MAX:
+ fprintf(file, "uav_read_max_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_MIN:
+ fprintf(file, "uav_min_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_READ_MIN:
+ fprintf(file, "uav_read_min_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_OR:
+ fprintf(file, "uav_or_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_READ_OR:
+ fprintf(file, "uav_read_or_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_AND:
+ fprintf(file, "uav_and_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_READ_AND:
+ fprintf(file, "uav_read_and_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_XOR:
+ fprintf(file, "uav_xor_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_UAV_READ_XOR:
+ fprintf(file, "uav_read_xor_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
case IL_OP_DCL_STRUCT_SRV:
fprintf(file, "dcl_struct_srv_id(%u) %u",
GET_BITS(instr->control, 0, 13), instr->extras[0]);
@@ -729,6 +759,13 @@ static void dumpInstruction(
fprintf(file, "srv_struct_load%s_id(%u)",
GET_BIT(instr->control, 12) ? "_ext" : "", GET_BITS(instr->control, 0, 7));
break;
+ case IL_OP_DCL_RAW_SRV:
+ fprintf(file, "dcl_raw_srv_id(%u)", GET_BITS(instr->control, 0, 13));
+ break;
+ case IL_OP_SRV_RAW_LOAD:
+ fprintf(file, "srv_raw_load%s_id(%u)",
+ GET_BIT(instr->control, 12) ? "_ext" : "", GET_BITS(instr->control, 0, 7));
+ break;
case IL_DCL_STRUCT_LDS:
fprintf(file, "dcl_struct_lds_id(%u) %u, %u",
GET_BITS(instr->control, 0, 13), instr->extras[0], instr->extras[1]); |
The instruction errors have disappeared, but the game still crashes: === GRVK 0.4.0 === |
Now that's weird, especially considering that there are no longer missing instructions in the log... |
I'm getting these errors while launching bf4 (also I'm getting graphical errors obviously), also I've resolved AMD IL opcodes myself:
|
ok, so I've implemented some changes regarding some of these instructions: diff --git a/src/amdilc/amdilc_compiler.c b/src/amdilc/amdilc_compiler.c
index a150d26..5d042d8 100644
--- a/src/amdilc/amdilc_compiler.c
+++ b/src/amdilc/amdilc_compiler.c
@@ -48,6 +48,7 @@ typedef struct {
uint32_t ilId;
uint8_t ilType;
IlcSpvId strideId;
+ bool structured;
} IlcResource;
typedef struct {
@@ -1144,6 +1145,7 @@ static void emitResource(
.ilId = id,
.ilType = type,
.strideId = 0,
+ .structured = false,
};
addResource(compiler, &resource);
@@ -1210,6 +1212,7 @@ static void emitTypedUav(
.ilId = id,
.ilType = type,
.strideId = 0,
+ .structured = false,
};
addResource(compiler, &resource);
@@ -1219,6 +1222,7 @@ static void emitUav(
IlcCompiler* compiler,
const Instruction* instr)
{
+ bool isStructured = instr->opcode == IL_OP_DCL_STRUCT_UAV;
uint16_t id = GET_BITS(instr->control, 0, 13);
IlcSpvId arrayId = ilcSpvPutRuntimeArrayType(compiler->module, compiler->floatId, true);
@@ -1234,7 +1238,7 @@ static void emitUav(
ilcSpvPutDecoration(compiler->module, structId, SpvDecorationBlock, 0, NULL);
ilcSpvPutMemberDecoration(compiler->module, structId, 0, SpvDecorationOffset, 1, &memberOffset);
- ilcSpvPutName(compiler->module, arrayId, "structUav");
+ ilcSpvPutName(compiler->module, arrayId, isStructured ? "structUav" : "rawUav");
emitBinding(compiler, resourceId, ILC_BASE_RESOURCE_ID + id, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
const IlcResource resource = {
@@ -1244,7 +1248,9 @@ static void emitUav(
.texelTypeId = compiler->floatId,
.ilId = id,
.ilType = IL_USAGE_PIXTEX_UNKNOWN,
- .strideId = instr->extras[0],
+ .strideId = ilcSpvPutConstant(compiler->module, compiler->intId,
+ isStructured ? instr->extras[0] : 4),
+ .structured = isStructured,
};
addResource(compiler, &resource);
@@ -1283,6 +1289,35 @@ static void emitSrv(
.ilType = IL_USAGE_PIXTEX_UNKNOWN,
.strideId = ilcSpvPutConstant(compiler->module, compiler->intId,
isStructured ? instr->extras[0] : 4),
+ .structured = isStructured,
+ };
+
+ addResource(compiler, &resource);
+}
+
+static void emitLds(
+ IlcCompiler* compiler,
+ const Instruction* instr)
+{
+ uint16_t id = GET_BITS(instr->control, 0, 13);
+ unsigned length = instr->extras[0];
+
+ IlcSpvId lengthId = ilcSpvPutConstant(compiler->module, compiler->uintId, length);
+ IlcSpvId arrayId = ilcSpvPutArrayType(compiler->module, compiler->uintId, lengthId);
+ IlcSpvId pArrayId = ilcSpvPutPointerType(compiler->module, SpvStorageClassWorkgroup, arrayId);
+ IlcSpvId resourceId = ilcSpvPutVariable(compiler->module, pArrayId, SpvStorageClassWorkgroup);
+
+ ilcSpvPutName(compiler->module, arrayId, "rawLds");
+
+ const IlcResource resource = {
+ .resType = RES_TYPE_LDS,
+ .id = resourceId,
+ .typeId = arrayId,
+ .texelTypeId = compiler->uintId,
+ .ilId = id,
+ .ilType = IL_USAGE_PIXTEX_UNKNOWN,
+ .strideId = ilcSpvPutConstant(compiler->module, compiler->intId, 4),
+ .structured = false,
};
addResource(compiler, &resource);
@@ -1311,6 +1346,7 @@ static void emitStructuredLds(
.ilId = id,
.ilType = IL_USAGE_PIXTEX_UNKNOWN,
.strideId = ilcSpvPutConstant(compiler->module, compiler->intId, stride),
+ .structured = true,
};
addResource(compiler, &resource);
@@ -2450,30 +2486,169 @@ static void emitUavStore(
ilcSpvPutImageWrite(compiler->module, resourceId, addressId, elementId);
}
-static void emitUavAtomicOp(
+static void emitStructUavStore(
IlcCompiler* compiler,
const Instruction* instr)
{
uint8_t ilResourceId = GET_BITS(instr->control, 0, 14);
const IlcResource* resource = findResource(compiler, RES_TYPE_GENERIC, ilResourceId);
+ const Destination* dst = &instr->dsts[0];
if (resource == NULL) {
LOGE("resource %d not found\n", ilResourceId);
return;
}
- IlcSpvId vecTypeId = ilcSpvPutVectorType(compiler->module, resource->texelTypeId, 4);
- IlcSpvId pointerTypeId = ilcSpvPutPointerType(compiler->module, SpvStorageClassImage,
+ //IlcSpvId resourceId = ilcSpvPutLoad(compiler->module, resource->typeId, resource->id);
+ IlcSpvId srcId = loadSource(compiler, &instr->srcs[0], COMP_MASK_XYZW, compiler->int4Id);
+ IlcSpvId indexId = emitVectorTrim(compiler, srcId, compiler->int4Id, COMP_INDEX_X, 1);
+ IlcSpvId offsetId = emitVectorTrim(compiler, srcId, compiler->int4Id, COMP_INDEX_Y, 1);
+
+ IlcSpvId elementTypeId = ilcSpvPutVectorType(compiler->module, resource->texelTypeId, 4);
+ IlcSpvId elementId = loadSource(compiler, &instr->srcs[1], COMP_MASK_XYZW, elementTypeId);
+
+ // addr = (index * stride + offset) / 4
+ const IlcSpvId mulIds[] = { indexId, resource->strideId };
+ IlcSpvId baseId = ilcSpvPutAlu(compiler->module, SpvOpIMul, compiler->intId, 2, mulIds);
+ const IlcSpvId addIds[] = { baseId, offsetId };
+ IlcSpvId byteAddrId = ilcSpvPutAlu(compiler->module, SpvOpIAdd, compiler->intId, 2, addIds);
+ const IlcSpvId divIds[] = {
+ byteAddrId, ilcSpvPutConstant(compiler->module, compiler->intId, 4)
+ };
+ IlcSpvId wordAddrId = ilcSpvPutAlu(compiler->module, SpvOpSDiv, compiler->intId, 2, divIds);
+
+ IlcSpvId oneId = ilcSpvPutConstant(compiler->module, compiler->intId, 1);
+ IlcSpvId ptrTypeId = ilcSpvPutPointerType(compiler->module, SpvStorageClassStorageBuffer,
+ resource->texelTypeId);
+ // Write up to four components based on the destination mask
+ for (unsigned i = 0; i < 4; i++) {
+ if (dst->component[i] == IL_MODCOMP_NOWRITE) {
+ break;
+ }
+
+ if (i > 0) {
+ // Increment address
+ const IlcSpvId incrementIds[] = { wordAddrId, oneId };
+ wordAddrId = ilcSpvPutAlu(compiler->module, SpvOpIAdd, compiler->intId,
+ 2, incrementIds);
+ }
+
+ IlcSpvId ptrId = ilcSpvPutAccessChain(compiler->module, ptrTypeId, resource->id,
+ 1, &wordAddrId);
+ IlcSpvId componentId = emitVectorTrim(compiler, elementId, elementTypeId, i, 1);
+ ilcSpvPutStore(compiler->module, ptrId, componentId);
+ }
+}
+
+static void emitLdsAtomicOp(
+ IlcCompiler* compiler,
+ const Instruction* instr)
+{
+ uint8_t ilResourceId = GET_BITS(instr->control, 0, 4);
+
+ const IlcResource* resource = findResource(compiler, RES_TYPE_LDS, ilResourceId);
+
+ if (resource == NULL) {
+ LOGE("resource %d not found\n", ilResourceId);
+ return;
+ }
+
+ IlcSpvId pointerTypeId = ilcSpvPutPointerType(compiler->module, SpvStorageClassWorkgroup,
resource->texelTypeId);
IlcSpvId addressId = loadSource(compiler, &instr->srcs[0], COMP_MASK_XYZW, compiler->int4Id);
- IlcSpvId trimAddressId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_X,
- getResourceDimensionCount(resource->ilType));
- IlcSpvId zeroId = ilcSpvPutConstant(compiler->module, compiler->intId, ZERO_LITERAL);
- IlcSpvId texelPtrId = ilcSpvPutImageTexelPointer(compiler->module, pointerTypeId, resource->id,
- trimAddressId, zeroId);
+ IlcSpvId byteAddrId;
+ if (resource->structured) {
+ IlcSpvId indexId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_X, 1);
+ IlcSpvId offsetId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_Y, 1);
+ // addr = (index * stride + offset) / 4
+ const IlcSpvId mulIds[] = { indexId, resource->strideId };
+ IlcSpvId baseId = ilcSpvPutAlu(compiler->module, SpvOpIMul, compiler->intId, 2, mulIds);
+ const IlcSpvId addIds[] = { baseId, offsetId };
+ byteAddrId = ilcSpvPutAlu(compiler->module, SpvOpIAdd, compiler->intId, 2, addIds);
+ } else {
+ byteAddrId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_X, 1);
+ }
+ const IlcSpvId divIds[] = {
+ byteAddrId, ilcSpvPutConstant(compiler->module, compiler->intId, 4)
+ };
+ IlcSpvId wordAddrId = ilcSpvPutAlu(compiler->module, SpvOpSDiv, compiler->intId, 2, divIds);
+ IlcSpvId bufferPtrId = ilcSpvPutAccessChain(compiler->module, pointerTypeId, resource->id,
+ 1, &wordAddrId);
+ IlcSpvId readId = 0;
+ IlcSpvId vecTypeId = ilcSpvPutVectorType(compiler->module, resource->texelTypeId, 4);
+ IlcSpvId scopeId = ilcSpvPutConstant(compiler->module, compiler->intId, SpvScopeDevice);
+ IlcSpvId semanticsId = ilcSpvPutConstant(compiler->module, compiler->intId,
+ SpvMemorySemanticsAcquireReleaseMask |
+ SpvMemorySemanticsImageMemoryMask);
+ IlcSpvId src1Id = loadSource(compiler, &instr->srcs[1], COMP_MASK_XYZW, vecTypeId);
+ IlcSpvId valueId = emitVectorTrim(compiler, src1Id, vecTypeId, COMP_INDEX_X, 1);
+
+ if (instr->opcode == IL_OP_LDS_ADD || instr->opcode == IL_OP_LDS_READ_ADD) {
+ readId = ilcSpvPutAtomicOp(compiler->module, SpvOpAtomicIAdd, resource->texelTypeId,
+ bufferPtrId, scopeId, semanticsId, valueId);
+ } else if (instr->opcode == IL_OP_LDS_UMAX || instr->opcode == IL_OP_LDS_READ_UMAX) {
+ readId = ilcSpvPutAtomicOp(compiler->module, SpvOpAtomicUMax, resource->texelTypeId,
+ bufferPtrId, scopeId, semanticsId, valueId);
+ } else {
+ assert(false);
+ }
+ if (instr->dstCount > 0) {
+ IlcSpvId resId = emitVectorGrow(compiler, readId, resource->texelTypeId, 1);
+ storeDestination(compiler, &instr->dsts[0], resId, vecTypeId);
+ }
+}
+
+static void emitUavAtomicOp(
+ IlcCompiler* compiler,
+ const Instruction* instr)
+{
+ uint8_t ilResourceId = GET_BITS(instr->control, 0, 14);
+
+ const IlcResource* resource = findResource(compiler, RES_TYPE_GENERIC, ilResourceId);
+
+ if (resource == NULL) {
+ LOGE("resource %d not found\n", ilResourceId);
+ return;
+ }
+
+ IlcSpvId texelPtrId ;
+
+ if (resource->strideId == 0) {
+ IlcSpvId pointerTypeId = ilcSpvPutPointerType(compiler->module, SpvStorageClassImage,
+ resource->texelTypeId);
+ IlcSpvId addressId = loadSource(compiler, &instr->srcs[0], COMP_MASK_XYZW, compiler->int4Id);
+ IlcSpvId trimAddressId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_X,
+ getResourceDimensionCount(resource->ilType));
+ IlcSpvId zeroId = ilcSpvPutConstant(compiler->module, compiler->intId, ZERO_LITERAL);
+ texelPtrId = ilcSpvPutImageTexelPointer(compiler->module, pointerTypeId, resource->id,
+ trimAddressId, zeroId);
+ } else {
+ IlcSpvId pointerTypeId = ilcSpvPutPointerType(compiler->module, SpvStorageClassStorageBuffer,
+ resource->texelTypeId);
+ IlcSpvId addressId = loadSource(compiler, &instr->srcs[0], COMP_MASK_XYZW, compiler->int4Id);
+ IlcSpvId byteAddrId;
+ if (resource->structured) {
+ IlcSpvId indexId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_X, 1);
+ IlcSpvId offsetId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_Y, 1);
+ // addr = (index * stride + offset) / 4
+ const IlcSpvId mulIds[] = { indexId, resource->strideId };
+ IlcSpvId baseId = ilcSpvPutAlu(compiler->module, SpvOpIMul, compiler->intId, 2, mulIds);
+ const IlcSpvId addIds[] = { baseId, offsetId };
+ byteAddrId = ilcSpvPutAlu(compiler->module, SpvOpIAdd, compiler->intId, 2, addIds);
+ } else {
+ byteAddrId = emitVectorTrim(compiler, addressId, compiler->int4Id, COMP_INDEX_X, 1);
+ }
+ const IlcSpvId divIds[] = {
+ byteAddrId, ilcSpvPutConstant(compiler->module, compiler->intId, 4)
+ };
+ IlcSpvId wordAddrId = ilcSpvPutAlu(compiler->module, SpvOpSDiv, compiler->intId, 2, divIds);
+ texelPtrId = ilcSpvPutAccessChain(compiler->module, pointerTypeId, resource->id,
+ 1, &wordAddrId);
+ }
IlcSpvId readId = 0;
+ IlcSpvId vecTypeId = ilcSpvPutVectorType(compiler->module, resource->texelTypeId, 4);
IlcSpvId scopeId = ilcSpvPutConstant(compiler->module, compiler->intId, SpvScopeDevice);
IlcSpvId semanticsId = ilcSpvPutConstant(compiler->module, compiler->intId,
SpvMemorySemanticsAcquireReleaseMask |
@@ -2484,6 +2659,9 @@ static void emitUavAtomicOp(
if (instr->opcode == IL_OP_UAV_ADD || instr->opcode == IL_OP_UAV_READ_ADD) {
readId = ilcSpvPutAtomicOp(compiler->module, SpvOpAtomicIAdd, resource->texelTypeId,
texelPtrId, scopeId, semanticsId, valueId);
+ } else if (instr->opcode == IL_OP_UAV_UMAX || instr->opcode == IL_OP_UAV_READ_UMAX) {
+ readId = ilcSpvPutAtomicOp(compiler->module, SpvOpAtomicUMax, resource->texelTypeId,
+ texelPtrId, scopeId, semanticsId, valueId);
} else {
assert(false);
}
@@ -2777,7 +2955,9 @@ static void emitInstr(
case IL_OP_DCL_TYPED_UAV:
emitTypedUav(compiler, instr);
break;
+ case IL_OP_DCL_STRUCT_UAV:
case IL_OP_DCL_TYPELESS_UAV:
+ case IL_OP_DCL_RAW_UAV:
emitUav(compiler, instr);
break;
case IL_OP_UAV_LOAD:
@@ -2786,10 +2966,21 @@ static void emitInstr(
case IL_OP_UAV_STORE:
emitUavStore(compiler, instr);
break;
+ case IL_OP_UAV_STRUCT_STORE:
+ emitStructUavStore(compiler, instr);
+ break;
case IL_OP_UAV_ADD:
case IL_OP_UAV_READ_ADD:
+ case IL_OP_UAV_UMAX:
+ case IL_OP_UAV_READ_UMAX:
emitUavAtomicOp(compiler, instr);
break;
+ case IL_OP_LDS_ADD:
+ case IL_OP_LDS_READ_ADD:
+ case IL_OP_LDS_UMAX:
+ case IL_OP_LDS_READ_UMAX:
+ emitLdsAtomicOp(compiler, instr);
+ break;
case IL_OP_DCL_RAW_SRV:
case IL_OP_DCL_STRUCT_SRV:
emitSrv(compiler, instr);
@@ -2800,6 +2991,9 @@ static void emitInstr(
case IL_DCL_STRUCT_LDS:
emitStructuredLds(compiler, instr);
break;
+ case IL_DCL_LDS:
+ emitLds(compiler, instr);
+ break;
case IL_DCL_GLOBAL_FLAGS:
emitGlobalFlags(compiler, instr);
break; But some changes must be made:
|
Tried out 0.5.0 on a Radeon 5700xt w/ Ryzen 1700x in Windows 10. For some reason, the game would only run in exclusive fullscreen mode. If I try to run in borderless I get a crash to desktop. Also, I noticed v-sync is broken. Beyond that, the only other bug I noticed is that some post-effects seem to break the graphics. Like if I go out of bounds or underwater, some or all parts of the world go black. As far as performance goes, compared to DX11 it looks like CPU is 20% slower but GPU seems about 10% faster, just based on a quick look at the game's built in performance graph. The settings I use DX11 run a tightrope between GPU and CPU though, so on some maps I would be GPU limited, others CPU limited. So with GRVK that's become completely CPU limited (unless there is some memory bandwidth bottleneck that the in-game performance graph wouldn't show). By the way, Frostbite Engine's peformance graph is super useful to analyze CPU/GPU performance. You can enable it in the dev console with Also, I noticed no mantle cache was created in Documents/Battlefield 4/cache. |
@bazookaben Thanks for the feedback, it's a small miracle that the game is running at all, looking at the logs some image format is not supported. You're correct that Vsync is not implemented right now, I kinda forgot about it because I'm using Freesync. I don't expect the native pipeline cache to be ever implemented, because Mantle assumes that the pipeline can be compiled on the spot, which isn't the case with the current state of Vulkan. I'll check out the performance graph for sure! |
@niobium93 check that the DLLs are in the correct place, and upload |
They are right next to bf4.exe |
@niobium93 what's your setup like? are you using BF4 from Steam? |
I'm on wine-tkg 6.22.r11.g61c3c024-326 and mesa-git-22.0.0_devel.147797.92d84f189c7. DXVK v1.9.2-62-gc13395db is also present. No Steam. |
Games status:
Details:
BF4 and Dragon Age Inquisiton Error Message (both the same)
Here's BF 4 log:
=== GRVK 0.3.0 ===
I/grInitAndEnumerateGpus: app "Battlefield" (01000000), engine "Frostbite" (00C00000), api 00018000
W/grInitAndEnumerateGpus: unhandled alloc callbacks
W/grGetExtensionSupport: STUB
W/grGetExtensionSupport: STUB
Here's DAI log:
=== GRVK 0.3.0 ===
I/grInitAndEnumerateGpus: app "DragonAgeInquisition" (01000000), engine "Frostbite" (00FDE001), api 00018000
W/grInitAndEnumerateGpus: unhandled alloc callbacks
W/grGetExtensionSupport: STUB
W/grGetExtensionSupport: STUB
The text was updated successfully, but these errors were encountered: