diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp index d79da53e0d..d04eb1c284 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp @@ -38,6 +38,8 @@ D3D_FEATURE_LEVEL featlevel; D3DTexture2D* backbuf = NULL; HWND hWnd; +bool bgra_textures_supported; + #define NUM_SUPPORTED_FEATURE_LEVELS 3 const D3D_FEATURE_LEVEL supported_feature_levels[NUM_SUPPORTED_FEATURE_LEVELS] = { D3D_FEATURE_LEVEL_11_0, @@ -145,6 +147,11 @@ HRESULT Create(HWND wnd) context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL); + // BGRA textures are easier to deal with in TextureCache, but might not be supported by the hardware + UINT format_support; + device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support); + bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; + gfxstate = new EmuGfxState; stateman = new StateManager; return S_OK; @@ -181,6 +188,8 @@ D3DTexture2D* &GetBackBuffer() { return backbuf; } unsigned int GetBackBufferWidth() { return xres; } unsigned int GetBackBufferHeight() { return yres; } +bool BGRATexturesSupported() { return bgra_textures_supported; } + void Reset() { // release all back buffer references diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h index ecb3ef73fb..3caeeeed18 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h @@ -49,6 +49,7 @@ unsigned int GetBackBufferHeight(); D3DTexture2D* &GetBackBuffer(); const char* PixelShaderVersionString(); const char* VertexShaderVersionString(); +bool BGRATexturesSupported(); // Ihis function will assign a name to the given resource. // The DirectX debug layer will make it easier to identify resources that way, diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp index 62f6af1a34..89f07da40f 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp @@ -50,7 +50,7 @@ void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int outptr = (u8*)map.pData; destPitch = map.RowPitch; } - else if (usage == D3D11_USAGE_DEFAULT && pcfmt != PC_TEX_FMT_BGRA32) + else if (usage == D3D11_USAGE_DEFAULT && !(pcfmt == PC_TEX_FMT_BGRA32 && fmt == DXGI_FORMAT_B8G8R8A8_UNORM)) { if (texbufsize < 4*width*height) { @@ -61,7 +61,7 @@ void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int outptr = texbuf; destPitch = width * 4; } - else if (usage == D3D11_USAGE_DEFAULT && pcfmt == PC_TEX_FMT_BGRA32) + else if (usage == D3D11_USAGE_DEFAULT && pcfmt == PC_TEX_FMT_BGRA32 && fmt == DXGI_FORMAT_B8G8R8A8_UNORM) { // BGRA32 textures can be uploaded directly to VRAM in this case D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1); @@ -103,9 +103,24 @@ void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int } break; case PC_TEX_FMT_BGRA32: - for (unsigned int y = 0; y < height; y++) - memcpy( outptr + y * destPitch, (u32*)buffer + y * pitch, destPitch ); - + if (fmt == DXGI_FORMAT_B8G8R8A8_UNORM) + { + for (unsigned int y = 0; y < height; y++) + memcpy( outptr + y * destPitch, (u32*)buffer + y * pitch, destPitch ); + } + else + { + for (unsigned int y = 0; y < height; y++) + { + u32* in = (u32*)buffer + y * pitch; + u32* pBits = (u32*)(outptr + y * destPitch); + for (unsigned int x = 0; x < width; x++) + { + *pBits++ = (*in & 0xFF00FF00) | ((*in >> 16) & 0xFF) | ((*in << 16) & 0xFF0000); + in++; + } + } + } break; case PC_TEX_FMT_RGB565: for (unsigned int y = 0; y < height; y++) @@ -117,9 +132,9 @@ void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int // we can't simply shift here, since e.g. 11111 must map to 11111111 and not 11111000 const u16 col = *in++; *(pBits++) = 0xFF000000 | // alpha - ((((col&0xF800) << 5) * 255 / 31) & 0xFF0000) | // red - ((((col& 0x7e0) << 3) * 255 / 63) & 0xFF00) | // green - (( (col& 0x1f) * 255 / 31)); // blue + (( (col&0xF800) >> 11) * 255 / 31) | // red + ((((col& 0x7e0) << 3) * 255 / 63) & 0xFF00) | // green + ((((col& 0x1f) << 16) * 255 / 31) & 0xFF0000); // blue } } break; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h index db8920ba62..51468ab532 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h @@ -33,7 +33,7 @@ public: // or let the texture automatically be created by D3DTexture2D::Create D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN); - static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt = DXGI_FORMAT_B8G8R8A8_UNORM, unsigned int levels = 1); + static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1); // reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore void AddRef(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp index 6df6ed28c1..2664066748 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp @@ -165,7 +165,7 @@ int CD3DFont::Init() // possible optimization: store the converted data in a buffer and fill the texture on creation. // That way, we can use a static texture ID3D11Texture2D* buftex; - D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, m_dwTexWidth, m_dwTexHeight, + D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, m_dwTexWidth, m_dwTexHeight, 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); hr = device->CreateTexture2D(&texdesc, NULL, &buftex); @@ -567,6 +567,7 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, lastrdest.bottom = rDest->bottom; } +// TODO: Check whether we're passing Color in the right order (should be RGBA) void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout) { static u32 lastcol = 0; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 5019da036f..ceed5d9bb2 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -768,7 +768,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE D3D::stateman->PushDepthState(cleardepthstates[zEnable]); D3D::stateman->PushRasterizerState(clearraststate); - D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF),PixelShaderCache::GetClearProgram(),VertexShaderCache::GetClearVertexShader(), VertexShaderCache::GetClearInputLayout()); + D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader(), VertexShaderCache::GetClearInputLayout()); D3D::stateman->PopDepthState(); D3D::stateman->PopRasterizerState(); @@ -908,7 +908,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) { u32* ptr = (u32*)((u8*)map.pData + y * map.RowPitch); for (unsigned int x = 0; x < D3D::GetBackBufferWidth(); ++x) - *ptr++ |= 0xFF000000; + *(u8*)ptr++ = 0xFF; } D3D::context->Unmap(buftex, 0); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index 6db655a6d1..e8c030063b 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -271,8 +271,9 @@ TextureCache::TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, u if (pcfmt == PC_TEX_FMT_NONE) pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt); - DXGI_FORMAT d3d_fmt = DXGI_FORMAT_B8G8R8A8_UNORM; + DXGI_FORMAT d3d_fmt = DXGI_FORMAT_R8G8B8A8_UNORM; bool swap_r_b = false; + if (pcfmt == PC_TEX_FMT_BGRA32 && D3D::BGRATexturesSupported()) d3d_fmt = DXGI_FORMAT_B8G8R8A8_UNORM; entry.oldpixel = ((u32*)ptr)[0]; if (g_ActiveConfig.bSafeTextureCache) entry.hash = hash_value; @@ -400,7 +401,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo entry.Scaledh = Scaledtex_h; entry.fmt = copyfmt; entry.isNonPow2 = true; - 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_B8G8R8A8_UNORM); + 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); if (entry.texture == NULL) PanicAlert("CopyRenderTargetToTexture failed to create entry.texture at %s %d\n", __FILE__, __LINE__); textures[address] = entry; tex = entry.texture; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp index 653ca1c921..04f6f8764a 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp @@ -139,7 +139,7 @@ void VertexShaderCache::Init() const D3D11_INPUT_ELEMENT_DESC clearelems[2] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; D3DBlob* blob;