mirror of https://github.com/PCSX2/pcsx2.git
GSdx: another useless revision...
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1405 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
6ef94cc707
commit
191a3d0c7e
|
@ -0,0 +1,870 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GSdx.h"
|
||||
#include "GSDevice11.h"
|
||||
#include "resource.h"
|
||||
|
||||
GSDevice11::GSDevice11()
|
||||
: m_vb(NULL)
|
||||
, m_vb_stride(0)
|
||||
, m_layout(NULL)
|
||||
, m_topology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED)
|
||||
, m_vs(NULL)
|
||||
, m_vs_cb(NULL)
|
||||
, m_gs(NULL)
|
||||
, m_ps(NULL)
|
||||
, m_ps_cb(NULL)
|
||||
, m_scissor(0, 0, 0, 0)
|
||||
, m_viewport(0, 0)
|
||||
, m_dss(NULL)
|
||||
, m_sref(0)
|
||||
, m_bs(NULL)
|
||||
, m_bf(-1)
|
||||
, m_rtv(NULL)
|
||||
, m_dsv(NULL)
|
||||
{
|
||||
memset(m_ps_srv, 0, sizeof(m_ps_srv));
|
||||
memset(m_ps_ss, 0, sizeof(m_ps_ss));
|
||||
|
||||
m_vertices.stride = 0;
|
||||
m_vertices.start = 0;
|
||||
m_vertices.count = 0;
|
||||
m_vertices.limit = 0;
|
||||
}
|
||||
|
||||
GSDevice11::~GSDevice11()
|
||||
{
|
||||
}
|
||||
|
||||
bool GSDevice11::Create(GSWnd* wnd, bool vsync)
|
||||
{
|
||||
if(!__super::Create(wnd, vsync))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
D3D11_BUFFER_DESC bd;
|
||||
D3D11_SAMPLER_DESC sd;
|
||||
D3D11_DEPTH_STENCIL_DESC dsd;
|
||||
D3D11_RASTERIZER_DESC rd;
|
||||
D3D11_BLEND_DESC bsd;
|
||||
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
|
||||
scd.BufferCount = 2;
|
||||
scd.BufferDesc.Width = 1;
|
||||
scd.BufferDesc.Height = 1;
|
||||
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
//scd.BufferDesc.RefreshRate.Numerator = 60;
|
||||
//scd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
scd.OutputWindow = (HWND)m_wnd->GetHandle();
|
||||
scd.SampleDesc.Count = 1;
|
||||
scd.SampleDesc.Quality = 0;
|
||||
scd.Windowed = TRUE;
|
||||
|
||||
uint32 flags = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
|
||||
// hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
|
||||
|
||||
if(FAILED(hr)) return false;
|
||||
|
||||
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options;
|
||||
|
||||
hr = m_dev->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS));
|
||||
|
||||
switch(m_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_9_1:
|
||||
case D3D_FEATURE_LEVEL_9_2:
|
||||
m_shader.model = "0x200";
|
||||
m_shader.vs = "vs_4_0_level_9_1";
|
||||
m_shader.ps = "ps_4_0_level_9_1";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_9_3:
|
||||
m_shader.model = "0x300";
|
||||
m_shader.vs = "vs_4_0_level_9_3";
|
||||
m_shader.ps = "ps_4_0_level_9_3";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
m_shader.model = "0x400";
|
||||
m_shader.vs = "vs_4_0";
|
||||
m_shader.gs = "gs_4_0";
|
||||
m_shader.ps = "ps_4_0";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
m_shader.model = "0x500";
|
||||
m_shader.vs = "vs_5_0";
|
||||
m_shader.gs = "gs_5_0";
|
||||
m_shader.ps = "ps_5_0";
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_level < D3D_FEATURE_LEVEL_10_0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC il_convert[] =
|
||||
{
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
};
|
||||
|
||||
hr = CompileShader(IDR_CONVERT_FX, "vs_main", NULL, &m_convert.vs, il_convert, countof(il_convert), &m_convert.il);
|
||||
|
||||
for(int i = 0; i < countof(m_convert.ps); i++)
|
||||
{
|
||||
hr = CompileShader(IDR_CONVERT_FX, format("ps_main%d", i), NULL, &m_convert.ps[i]);
|
||||
}
|
||||
|
||||
memset(&dsd, 0, sizeof(dsd));
|
||||
|
||||
dsd.DepthEnable = false;
|
||||
dsd.StencilEnable = false;
|
||||
|
||||
hr = m_dev->CreateDepthStencilState(&dsd, &m_convert.dss);
|
||||
|
||||
memset(&bsd, 0, sizeof(bsd));
|
||||
|
||||
bsd.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
|
||||
hr = m_dev->CreateBlendState(&bsd, &m_convert.bs);
|
||||
|
||||
// merge
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
bd.ByteWidth = sizeof(MergeConstantBuffer);
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
|
||||
hr = m_dev->CreateBuffer(&bd, NULL, &m_merge.cb);
|
||||
|
||||
for(int i = 0; i < countof(m_merge.ps); i++)
|
||||
{
|
||||
hr = CompileShader(IDR_MERGE_FX, format("ps_main%d", i), NULL, &m_merge.ps[i]);
|
||||
}
|
||||
|
||||
memset(&bsd, 0, sizeof(bsd));
|
||||
|
||||
bsd.RenderTarget[0].BlendEnable = true;
|
||||
bsd.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
bsd.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||
bsd.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
bsd.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
bsd.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
bsd.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
bsd.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
|
||||
hr = m_dev->CreateBlendState(&bsd, &m_merge.bs);
|
||||
|
||||
// interlace
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
bd.ByteWidth = sizeof(InterlaceConstantBuffer);
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
|
||||
hr = m_dev->CreateBuffer(&bd, NULL, &m_interlace.cb);
|
||||
|
||||
for(int i = 0; i < countof(m_interlace.ps); i++)
|
||||
{
|
||||
hr = CompileShader(IDR_INTERLACE_FX, format("ps_main%d", i), NULL, &m_interlace.ps[i]);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
memset(&rd, 0, sizeof(rd));
|
||||
|
||||
rd.FillMode = D3D11_FILL_SOLID;
|
||||
rd.CullMode = D3D11_CULL_NONE;
|
||||
rd.FrontCounterClockwise = false;
|
||||
rd.DepthBias = false;
|
||||
rd.DepthBiasClamp = 0;
|
||||
rd.SlopeScaledDepthBias = 0;
|
||||
rd.DepthClipEnable = false; // ???
|
||||
rd.ScissorEnable = true;
|
||||
rd.MultisampleEnable = false;
|
||||
rd.AntialiasedLineEnable = false;
|
||||
|
||||
hr = m_dev->CreateRasterizerState(&rd, &m_rs);
|
||||
|
||||
m_ctx->RSSetState(m_rs);
|
||||
|
||||
//
|
||||
|
||||
memset(&sd, 0, sizeof(sd));
|
||||
|
||||
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
sd.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.MaxLOD = FLT_MAX;
|
||||
sd.MaxAnisotropy = 16;
|
||||
sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
|
||||
hr = m_dev->CreateSamplerState(&sd, &m_convert.ln);
|
||||
|
||||
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
|
||||
hr = m_dev->CreateSamplerState(&sd, &m_convert.pt);
|
||||
|
||||
//
|
||||
|
||||
Reset(1, 1, false);
|
||||
|
||||
//
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSDevice11::Reset(int w, int h, bool fs)
|
||||
{
|
||||
if(!__super::Reset(w, h, fs))
|
||||
return false;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
m_swapchain->GetDesc(&scd);
|
||||
m_swapchain->ResizeBuffers(scd.BufferCount, w, h, scd.BufferDesc.Format, 0);
|
||||
|
||||
CComPtr<ID3D11Texture2D> backbuffer;
|
||||
m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backbuffer);
|
||||
m_backbuffer = new GSTexture11(backbuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDevice11::Flip()
|
||||
{
|
||||
m_swapchain->Present(m_vsync ? 1 : 0, 0);
|
||||
}
|
||||
|
||||
void GSDevice11::BeginScene()
|
||||
{
|
||||
}
|
||||
|
||||
void GSDevice11::DrawPrimitive()
|
||||
{
|
||||
m_ctx->Draw(m_vertices.count, m_vertices.start);
|
||||
}
|
||||
|
||||
void GSDevice11::EndScene()
|
||||
{
|
||||
PSSetShaderResources(NULL, NULL);
|
||||
|
||||
// not clearing the rt/ds gives a little fps boost in complex games (5-10%)
|
||||
|
||||
// OMSetRenderTargets(NULL, NULL);
|
||||
|
||||
m_vertices.start += m_vertices.count;
|
||||
m_vertices.count = 0;
|
||||
}
|
||||
|
||||
void GSDevice11::ClearRenderTarget(GSTexture* t, const GSVector4& c)
|
||||
{
|
||||
m_ctx->ClearRenderTargetView(*(GSTexture11*)t, c.v);
|
||||
}
|
||||
|
||||
void GSDevice11::ClearRenderTarget(GSTexture* t, uint32 c)
|
||||
{
|
||||
GSVector4 color = GSVector4(c) * (1.0f / 255);
|
||||
|
||||
m_ctx->ClearRenderTargetView(*(GSTexture11*)t, color.v);
|
||||
}
|
||||
|
||||
void GSDevice11::ClearDepth(GSTexture* t, float c)
|
||||
{
|
||||
m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_DEPTH, c, 0);
|
||||
}
|
||||
|
||||
void GSDevice11::ClearStencil(GSTexture* t, uint8 c)
|
||||
{
|
||||
m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_STENCIL, 0, c);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::Create(int type, int w, int h, int format)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
desc.Width = w;
|
||||
desc.Height = h;
|
||||
desc.Format = (DXGI_FORMAT)format;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case GSTexture::RenderTarget:
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case GSTexture::DepthStencil:
|
||||
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||
break;
|
||||
case GSTexture::Texture:
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case GSTexture::Offscreen:
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
GSTexture11* t = NULL;
|
||||
|
||||
CComPtr<ID3D11Texture2D> texture;
|
||||
|
||||
hr = m_dev->CreateTexture2D(&desc, NULL, &texture);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
t = new GSTexture11(texture);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case GSTexture::RenderTarget:
|
||||
ClearRenderTarget(t, 0);
|
||||
break;
|
||||
case GSTexture::DepthStencil:
|
||||
ClearDepth(t, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::CreateRenderTarget(int w, int h, int format)
|
||||
{
|
||||
return __super::CreateRenderTarget(w, h, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::CreateDepthStencil(int w, int h, int format)
|
||||
{
|
||||
return __super::CreateDepthStencil(w, h, format ? format : DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::CreateTexture(int w, int h, int format)
|
||||
{
|
||||
return __super::CreateTexture(w, h, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::CreateOffscreen(int w, int h, int format)
|
||||
{
|
||||
return __super::CreateOffscreen(w, h, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice11::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
|
||||
{
|
||||
GSTexture* dst = NULL;
|
||||
|
||||
if(format == 0)
|
||||
{
|
||||
format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
|
||||
if(format != DXGI_FORMAT_R8G8B8A8_UNORM && format != DXGI_FORMAT_R16_UINT)
|
||||
{
|
||||
ASSERT(0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(GSTexture* rt = CreateRenderTarget(w, h, format))
|
||||
{
|
||||
GSVector4 dr(0, 0, w, h);
|
||||
|
||||
StretchRect(src, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL);
|
||||
|
||||
dst = CreateOffscreen(w, h, format);
|
||||
|
||||
if(dst)
|
||||
{
|
||||
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
|
||||
}
|
||||
|
||||
Recycle(rt);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
|
||||
{
|
||||
StretchRect(st, sr, dt, dr, m_convert.ps[shader], NULL, linear);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear)
|
||||
{
|
||||
StretchRect(st, sr, dt, dr, ps, ps_cb, m_convert.bs, linear);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear)
|
||||
{
|
||||
BeginScene();
|
||||
|
||||
GSVector2i ds = dt->GetSize();
|
||||
|
||||
// om
|
||||
|
||||
OMSetDepthStencilState(m_convert.dss, 0);
|
||||
OMSetBlendState(bs, 0);
|
||||
OMSetRenderTargets(dt, NULL);
|
||||
|
||||
// ia
|
||||
|
||||
float left = dr.x * 2 / ds.x - 1.0f;
|
||||
float top = 1.0f - dr.y * 2 / ds.y;
|
||||
float right = dr.z * 2 / ds.x - 1.0f;
|
||||
float bottom = 1.0f - dr.w * 2 / ds.y;
|
||||
|
||||
GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(left, top, 0.5f, 1.0f), GSVector2(sr.x, sr.y)},
|
||||
{GSVector4(right, top, 0.5f, 1.0f), GSVector2(sr.z, sr.y)},
|
||||
{GSVector4(left, bottom, 0.5f, 1.0f), GSVector2(sr.x, sr.w)},
|
||||
{GSVector4(right, bottom, 0.5f, 1.0f), GSVector2(sr.z, sr.w)},
|
||||
};
|
||||
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
|
||||
IASetInputLayout(m_convert.il);
|
||||
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
// vs
|
||||
|
||||
VSSetShader(m_convert.vs, NULL);
|
||||
|
||||
// gs
|
||||
|
||||
GSSetShader(NULL);
|
||||
|
||||
// ps
|
||||
|
||||
PSSetShader(ps, ps_cb);
|
||||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, NULL);
|
||||
PSSetShaderResources(st, NULL);
|
||||
|
||||
// rs
|
||||
|
||||
RSSet(ds.x, ds.y);
|
||||
|
||||
//
|
||||
|
||||
DrawPrimitive();
|
||||
|
||||
//
|
||||
|
||||
EndScene();
|
||||
}
|
||||
|
||||
void GSDevice11::DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c)
|
||||
{
|
||||
ClearRenderTarget(dt, c);
|
||||
|
||||
if(st[1] && !slbg)
|
||||
{
|
||||
StretchRect(st[1], sr[1], dt, dr[1], m_merge.ps[0], NULL, true);
|
||||
}
|
||||
|
||||
if(st[0])
|
||||
{
|
||||
m_ctx->UpdateSubresource(m_merge.cb, 0, NULL, &c, 0, 0);
|
||||
|
||||
StretchRect(st[0], sr[0], dt, dr[0], m_merge.ps[mmod ? 1 : 0], m_merge.cb, m_merge.bs, true);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset)
|
||||
{
|
||||
GSVector4 s = GSVector4(dt->GetSize());
|
||||
|
||||
GSVector4 sr(0, 0, 1, 1);
|
||||
GSVector4 dr(0.0f, yoffset, s.x, s.y + yoffset);
|
||||
|
||||
InterlaceConstantBuffer cb;
|
||||
|
||||
cb.ZrH = GSVector2(0, 1.0f / s.y);
|
||||
cb.hH = s.y / 2;
|
||||
|
||||
m_ctx->UpdateSubresource(m_interlace.cb, 0, NULL, &cb, 0, 0);
|
||||
|
||||
StretchRect(st, sr, dt, dr, m_interlace.ps[shader], m_interlace.cb, linear);
|
||||
}
|
||||
|
||||
void GSDevice11::IASetVertexBuffer(const void* vertices, size_t stride, size_t count)
|
||||
{
|
||||
ASSERT(m_vertices.count == 0);
|
||||
|
||||
if(count * stride > m_vertices.limit * m_vertices.stride)
|
||||
{
|
||||
m_vertices.vb_old = m_vertices.vb;
|
||||
m_vertices.vb = NULL;
|
||||
m_vertices.start = 0;
|
||||
m_vertices.count = 0;
|
||||
m_vertices.limit = max(count * 3 / 2, 10000);
|
||||
}
|
||||
|
||||
if(m_vertices.vb == NULL)
|
||||
{
|
||||
D3D11_BUFFER_DESC bd;
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
bd.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bd.ByteWidth = m_vertices.limit * stride;
|
||||
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
hr = m_dev->CreateBuffer(&bd, NULL, &m_vertices.vb);
|
||||
|
||||
if(FAILED(hr)) return;
|
||||
}
|
||||
|
||||
D3D11_MAP type = D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
|
||||
if(m_vertices.start + count > m_vertices.limit || stride != m_vertices.stride)
|
||||
{
|
||||
m_vertices.start = 0;
|
||||
|
||||
type = D3D11_MAP_WRITE_DISCARD;
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE m;
|
||||
|
||||
if(SUCCEEDED(m_ctx->Map(m_vertices.vb, 0, type, 0, &m)))
|
||||
{
|
||||
GSVector4i::storent((uint8*)m.pData + m_vertices.start * stride, vertices, count * stride);
|
||||
|
||||
m_ctx->Unmap(m_vertices.vb, 0);
|
||||
}
|
||||
|
||||
m_vertices.count = count;
|
||||
m_vertices.stride = stride;
|
||||
|
||||
IASetVertexBuffer(m_vertices.vb, stride);
|
||||
}
|
||||
|
||||
void GSDevice11::IASetVertexBuffer(ID3D11Buffer* vb, size_t stride)
|
||||
{
|
||||
if(m_vb != vb || m_vb_stride != stride)
|
||||
{
|
||||
uint32 offset = 0;
|
||||
|
||||
m_ctx->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
|
||||
|
||||
m_vb = vb;
|
||||
m_vb_stride = stride;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::IASetInputLayout(ID3D11InputLayout* layout)
|
||||
{
|
||||
if(m_layout != layout)
|
||||
{
|
||||
m_ctx->IASetInputLayout(layout);
|
||||
|
||||
m_layout = layout;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology)
|
||||
{
|
||||
if(m_topology != topology)
|
||||
{
|
||||
m_ctx->IASetPrimitiveTopology(topology);
|
||||
|
||||
m_topology = topology;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb)
|
||||
{
|
||||
if(m_vs != vs)
|
||||
{
|
||||
m_ctx->VSSetShader(vs, NULL, 0);
|
||||
|
||||
m_vs = vs;
|
||||
}
|
||||
|
||||
if(m_vs_cb != vs_cb)
|
||||
{
|
||||
m_ctx->VSSetConstantBuffers(0, 1, &vs_cb);
|
||||
|
||||
m_vs_cb = vs_cb;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::GSSetShader(ID3D11GeometryShader* gs)
|
||||
{
|
||||
if(m_gs != gs)
|
||||
{
|
||||
m_ctx->GSSetShader(gs, NULL, 0);
|
||||
|
||||
m_gs = gs;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
||||
{
|
||||
ID3D11ShaderResourceView* srv0 = NULL;
|
||||
ID3D11ShaderResourceView* srv1 = NULL;
|
||||
|
||||
if(sr0) srv0 = *(GSTexture11*)sr0;
|
||||
if(sr1) srv1 = *(GSTexture11*)sr1;
|
||||
|
||||
if(m_ps_srv[0] != srv0 || m_ps_srv[1] != srv1)
|
||||
{
|
||||
ID3D11ShaderResourceView* srvs[] = {srv0, srv1};
|
||||
|
||||
m_ctx->PSSetShaderResources(0, 2, srvs);
|
||||
|
||||
m_ps_srv[0] = srv0;
|
||||
m_ps_srv[1] = srv1;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb)
|
||||
{
|
||||
if(m_ps != ps)
|
||||
{
|
||||
m_ctx->PSSetShader(ps, NULL, 0);
|
||||
|
||||
m_ps = ps;
|
||||
}
|
||||
|
||||
if(m_ps_cb != ps_cb)
|
||||
{
|
||||
m_ctx->PSSetConstantBuffers(0, 1, &ps_cb);
|
||||
|
||||
m_ps_cb = ps_cb;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::PSSetSamplerState(ID3D11SamplerState* ss0, ID3D11SamplerState* ss1)
|
||||
{
|
||||
if(m_ps_ss[0] != ss0 || m_ps_ss[1] != ss1)
|
||||
{
|
||||
ID3D11SamplerState* sss[] = {ss0, ss1};
|
||||
|
||||
m_ctx->PSSetSamplers(0, 2, sss);
|
||||
|
||||
m_ps_ss[0] = ss0;
|
||||
m_ps_ss[1] = ss1;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::RSSet(int width, int height, const GSVector4i* scissor)
|
||||
{
|
||||
if(m_viewport.x != width || m_viewport.y != height)
|
||||
{
|
||||
D3D11_VIEWPORT vp;
|
||||
|
||||
memset(&vp, 0, sizeof(vp));
|
||||
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
|
||||
m_ctx->RSSetViewports(1, &vp);
|
||||
|
||||
m_viewport = GSVector2i(width, height);
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(0, 0, width, height);
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_ctx->RSSetScissorRects(1, r);
|
||||
|
||||
m_scissor = r;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::OMSetDepthStencilState(ID3D11DepthStencilState* dss, uint8 sref)
|
||||
{
|
||||
if(m_dss != dss || m_sref != sref)
|
||||
{
|
||||
m_ctx->OMSetDepthStencilState(dss, sref);
|
||||
|
||||
m_dss = dss;
|
||||
m_sref = sref;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::OMSetBlendState(ID3D11BlendState* bs, float bf)
|
||||
{
|
||||
if(m_bs != bs || m_bf != bf)
|
||||
{
|
||||
float BlendFactor[] = {bf, bf, bf, 0};
|
||||
|
||||
m_ctx->OMSetBlendState(bs, BlendFactor, 0xffffffff);
|
||||
|
||||
m_bs = bs;
|
||||
m_bf = bf;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
||||
{
|
||||
ID3D11RenderTargetView* rtv = NULL;
|
||||
ID3D11DepthStencilView* dsv = NULL;
|
||||
|
||||
if(rt) rtv = *(GSTexture11*)rt;
|
||||
if(ds) dsv = *(GSTexture11*)ds;
|
||||
|
||||
if(m_rtv != rtv || m_dsv != dsv)
|
||||
{
|
||||
m_ctx->OMSetRenderTargets(1, &rtv, dsv);
|
||||
|
||||
m_rtv = rtv;
|
||||
m_dsv = dsv;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT GSDevice11::CompileShader(uint32 id, const string& entry, D3D11_SHADER_MACRO* macro, ID3D11VertexShader** vs, D3D11_INPUT_ELEMENT_DESC* layout, int count, ID3D11InputLayout** il)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
vector<D3D11_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, m_shader.model.c_str());
|
||||
|
||||
CComPtr<ID3D11Blob> shader, error;
|
||||
|
||||
hr = D3DX11CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), m_shader.vs.c_str(), 0, 0, NULL, &shader, &error, NULL);
|
||||
|
||||
if(error)
|
||||
{
|
||||
printf("%s\n", (const char*)error->GetBufferPointer());
|
||||
}
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = m_dev->CreateVertexShader((void*)shader->GetBufferPointer(), shader->GetBufferSize(), NULL, vs);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = m_dev->CreateInputLayout(layout, count, shader->GetBufferPointer(), shader->GetBufferSize(), il);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GSDevice11::CompileShader(uint32 id, const string& entry, D3D11_SHADER_MACRO* macro, ID3D11GeometryShader** gs)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
vector<D3D11_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, m_shader.model.c_str());
|
||||
|
||||
CComPtr<ID3D11Blob> shader, error;
|
||||
|
||||
hr = D3DX11CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), m_shader.gs.c_str(), 0, 0, NULL, &shader, &error, NULL);
|
||||
|
||||
if(error)
|
||||
{
|
||||
printf("%s\n", (const char*)error->GetBufferPointer());
|
||||
}
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = m_dev->CreateGeometryShader((void*)shader->GetBufferPointer(), shader->GetBufferSize(), NULL, gs);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GSDevice11::CompileShader(uint32 id, const string& entry, D3D11_SHADER_MACRO* macro, ID3D11PixelShader** ps)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
vector<D3D11_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, m_shader.model.c_str());
|
||||
|
||||
CComPtr<ID3D10Blob> shader, error;
|
||||
|
||||
hr = D3DX11CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), m_shader.ps.c_str(), 0, 0, NULL, &shader, &error, NULL);
|
||||
|
||||
if(error)
|
||||
{
|
||||
printf("%s\n", (const char*)error->GetBufferPointer());
|
||||
}
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = m_dev->CreatePixelShader((void*)shader->GetBufferPointer(), shader->GetBufferSize(),NULL, ps);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSDevice.h"
|
||||
#include "GSTexture11.h"
|
||||
|
||||
class GSDevice11 : public GSDevice
|
||||
{
|
||||
ID3D11Buffer* m_vb;
|
||||
size_t m_vb_stride;
|
||||
ID3D11InputLayout* m_layout;
|
||||
D3D11_PRIMITIVE_TOPOLOGY m_topology;
|
||||
ID3D11VertexShader* m_vs;
|
||||
ID3D11Buffer* m_vs_cb;
|
||||
ID3D11GeometryShader* m_gs;
|
||||
ID3D11ShaderResourceView* m_ps_srv[2];
|
||||
ID3D11PixelShader* m_ps;
|
||||
ID3D11Buffer* m_ps_cb;
|
||||
ID3D11SamplerState* m_ps_ss[2];
|
||||
GSVector2i m_viewport;
|
||||
GSVector4i m_scissor;
|
||||
ID3D11DepthStencilState* m_dss;
|
||||
uint8 m_sref;
|
||||
ID3D11BlendState* m_bs;
|
||||
float m_bf;
|
||||
ID3D11RenderTargetView* m_rtv;
|
||||
ID3D11DepthStencilView* m_dsv;
|
||||
|
||||
//
|
||||
|
||||
GSTexture* Create(int type, int w, int h, int format);
|
||||
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
|
||||
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
|
||||
|
||||
//
|
||||
|
||||
D3D_FEATURE_LEVEL m_level;
|
||||
CComPtr<ID3D11Device> m_dev;
|
||||
CComPtr<ID3D11DeviceContext> m_ctx;
|
||||
CComPtr<IDXGISwapChain> m_swapchain;
|
||||
struct {string model, vs, gs, ps;} m_shader;
|
||||
|
||||
struct
|
||||
{
|
||||
CComPtr<ID3D11Buffer> vb, vb_old;
|
||||
size_t stride, start, count, limit;
|
||||
} m_vertices;
|
||||
|
||||
public: // TODO
|
||||
CComPtr<ID3D11RasterizerState> m_rs;
|
||||
|
||||
struct
|
||||
{
|
||||
CComPtr<ID3D11InputLayout> il;
|
||||
CComPtr<ID3D11VertexShader> vs;
|
||||
CComPtr<ID3D11PixelShader> ps[7];
|
||||
CComPtr<ID3D11SamplerState> ln;
|
||||
CComPtr<ID3D11SamplerState> pt;
|
||||
CComPtr<ID3D11DepthStencilState> dss;
|
||||
CComPtr<ID3D11BlendState> bs;
|
||||
} m_convert;
|
||||
|
||||
struct
|
||||
{
|
||||
CComPtr<ID3D11PixelShader> ps[2];
|
||||
CComPtr<ID3D11Buffer> cb;
|
||||
CComPtr<ID3D11BlendState> bs;
|
||||
} m_merge;
|
||||
|
||||
struct
|
||||
{
|
||||
CComPtr<ID3D11PixelShader> ps[4];
|
||||
CComPtr<ID3D11Buffer> cb;
|
||||
} m_interlace;
|
||||
|
||||
public:
|
||||
GSDevice11();
|
||||
virtual ~GSDevice11();
|
||||
|
||||
bool Create(GSWnd* wnd, bool vsync);
|
||||
bool Reset(int w, int h, bool fs);
|
||||
|
||||
void Flip();
|
||||
|
||||
void BeginScene();
|
||||
void DrawPrimitive();
|
||||
void EndScene();
|
||||
|
||||
void ClearRenderTarget(GSTexture* t, const GSVector4& c);
|
||||
void ClearRenderTarget(GSTexture* t, uint32 c);
|
||||
void ClearDepth(GSTexture* t, float c);
|
||||
void ClearStencil(GSTexture* t, uint8 c);
|
||||
|
||||
GSTexture* CreateRenderTarget(int w, int h, int format = 0);
|
||||
GSTexture* CreateDepthStencil(int w, int h, int format = 0);
|
||||
GSTexture* CreateTexture(int w, int h, int format = 0);
|
||||
GSTexture* CreateOffscreen(int w, int h, int format = 0);
|
||||
|
||||
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
|
||||
|
||||
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
|
||||
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear = true);
|
||||
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear = true);
|
||||
|
||||
void IASetVertexBuffer(const void* vertices, size_t stride, size_t count);
|
||||
void IASetVertexBuffer(ID3D11Buffer* vb, size_t stride);
|
||||
void IASetInputLayout(ID3D11InputLayout* layout);
|
||||
void IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology);
|
||||
void VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb);
|
||||
void GSSetShader(ID3D11GeometryShader* gs);
|
||||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb);
|
||||
void PSSetSamplerState(ID3D11SamplerState* ss0, ID3D11SamplerState* ss1);
|
||||
void RSSet(int width, int height, const GSVector4i* scissor = NULL);
|
||||
void OMSetDepthStencilState(ID3D11DepthStencilState* dss, uint8 sref);
|
||||
void OMSetBlendState(ID3D11BlendState* bs, float bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds);
|
||||
|
||||
ID3D11Device* operator->() {return m_dev;}
|
||||
operator ID3D11Device*() {return m_dev;}
|
||||
operator ID3D11DeviceContext*() {return m_ctx;}
|
||||
|
||||
HRESULT CompileShader(uint32 id, const string& entry, D3D11_SHADER_MACRO* macro, ID3D11VertexShader** vs, D3D11_INPUT_ELEMENT_DESC* layout, int count, ID3D11InputLayout** il);
|
||||
HRESULT CompileShader(uint32 id, const string& entry, D3D11_SHADER_MACRO* macro, ID3D11GeometryShader** gs);
|
||||
HRESULT CompileShader(uint32 id, const string& entry, D3D11_SHADER_MACRO* macro, ID3D11PixelShader** ps);
|
||||
};
|
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GSRendererHW11.h"
|
||||
#include "GSCrc.h"
|
||||
#include "resource.h"
|
||||
|
||||
GSRendererHW11::GSRendererHW11(uint8* base, bool mt, void (*irq)())
|
||||
: GSRendererHW<GSVertexHW11>(base, mt, irq, new GSDevice11(), new GSTextureCache11(this))
|
||||
{
|
||||
InitVertexKick<GSRendererHW11>();
|
||||
}
|
||||
|
||||
bool GSRendererHW11::Create(const string& title)
|
||||
{
|
||||
if(!__super::Create(title))
|
||||
return false;
|
||||
|
||||
if(!m_tfx.Create((GSDevice11*)m_dev))
|
||||
return false;
|
||||
|
||||
//
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC dsd;
|
||||
|
||||
memset(&dsd, 0, sizeof(dsd));
|
||||
|
||||
dsd.DepthEnable = false;
|
||||
dsd.StencilEnable = true;
|
||||
dsd.StencilReadMask = 1;
|
||||
dsd.StencilWriteMask = 1;
|
||||
dsd.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||
dsd.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
|
||||
dsd.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||
dsd.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
|
||||
dsd.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
|
||||
(*(GSDevice11*)m_dev)->CreateDepthStencilState(&dsd, &m_date.dss);
|
||||
|
||||
D3D11_BLEND_DESC bd;
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
(*(GSDevice11*)m_dev)->CreateBlendState(&bd, &m_date.bs);
|
||||
|
||||
//
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<uint32 prim, uint32 tme, uint32 fst>
|
||||
void GSRendererHW11::VertexKick(bool skip)
|
||||
{
|
||||
GSVertexHW11& dst = m_vl.AddTail();
|
||||
|
||||
dst.vi[0] = m_v.vi[0];
|
||||
dst.vi[1] = m_v.vi[1];
|
||||
|
||||
if(tme && fst)
|
||||
{
|
||||
GSVector4::storel(&dst.ST, m_v.GetUV());
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
if(GSVertexHW11* v = DrawingKick<prim>(skip, count))
|
||||
{
|
||||
GSVector4i scissor = m_context->scissor.dx10;
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
GSVector4i pmin, pmax, v0, v1, v2;
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy).upl16();
|
||||
pmin = v0;
|
||||
pmax = v0;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy);
|
||||
v1 = GSVector4i::load((int)v[1].p.xy);
|
||||
pmin = v0.min_u16(v1).upl16();
|
||||
pmax = v0.max_u16(v1).upl16();
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy);
|
||||
v1 = GSVector4i::load((int)v[1].p.xy);
|
||||
v2 = GSVector4i::load((int)v[2].p.xy);
|
||||
pmin = v0.min_u16(v1).min_u16(v2).upl16();
|
||||
pmax = v0.max_u16(v1).max_u16(v2).upl16();
|
||||
break;
|
||||
}
|
||||
|
||||
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
if(test.mask() & 0xff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
if(v[0].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRendererHW11::Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex)
|
||||
{
|
||||
GSDrawingEnvironment& env = m_env;
|
||||
GSDrawingContext* context = m_context;
|
||||
/*
|
||||
if(s_dump)
|
||||
{
|
||||
TRACE(_T("\n"));
|
||||
|
||||
TRACE(_T("PRIM = %d, ZMSK = %d, ZTE = %d, ZTST = %d, ATE = %d, ATST = %d, AFAIL = %d, AREF = %02x\n"),
|
||||
PRIM->PRIM, context->ZBUF.ZMSK,
|
||||
context->TEST.ZTE, context->TEST.ZTST,
|
||||
context->TEST.ATE, context->TEST.ATST, context->TEST.AFAIL, context->TEST.AREF);
|
||||
|
||||
for(int i = 0; i < m_count; i++)
|
||||
{
|
||||
TRACE(_T("[%d] %3.0f %3.0f %3.0f %3.0f\n"), i, (float)m_vertices[i].p.x / 16, (float)m_vertices[i].p.y / 16, (float)m_vertices[i].p.z, (float)m_vertices[i].a);
|
||||
}
|
||||
}
|
||||
*/
|
||||
D3D11_PRIMITIVE_TOPOLOGY topology;
|
||||
int prims = 0;
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
|
||||
prims = m_count;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
topology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
|
||||
prims = m_count / 2;
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
prims = m_count / 3;
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Prim, prims);
|
||||
m_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
|
||||
// date
|
||||
|
||||
SetupDATE(rt, ds);
|
||||
|
||||
//
|
||||
|
||||
m_dev->BeginScene();
|
||||
|
||||
// om
|
||||
|
||||
GSTextureFX11::OMDepthStencilSelector om_dssel;
|
||||
|
||||
om_dssel.zte = context->TEST.ZTE;
|
||||
om_dssel.ztst = context->TEST.ZTST;
|
||||
om_dssel.zwe = !context->ZBUF.ZMSK;
|
||||
om_dssel.date = context->FRAME.PSM != PSM_PSMCT24 ? context->TEST.DATE : 0;
|
||||
|
||||
GSTextureFX11::OMBlendSelector om_bsel;
|
||||
|
||||
om_bsel.abe = PRIM->ABE || (prim == 1 || prim == 2) && PRIM->AA1;
|
||||
om_bsel.a = context->ALPHA.A;
|
||||
om_bsel.b = context->ALPHA.B;
|
||||
om_bsel.c = context->ALPHA.C;
|
||||
om_bsel.d = context->ALPHA.D;
|
||||
om_bsel.wr = (context->FRAME.FBMSK & 0x000000ff) != 0x000000ff;
|
||||
om_bsel.wg = (context->FRAME.FBMSK & 0x0000ff00) != 0x0000ff00;
|
||||
om_bsel.wb = (context->FRAME.FBMSK & 0x00ff0000) != 0x00ff0000;
|
||||
om_bsel.wa = (context->FRAME.FBMSK & 0xff000000) != 0xff000000;
|
||||
|
||||
float bf = (float)(int)context->ALPHA.FIX / 0x80;
|
||||
|
||||
// vs
|
||||
|
||||
GSTextureFX11::VSSelector vs_sel;
|
||||
|
||||
vs_sel.bppz = 0;
|
||||
vs_sel.tme = PRIM->TME;
|
||||
vs_sel.fst = PRIM->FST;
|
||||
vs_sel.prim = prim;
|
||||
|
||||
if(om_dssel.zte && om_dssel.ztst > 0 && om_dssel.zwe)
|
||||
{
|
||||
if(context->ZBUF.PSM == PSM_PSMZ24)
|
||||
{
|
||||
if(WrapZ(0xffffff))
|
||||
{
|
||||
vs_sel.bppz = 1;
|
||||
om_dssel.ztst = 1;
|
||||
}
|
||||
}
|
||||
else if(context->ZBUF.PSM == PSM_PSMZ16 || context->ZBUF.PSM == PSM_PSMZ16S)
|
||||
{
|
||||
if(WrapZ(0xffff))
|
||||
{
|
||||
vs_sel.bppz = 2;
|
||||
om_dssel.ztst = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSTextureFX11::VSConstantBuffer vs_cb;
|
||||
|
||||
float sx = 2.0f * rt->m_scale.x / (rt->GetWidth() * 16);
|
||||
float sy = 2.0f * rt->m_scale.y / (rt->GetHeight() * 16);
|
||||
float ox = (float)(int)context->XYOFFSET.OFX;
|
||||
float oy = (float)(int)context->XYOFFSET.OFY;
|
||||
float ox2 = 1.0f / rt->GetWidth();
|
||||
float oy2 = 1.0f / rt->GetHeight();
|
||||
|
||||
vs_cb.VertexScale = GSVector4(sx, -sy, 1.0f / UINT_MAX, 0.0f);
|
||||
vs_cb.VertexOffset = GSVector4(ox * sx - ox2 + 1, -(oy * sy - oy2 + 1), 0.0f, -1.0f);
|
||||
vs_cb.TextureScale = GSVector2(1.0f, 1.0f);
|
||||
|
||||
if(PRIM->TME && PRIM->FST)
|
||||
{
|
||||
vs_cb.TextureScale.x = 1.0f / (16 << context->TEX0.TW);
|
||||
vs_cb.TextureScale.y = 1.0f / (16 << context->TEX0.TH);
|
||||
}
|
||||
|
||||
// gs
|
||||
|
||||
GSTextureFX11::GSSelector gs_sel;
|
||||
|
||||
gs_sel.iip = PRIM->IIP;
|
||||
gs_sel.prim = GSUtil::GetPrimClass(prim);
|
||||
|
||||
// ps
|
||||
|
||||
GSTextureFX11::PSSelector ps_sel;
|
||||
|
||||
ps_sel.fst = PRIM->FST;
|
||||
ps_sel.wms = context->CLAMP.WMS;
|
||||
ps_sel.wmt = context->CLAMP.WMT;
|
||||
ps_sel.bpp = 0;
|
||||
ps_sel.aem = env.TEXA.AEM;
|
||||
ps_sel.tfx = context->TEX0.TFX;
|
||||
ps_sel.tcc = context->TEX0.TCC;
|
||||
ps_sel.ate = context->TEST.ATE;
|
||||
ps_sel.atst = context->TEST.ATST;
|
||||
ps_sel.fog = PRIM->FGE;
|
||||
ps_sel.clr1 = om_bsel.abe && om_bsel.a == 1 && om_bsel.b == 2 && om_bsel.d == 1;
|
||||
ps_sel.fba = context->FBA.FBA;
|
||||
ps_sel.aout = context->FRAME.PSM == PSM_PSMCT16 || context->FRAME.PSM == PSM_PSMCT16S || (context->FRAME.FBMSK & 0xff000000) == 0x7f000000 ? 1 : 0;
|
||||
ps_sel.ltf = m_filter == 2 ? context->TEX1.IsLinear() : m_filter;
|
||||
|
||||
GSTextureFX11::PSSamplerSelector ps_ssel;
|
||||
|
||||
ps_ssel.tau = 0;
|
||||
ps_ssel.tav = 0;
|
||||
ps_ssel.ltf = ps_sel.ltf;
|
||||
|
||||
GSTextureFX11::PSConstantBuffer ps_cb;
|
||||
|
||||
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, (int)context->TEST.AREF) / 255;
|
||||
|
||||
if(context->TEST.ATST == 2 || context->TEST.ATST == 5)
|
||||
{
|
||||
ps_cb.FogColor_AREF.a -= 0.9f / 255;
|
||||
}
|
||||
else if(context->TEST.ATST == 3 || context->TEST.ATST == 6)
|
||||
{
|
||||
ps_cb.FogColor_AREF.a += 0.9f / 255;
|
||||
}
|
||||
|
||||
if(tex)
|
||||
{
|
||||
ps_sel.bpp = tex->m_bpp;
|
||||
|
||||
int w = tex->m_texture->GetWidth();
|
||||
int h = tex->m_texture->GetHeight();
|
||||
|
||||
ps_cb.WH_TA = GSVector4((int)(1 << context->TEX0.TW), (int)(1 << context->TEX0.TH), env.TEXA.TA0, env.TEXA.TA1) / GSVector4(1, 255).xxyy();
|
||||
ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / GSVector4(w, h).xyxy();
|
||||
|
||||
switch(context->CLAMP.WMS)
|
||||
{
|
||||
case 0:
|
||||
ps_ssel.tau = 1;
|
||||
break;
|
||||
case 1:
|
||||
ps_ssel.tau = 0;
|
||||
break;
|
||||
case 2:
|
||||
ps_cb.MinMax.x = ((float)(int)context->CLAMP.MINU) / (1 << context->TEX0.TW);
|
||||
ps_cb.MinMax.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
|
||||
ps_cb.MinMaxF.x = ((float)(int)context->CLAMP.MINU + 0.5f) / (1 << context->TEX0.TW);
|
||||
ps_cb.MinMaxF.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
|
||||
ps_ssel.tau = 0;
|
||||
break;
|
||||
case 3:
|
||||
ps_cb.MskFix.x = context->CLAMP.MINU;
|
||||
ps_cb.MskFix.z = context->CLAMP.MAXU;
|
||||
ps_ssel.tau = 1;
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
switch(context->CLAMP.WMT)
|
||||
{
|
||||
case 0:
|
||||
ps_ssel.tav = 1;
|
||||
break;
|
||||
case 1:
|
||||
ps_ssel.tav = 0;
|
||||
break;
|
||||
case 2:
|
||||
ps_cb.MinMax.y = ((float)(int)context->CLAMP.MINV) / (1 << context->TEX0.TH);
|
||||
ps_cb.MinMax.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
|
||||
ps_cb.MinMaxF.y = ((float)(int)context->CLAMP.MINV + 0.5f) / (1 << context->TEX0.TH);
|
||||
ps_cb.MinMaxF.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
|
||||
ps_ssel.tav = 0;
|
||||
break;
|
||||
case 3:
|
||||
ps_cb.MskFix.y = context->CLAMP.MINV;
|
||||
ps_cb.MskFix.w = context->CLAMP.MAXV;
|
||||
ps_ssel.tav = 1;
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ps_sel.tfx = 4;
|
||||
}
|
||||
|
||||
// rs
|
||||
|
||||
int w = rt->GetWidth();
|
||||
int h = rt->GetHeight();
|
||||
|
||||
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(0, 0, w, h));
|
||||
|
||||
//
|
||||
|
||||
m_tfx.SetupOM(om_dssel, om_bsel, bf, rt, ds);
|
||||
m_tfx.SetupIA(m_vertices, m_count, topology);
|
||||
m_tfx.SetupVS(vs_sel, &vs_cb);
|
||||
m_tfx.SetupGS(gs_sel);
|
||||
m_tfx.SetupPS(ps_sel, &ps_cb, ps_ssel, tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);
|
||||
m_tfx.SetupRS(w, h, scissor);
|
||||
|
||||
// draw
|
||||
|
||||
if(context->TEST.DoFirstPass())
|
||||
{
|
||||
m_tfx.Draw();
|
||||
}
|
||||
|
||||
if(context->TEST.DoSecondPass())
|
||||
{
|
||||
ASSERT(!env.PABE.PABE);
|
||||
|
||||
static const uint32 iatst[] = {1, 0, 5, 6, 7, 2, 3, 4};
|
||||
|
||||
ps_sel.atst = iatst[ps_sel.atst];
|
||||
|
||||
m_tfx.UpdatePS(ps_sel, &ps_cb, ps_ssel);
|
||||
|
||||
bool z = om_dssel.zwe;
|
||||
bool r = om_bsel.wr;
|
||||
bool g = om_bsel.wg;
|
||||
bool b = om_bsel.wb;
|
||||
bool a = om_bsel.wa;
|
||||
|
||||
switch(context->TEST.AFAIL)
|
||||
{
|
||||
case 0: z = r = g = b = a = false; break; // none
|
||||
case 1: z = false; break; // rgba
|
||||
case 2: r = g = b = a = false; break; // z
|
||||
case 3: z = a = false; break; // rgb
|
||||
default: __assume(0);
|
||||
}
|
||||
|
||||
if(z || r || g || b || a)
|
||||
{
|
||||
om_dssel.zwe = z;
|
||||
om_bsel.wr = r;
|
||||
om_bsel.wg = g;
|
||||
om_bsel.wb = b;
|
||||
om_bsel.wa = a;
|
||||
|
||||
m_tfx.UpdateOM(om_dssel, om_bsel, bf);
|
||||
|
||||
m_tfx.Draw();
|
||||
}
|
||||
}
|
||||
|
||||
m_dev->EndScene();
|
||||
}
|
||||
|
||||
bool GSRendererHW11::WrapZ(uint32 maxz)
|
||||
{
|
||||
// should only run once if z values are in the z buffer range
|
||||
|
||||
for(int i = 0, j = m_count; i < j; i++)
|
||||
{
|
||||
if(m_vertices[i].p.z <= maxz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSRendererHW11::SetupDATE(GSTexture* rt, GSTexture* ds)
|
||||
{
|
||||
if(!m_context->TEST.DATE) return; // || (::GetAsyncKeyState(VK_CONTROL) & 0x8000)
|
||||
|
||||
GSDevice11* dev = (GSDevice11*)m_dev;
|
||||
|
||||
int w = rt->GetWidth();
|
||||
int h = rt->GetHeight();
|
||||
|
||||
if(GSTexture* t = dev->CreateRenderTarget(w, h))
|
||||
{
|
||||
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
|
||||
|
||||
GSVector4 mm;
|
||||
|
||||
// TODO
|
||||
|
||||
mm = GSVector4(-1, -1, 1, 1);
|
||||
|
||||
// if(m_count < 100)
|
||||
{
|
||||
GSVector4 pmin(65535, 65535, 0, 0);
|
||||
GSVector4 pmax = GSVector4::zero();
|
||||
|
||||
for(int i = 0, j = m_count; i < j; i++)
|
||||
{
|
||||
GSVector4 p(m_vertices[i].vi[0].uph16());
|
||||
|
||||
pmin = p.minv(pmin);
|
||||
pmax = p.maxv(pmax);
|
||||
}
|
||||
|
||||
mm += pmin.xyxy(pmax);
|
||||
|
||||
float sx = 2.0f * rt->m_scale.x / (w * 16);
|
||||
float sy = 2.0f * rt->m_scale.y / (h * 16);
|
||||
float ox = (float)(int)m_context->XYOFFSET.OFX;
|
||||
float oy = (float)(int)m_context->XYOFFSET.OFY;
|
||||
|
||||
mm.x = (mm.x - ox) * sx - 1;
|
||||
mm.y = (mm.y - oy) * sy - 1;
|
||||
mm.z = (mm.z - ox) * sx - 1;
|
||||
mm.w = (mm.w - oy) * sy - 1;
|
||||
|
||||
if(mm.x < -1) mm.x = -1;
|
||||
if(mm.y < -1) mm.y = -1;
|
||||
if(mm.z > +1) mm.z = +1;
|
||||
if(mm.w > +1) mm.w = +1;
|
||||
}
|
||||
|
||||
GSVector4 uv = (mm + 1.0f) / 2.0f;
|
||||
|
||||
//
|
||||
|
||||
dev->BeginScene();
|
||||
|
||||
dev->ClearStencil(ds, 0);
|
||||
|
||||
// om
|
||||
|
||||
dev->OMSetDepthStencilState(m_date.dss, 1);
|
||||
dev->OMSetBlendState(m_date.bs, 0);
|
||||
dev->OMSetRenderTargets(t, ds);
|
||||
|
||||
// ia
|
||||
|
||||
GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(mm.x, -mm.y, 0.5f, 1.0f), GSVector2(uv.x, uv.y)},
|
||||
{GSVector4(mm.z, -mm.y, 0.5f, 1.0f), GSVector2(uv.z, uv.y)},
|
||||
{GSVector4(mm.x, -mm.w, 0.5f, 1.0f), GSVector2(uv.x, uv.w)},
|
||||
{GSVector4(mm.z, -mm.w, 0.5f, 1.0f), GSVector2(uv.z, uv.w)},
|
||||
};
|
||||
|
||||
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
|
||||
dev->IASetInputLayout(dev->m_convert.il);
|
||||
dev->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
// vs
|
||||
|
||||
dev->VSSetShader(dev->m_convert.vs, NULL);
|
||||
|
||||
// gs
|
||||
|
||||
dev->GSSetShader(NULL);
|
||||
|
||||
// ps
|
||||
|
||||
dev->PSSetShaderResources(rt, NULL);
|
||||
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
|
||||
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
|
||||
|
||||
// rs
|
||||
|
||||
dev->RSSet(w, h);
|
||||
|
||||
// set
|
||||
|
||||
dev->DrawPrimitive();
|
||||
|
||||
//
|
||||
|
||||
dev->EndScene();
|
||||
|
||||
dev->Recycle(t);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSRendererHW.h"
|
||||
#include "GSVertexHW.h"
|
||||
#include "GSTextureCache11.h"
|
||||
#include "GSTextureFX11.h"
|
||||
|
||||
class GSRendererHW11 : public GSRendererHW<GSVertexHW11>
|
||||
{
|
||||
bool WrapZ(uint32 maxz);
|
||||
|
||||
protected:
|
||||
GSTextureFX11 m_tfx;
|
||||
|
||||
void Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex);
|
||||
|
||||
struct
|
||||
{
|
||||
CComPtr<ID3D11DepthStencilState> dss;
|
||||
CComPtr<ID3D11BlendState> bs;
|
||||
} m_date;
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds);
|
||||
|
||||
public:
|
||||
GSRendererHW11(uint8* base, bool mt, void (*irq)());
|
||||
|
||||
bool Create(const string& title);
|
||||
|
||||
template<uint32 prim, uint32 tme, uint32 fst> void VertexKick(bool skip);
|
||||
};
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GSTexture11.h"
|
||||
|
||||
GSTexture11::GSTexture11(ID3D11Texture2D* texture)
|
||||
: m_texture(texture)
|
||||
{
|
||||
ASSERT(m_texture);
|
||||
|
||||
m_texture->GetDevice(&m_dev);
|
||||
m_texture->GetDesc(&m_desc);
|
||||
|
||||
m_dev->GetImmediateContext(&m_ctx);
|
||||
}
|
||||
|
||||
int GSTexture11::GetType() const
|
||||
{
|
||||
if(m_desc.BindFlags & D3D11_BIND_RENDER_TARGET) return GSTexture::RenderTarget;
|
||||
if(m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL) return GSTexture::DepthStencil;
|
||||
if(m_desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) return GSTexture::Texture;
|
||||
if(m_desc.Usage == D3D11_USAGE_STAGING) return GSTexture::Offscreen;
|
||||
return GSTexture::None;
|
||||
}
|
||||
|
||||
int GSTexture11::GetWidth() const
|
||||
{
|
||||
return m_desc.Width;
|
||||
}
|
||||
|
||||
int GSTexture11::GetHeight() const
|
||||
{
|
||||
return m_desc.Height;
|
||||
}
|
||||
|
||||
int GSTexture11::GetFormat() const
|
||||
{
|
||||
return m_desc.Format;
|
||||
}
|
||||
|
||||
bool GSTexture11::Update(const GSVector4i& r, const void* data, int pitch)
|
||||
{
|
||||
if(m_dev && m_texture)
|
||||
{
|
||||
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
|
||||
|
||||
m_ctx->UpdateSubresource(m_texture, 0, &box, data, pitch, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GSTexture11::Map(GSMap& m, const GSVector4i* r)
|
||||
{
|
||||
if(r != NULL)
|
||||
{
|
||||
// ASSERT(0); // not implemented
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_texture)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
|
||||
if(SUCCEEDED(m_ctx->Map(m_texture, 0, D3D11_MAP_READ_WRITE, 0, &map)))
|
||||
{
|
||||
m.bits = (uint8*)map.pData;
|
||||
m.pitch = (int)map.RowPitch;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GSTexture11::Unmap()
|
||||
{
|
||||
if(m_texture)
|
||||
{
|
||||
m_ctx->Unmap(m_texture, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool GSTexture11::Save(const string& fn, bool dds)
|
||||
{
|
||||
CComPtr<ID3D11Resource> res;
|
||||
|
||||
if(m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
m_texture->GetDesc(&desc);
|
||||
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
|
||||
CComPtr<ID3D11Texture2D> src, dst;
|
||||
|
||||
hr = m_dev->CreateTexture2D(&desc, NULL, &src);
|
||||
|
||||
m_ctx->CopyResource(src, m_texture);
|
||||
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
|
||||
hr = m_dev->CreateTexture2D(&desc, NULL, &dst);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sm, dm;
|
||||
|
||||
hr = m_ctx->Map(src, 0, D3D11_MAP_READ, 0, &sm);
|
||||
hr = m_ctx->Map(dst, 0, D3D11_MAP_WRITE, 0, &dm);
|
||||
|
||||
uint8* s = (uint8*)sm.pData;
|
||||
uint8* d = (uint8*)dm.pData;
|
||||
|
||||
for(uint32 y = 0; y < desc.Height; y++, s += sm.RowPitch, d += dm.RowPitch)
|
||||
{
|
||||
for(uint32 x = 0; x < desc.Width; x++)
|
||||
{
|
||||
((uint32*)d)[x] = (uint32)(((float*)s)[x*2] * UINT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
m_ctx->Unmap(src, 0);
|
||||
m_ctx->Unmap(dst, 0);
|
||||
|
||||
res = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = m_texture;
|
||||
}
|
||||
|
||||
return SUCCEEDED(D3DX11SaveTextureToFile(m_ctx, res, dds ? D3DX11_IFF_DDS : D3DX11_IFF_BMP, fn.c_str()));
|
||||
}
|
||||
|
||||
GSTexture11::operator ID3D11Texture2D*()
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
GSTexture11::operator ID3D11ShaderResourceView*()
|
||||
{
|
||||
if(!m_srv && m_dev && m_texture)
|
||||
{
|
||||
m_dev->CreateShaderResourceView(m_texture, NULL, &m_srv);
|
||||
}
|
||||
|
||||
return m_srv;
|
||||
}
|
||||
|
||||
GSTexture11::operator ID3D11RenderTargetView*()
|
||||
{
|
||||
ASSERT(m_dev);
|
||||
|
||||
if(!m_rtv && m_dev && m_texture)
|
||||
{
|
||||
m_dev->CreateRenderTargetView(m_texture, NULL, &m_rtv);
|
||||
}
|
||||
|
||||
return m_rtv;
|
||||
}
|
||||
|
||||
GSTexture11::operator ID3D11DepthStencilView*()
|
||||
{
|
||||
if(!m_dsv && m_dev && m_texture)
|
||||
{
|
||||
m_dev->CreateDepthStencilView(m_texture, NULL, &m_dsv);
|
||||
}
|
||||
|
||||
return m_dsv;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSTexture.h"
|
||||
|
||||
class GSTexture11 : public GSTexture
|
||||
{
|
||||
CComPtr<ID3D11Device> m_dev;
|
||||
CComPtr<ID3D11DeviceContext> m_ctx;
|
||||
CComPtr<ID3D11Texture2D> m_texture;
|
||||
D3D11_TEXTURE2D_DESC m_desc;
|
||||
CComPtr<ID3D11ShaderResourceView> m_srv;
|
||||
CComPtr<ID3D11RenderTargetView> m_rtv;
|
||||
CComPtr<ID3D11DepthStencilView> m_dsv;
|
||||
|
||||
public:
|
||||
explicit GSTexture11(ID3D11Texture2D* texture);
|
||||
|
||||
int GetType() const;
|
||||
int GetWidth() const;
|
||||
int GetHeight() const;
|
||||
int GetFormat() const;
|
||||
|
||||
bool Update(const GSVector4i& r, const void* data, int pitch);
|
||||
bool Map(GSMap& m, const GSVector4i* r);
|
||||
void Unmap();
|
||||
bool Save(const string& fn, bool dds = false);
|
||||
|
||||
operator ID3D11Texture2D*();
|
||||
operator ID3D11ShaderResourceView*();
|
||||
operator ID3D11RenderTargetView*();
|
||||
operator ID3D11DepthStencilView*();
|
||||
};
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "GSTextureCache11.h"
|
||||
|
||||
// GSTextureCache11
|
||||
|
||||
GSTextureCache11::GSTextureCache11(GSRenderer* r)
|
||||
: GSTextureCache(r)
|
||||
{
|
||||
}
|
||||
|
||||
// GSRenderTargetHW10
|
||||
|
||||
void GSTextureCache11::GSRenderTargetHW11::Read(const GSVector4i& r)
|
||||
{
|
||||
if(m_TEX0.PSM != PSM_PSMCT32
|
||||
&& m_TEX0.PSM != PSM_PSMCT24
|
||||
&& m_TEX0.PSM != PSM_PSMCT16
|
||||
&& m_TEX0.PSM != PSM_PSMCT16S)
|
||||
{
|
||||
//ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_dirty.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, m_TEX0.TBP0);
|
||||
|
||||
// m_renderer->m_perfmon.Put(GSPerfMon::ReadRT, 1);
|
||||
|
||||
int w = r.width();
|
||||
int h = r.height();
|
||||
|
||||
GSVector4 src = GSVector4(r) * GSVector4(m_texture->m_scale).xyxy() / GSVector4(m_texture->GetSize()).xyxy();
|
||||
|
||||
DXGI_FORMAT format = m_TEX0.PSM == PSM_PSMCT16 || m_TEX0.PSM == PSM_PSMCT16S ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(m_texture, src, w, h, format))
|
||||
{
|
||||
GSTexture::GSMap m;
|
||||
|
||||
if(offscreen->Map(m))
|
||||
{
|
||||
// TODO: block level write
|
||||
|
||||
uint32 bp = m_TEX0.TBP0;
|
||||
uint32 bw = m_TEX0.TBW;
|
||||
|
||||
GSLocalMemory::pixelAddress pa = GSLocalMemory::m_psm[m_TEX0.PSM].pa;
|
||||
|
||||
if(m_TEX0.PSM == PSM_PSMCT32)
|
||||
{
|
||||
for(int y = r.top; y < r.bottom; y++, m.bits += m.pitch)
|
||||
{
|
||||
uint32 addr = pa(0, y, bp, bw);
|
||||
int* offset = GSLocalMemory::m_psm[m_TEX0.PSM].rowOffset[y & 7];
|
||||
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
{
|
||||
m_renderer->m_mem.WritePixel32(addr + offset[x], ((uint32*)m.bits)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_TEX0.PSM == PSM_PSMCT24)
|
||||
{
|
||||
for(int y = r.top; y < r.bottom; y++, m.bits += m.pitch)
|
||||
{
|
||||
uint32 addr = pa(0, y, bp, bw);
|
||||
int* offset = GSLocalMemory::m_psm[m_TEX0.PSM].rowOffset[y & 7];
|
||||
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
{
|
||||
m_renderer->m_mem.WritePixel24(addr + offset[x], ((uint32*)m.bits)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_TEX0.PSM == PSM_PSMCT16 || m_TEX0.PSM == PSM_PSMCT16S)
|
||||
{
|
||||
for(int y = r.top; y < r.bottom; y++, m.bits += m.pitch)
|
||||
{
|
||||
uint32 addr = pa(0, y, bp, bw);
|
||||
int* offset = GSLocalMemory::m_psm[m_TEX0.PSM].rowOffset[y & 7];
|
||||
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
{
|
||||
m_renderer->m_mem.WritePixel16(addr + offset[x], ((uint16*)m.bits)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
offscreen->Unmap();
|
||||
}
|
||||
|
||||
m_renderer->m_dev->Recycle(offscreen);
|
||||
}
|
||||
}
|
||||
|
||||
// GSTextureHW10
|
||||
|
||||
bool GSTextureCache11::GSCachedTextureHW11::Create()
|
||||
{
|
||||
// m_renderer->m_perfmon.Put(GSPerfMon::WriteTexture, 1);
|
||||
|
||||
m_TEX0 = m_renderer->m_context->TEX0;
|
||||
m_TEXA = m_renderer->m_env.TEXA;
|
||||
|
||||
m_bpp = 0;
|
||||
|
||||
ASSERT(m_texture == NULL);
|
||||
|
||||
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
|
||||
|
||||
return m_texture != NULL;
|
||||
}
|
||||
|
||||
bool GSTextureCache11::GSCachedTextureHW11::Create(GSRenderTarget* rt)
|
||||
{
|
||||
// TODO: clean up this mess
|
||||
|
||||
rt->Update();
|
||||
|
||||
// m_renderer->m_perfmon.Put(GSPerfMon::ConvertRT2T, 1);
|
||||
|
||||
m_TEX0 = m_renderer->m_context->TEX0;
|
||||
m_TEXA = m_renderer->m_env.TEXA;
|
||||
|
||||
m_rendered = true;
|
||||
|
||||
int tw = 1 << m_TEX0.TW;
|
||||
int th = 1 << m_TEX0.TH;
|
||||
int tp = (int)m_TEX0.TW << 6;
|
||||
|
||||
// do not round here!!! if edge becomes a black pixel and addressing mode is clamp => everything outside the clamped area turns into black (kh2 shadows)
|
||||
|
||||
int w = (int)(rt->m_texture->m_scale.x * tw);
|
||||
int h = (int)(rt->m_texture->m_scale.y * th);
|
||||
|
||||
GSVector2i rtsize = rt->m_texture->GetSize();
|
||||
|
||||
// pitch conversion
|
||||
|
||||
if(rt->m_TEX0.TBW != m_TEX0.TBW) // && rt->m_TEX0.PSM == m_TEX0.PSM
|
||||
{
|
||||
// sfex3 uses this trick (bw: 10 -> 5, wraps the right side below the left)
|
||||
|
||||
// ASSERT(rt->m_TEX0.TBW > m_TEX0.TBW); // otherwise scale.x need to be reduced to make the larger texture fit (TODO)
|
||||
|
||||
ASSERT(m_texture == NULL);
|
||||
|
||||
m_texture = m_renderer->m_dev->CreateRenderTarget(rtsize.x, rtsize.y);
|
||||
|
||||
GSVector4 size = GSVector4(rtsize).xyxy();
|
||||
GSVector4 scale = GSVector4(rt->m_texture->m_scale).xyxy();
|
||||
|
||||
int bw = 64;
|
||||
int bh = m_TEX0.PSM == PSM_PSMCT32 || m_TEX0.PSM == PSM_PSMCT24 ? 32 : 64;
|
||||
|
||||
GSVector4i br(0, 0, bw, bh);
|
||||
|
||||
int sw = (int)rt->m_TEX0.TBW << 6;
|
||||
|
||||
int dw = (int)m_TEX0.TBW << 6;
|
||||
int dh = 1 << m_TEX0.TH;
|
||||
|
||||
if(sw != 0)
|
||||
for(int dy = 0; dy < dh; dy += bh)
|
||||
{
|
||||
for(int dx = 0; dx < dw; dx += bw)
|
||||
{
|
||||
int o = dy * dw / bh + dx;
|
||||
|
||||
int sx = o % sw;
|
||||
int sy = o / sw;
|
||||
|
||||
GSVector4 src = GSVector4(GSVector4i(sx, sy).xyxy() + br) * scale / size;
|
||||
GSVector4 dst = GSVector4(GSVector4i(dx, dy).xyxy() + br) * scale;
|
||||
|
||||
m_renderer->m_dev->StretchRect(rt->m_texture, src, m_texture, dst);
|
||||
|
||||
// TODO: this is quite a lot of StretchRect, do it with one Draw
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(tw < tp)
|
||||
{
|
||||
// FIXME: timesplitters blurs the render target by blending itself over a couple of times
|
||||
|
||||
if(tw == 256 && th == 128 && tp == 512 && (m_TEX0.TBP0 == 0 || m_TEX0.TBP0 == 0x00e00))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// width/height conversion
|
||||
|
||||
GSVector2 scale = rt->m_texture->m_scale;
|
||||
|
||||
GSVector4 dst(0, 0, w, h);
|
||||
|
||||
if(w > rtsize.x)
|
||||
{
|
||||
scale.x = (float)rtsize.x / tw;
|
||||
dst.z = (float)rtsize.x * scale.x / rt->m_texture->m_scale.x;
|
||||
w = rtsize.x;
|
||||
}
|
||||
|
||||
if(h > rtsize.y)
|
||||
{
|
||||
scale.y = (float)rtsize.y / th;
|
||||
dst.w = (float)rtsize.y * scale.y / rt->m_texture->m_scale.y;
|
||||
h = rtsize.y;
|
||||
}
|
||||
|
||||
GSVector4 src(0, 0, w, h);
|
||||
|
||||
GSTexture* st = m_texture ? m_texture : rt->m_texture;
|
||||
GSTexture* dt = m_renderer->m_dev->CreateRenderTarget(w, h);
|
||||
|
||||
if(!m_texture)
|
||||
{
|
||||
m_texture = dt;
|
||||
}
|
||||
|
||||
if(src.x == dst.x && src.y == dst.y && src.z == dst.z && src.w == dst.w)
|
||||
{
|
||||
D3D11_BOX box = {0, 0, 0, w, h, 1};
|
||||
|
||||
ID3D11DeviceContext* ctx = *(GSDevice11*)m_renderer->m_dev;
|
||||
|
||||
ctx->CopySubresourceRegion(*(GSTexture11*)dt, 0, 0, 0, 0, *(GSTexture11*)st, 0, &box);
|
||||
}
|
||||
else
|
||||
{
|
||||
src.z /= st->GetWidth();
|
||||
src.w /= st->GetHeight();
|
||||
|
||||
m_renderer->m_dev->StretchRect(st, src, dt, dst);
|
||||
}
|
||||
|
||||
if(dt != m_texture)
|
||||
{
|
||||
m_renderer->m_dev->Recycle(m_texture);
|
||||
|
||||
m_texture = dt;
|
||||
}
|
||||
|
||||
m_texture->m_scale = scale;
|
||||
|
||||
switch(m_TEX0.PSM)
|
||||
{
|
||||
case PSM_PSMCT32:
|
||||
m_bpp = 0;
|
||||
break;
|
||||
case PSM_PSMCT24:
|
||||
m_bpp = 1;
|
||||
break;
|
||||
case PSM_PSMCT16:
|
||||
case PSM_PSMCT16S:
|
||||
m_bpp = 2;
|
||||
break;
|
||||
case PSM_PSMT8H:
|
||||
m_bpp = 3;
|
||||
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
|
||||
m_initpalette = true;
|
||||
break;
|
||||
case PSM_PSMT4HL:
|
||||
case PSM_PSMT4HH:
|
||||
ASSERT(0); // TODO
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSTextureCache11::GSCachedTextureHW11::Create(GSDepthStencil* ds)
|
||||
{
|
||||
m_rendered = true;
|
||||
|
||||
// TODO
|
||||
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSTextureCache.h"
|
||||
#include "GSDevice11.h"
|
||||
|
||||
class GSTextureCache11 : public GSTextureCache
|
||||
{
|
||||
class GSRenderTargetHW11 : public GSRenderTarget
|
||||
{
|
||||
public:
|
||||
explicit GSRenderTargetHW11(GSRenderer* r) : GSRenderTarget(r) {}
|
||||
|
||||
void Read(const GSVector4i& r);
|
||||
};
|
||||
|
||||
class GSDepthStencilHW11 : public GSDepthStencil
|
||||
{
|
||||
public:
|
||||
explicit GSDepthStencilHW11(GSRenderer* r) : GSDepthStencil(r) {}
|
||||
};
|
||||
|
||||
class GSCachedTextureHW11 : public GSCachedTexture
|
||||
{
|
||||
public:
|
||||
explicit GSCachedTextureHW11(GSRenderer* r) : GSCachedTexture(r) {}
|
||||
|
||||
bool Create();
|
||||
bool Create(GSRenderTarget* rt);
|
||||
bool Create(GSDepthStencil* ds);
|
||||
};
|
||||
|
||||
protected:
|
||||
GSRenderTarget* CreateRenderTarget() {return new GSRenderTargetHW11(m_renderer);}
|
||||
GSDepthStencil* CreateDepthStencil() {return new GSDepthStencilHW11(m_renderer);}
|
||||
GSCachedTexture* CreateTexture() {return new GSCachedTextureHW11(m_renderer);}
|
||||
|
||||
public:
|
||||
GSTextureCache11(GSRenderer* r);
|
||||
};
|
|
@ -0,0 +1,526 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GSTextureFX11.h"
|
||||
#include "resource.h"
|
||||
|
||||
GSTextureFX11::GSTextureFX11()
|
||||
: m_dev(NULL)
|
||||
{
|
||||
memset(&m_vs_cb_cache, 0, sizeof(m_vs_cb_cache));
|
||||
memset(&m_ps_cb_cache, 0, sizeof(m_ps_cb_cache));
|
||||
}
|
||||
|
||||
bool GSTextureFX11::Create(GSDevice11* dev)
|
||||
{
|
||||
m_dev = dev;
|
||||
|
||||
VSSelector sel;
|
||||
|
||||
sel.bppz = 0;
|
||||
sel.tme = 0;
|
||||
sel.fst = 0;
|
||||
|
||||
VSConstantBuffer cb;
|
||||
|
||||
SetupVS(sel, &cb); // creates layout
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_BUFFER_DESC bd;
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
bd.ByteWidth = sizeof(VSConstantBuffer);
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
|
||||
hr = (*m_dev)->CreateBuffer(&bd, NULL, &m_vs_cb);
|
||||
|
||||
if(FAILED(hr)) return false;
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
bd.ByteWidth = sizeof(PSConstantBuffer);
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
|
||||
hr = (*m_dev)->CreateBuffer(&bd, NULL, &m_ps_cb);
|
||||
|
||||
if(FAILED(hr)) return false;
|
||||
|
||||
D3D11_SAMPLER_DESC sd;
|
||||
|
||||
memset(&sd, 0, sizeof(sd));
|
||||
|
||||
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
sd.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.MaxLOD = FLT_MAX;
|
||||
sd.MaxAnisotropy = 16;
|
||||
sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
|
||||
hr = (*m_dev)->CreateSamplerState(&sd, &m_palette_ss);
|
||||
|
||||
if(FAILED(hr)) return false;
|
||||
|
||||
//
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSTextureFX11::SetupIA(const GSVertexHW11* vertices, int count, D3D11_PRIMITIVE_TOPOLOGY prim)
|
||||
{
|
||||
m_dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), count);
|
||||
m_dev->IASetInputLayout(m_il);
|
||||
m_dev->IASetPrimitiveTopology(prim);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSTextureFX11::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
|
||||
{
|
||||
hash_map<uint32, CComPtr<ID3D11VertexShader> >::const_iterator i = m_vs.find(sel);
|
||||
|
||||
if(i == m_vs.end())
|
||||
{
|
||||
string str[4];
|
||||
|
||||
str[0] = format("%d", sel.bppz);
|
||||
str[1] = format("%d", sel.tme);
|
||||
str[2] = format("%d", sel.fst);
|
||||
str[3] = format("%d", sel.prim);
|
||||
|
||||
D3D11_SHADER_MACRO macro[] =
|
||||
{
|
||||
{"VS_BPPZ", str[0].c_str()},
|
||||
{"VS_TME", str[1].c_str()},
|
||||
{"VS_FST", str[2].c_str()},
|
||||
{"VS_PRIM", str[3].c_str()},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC layout[] =
|
||||
{
|
||||
{"POSITION", 0, DXGI_FORMAT_R16G16_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"POSITION", 1, DXGI_FORMAT_R32_UINT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
};
|
||||
|
||||
CComPtr<ID3D11InputLayout> il;
|
||||
CComPtr<ID3D11VertexShader> vs;
|
||||
|
||||
m_dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
|
||||
|
||||
if(m_il == NULL)
|
||||
{
|
||||
m_il = il;
|
||||
}
|
||||
|
||||
m_vs[sel] = vs;
|
||||
|
||||
i = m_vs.find(sel);
|
||||
}
|
||||
|
||||
if(m_vs_cb_cache.Update(cb))
|
||||
{
|
||||
ID3D11DeviceContext* ctx = *m_dev;
|
||||
|
||||
ctx->UpdateSubresource(m_vs_cb, 0, NULL, cb, 0, 0);
|
||||
}
|
||||
|
||||
m_dev->VSSetShader((*i).second, m_vs_cb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSTextureFX11::SetupGS(GSSelector sel)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
ID3D11GeometryShader* gs = NULL;
|
||||
|
||||
if(sel.prim > 0 && (sel.iip == 0 || sel.prim == 3)) // geometry shader works in every case, but not needed
|
||||
{
|
||||
hash_map<uint32, CComPtr<ID3D11GeometryShader> >::const_iterator i = m_gs.find(sel);
|
||||
|
||||
if(i != m_gs.end())
|
||||
{
|
||||
gs = (*i).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
string str[2];
|
||||
|
||||
str[0] = format("%d", sel.iip);
|
||||
str[1] = format("%d", sel.prim);
|
||||
|
||||
D3D11_SHADER_MACRO macro[] =
|
||||
{
|
||||
{"IIP", str[0].c_str()},
|
||||
{"PRIM", str[1].c_str()},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
hr = m_dev->CompileShader(IDR_TFX_FX, "gs_main", macro, &gs);
|
||||
|
||||
m_gs[sel] = gs;
|
||||
}
|
||||
}
|
||||
|
||||
m_dev->GSSetShader(gs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSTextureFX11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal)
|
||||
{
|
||||
m_dev->PSSetShaderResources(tex, pal);
|
||||
|
||||
UpdatePS(sel, cb, ssel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSTextureFX11::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hash_map<uint32, CComPtr<ID3D11PixelShader> >::const_iterator i = m_ps.find(sel);
|
||||
|
||||
if(i == m_ps.end())
|
||||
{
|
||||
string str[14];
|
||||
|
||||
str[0] = format("%d", sel.fst);
|
||||
str[1] = format("%d", sel.wms);
|
||||
str[2] = format("%d", sel.wmt);
|
||||
str[3] = format("%d", sel.bpp);
|
||||
str[4] = format("%d", sel.aem);
|
||||
str[5] = format("%d", sel.tfx);
|
||||
str[6] = format("%d", sel.tcc);
|
||||
str[7] = format("%d", sel.ate);
|
||||
str[8] = format("%d", sel.atst);
|
||||
str[9] = format("%d", sel.fog);
|
||||
str[10] = format("%d", sel.clr1);
|
||||
str[11] = format("%d", sel.fba);
|
||||
str[12] = format("%d", sel.aout);
|
||||
str[13] = format("%d", sel.ltf);
|
||||
|
||||
D3D11_SHADER_MACRO macro[] =
|
||||
{
|
||||
{"FST", str[0].c_str()},
|
||||
{"WMS", str[1].c_str()},
|
||||
{"WMT", str[2].c_str()},
|
||||
{"BPP", str[3].c_str()},
|
||||
{"AEM", str[4].c_str()},
|
||||
{"TFX", str[5].c_str()},
|
||||
{"TCC", str[6].c_str()},
|
||||
{"ATE", str[7].c_str()},
|
||||
{"ATST", str[8].c_str()},
|
||||
{"FOG", str[9].c_str()},
|
||||
{"CLR1", str[10].c_str()},
|
||||
{"FBA", str[11].c_str()},
|
||||
{"AOUT", str[12].c_str()},
|
||||
{"LTF", str[13].c_str()},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
CComPtr<ID3D11PixelShader> ps;
|
||||
|
||||
hr = m_dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
|
||||
|
||||
m_ps[sel] = ps;
|
||||
|
||||
i = m_ps.find(sel);
|
||||
}
|
||||
|
||||
if(m_ps_cb_cache.Update(cb))
|
||||
{
|
||||
ID3D11DeviceContext* ctx = *m_dev;
|
||||
|
||||
ctx->UpdateSubresource(m_ps_cb, 0, NULL, cb, 0, 0);
|
||||
}
|
||||
|
||||
m_dev->PSSetShader((*i).second, m_ps_cb);
|
||||
|
||||
ID3D11SamplerState* ss0 = NULL;
|
||||
ID3D11SamplerState* ss1 = NULL;
|
||||
|
||||
if(sel.tfx != 4)
|
||||
{
|
||||
if(!(sel.bpp < 3 && sel.wms < 3 && sel.wmt < 3))
|
||||
{
|
||||
ssel.ltf = 0;
|
||||
}
|
||||
|
||||
hash_map<uint32, CComPtr<ID3D11SamplerState> >::const_iterator i = m_ps_ss.find(ssel);
|
||||
|
||||
if(i != m_ps_ss.end())
|
||||
{
|
||||
ss0 = (*i).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_SAMPLER_DESC sd;
|
||||
|
||||
memset(&sd, 0, sizeof(sd));
|
||||
|
||||
sd.Filter = ssel.ltf ? D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
|
||||
sd.AddressU = ssel.tau ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.AddressV = ssel.tav ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
|
||||
sd.MaxLOD = FLT_MAX;
|
||||
sd.MaxAnisotropy = 16;
|
||||
sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
|
||||
hr = (*m_dev)->CreateSamplerState(&sd, &ss0);
|
||||
|
||||
m_ps_ss[ssel] = ss0;
|
||||
}
|
||||
|
||||
if(sel.bpp == 3)
|
||||
{
|
||||
ss1 = m_palette_ss;
|
||||
}
|
||||
}
|
||||
|
||||
m_dev->PSSetSamplerState(ss0, ss1);
|
||||
}
|
||||
|
||||
void GSTextureFX11::SetupRS(int w, int h, const GSVector4i& scissor)
|
||||
{
|
||||
m_dev->RSSet(w, h, &scissor);
|
||||
}
|
||||
|
||||
void GSTextureFX11::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf, GSTexture* rt, GSTexture* ds)
|
||||
{
|
||||
UpdateOM(dssel, bsel, bf);
|
||||
|
||||
m_dev->OMSetRenderTargets(rt, ds);
|
||||
}
|
||||
|
||||
void GSTextureFX11::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hash_map<uint32, CComPtr<ID3D11DepthStencilState> >::const_iterator i = m_om_dss.find(dssel);
|
||||
|
||||
if(i == m_om_dss.end())
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC dsd;
|
||||
|
||||
memset(&dsd, 0, sizeof(dsd));
|
||||
|
||||
if(dssel.date)
|
||||
{
|
||||
dsd.StencilEnable = true;
|
||||
dsd.StencilReadMask = 1;
|
||||
dsd.StencilWriteMask = 1;
|
||||
dsd.FrontFace.StencilFunc = D3D11_COMPARISON_EQUAL;
|
||||
dsd.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.BackFace.StencilFunc = D3D11_COMPARISON_EQUAL;
|
||||
dsd.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
dsd.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
||||
}
|
||||
|
||||
if(!(dssel.zte && dssel.ztst == 1 && !dssel.zwe))
|
||||
{
|
||||
static const D3D11_COMPARISON_FUNC ztst[] =
|
||||
{
|
||||
D3D11_COMPARISON_NEVER,
|
||||
D3D11_COMPARISON_ALWAYS,
|
||||
D3D11_COMPARISON_GREATER_EQUAL,
|
||||
D3D11_COMPARISON_GREATER
|
||||
};
|
||||
|
||||
dsd.DepthEnable = dssel.zte;
|
||||
dsd.DepthWriteMask = dssel.zwe ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
dsd.DepthFunc = ztst[dssel.ztst];
|
||||
}
|
||||
|
||||
CComPtr<ID3D11DepthStencilState> dss;
|
||||
|
||||
hr = (*m_dev)->CreateDepthStencilState(&dsd, &dss);
|
||||
|
||||
m_om_dss[dssel] = dss;
|
||||
|
||||
i = m_om_dss.find(dssel);
|
||||
}
|
||||
|
||||
m_dev->OMSetDepthStencilState((*i).second, 1);
|
||||
|
||||
hash_map<uint32, CComPtr<ID3D11BlendState> >::const_iterator j = m_om_bs.find(bsel);
|
||||
|
||||
if(j == m_om_bs.end())
|
||||
{
|
||||
D3D11_BLEND_DESC bd;
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
bd.RenderTarget[0].BlendEnable = bsel.abe;
|
||||
|
||||
if(bsel.abe)
|
||||
{
|
||||
// (A:Cs/Cd/0 - B:Cs/Cd/0) * C:As/Ad/FIX + D:Cs/Cd/0
|
||||
|
||||
static const struct {int bogus; D3D11_BLEND_OP op; D3D11_BLEND src, dst;} map[3*3*3*3] =
|
||||
{
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 0000: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 0001: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 0002: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 0010: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 0011: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 0012: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 0020: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 0021: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 0022: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{1, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_SRC1_ALPHA}, // * 0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA}, // 0101: (Cs - Cd)*As + Cd ==> Cs*As + Cd*(1 - As)
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_SRC1_ALPHA}, // 0102: (Cs - Cd)*As + 0 ==> Cs*As - Cd*As
|
||||
{1, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_DEST_ALPHA}, // * 0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_INV_DEST_ALPHA}, // 0111: (Cs - Cd)*Ad + Cd ==> Cs*Ad + Cd*(1 - Ad)
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_DEST_ALPHA}, // 0112: (Cs - Cd)*Ad + 0 ==> Cs*Ad - Cd*Ad
|
||||
{1, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_BLEND_FACTOR}, // * 0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR}, // 0121: (Cs - Cd)*F + Cd ==> Cs*F + Cd*(1 - F)
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_BLEND_FACTOR}, // 0122: (Cs - Cd)*F + 0 ==> Cs*F - Cd*F
|
||||
{1, D3D11_BLEND_OP_ADD, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_ZERO}, // * 0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_ONE}, // 0201: (Cs - 0)*As + Cd ==> Cs*As + Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_ZERO}, // 0202: (Cs - 0)*As + 0 ==> Cs*As
|
||||
{1, D3D11_BLEND_OP_ADD, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_ZERO}, // * 0210: (Cs - 0)*Ad + Cs ==> Cs*(Ad + 1)
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_ONE}, // 0211: (Cs - 0)*Ad + Cd ==> Cs*Ad + Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_ZERO}, // 0212: (Cs - 0)*Ad + 0 ==> Cs*Ad
|
||||
{1, D3D11_BLEND_OP_ADD, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_ZERO}, // * 0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_ONE}, // 0221: (Cs - 0)*F + Cd ==> Cs*F + Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_ZERO}, // 0222: (Cs - 0)*F + 0 ==> Cs*F
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_INV_SRC1_ALPHA, D3D11_BLEND_SRC1_ALPHA}, // 1000: (Cd - Cs)*As + Cs ==> Cd*As + Cs*(1 - As)
|
||||
{1, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_SRC1_ALPHA}, // * 1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_SRC1_ALPHA}, // 1002: (Cd - Cs)*As + 0 ==> Cd*As - Cs*As
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_DEST_ALPHA}, // 1010: (Cd - Cs)*Ad + Cs ==> Cd*Ad + Cs*(1 - Ad)
|
||||
{1, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_DEST_ALPHA}, // * 1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_DEST_ALPHA}, // 1012: (Cd - Cs)*Ad + 0 ==> Cd*Ad - Cs*Ad
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_BLEND_FACTOR}, // 1020: (Cd - Cs)*F + Cs ==> Cd*F + Cs*(1 - F)
|
||||
{1, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_BLEND_FACTOR},// * 1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_BLEND_FACTOR},// 1022: (Cd - Cs)*F + 0 ==> Cd*F - Cs*F
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 1100: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 1101: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 1102: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 1110: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 1111: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 1112: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 1120: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 1121: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 1122: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_SRC1_ALPHA}, // 1200: (Cd - 0)*As + Cs ==> Cs + Cd*As
|
||||
{2, D3D11_BLEND_OP_ADD, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_SRC1_ALPHA}, // ** 1201: (Cd - 0)*As + Cd ==> Cd*(1 + As) // ffxii main menu background glow effect
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_SRC1_ALPHA}, // 1202: (Cd - 0)*As + 0 ==> Cd*As
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_DEST_ALPHA}, // 1210: (Cd - 0)*Ad + Cs ==> Cs + Cd*Ad
|
||||
{2, D3D11_BLEND_OP_ADD, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_DEST_ALPHA}, // ** 1211: (Cd - 0)*Ad + Cd ==> Cd*(1 + Ad)
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_DEST_ALPHA}, // 1212: (Cd - 0)*Ad + 0 ==> Cd*Ad
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_BLEND_FACTOR}, // 1220: (Cd - 0)*F + Cs ==> Cs + Cd*F
|
||||
{2, D3D11_BLEND_OP_ADD, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_BLEND_FACTOR}, // ** 1221: (Cd - 0)*F + Cd ==> Cd*(1 + F)
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_BLEND_FACTOR}, // 1222: (Cd - 0)*F + 0 ==> Cd*F
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_INV_SRC1_ALPHA, D3D11_BLEND_ZERO}, // 2000: (0 - Cs)*As + Cs ==> Cs*(1 - As)
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_ONE}, // 2001: (0 - Cs)*As + Cd ==> Cd - Cs*As
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_ZERO}, // 2002: (0 - Cs)*As + 0 ==> 0 - Cs*As
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_ZERO}, // 2010: (0 - Cs)*Ad + Cs ==> Cs*(1 - Ad)
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_ONE}, // 2011: (0 - Cs)*Ad + Cd ==> Cd - Cs*Ad
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_ZERO}, // 2012: (0 - Cs)*Ad + 0 ==> 0 - Cs*Ad
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_ZERO}, // 2020: (0 - Cs)*F + Cs ==> Cs*(1 - F)
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_ONE}, // 2021: (0 - Cs)*F + Cd ==> Cd - Cs*F
|
||||
{0, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_ZERO}, // 2022: (0 - Cs)*F + 0 ==> 0 - Cs*F
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ONE, D3D11_BLEND_SRC1_ALPHA}, // 2100: (0 - Cd)*As + Cs ==> Cs - Cd*As
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_INV_SRC1_ALPHA}, // 2101: (0 - Cd)*As + Cd ==> Cd*(1 - As)
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ZERO, D3D11_BLEND_SRC1_ALPHA}, // 2102: (0 - Cd)*As + 0 ==> 0 - Cd*As
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ONE, D3D11_BLEND_DEST_ALPHA}, // 2110: (0 - Cd)*Ad + Cs ==> Cs - Cd*Ad
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_INV_DEST_ALPHA}, // 2111: (0 - Cd)*Ad + Cd ==> Cd*(1 - Ad)
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ONE, D3D11_BLEND_DEST_ALPHA}, // 2112: (0 - Cd)*Ad + 0 ==> 0 - Cd*Ad
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ONE, D3D11_BLEND_BLEND_FACTOR}, // 2120: (0 - Cd)*F + Cs ==> Cs - Cd*F
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_INV_BLEND_FACTOR}, // 2121: (0 - Cd)*F + Cd ==> Cd*(1 - F)
|
||||
{0, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_ONE, D3D11_BLEND_BLEND_FACTOR}, // 2122: (0 - Cd)*F + 0 ==> 0 - Cd*F
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 2200: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 2201: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 2202: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 2210: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 2211: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 2212: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ONE, D3D11_BLEND_ZERO}, // 2220: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ONE}, // 2221: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
||||
{0, D3D11_BLEND_OP_ADD, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO}, // 2222: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
||||
};
|
||||
|
||||
// bogus: 0100, 0110, 0120, 0200, 0210, 0220, 1001, 1011, 1021
|
||||
|
||||
// tricky: 1201, 1211, 1221
|
||||
//
|
||||
// Source.rgb = float3(1, 1, 1);
|
||||
// 1201 Cd*(1 + As) => Source * Dest color + Dest * Source1 alpha
|
||||
// 1211 Cd*(1 + Ad) => Source * Dest color + Dest * Dest alpha
|
||||
// 1221 Cd*(1 + F) => Source * Dest color + Dest * Factor
|
||||
|
||||
int i = ((bsel.a * 3 + bsel.b) * 3 + bsel.c) * 3 + bsel.d;
|
||||
|
||||
bd.RenderTarget[0].BlendOp = map[i].op;
|
||||
bd.RenderTarget[0].SrcBlend = map[i].src;
|
||||
bd.RenderTarget[0].DestBlend = map[i].dst;
|
||||
bd.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
bd.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
bd.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
|
||||
if(map[i].bogus == 1)
|
||||
{
|
||||
ASSERT(0);
|
||||
|
||||
(bsel.a == 0 ? bd.RenderTarget[0].SrcBlend : bd.RenderTarget[0].DestBlend) = D3D11_BLEND_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
if(bsel.wr) bd.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_RED;
|
||||
if(bsel.wg) bd.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
|
||||
if(bsel.wb) bd.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
|
||||
if(bsel.wa) bd.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
|
||||
|
||||
CComPtr<ID3D11BlendState> bs;
|
||||
|
||||
hr = (*m_dev)->CreateBlendState(&bd, &bs);
|
||||
|
||||
m_om_bs[bsel] = bs;
|
||||
|
||||
j = m_om_bs.find(bsel);
|
||||
}
|
||||
|
||||
m_dev->OMSetBlendState((*j).second, bf);
|
||||
}
|
||||
|
||||
void GSTextureFX11::Draw()
|
||||
{
|
||||
m_dev->DrawPrimitive();
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSDevice11.h"
|
||||
|
||||
class GSTextureFX11
|
||||
{
|
||||
public:
|
||||
#pragma pack(push, 1)
|
||||
|
||||
__declspec(align(16)) struct VSConstantBuffer
|
||||
{
|
||||
GSVector4 VertexScale;
|
||||
GSVector4 VertexOffset;
|
||||
GSVector2 TextureScale;
|
||||
float _pad[2];
|
||||
|
||||
struct VSConstantBuffer() {memset(this, 0, sizeof(*this));}
|
||||
|
||||
__forceinline bool Update(const VSConstantBuffer* cb)
|
||||
{
|
||||
GSVector4i* a = (GSVector4i*)this;
|
||||
GSVector4i* b = (GSVector4i*)cb;
|
||||
|
||||
GSVector4i b0 = b[0];
|
||||
GSVector4i b1 = b[1];
|
||||
GSVector4i b2 = b[2];
|
||||
|
||||
if(!((a[0] == b0) & (a[1] == b1) & (a[2] == b2)).alltrue())
|
||||
{
|
||||
a[0] = b0;
|
||||
a[1] = b1;
|
||||
a[2] = b2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
union VSSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 bppz:2;
|
||||
uint32 tme:1;
|
||||
uint32 fst:1;
|
||||
uint32 prim:3;
|
||||
};
|
||||
|
||||
uint32 key;
|
||||
|
||||
operator uint32() {return key & 0x7f;}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct PSConstantBuffer
|
||||
{
|
||||
GSVector4 FogColor_AREF;
|
||||
GSVector4 HalfTexel;
|
||||
GSVector4 WH_TA;
|
||||
GSVector4 MinMax;
|
||||
GSVector4 MinMaxF;
|
||||
GSVector4i MskFix;
|
||||
|
||||
struct PSConstantBuffer() {memset(this, 0, sizeof(*this));}
|
||||
|
||||
__forceinline bool Update(const PSConstantBuffer* cb)
|
||||
{
|
||||
GSVector4i* a = (GSVector4i*)this;
|
||||
GSVector4i* b = (GSVector4i*)cb;
|
||||
|
||||
GSVector4i b0 = b[0];
|
||||
GSVector4i b1 = b[1];
|
||||
GSVector4i b2 = b[2];
|
||||
GSVector4i b3 = b[3];
|
||||
GSVector4i b4 = b[4];
|
||||
GSVector4i b5 = b[5];
|
||||
|
||||
if(!((a[0] == b0) & (a[1] == b1) & (a[2] == b2) & (a[3] == b3) & (a[4] == b4) & (a[5] == b5)).alltrue())
|
||||
{
|
||||
a[0] = b0;
|
||||
a[1] = b1;
|
||||
a[2] = b2;
|
||||
a[3] = b3;
|
||||
a[4] = b4;
|
||||
a[5] = b5;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
union GSSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 iip:1;
|
||||
uint32 prim:2;
|
||||
};
|
||||
|
||||
uint32 key;
|
||||
|
||||
operator uint32() {return key & 0x7;}
|
||||
};
|
||||
|
||||
union PSSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 fst:1;
|
||||
uint32 wms:2;
|
||||
uint32 wmt:2;
|
||||
uint32 bpp:3;
|
||||
uint32 aem:1;
|
||||
uint32 tfx:3;
|
||||
uint32 tcc:1;
|
||||
uint32 ate:1;
|
||||
uint32 atst:3;
|
||||
uint32 fog:1;
|
||||
uint32 clr1:1;
|
||||
uint32 fba:1;
|
||||
uint32 aout:1;
|
||||
uint32 ltf:1;
|
||||
};
|
||||
|
||||
uint32 key;
|
||||
|
||||
operator uint32() {return key & 0x3fffff;}
|
||||
};
|
||||
|
||||
union PSSamplerSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 tau:1;
|
||||
uint32 tav:1;
|
||||
uint32 ltf:1;
|
||||
};
|
||||
|
||||
uint32 key;
|
||||
|
||||
operator uint32() {return key & 0x7;}
|
||||
};
|
||||
|
||||
union OMDepthStencilSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 zte:1;
|
||||
uint32 ztst:2;
|
||||
uint32 zwe:1;
|
||||
uint32 date:1;
|
||||
};
|
||||
|
||||
uint32 key;
|
||||
|
||||
operator uint32() {return key & 0x1f;}
|
||||
};
|
||||
|
||||
union OMBlendSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 abe:1;
|
||||
uint32 a:2;
|
||||
uint32 b:2;
|
||||
uint32 c:2;
|
||||
uint32 d:2;
|
||||
uint32 wr:1;
|
||||
uint32 wg:1;
|
||||
uint32 wb:1;
|
||||
uint32 wa:1;
|
||||
};
|
||||
|
||||
uint32 key;
|
||||
|
||||
operator uint32() {return key & 0x1fff;}
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
private:
|
||||
GSDevice11* m_dev;
|
||||
CComPtr<ID3D11InputLayout> m_il;
|
||||
hash_map<uint32, CComPtr<ID3D11VertexShader> > m_vs;
|
||||
CComPtr<ID3D11Buffer> m_vs_cb;
|
||||
hash_map<uint32, CComPtr<ID3D11GeometryShader> > m_gs;
|
||||
hash_map<uint32, CComPtr<ID3D11PixelShader> > m_ps;
|
||||
CComPtr<ID3D11Buffer> m_ps_cb;
|
||||
hash_map<uint32, CComPtr<ID3D11SamplerState> > m_ps_ss;
|
||||
CComPtr<ID3D11SamplerState> m_palette_ss;
|
||||
hash_map<uint32, CComPtr<ID3D11DepthStencilState> > m_om_dss;
|
||||
hash_map<uint32, CComPtr<ID3D11BlendState> > m_om_bs;
|
||||
|
||||
CComPtr<ID3D11Buffer> m_vb, m_vb_old;
|
||||
int m_vb_max;
|
||||
int m_vb_start;
|
||||
int m_vb_count;
|
||||
|
||||
VSConstantBuffer m_vs_cb_cache;
|
||||
PSConstantBuffer m_ps_cb_cache;
|
||||
|
||||
public:
|
||||
GSTextureFX11();
|
||||
|
||||
bool Create(GSDevice11* dev);
|
||||
|
||||
bool SetupIA(const GSVertexHW11* vertices, int count, D3D11_PRIMITIVE_TOPOLOGY prim);
|
||||
bool SetupVS(VSSelector sel, const VSConstantBuffer* cb);
|
||||
bool SetupGS(GSSelector sel);
|
||||
bool SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal);
|
||||
void UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
|
||||
void SetupRS(int w, int h, const GSVector4i& scissor);
|
||||
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf, GSTexture* rt, GSTexture* ds);
|
||||
void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf);
|
||||
void Draw();
|
||||
};
|
Loading…
Reference in New Issue