1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
21 #include "Statistics.h"
22 #include "MemoryUtil.h"
25 #include "CommonPaths.h"
29 #include "D3DTexture.h"
31 #include "FramebufferManager.h"
32 #include "PixelShaderCache.h"
33 #include "PixelShaderManager.h"
34 #include "VertexShaderManager.h"
35 #include "VertexShaderCache.h"
39 #include "TextureDecoder.h"
40 #include "TextureCache.h"
41 #include "HiresTextures.h"
43 ID3D11BlendState
* efbcopyblendstate
= NULL
;
44 ID3D11RasterizerState
* efbcopyraststate
= NULL
;
45 ID3D11DepthStencilState
* efbcopydepthstate
= NULL
;
46 ID3D11Buffer
* efbcopycbuf
[20] = { NULL
};
48 u8
* TextureCache::temp
= NULL
;
49 TextureCache::TexCache
TextureCache::textures
;
51 extern int frameCount
;
53 #define TEMP_SIZE (2048*2048*4)
54 #define TEXTURE_KILL_THRESHOLD 200
56 void TextureCache::TCacheEntry::Destroy(bool shutdown
)
58 SAFE_RELEASE(texture
);
60 if (!isRenderTarget
&& !shutdown
&& !g_ActiveConfig
.bSafeTextureCache
)
62 u32
*ptr
= (u32
*)g_VideoInitialize
.pGetMemoryPointer(addr
);
63 if (ptr
&& *ptr
== hash
)
68 void TextureCache::Init()
72 temp
= (u8
*)AllocateMemoryPages(TEMP_SIZE
);
73 TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig
.bTexFmtOverlayEnable
, g_ActiveConfig
.bTexFmtOverlayCenter
);
74 HiresTextures::Init(globals
->unique_id
);
76 D3D11_BLEND_DESC blenddesc
;
77 blenddesc
.AlphaToCoverageEnable
= FALSE
;
78 blenddesc
.IndependentBlendEnable
= FALSE
;
79 blenddesc
.RenderTarget
[0].BlendEnable
= FALSE
;
80 blenddesc
.RenderTarget
[0].RenderTargetWriteMask
= D3D11_COLOR_WRITE_ENABLE_ALL
;
81 blenddesc
.RenderTarget
[0].SrcBlend
= D3D11_BLEND_ONE
;
82 blenddesc
.RenderTarget
[0].DestBlend
= D3D11_BLEND_ZERO
;
83 blenddesc
.RenderTarget
[0].BlendOp
= D3D11_BLEND_OP_ADD
;
84 blenddesc
.RenderTarget
[0].SrcBlendAlpha
= D3D11_BLEND_ONE
;
85 blenddesc
.RenderTarget
[0].DestBlendAlpha
= D3D11_BLEND_ZERO
;
86 blenddesc
.RenderTarget
[0].BlendOpAlpha
= D3D11_BLEND_OP_ADD
;
87 hr
= D3D::device
->CreateBlendState(&blenddesc
, &efbcopyblendstate
);
88 CHECK(hr
==S_OK
, "Create blend state for TextureCache::CopyRenderTargetToTexture");
89 D3D::SetDebugObjectName((ID3D11DeviceChild
*)efbcopyblendstate
, "blend state used in TextureCache::CopyRenderTargetToTexture");
91 D3D11_DEPTH_STENCIL_DESC depthdesc
;
92 depthdesc
.DepthEnable
= FALSE
;
93 depthdesc
.DepthWriteMask
= D3D11_DEPTH_WRITE_MASK_ALL
;
94 depthdesc
.DepthFunc
= D3D11_COMPARISON_LESS
;
95 depthdesc
.StencilEnable
= FALSE
;
96 depthdesc
.StencilReadMask
= D3D11_DEFAULT_STENCIL_READ_MASK
;
97 depthdesc
.StencilWriteMask
= D3D11_DEFAULT_STENCIL_WRITE_MASK
;
98 hr
= D3D::device
->CreateDepthStencilState(&depthdesc
, &efbcopydepthstate
);
99 CHECK(hr
==S_OK
, "Create depth state for TextureCache::CopyRenderTargetToTexture");
100 D3D::SetDebugObjectName((ID3D11DeviceChild
*)efbcopydepthstate
, "depth stencil state used in TextureCache::CopyRenderTargetToTexture");
102 D3D11_RASTERIZER_DESC rastdesc
;
103 rastdesc
.CullMode
= D3D11_CULL_NONE
;
104 rastdesc
.FillMode
= D3D11_FILL_SOLID
;
105 rastdesc
.FrontCounterClockwise
= false;
106 rastdesc
.DepthBias
= false;
107 rastdesc
.DepthBiasClamp
= 0;
108 rastdesc
.SlopeScaledDepthBias
= 0;
109 rastdesc
.DepthClipEnable
= false;
110 rastdesc
.ScissorEnable
= false;
111 rastdesc
.MultisampleEnable
= false;
112 rastdesc
.AntialiasedLineEnable
= false;
113 hr
= D3D::device
->CreateRasterizerState(&rastdesc
, &efbcopyraststate
);
114 CHECK(hr
==S_OK
, "Create rasterizer state for TextureCache::CopyRenderTargetToTexture");
115 D3D::SetDebugObjectName((ID3D11DeviceChild
*)efbcopyraststate
, "rasterizer state used in TextureCache::CopyRenderTargetToTexture");
118 void TextureCache::Invalidate(bool shutdown
)
120 for (TexCache::iterator iter
= textures
.begin(); iter
!= textures
.end(); ++iter
)
121 iter
->second
.Destroy(shutdown
);
123 HiresTextures::Shutdown();
126 void TextureCache::Shutdown()
129 FreeMemoryPages(temp
, TEMP_SIZE
);
132 SAFE_RELEASE(efbcopyblendstate
);
133 SAFE_RELEASE(efbcopyraststate
);
134 SAFE_RELEASE(efbcopydepthstate
);
136 for (unsigned int k
= 0; k
< 20;k
++)
137 SAFE_RELEASE(efbcopycbuf
[k
]);
140 void TextureCache::Cleanup()
142 TexCache::iterator iter
= textures
.begin();
143 while (iter
!= textures
.end())
145 if (frameCount
> TEXTURE_KILL_THRESHOLD
+ iter
->second
.frameCount
)
147 iter
->second
.Destroy(false);
148 iter
= textures
.erase(iter
);
157 void TextureCache::InvalidateRange(u32 start_address
, u32 size
)
159 TexCache::iterator iter
= textures
.begin();
160 while (iter
!= textures
.end())
162 if (iter
->second
.IntersectsMemoryRange(start_address
, size
))
164 iter
->second
.Destroy(false);
165 textures
.erase(iter
++);
174 bool TextureCache::TCacheEntry::IntersectsMemoryRange(u32 range_address
, u32 range_size
)
176 if (addr
+ size_in_bytes
< range_address
) return false;
177 if (addr
>= range_address
+ range_size
) return false;
182 // returns the exponent of the smallest power of two which is greater than val
183 unsigned int GetPow2(unsigned int val
)
185 unsigned int ret
= 0;
186 for (;val
;val
>>=1) ret
++;
190 TextureCache::TCacheEntry
* TextureCache::Load(unsigned int stage
, u32 address
, unsigned int width
, unsigned int height
, unsigned int tex_format
, unsigned int tlutaddr
, unsigned int tlutfmt
, bool UseNativeMips
, unsigned int maxlevel
)
192 // notes (about "UNsafe texture cache"):
193 // Have to be removed soon.
194 // But we keep it until the "safe" way became rock solid
195 // pros: it has an unique ID held by the texture data itself (@address) once cached.
196 // cons: it writes this unique ID in the gc RAM <- very dangerous (break MP1) and ugly
198 // notes (about "safe texture cache"):
199 // Metroids text issue (character table):
200 // Same addr, same GX_TF_C4 texture data but different TLUT (hence different outputs).
201 // That's why we have to hash the TLUT too for TLUT tex_format dependent textures (ie. GX_TF_C4, GX_TF_C8, GX_TF_C14X2).
202 // And since the address and tex data don't change, the key index in the cacheEntry map can't be the address but
203 // have to be a real unique ID.
204 // DONE but not satifiying yet -> may break copyEFBToTexture sometimes.
206 // Pokemon Colosseum text issue (plain text):
207 // Use a GX_TF_I4 512x512 text-flush-texture at a const address.
208 // The problem here was just the sparse hash on the texture. This texture is partly overwrited (what is needed only)
209 // so lot's of remaning old text. Thin white chars on black bg too.
211 // TODO: - clean this up when ready to kill old "unsafe texture cache"
212 // - fix the key index situation with CopyRenderTargetToTexture.
213 // Could happen only for GX_TF_C4, GX_TF_C8 and GX_TF_C14X2 fmt.
214 // Wonder if we can't use tex width&height to know if EFB might be copied to it...
215 // raw idea: TOCHECK if addresses are aligned we have few bits left...
220 u8
*ptr
= g_VideoInitialize
.pGetMemoryPointer(address
);
221 unsigned int bsw
= TexDecoder_GetBlockWidthInTexels(tex_format
) - 1; // TexelSizeInNibbles(format)*width*height/16;
222 unsigned int bsh
= TexDecoder_GetBlockHeightInTexels(tex_format
) - 1; // TexelSizeInNibbles(format)*width*height/16;
223 unsigned int bsdepth
= TexDecoder_GetTexelSizeInNibbles(tex_format
);
224 unsigned int expandedWidth
= (width
+ bsw
) & (~bsw
);
225 unsigned int expandedHeight
= (height
+ bsh
) & (~bsh
);
230 u32 FullFormat
= tex_format
;
231 if ((tex_format
== GX_TF_C4
) || (tex_format
== GX_TF_C8
) || (tex_format
== GX_TF_C14X2
))
232 FullFormat
= (tex_format
| (tlutfmt
<< 16));
234 // hires texture loading and texture dumping require accurate hashes
235 if (g_ActiveConfig
.bSafeTextureCache
|| g_ActiveConfig
.bHiresTextures
|| g_ActiveConfig
.bDumpTextures
)
237 texHash
= GetHash64(ptr
,TexDecoder_GetTextureSizeInBytes(expandedWidth
, expandedHeight
, tex_format
),g_ActiveConfig
.iSafeTextureCache_ColorSamples
);
238 if ((tex_format
== GX_TF_C4
) || (tex_format
== GX_TF_C8
) || (tex_format
== GX_TF_C14X2
))
240 // WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up)
241 // tlut size can be up to 32768B (GX_TF_C14X2) but Safer == Slower.
242 // This trick (to change the texID depending on the TLUT addr) is a trick to get around
243 // an issue with metroid prime's fonts, where it has multiple sets of fonts on top of
244 // each other stored in a single texture, and uses the palette to make different characters
245 // visible or invisible. Thus, unless we want to recreate the textures for every drawn character,
246 // we must make sure that texture with different tluts get different IDs.
247 u64 tlutHash
= GetHash64(&texMem
[tlutaddr
], TexDecoder_GetPaletteSize(tex_format
),g_ActiveConfig
.iSafeTextureCache_ColorSamples
);
249 if (g_ActiveConfig
.bSafeTextureCache
)
251 texID
= texID
^ ((u32
)(tlutHash
& 0xFFFFFFFF)) ^ ((u32
)((tlutHash
>> 32) & 0xFFFFFFFF));
254 if (g_ActiveConfig
.bSafeTextureCache
)
255 hash_value
= texHash
;
258 bool skip_texture_create
= false;
259 TexCache::iterator iter
= textures
.find(texID
);
261 if (iter
!= textures
.end())
263 TCacheEntry
&entry
= iter
->second
;
265 if (!g_ActiveConfig
.bSafeTextureCache
)
266 hash_value
= ((u32
*)ptr
)[0];
268 // TODO: Is the (entry.MipLevels == maxlevel) check needed?
269 if (entry
.isRenderTarget
|| ((address
== entry
.addr
) && (hash_value
== entry
.hash
) && FullFormat
== entry
.fmt
&& entry
.MipLevels
== maxlevel
))
271 entry
.frameCount
= frameCount
;
272 D3D::gfxstate
->SetShaderResource(stage
, entry
.texture
->GetSRV());
277 // Let's reload the new texture data into the same texture,
278 // instead of destroying it and having to create a new one.
279 // Might speed up movie playback very, very slightly.
281 // TODO: Is the (entry.MipLevels < maxlevel) check needed?
282 if (width
== entry
.w
&& height
==entry
.h
&& FullFormat
== entry
.fmt
&& entry
.MipLevels
< maxlevel
)
284 skip_texture_create
= true;
288 entry
.Destroy(false);
289 textures
.erase(iter
);
294 // Make an entry in the table
295 TCacheEntry
& entry
= textures
[texID
];
297 entry
.Realh
= height
;
298 PC_TexFormat pcfmt
= PC_TEX_FMT_NONE
;
300 pcfmt
= TexDecoder_Decode(temp
, ptr
, expandedWidth
, expandedHeight
, tex_format
, tlutaddr
, tlutfmt
, true);
301 if (g_ActiveConfig
.bHiresTextures
)
303 // Load Custom textures
304 char texPathTemp
[MAX_PATH
];
305 int newWidth
= width
;
306 int newHeight
= height
;
308 sprintf(texPathTemp
, "%s_%08x_%i", globals
->unique_id
, texHash
, tex_format
);
309 pcfmt
= HiresTextures::GetHiresTex(texPathTemp
, &newWidth
, &newHeight
, GX_TF_RGBA8
, temp
);
310 if (pcfmt
!= PC_TEX_FMT_NONE
)
312 expandedWidth
= width
= newWidth
;
313 expandedHeight
= height
= newHeight
;
317 if (pcfmt
== PC_TEX_FMT_NONE
)
318 pcfmt
= TexDecoder_Decode(temp
, ptr
, expandedWidth
, expandedHeight
, tex_format
, tlutaddr
, tlutfmt
, true);
320 entry
.oldpixel
= ((u32
*)ptr
)[0];
321 if (g_ActiveConfig
.bSafeTextureCache
) entry
.hash
= hash_value
;
322 else entry
.hash
= ((u32
*)ptr
)[0] = (u32
)(((double)rand() / RAND_MAX
) * 0xFFFFFFFF);
324 bool isPow2
= !((width
& (width
- 1)) || (height
& (height
- 1)));
325 unsigned int TexLevels
= (isPow2
&& UseNativeMips
&& maxlevel
) ? GetPow2(max(width
, height
)) : ((isPow2
)? 0 : 1);
326 if (TexLevels
> (maxlevel
+ 1) && maxlevel
)
327 TexLevels
= maxlevel
+ 1;
329 D3D11_USAGE usage
= (TexLevels
== 1) ? D3D11_USAGE_DYNAMIC
: D3D11_USAGE_DEFAULT
;
331 if (!skip_texture_create
)
333 // TODO: A little more verbosity in the debug names would be quite helpful..
334 D3D11_CPU_ACCESS_FLAG cpu_access
= (TexLevels
== 1) ? D3D11_CPU_ACCESS_WRITE
: (D3D11_CPU_ACCESS_FLAG
)0;
335 ID3D11Texture2D
* pTexture
= NULL
;
337 D3D11_SUBRESOURCE_DATA data
;
339 data
.SysMemPitch
= 4*expandedWidth
;
341 D3D11_TEXTURE2D_DESC texdesc
= CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM
, width
, height
, 1, TexLevels
, D3D11_BIND_SHADER_RESOURCE
, usage
, cpu_access
);
342 hr
= D3D::device
->CreateTexture2D(&texdesc
, (TexLevels
==1)?&data
:NULL
, &pTexture
);
343 CHECK(hr
==S_OK
, "Create texture of the TextureCache");
344 entry
.texture
= new D3DTexture2D(pTexture
, D3D11_BIND_SHADER_RESOURCE
);
345 CHECK(entry
.texture
!=NULL
, "Create texture of the TextureCache");
346 D3D::SetDebugObjectName((ID3D11DeviceChild
*)entry
.texture
->GetTex(), "a texture of the TextureCache");
347 D3D::SetDebugObjectName((ID3D11DeviceChild
*)entry
.texture
->GetSRV(), "shader resource view of a texture of the TextureCache");
348 SAFE_RELEASE(pTexture
);
350 // if (TexLevels == 1), we already loaded the data into our texture upon creation
351 if (TexLevels
!= 1) D3D::ReplaceRGBATexture2D(entry
.texture
->GetTex(), temp
, width
, height
, expandedWidth
, 0, usage
);
355 D3D::ReplaceRGBATexture2D(entry
.texture
->GetTex(), temp
, width
, height
, expandedWidth
, 0, usage
);
358 entry
.addr
= address
;
359 entry
.size_in_bytes
= TexDecoder_GetTextureSizeInBytes(expandedWidth
, expandedHeight
, tex_format
);
360 entry
.isRenderTarget
= false;
361 entry
.isNonPow2
= false;
362 entry
.MipLevels
= maxlevel
;
364 if (TexLevels
== 0) PD3DX11FilterTexture(D3D::context
, entry
.texture
->GetTex(), 0, D3DX11_DEFAULT
);
365 else if (TexLevels
> 1 && pcfmt
!= PC_TEX_FMT_NONE
)
367 unsigned int level
= 1;
368 unsigned int mipWidth
= (width
+ 1) >> 1;
369 unsigned int mipHeight
= (height
+ 1) >> 1;
370 ptr
+= entry
.size_in_bytes
;
371 while ((mipHeight
|| mipWidth
) && (level
< TexLevels
))
373 unsigned int currentWidth
= (mipWidth
> 0) ? mipWidth
: 1;
374 unsigned int currentHeight
= (mipHeight
> 0) ? mipHeight
: 1;
375 expandedWidth
= (currentWidth
+ bsw
) & (~bsw
);
376 expandedHeight
= (currentHeight
+ bsh
) & (~bsh
);
377 TexDecoder_Decode(temp
, ptr
, expandedWidth
, expandedHeight
, tex_format
, tlutaddr
, tlutfmt
, true);
378 D3D::ReplaceRGBATexture2D(entry
.texture
->GetTex(), temp
, currentWidth
, currentHeight
, expandedWidth
, level
, usage
);
379 u32 size
= (max(mipWidth
, bsw
) * max(mipHeight
, bsh
) * bsdepth
) >> 1;
386 entry
.frameCount
= frameCount
;
389 entry
.Scaledw
= width
;
390 entry
.Scaledh
= height
;
391 entry
.fmt
= FullFormat
;
393 // dump texture to file
394 if (g_ActiveConfig
.bDumpTextures
)
396 char szTemp
[MAX_PATH
];
397 char szDir
[MAX_PATH
];
399 // make sure that the directory exists
400 sprintf(szDir
, "%s%s", File::GetUserPath(D_DUMPTEXTURES_IDX
), globals
->unique_id
);
401 if (!File::Exists(szDir
) || !File::IsDirectory(szDir
))
402 File::CreateDir(szDir
);
404 sprintf(szTemp
, "%s/%s_%08x_%i.png", szDir
, globals
->unique_id
, texHash
, tex_format
);
405 if (!File::Exists(szTemp
))
406 if(FAILED(PD3DX11SaveTextureToFileA(D3D::context
, entry
.texture
->GetTex(), D3DX11_IFF_PNG
, szTemp
))) PanicAlert("!!!");
409 INCSTAT(stats
.numTexturesCreated
);
410 SETSTAT(stats
.numTexturesAlive
, textures
.size());
412 D3D::gfxstate
->SetShaderResource(stage
, entry
.texture
->GetSRV());
417 void TextureCache::CopyRenderTargetToTexture(u32 address
, bool bFromZBuffer
, bool bIsIntensityFmt
, u32 copyfmt
, unsigned int bScaleByHalf
, const EFBRectangle
&source_rect
)
419 int efb_w
= source_rect
.GetWidth();
420 int efb_h
= source_rect
.GetHeight();
422 int tex_w
= (abs(source_rect
.GetWidth()) >> bScaleByHalf
);
423 int tex_h
= (abs(source_rect
.GetHeight()) >> bScaleByHalf
);
425 int Scaledtex_w
= (g_ActiveConfig
.bCopyEFBScaled
) ? ((int)(Renderer::GetTargetScaleX() * tex_w
)) : tex_w
;
426 int Scaledtex_h
= (g_ActiveConfig
.bCopyEFBScaled
) ? ((int)(Renderer::GetTargetScaleY() * tex_h
)) : tex_h
;
428 TexCache::iterator iter
;
429 D3DTexture2D
* tex
= NULL
;
430 iter
= textures
.find(address
);
431 if (iter
!= textures
.end())
433 if (iter
->second
.isRenderTarget
&& iter
->second
.Scaledw
== Scaledtex_w
&& iter
->second
.Scaledh
== Scaledtex_h
)
435 tex
= iter
->second
.texture
;
436 iter
->second
.frameCount
= frameCount
;
440 // Remove it and recreate it as a render target
441 SAFE_RELEASE(iter
->second
.texture
);
442 textures
.erase(iter
);
449 entry
.isRenderTarget
= true;
451 entry
.frameCount
= frameCount
;
452 entry
.w
= entry
.Realw
= tex_w
;
453 entry
.h
= entry
.Realh
= tex_h
;
454 entry
.Scaledw
= Scaledtex_w
;
455 entry
.Scaledh
= Scaledtex_h
;
457 entry
.isNonPow2
= true;
458 entry
.texture
= D3DTexture2D::Create(Scaledtex_w
, Scaledtex_h
, (D3D11_BIND_FLAG
)((int)D3D11_BIND_RENDER_TARGET
|(int)D3D11_BIND_SHADER_RESOURCE
), D3D11_USAGE_DEFAULT
, DXGI_FORMAT_R8G8B8A8_UNORM
);
459 if (entry
.texture
== NULL
) PanicAlert("CopyRenderTargetToTexture failed to create entry.texture at %s %d\n", __FILE__
, __LINE__
);
460 textures
[address
] = entry
;
464 float colmat
[20]= {0.0f
}; // last four floats for fConstAdd
465 unsigned int cbufid
= (unsigned int)-1;
467 // TODO: Move this to TextureCache::Init()
474 colmat
[0] = colmat
[4] = colmat
[8] = colmat
[12] = 1.0f
;
478 colmat
[1] = colmat
[5] = colmat
[9] = colmat
[12] = 1.0f
;
481 case 11: // Z16 (reverse order)
482 colmat
[0] = colmat
[4] = colmat
[8] = colmat
[13] = 1.0f
;
486 colmat
[0] = colmat
[5] = colmat
[10] = 1.0f
;
490 colmat
[1] = colmat
[5] = colmat
[9] = colmat
[13] = 1.0f
;
494 colmat
[2] = colmat
[6] = colmat
[10] = colmat
[14] = 1.0f
;
498 colmat
[2] = colmat
[6] = colmat
[10] = colmat
[13] = 1.0f
;
502 ERROR_LOG(VIDEO
, "Unknown copy zbuf format: 0x%x", copyfmt
);
503 colmat
[2] = colmat
[5] = colmat
[8] = 1.0f
;
508 else if (bIsIntensityFmt
)
510 colmat
[16] = colmat
[17] = colmat
[18] = 16.0f
/255.0f
;
517 // TODO - verify these coefficients
518 colmat
[0] = 0.257f
; colmat
[1] = 0.504f
; colmat
[2] = 0.098f
;
519 colmat
[4] = 0.257f
; colmat
[5] = 0.504f
; colmat
[6] = 0.098f
;
520 colmat
[8] = 0.257f
; colmat
[9] = 0.504f
; colmat
[10] = 0.098f
;
524 colmat
[19] = 16.0f
/ 255.0f
;
525 colmat
[12] = 0.257f
; colmat
[13] = 0.504f
; colmat
[14] = 0.098f
;
536 ERROR_LOG(VIDEO
, "Unknown copy intensity format: 0x%x", copyfmt
);
537 colmat
[0] = colmat
[5] = colmat
[10] = colmat
[15] = 1;
547 colmat
[0] = colmat
[4] = colmat
[8] = colmat
[12] = 1;
552 colmat
[0] = colmat
[4] = colmat
[8] = colmat
[15] = 1;
557 colmat
[3] = colmat
[7] = colmat
[11] = colmat
[15] = 1;
561 colmat
[1] = colmat
[5] = colmat
[9] = colmat
[13] = 1;
565 colmat
[2] = colmat
[6] = colmat
[10] = colmat
[14] = 1;
569 colmat
[0] = colmat
[4] = colmat
[8] = colmat
[13] = 1;
573 colmat
[1] = colmat
[5] = colmat
[9] = colmat
[14] = 1;
578 colmat
[0] = colmat
[5] = colmat
[10] = 1;
579 colmat
[19] = 1; // set alpha to 1
584 colmat
[0] = colmat
[5] = colmat
[10] = colmat
[15] = 1;
589 ERROR_LOG(VIDEO
, "Unknown copy color format: 0x%x", copyfmt
);
590 colmat
[0] = colmat
[5] = colmat
[10] = colmat
[15] = 1;
596 Renderer::ResetAPIState(); // reset any game specific settings
598 // stretch picture with increased internal resolution
599 D3D11_VIEWPORT vp
= CD3D11_VIEWPORT(0.f
, 0.f
, (float)Scaledtex_w
, (float)Scaledtex_h
);
600 D3D::context
->RSSetViewports(1, &vp
);
601 D3D11_RECT destrect
= CD3D11_RECT(0, 0, Scaledtex_w
, Scaledtex_h
);
603 // set transformation
604 if (efbcopycbuf
[cbufid
] == NULL
)
606 D3D11_BUFFER_DESC cbdesc
= CD3D11_BUFFER_DESC(20*sizeof(float), D3D11_BIND_CONSTANT_BUFFER
, D3D11_USAGE_DEFAULT
);
607 D3D11_SUBRESOURCE_DATA data
;
608 data
.pSysMem
= colmat
;
609 HRESULT hr
= D3D::device
->CreateBuffer(&cbdesc
, &data
, &efbcopycbuf
[cbufid
]);
610 CHECK(hr
==S_OK
, "Create efb copy constant buffer %d", cbufid
);
611 D3D::SetDebugObjectName((ID3D11DeviceChild
*)efbcopycbuf
[cbufid
], "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
613 D3D::context
->PSSetConstantBuffers(0, 1, &efbcopycbuf
[cbufid
]);
615 TargetRectangle targetSource
= Renderer::ConvertEFBRectangle(source_rect
);
616 D3D11_RECT sourcerect
= CD3D11_RECT(targetSource
.left
, targetSource
.top
, targetSource
.right
, targetSource
.bottom
);
618 // Use linear filtering if (bScaleByHalf), use point filtering otherwise
619 if (bScaleByHalf
) D3D::SetLinearCopySampler();
620 else D3D::SetPointCopySampler();
622 D3D::stateman
->PushBlendState(efbcopyblendstate
);
623 D3D::stateman
->PushRasterizerState(efbcopyraststate
);
624 D3D::stateman
->PushDepthState(efbcopydepthstate
);
625 D3D::context
->OMSetRenderTargets(1, &tex
->GetRTV(), NULL
);
626 D3D::drawShadedTexQuad(
627 (bFromZBuffer
) ? g_framebufferManager
.GetEFBDepthTexture()->GetSRV() : g_framebufferManager
.GetEFBColorTexture()->GetSRV(),
629 Renderer::GetFullTargetWidth(),
630 Renderer::GetFullTargetHeight(),
631 (bFromZBuffer
) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
633 D3D::context
->OMSetRenderTargets(1, &g_framebufferManager
.GetEFBColorTexture()->GetRTV(), g_framebufferManager
.GetEFBDepthTexture()->GetDSV());
634 D3D::stateman
->PopBlendState();
635 D3D::stateman
->PopDepthState();
636 D3D::stateman
->PopRasterizerState();
637 Renderer::RestoreAPIState();