@@ -18,6 +18,19 @@ static const GUID IID_MSAATexture = {0xe2728d94,0x9fdd,0x40d0,{0x87,0xa8,0x09,0x
18
18
static const GUID IID_AlphaToCoverage = {0xe2728d95 ,0x9fdd ,0x40d0 ,{0x87 ,0xa8 ,0x09 ,0xb6 ,0x2d ,0xf3 ,0x14 ,0x9a }};
19
19
static const GUID IID_OriginalShader = {0xe2728d96 ,0x9fdd ,0x40d0 ,{0x87 ,0xa8 ,0x09 ,0xb6 ,0x2d ,0xf3 ,0x14 ,0x9a }};
20
20
21
+ enum class MSAACandidateState : UINT {
22
+ None = 0 ,
23
+ Possible, // Created SRV, not shadow buffer
24
+ Probable, // Likely to be the main RV
25
+ Dirty, // MSAA texture created, not yet resolved
26
+ Clean, // MSAA texture created, has been resolved
27
+ };
28
+ // Static const versions that we can take pointers to
29
+ static const MSAACandidateState MSAACandidateStatePossible = MSAACandidateState::Possible;
30
+ static const MSAACandidateState MSAACandidateStateProbable = MSAACandidateState::Probable;
31
+ static const MSAACandidateState MSAACandidateStateDirty = MSAACandidateState::Dirty;
32
+ static const MSAACandidateState MSAACandidateStateClean = MSAACandidateState::Clean;
33
+
21
34
struct ATFIX_RESOURCE_INFO {
22
35
D3D11_RESOURCE_DIMENSION Dim;
23
36
DXGI_FORMAT Format;
@@ -290,6 +303,7 @@ ID3D11DepthStencilView* getOrCreateMSAADSV(ID3D11Device* dev, ID3D11DepthStencil
290
303
desc.Format = vdesc.Format ;
291
304
desc.SampleDesc .Count = config.msaaSamples ;
292
305
desc.SampleDesc .Quality = 0 ;
306
+ desc.BindFlags &= ~D3D11_BIND_SHADER_RESOURCE;
293
307
while (desc.SampleDesc .Count > 1 ) {
294
308
UINT quality = 0 ;
295
309
if (SUCCEEDED (dev->CheckMultisampleQualityLevels (desc.Format , desc.SampleDesc .Count , &quality)) && quality > 0 )
@@ -310,12 +324,17 @@ ID3D11DepthStencilView* getOrCreateMSAADSV(ID3D11Device* dev, ID3D11DepthStencil
310
324
311
325
void resolveIfMSAA (ID3D11DeviceContext* ctx, ID3D11Resource* res) {
312
326
if (ID3D11Resource* msaa = getMSAATexture (res)) {
313
- ID3D11Texture2D* tex;
314
- D3D11_TEXTURE2D_DESC desc;
315
- msaa->QueryInterface (IID_PPV_ARGS (&tex));
316
- tex->GetDesc (&desc);
317
- tex->Release ();
318
- ctx->ResolveSubresource (res, 0 , msaa, 0 , desc.Format );
327
+ MSAACandidateState state = MSAACandidateState::None;
328
+ UINT size = sizeof (state);
329
+ if (SUCCEEDED (res->GetPrivateData (IID_MSAACandidate, &size, &state)) && state == MSAACandidateState::Dirty) {
330
+ ID3D11Texture2D* tex;
331
+ D3D11_TEXTURE2D_DESC desc;
332
+ msaa->QueryInterface (IID_PPV_ARGS (&tex));
333
+ tex->GetDesc (&desc);
334
+ tex->Release ();
335
+ ctx->ResolveSubresource (res, 0 , msaa, 0 , desc.Format );
336
+ msaa->SetPrivateData (IID_MSAACandidate, sizeof (state), &MSAACandidateStateClean);
337
+ }
319
338
msaa->Release ();
320
339
}
321
340
}
@@ -837,6 +856,13 @@ class DeviceWrapper final : public ID3D11Device, IDXGIDevice1 {
837
856
desc.Format = DXGI_FORMAT_R16_UNORM;
838
857
pDesc = &desc;
839
858
}
859
+ if (config.msaaSamples && tdesc.Format == DXGI_FORMAT_B8G8R8A8_TYPELESS && !(isPowerOfTwo (tdesc.Width ) && !isPowerOfTwo (tdesc.Height ))) {
860
+ // Not shadow texture
861
+ MSAACandidateState state = MSAACandidateState::None;
862
+ UINT size = sizeof (state);
863
+ if (FAILED (tex->GetPrivateData (IID_MSAACandidate, &size, &state)) || state == MSAACandidateState::None)
864
+ tex->SetPrivateData (IID_MSAACandidate, sizeof (state), &MSAACandidateStatePossible);
865
+ }
840
866
tex->Release ();
841
867
}
842
868
return dev->CreateRenderTargetView (pResource, pDesc, ppRTView);
@@ -967,6 +993,7 @@ class DeviceWrapper final : public ID3D11Device, IDXGIDevice1 {
967
993
968
994
class ContextWrapper final : public ID3D11DeviceContext {
969
995
LONG refcnt;
996
+ UINT numIndexedDraws = 0 ;
970
997
ID3D11DeviceContext* ctx;
971
998
ID3D11BlendState* alphaToCoverageBlend = nullptr ;
972
999
ID3D11BlendState* requestedBlend = nullptr ;
@@ -1027,10 +1054,8 @@ class ContextWrapper final : public ID3D11DeviceContext {
1027
1054
1028
1055
// ID3D11DeviceContext
1029
1056
void VSSetConstantBuffers (UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const * ppConstantBuffers) override { ctx->VSSetConstantBuffers (StartSlot, NumBuffers, ppConstantBuffers); }
1030
- void PSSetShaderResources (UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView* const * ppShaderResourceViews) override { ctx->PSSetShaderResources (StartSlot, NumViews, ppShaderResourceViews); }
1031
1057
void PSSetSamplers (UINT StartSlot, UINT NumSamplers, ID3D11SamplerState* const * ppSamplers) override { ctx->PSSetSamplers (StartSlot, NumSamplers, ppSamplers); }
1032
1058
void VSSetShader (ID3D11VertexShader* pVertexShader, ID3D11ClassInstance* const * ppClassInstances, UINT NumClassInstances) override { ctx->VSSetShader (pVertexShader, ppClassInstances, NumClassInstances); }
1033
- void DrawIndexed (UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation) override { ctx->DrawIndexed (IndexCount, StartIndexLocation, BaseVertexLocation); }
1034
1059
void Draw (UINT VertexCount, UINT StartVertexLocation) override { ctx->Draw (VertexCount, StartVertexLocation); }
1035
1060
HRESULT Map (ID3D11Resource* pResource, UINT Subresource, D3D11_MAP MapType, UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) override { return ctx->Map (pResource, Subresource, MapType, MapFlags, pMappedResource); }
1036
1061
void Unmap (ID3D11Resource* pResource, UINT Subresource) override { ctx->Unmap (pResource, Subresource); }
@@ -1122,6 +1147,23 @@ class ContextWrapper final : public ID3D11DeviceContext {
1122
1147
UINT GetContextFlags () override { return ctx->GetContextFlags (); }
1123
1148
HRESULT FinishCommandList (BOOL RestoreDeferredContextState, ID3D11CommandList** ppCommandList) override { return ctx->FinishCommandList (RestoreDeferredContextState, ppCommandList); }
1124
1149
1150
+ void DrawIndexed (UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation) override {
1151
+ numIndexedDraws++;
1152
+ ctx->DrawIndexed (IndexCount, StartIndexLocation, BaseVertexLocation);
1153
+ }
1154
+
1155
+ void PSSetShaderResources (UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView* const * ppShaderResourceViews) override {
1156
+ for (UINT i = 0 ; i < NumViews; i++) {
1157
+ if (ppShaderResourceViews[i]) {
1158
+ ID3D11Resource* res = nullptr ;
1159
+ ppShaderResourceViews[i]->GetResource (&res);
1160
+ resolveIfMSAA (ctx, res);
1161
+ res->Release ();
1162
+ }
1163
+ }
1164
+ ctx->PSSetShaderResources (StartSlot, NumViews, ppShaderResourceViews);
1165
+ }
1166
+
1125
1167
void PSSetShader (ID3D11PixelShader* pPixelShader, ID3D11ClassInstance* const * ppClassInstances, UINT NumClassInstances) override {
1126
1168
requestedPS = pPixelShader;
1127
1169
ID3D11PixelShader* a2c = nullptr ;
@@ -1258,14 +1300,6 @@ class ContextWrapper final : public ID3D11DeviceContext {
1258
1300
ID3D11Resource* dstShadow = getShadowResource (pDstResource);
1259
1301
1260
1302
resolveIfMSAA (ctx, pSrcResource);
1261
- UINT info;
1262
- UINT size = sizeof (info);
1263
- if (SUCCEEDED (pSrcResource->GetPrivateData (IID_MSAACandidate, &size, &info)) && info == 1 ) {
1264
- // Sophie always copies from its main render target to another one for postprocessing effects
1265
- // Detect that to enable MSAA on it
1266
- info = 2 ;
1267
- pSrcResource->SetPrivateData (IID_MSAACandidate, sizeof (info), &info);
1268
- }
1269
1303
1270
1304
bool needsBaseCopy = true ;
1271
1305
bool needsShadowCopy = true ;
@@ -1325,38 +1359,52 @@ class ContextWrapper final : public ID3D11DeviceContext {
1325
1359
ID3D11DepthStencilView* pDSV) override {
1326
1360
updateRtvShadowResources (ctx);
1327
1361
1328
- ID3D11Resource* base = nullptr ;
1362
+ // Sophie seems to only use indexed draws on the main RT, shadow texture, and a texture where they pre-blend ground tiles
1363
+ // There's usually only 10-20 ground tile draws, so target 64 as a safe number to avoid the ground tile draws
1364
+ if (config.msaaSamples > 1 && numIndexedDraws > 64 ) {
1365
+ ID3D11DepthStencilView* dsv = nullptr ;
1366
+ ID3D11RenderTargetView* rtv = nullptr ;
1367
+ MSAACandidateState state = MSAACandidateState::None;
1368
+ UINT size = sizeof (state);
1369
+ ctx->OMGetRenderTargets (1 , &rtv, &dsv);
1370
+ if (rtv && dsv) {
1371
+ ID3D11Resource* rtvtex = nullptr ;
1372
+ rtv->GetResource (&rtvtex);
1373
+ if (SUCCEEDED (rtvtex->GetPrivateData (IID_MSAACandidate, &size, &state)) && state == MSAACandidateState::Possible) {
1374
+ rtvtex->SetPrivateData (IID_MSAACandidate, sizeof (state), &MSAACandidateStateProbable);
1375
+ log (" Marking texture with " , std::dec, numIndexedDraws, " indexed draws as MSAA target" );
1376
+ }
1377
+ rtvtex->Release ();
1378
+ }
1379
+ if (dsv) dsv->Release ();
1380
+ if (rtv) rtv->Release ();
1381
+ }
1382
+ numIndexedDraws = 0 ;
1383
+
1329
1384
ID3D11RenderTargetView* msaaTex = nullptr ;
1330
1385
ID3D11DepthStencilView* msaaDepth = nullptr ;
1331
1386
1332
1387
if (config.msaaSamples > 1 && ppRTVs && RTVCount == 1 && pDSV) {
1388
+ ID3D11Resource* base = nullptr ;
1333
1389
ppRTVs[0 ]->GetResource (&base);
1334
- UINT info ;
1335
- UINT size = sizeof (info );
1336
- if (SUCCEEDED (base->GetPrivateData (IID_MSAACandidate, &size, &info )) && info == 2 ) {
1390
+ MSAACandidateState state = MSAACandidateState::None ;
1391
+ UINT size = sizeof (state );
1392
+ if (SUCCEEDED (base->GetPrivateData (IID_MSAACandidate, &size, &state )) && state >= MSAACandidateState::Probable ) {
1337
1393
ID3D11Device* dev;
1338
1394
ctx->GetDevice (&dev);
1339
1395
msaaTex = getOrCreateMSAARTV (dev, ppRTVs[0 ]);
1340
1396
msaaDepth = getOrCreateMSAADSV (dev, pDSV);
1341
1397
ppRTVs = &msaaTex;
1342
1398
pDSV = msaaDepth;
1343
1399
dev->Release ();
1400
+ // We're rendering to the texture so it's now dirty
1401
+ base->SetPrivateData (IID_MSAACandidate, sizeof (state), &MSAACandidateStateDirty);
1344
1402
}
1403
+ base->Release ();
1345
1404
}
1346
1405
1347
1406
ctx->OMSetRenderTargets (RTVCount, ppRTVs, pDSV);
1348
1407
1349
- if (base && pDSV && !msaaTex) {
1350
- UINT value = 1 ;
1351
- ID3D11Texture2D* tex;
1352
- D3D11_TEXTURE2D_DESC desc;
1353
- base->QueryInterface (IID_PPV_ARGS (&tex));
1354
- tex->GetDesc (&desc);
1355
- tex->Release ();
1356
- base->SetPrivateData (IID_MSAACandidate, sizeof (value), &value);
1357
- }
1358
-
1359
- if (base) base->Release ();
1360
1408
if (msaaTex) msaaTex->Release ();
1361
1409
if (msaaDepth) msaaDepth->Release ();
1362
1410
}
0 commit comments