DX11 code maintenance, part 6:
Move constant buffer management from EmuGfxState to Vertex/PixelShaderCache. Finally remove the EmuGfxState class, cheers! git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6915 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
81aebe5e96
commit
cd6f00a3e5
|
@ -337,7 +337,6 @@ HRESULT Create(HWND wnd)
|
|||
device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support);
|
||||
bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
|
||||
|
||||
gfxstate = new EmuGfxState;
|
||||
stateman = new StateManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -348,7 +347,6 @@ void Close()
|
|||
context->ClearState();
|
||||
SAFE_RELEASE(backbuf);
|
||||
SAFE_RELEASE(swapchain);
|
||||
SAFE_DELETE(gfxstate);
|
||||
SAFE_DELETE(stateman);
|
||||
context->Flush(); // immediately destroy device objects
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Common.h"
|
||||
#include "D3DBlob.h"
|
||||
#include "GfxState.h"
|
||||
#include <vector>
|
||||
|
||||
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
|
||||
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
|
||||
|
|
|
@ -22,78 +22,8 @@
|
|||
namespace D3D
|
||||
{
|
||||
|
||||
EmuGfxState* gfxstate;
|
||||
StateManager* stateman;
|
||||
|
||||
EmuGfxState::EmuGfxState() : apply_called(false)
|
||||
{
|
||||
pscbuf = NULL;
|
||||
vscbuf = NULL;
|
||||
|
||||
pscbufchanged = false;
|
||||
vscbufchanged = false;
|
||||
}
|
||||
|
||||
EmuGfxState::~EmuGfxState()
|
||||
{
|
||||
SAFE_RELEASE(pscbuf);
|
||||
SAFE_RELEASE(vscbuf);
|
||||
}
|
||||
|
||||
void EmuGfxState::ApplyState()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// vertex shader
|
||||
// TODO: divide the global variables of the generated shaders into about 5 constant buffers
|
||||
// TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time
|
||||
if (!vscbuf)
|
||||
{
|
||||
unsigned int size = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf);
|
||||
CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "a vertex shader constant buffer of EmuGfxState");
|
||||
}
|
||||
if (vscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, vsconstants, sizeof(vsconstants));
|
||||
context->Unmap(vscbuf, 0);
|
||||
vscbufchanged = false;
|
||||
}
|
||||
D3D::context->VSSetConstantBuffers(0, 1, &vscbuf);
|
||||
|
||||
// pixel shader
|
||||
if (!pscbuf)
|
||||
{
|
||||
unsigned int size = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
device->CreateBuffer(&cbdesc, NULL, &pscbuf);
|
||||
CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size);
|
||||
SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "a pixel shader constant buffer of EmuGfxState");
|
||||
}
|
||||
if (pscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, psconstants, sizeof(psconstants));
|
||||
context->Unmap(pscbuf, 0);
|
||||
pscbufchanged = false;
|
||||
}
|
||||
D3D::context->PSSetConstantBuffers(0, 1, &pscbuf);
|
||||
|
||||
apply_called = true;
|
||||
}
|
||||
|
||||
void EmuGfxState::Reset()
|
||||
{
|
||||
if (apply_called)
|
||||
{
|
||||
apply_called = false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> AutoState<T>::AutoState(const T* object) : state(object)
|
||||
{
|
||||
|
|
|
@ -17,38 +17,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "PixelShaderGen.h"
|
||||
#include <stack>
|
||||
using std::stack;
|
||||
|
||||
struct ID3D11BlendState;
|
||||
struct ID3D11DepthStencilState;
|
||||
struct ID3D11RasterizerState;
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// stores the pipeline state to use when calling VertexManager::Flush()
|
||||
class EmuGfxState
|
||||
{
|
||||
public:
|
||||
EmuGfxState();
|
||||
~EmuGfxState();
|
||||
|
||||
void ApplyState(); // apply current state
|
||||
void Reset();
|
||||
|
||||
|
||||
float psconstants[C_PENVCONST_END*4];
|
||||
float vsconstants[C_VENVCONST_END*4];
|
||||
bool vscbufchanged;
|
||||
bool pscbufchanged;
|
||||
|
||||
private:
|
||||
ID3D11Buffer* vscbuf;
|
||||
ID3D11Buffer* pscbuf;
|
||||
|
||||
bool apply_called;
|
||||
};
|
||||
|
||||
template<typename T> class AutoState
|
||||
{
|
||||
public:
|
||||
|
@ -85,15 +62,14 @@ public:
|
|||
void Apply();
|
||||
|
||||
private:
|
||||
stack<AutoBlendState> blendstates;
|
||||
stack<AutoDepthStencilState> depthstates;
|
||||
stack<AutoRasterizerState> raststates;
|
||||
std::stack<AutoBlendState> blendstates;
|
||||
std::stack<AutoDepthStencilState> depthstates;
|
||||
std::stack<AutoRasterizerState> raststates;
|
||||
ID3D11BlendState* cur_blendstate;
|
||||
ID3D11DepthStencilState* cur_depthstate;
|
||||
ID3D11RasterizerState* cur_raststate;
|
||||
};
|
||||
|
||||
extern EmuGfxState* gfxstate;
|
||||
extern StateManager* stateman;
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -46,6 +46,10 @@ ID3D11PixelShader* s_ColorCopyProgram[2] = {NULL};
|
|||
ID3D11PixelShader* s_DepthMatrixProgram[2] = {NULL};
|
||||
ID3D11PixelShader* s_ClearProgram = NULL;
|
||||
|
||||
float psconstants[C_PENVCONST_END*4];
|
||||
bool pscbufchanged = true;
|
||||
ID3D11Buffer* pscbuf = NULL;
|
||||
|
||||
const char clear_program_code[] = {
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
|
@ -157,6 +161,7 @@ ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram(bool multisampled)
|
|||
else if (s_ColorCopyProgram[1]) return s_ColorCopyProgram[1];
|
||||
else
|
||||
{
|
||||
// TODO: recreate shader on AA mode change!
|
||||
// create MSAA shader for current AA mode
|
||||
char buf[1024];
|
||||
int l = sprintf_s(buf, 1024, color_copy_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode));
|
||||
|
@ -173,6 +178,7 @@ ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram(bool multisampled)
|
|||
else if (s_ColorMatrixProgram[1]) return s_ColorMatrixProgram[1];
|
||||
else
|
||||
{
|
||||
// TODO: recreate shader on AA mode change!
|
||||
// create MSAA shader for current AA mode
|
||||
char buf[1024];
|
||||
int l = sprintf_s(buf, 1024, color_matrix_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode));
|
||||
|
@ -189,6 +195,7 @@ ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram(bool multisampled)
|
|||
else if (s_DepthMatrixProgram[1]) return s_DepthMatrixProgram[1];
|
||||
else
|
||||
{
|
||||
// TODO: recreate shader on AA mode change!
|
||||
// create MSAA shader for current AA mode
|
||||
char buf[1024];
|
||||
int l = sprintf_s(buf, 1024, depth_matrix_program_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode));
|
||||
|
@ -228,23 +235,37 @@ unsigned int ps_constant_offset_table[] = {
|
|||
};
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number] ] = f1;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+1] = f2;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+2] = f3;
|
||||
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+3] = f4;
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
psconstants[ps_constant_offset_table[const_number] ] = f1;
|
||||
psconstants[ps_constant_offset_table[const_number]+1] = f2;
|
||||
psconstants[ps_constant_offset_table[const_number]+2] = f3;
|
||||
psconstants[ps_constant_offset_table[const_number]+3] = f4;
|
||||
pscbufchanged = true;
|
||||
}
|
||||
|
||||
void SetPSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
memcpy(&psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
pscbufchanged = true;
|
||||
}
|
||||
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
D3D::gfxstate->pscbufchanged = true;
|
||||
memcpy(&psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
pscbufchanged = true;
|
||||
}
|
||||
|
||||
ID3D11Buffer* &PixelShaderCache::GetConstantBuffer()
|
||||
{
|
||||
// TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up
|
||||
if (pscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
D3D::context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, psconstants, sizeof(psconstants));
|
||||
D3D::context->Unmap(pscbuf, 0);
|
||||
pscbufchanged = false;
|
||||
}
|
||||
return pscbuf;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
|
@ -259,6 +280,12 @@ public:
|
|||
|
||||
void PixelShaderCache::Init()
|
||||
{
|
||||
unsigned int cbsize = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
D3D::device->CreateBuffer(&cbdesc, NULL, &pscbuf);
|
||||
CHECK(pscbuf!=NULL, "Create pixel shader constant buffer");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "pixel shader constant buffer used to emulate the GX pipeline");
|
||||
|
||||
// used when drawing clear quads
|
||||
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code));
|
||||
CHECK(s_ClearProgram!=NULL, "Create clear pixel shader");
|
||||
|
@ -311,6 +338,8 @@ void PixelShaderCache::InvalidateMSAAShaders()
|
|||
|
||||
void PixelShaderCache::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE(pscbuf);
|
||||
|
||||
SAFE_RELEASE(s_ClearProgram);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
|
@ -356,7 +385,7 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
|
|||
const char* code = GeneratePixelShaderCode(dstAlphaMode, API_D3D11, components);
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompilePixelShader(code, strlen(code), &pbytecode))
|
||||
if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode))
|
||||
{
|
||||
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
static bool InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen);
|
||||
|
||||
static ID3D11PixelShader* GetActiveShader() { return last_entry->shader; }
|
||||
static ID3D11Buffer* &GetConstantBuffer();
|
||||
|
||||
static ID3D11PixelShader* GetColorMatrixProgram(bool multisampled);
|
||||
static ID3D11PixelShader* GetColorCopyProgram(bool multisampled);
|
||||
|
|
|
@ -1233,6 +1233,9 @@ void Renderer::ApplyState(bool bUseDstAlpha)
|
|||
SetLogicOpMode();
|
||||
}
|
||||
|
||||
D3D::context->PSSetConstantBuffers(0, 1, &PixelShaderCache::GetConstantBuffer());
|
||||
D3D::context->VSSetConstantBuffers(0, 1, &VertexShaderCache::GetConstantBuffer());
|
||||
|
||||
D3D::context->PSSetShader(PixelShaderCache::GetActiveShader(), NULL, 0);
|
||||
D3D::context->VSSetShader(VertexShaderCache::GetActiveShader(), NULL, 0);
|
||||
}
|
||||
|
|
|
@ -228,7 +228,6 @@ void VertexManager::vFlush()
|
|||
unsigned int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
|
||||
D3D::gfxstate->ApplyState();
|
||||
g_renderer->ApplyState(useDstAlpha);
|
||||
LoadBuffers();
|
||||
Draw(stride);
|
||||
|
@ -236,7 +235,6 @@ void VertexManager::vFlush()
|
|||
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
|
||||
|
||||
g_renderer->RestoreState();
|
||||
D3D::gfxstate->Reset();
|
||||
|
||||
shader_fail:
|
||||
ResetBuffer();
|
||||
|
|
|
@ -48,37 +48,55 @@ ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVert
|
|||
ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; }
|
||||
ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; }
|
||||
|
||||
float vsconstants[C_VENVCONST_END*4];
|
||||
bool vscbufchanged = true;
|
||||
ID3D11Buffer* vscbuf = NULL;
|
||||
|
||||
// maps the constant numbers to float indices in the constant buffer
|
||||
unsigned int vs_constant_offset_table[C_VENVCONST_END];
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number] ] = f1;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+1] = f2;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+2] = f3;
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+3] = f4;
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
vsconstants[vs_constant_offset_table[const_number] ] = f1;
|
||||
vsconstants[vs_constant_offset_table[const_number]+1] = f2;
|
||||
vsconstants[vs_constant_offset_table[const_number]+2] = f3;
|
||||
vsconstants[vs_constant_offset_table[const_number]+3] = f4;
|
||||
vscbufchanged = true;
|
||||
}
|
||||
|
||||
void SetVSConstant4fv(unsigned int const_number, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
memcpy(&vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4);
|
||||
vscbufchanged = true;
|
||||
}
|
||||
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3);
|
||||
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f;
|
||||
memcpy(&vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3);
|
||||
vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f;
|
||||
}
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
vscbufchanged = true;
|
||||
}
|
||||
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
|
||||
{
|
||||
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
D3D::gfxstate->vscbufchanged = true;
|
||||
memcpy(&vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count);
|
||||
vscbufchanged = true;
|
||||
}
|
||||
|
||||
ID3D11Buffer* &VertexShaderCache::GetConstantBuffer()
|
||||
{
|
||||
// TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up
|
||||
if (vscbufchanged)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
D3D::context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, vsconstants, sizeof(vsconstants));
|
||||
D3D::context->Unmap(vscbuf, 0);
|
||||
vscbufchanged = false;
|
||||
}
|
||||
return vscbuf;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
|
@ -140,6 +158,12 @@ void VertexShaderCache::Init()
|
|||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
unsigned int cbsize = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16
|
||||
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
HRESULT hr = D3D::device->CreateBuffer(&cbdesc, NULL, &vscbuf);
|
||||
CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", cbsize);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "vertex shader constant buffer used to emulate the GX pipeline");
|
||||
|
||||
D3DBlob* blob;
|
||||
D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob);
|
||||
D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout);
|
||||
|
@ -193,6 +217,8 @@ void VertexShaderCache::Clear()
|
|||
|
||||
void VertexShaderCache::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE(vscbuf);
|
||||
|
||||
SAFE_RELEASE(SimpleVertexShader);
|
||||
SAFE_RELEASE(ClearVertexShader);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
|
||||
static ID3D11VertexShader* GetActiveShader() { return last_entry->shader; }
|
||||
static D3DBlob* GetActiveShaderBytecode() { return last_entry->bytecode; }
|
||||
static ID3D11Buffer* &GetConstantBuffer();
|
||||
|
||||
static ID3D11VertexShader* GetSimpleVertexShader();
|
||||
static ID3D11VertexShader* GetClearVertexShader();
|
||||
|
|
Loading…
Reference in New Issue