Caching states.
This commit is contained in:
parent
6514eaa780
commit
daa8a24173
|
@ -71,6 +71,18 @@ D3D11GraphicsDriver::~D3D11GraphicsDriver() {
|
|||
XESAFERELEASE(state_.constant_buffers.loop_constants);
|
||||
XESAFERELEASE(state_.constant_buffers.vs_consts);
|
||||
XESAFERELEASE(state_.constant_buffers.gs_consts);
|
||||
for (auto it = rasterizer_state_cache_.begin();
|
||||
it != rasterizer_state_cache_.end(); ++it) {
|
||||
XESAFERELEASE(it->second);
|
||||
}
|
||||
for (auto it = blend_state_cache_.begin();
|
||||
it != blend_state_cache_.end(); ++it) {
|
||||
XESAFERELEASE(it->second);
|
||||
}
|
||||
for (auto it = depth_stencil_state_cache_.begin();
|
||||
it != depth_stencil_state_cache_.end(); ++it) {
|
||||
XESAFERELEASE(it->second);
|
||||
}
|
||||
XESAFERELEASE(invalid_texture_view_);
|
||||
XESAFERELEASE(invalid_texture_sampler_state_);
|
||||
delete resource_cache_;
|
||||
|
@ -271,39 +283,6 @@ int D3D11GraphicsDriver::UpdateState(const DrawCommand& command) {
|
|||
// TODO(benvanik): only enable the number of valid render targets.
|
||||
context_->OMSetRenderTargets(4, render_target_views, depth_stencil_view);
|
||||
|
||||
// General rasterizer state.
|
||||
uint32_t mode_control = register_file_[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32;
|
||||
D3D11_RASTERIZER_DESC rasterizer_desc;
|
||||
xe_zero_struct(&rasterizer_desc, sizeof(rasterizer_desc));
|
||||
rasterizer_desc.FillMode = D3D11_FILL_SOLID; // D3D11_FILL_WIREFRAME;
|
||||
switch (mode_control & 0x3) {
|
||||
case 0:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_NONE;
|
||||
break;
|
||||
case 1:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_FRONT;
|
||||
break;
|
||||
case 2:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_BACK;
|
||||
break;
|
||||
}
|
||||
if (command.prim_type == XE_GPU_PRIMITIVE_TYPE_RECTANGLE_LIST) {
|
||||
// Rect lists aren't culled. There may be other things they skip too.
|
||||
rasterizer_desc.CullMode = D3D11_CULL_NONE;
|
||||
}
|
||||
rasterizer_desc.FrontCounterClockwise = (mode_control & 0x4) == 0;
|
||||
rasterizer_desc.DepthBias = 0;
|
||||
rasterizer_desc.DepthBiasClamp = 0;
|
||||
rasterizer_desc.SlopeScaledDepthBias = 0;
|
||||
rasterizer_desc.DepthClipEnable = false; // ?
|
||||
rasterizer_desc.ScissorEnable = false;
|
||||
rasterizer_desc.MultisampleEnable = false;
|
||||
rasterizer_desc.AntialiasedLineEnable = false;
|
||||
ID3D11RasterizerState* rasterizer_state = 0;
|
||||
device_->CreateRasterizerState(&rasterizer_desc, &rasterizer_state);
|
||||
context_->RSSetState(rasterizer_state);
|
||||
XESAFERELEASE(rasterizer_state);
|
||||
|
||||
// Viewport.
|
||||
// If we have resized the window we will want to change this.
|
||||
uint32_t window_offset = register_file_[XE_GPU_REG_PA_SC_WINDOW_OFFSET].u32;
|
||||
|
@ -391,6 +370,162 @@ int D3D11GraphicsDriver::UpdateState(const DrawCommand& command) {
|
|||
context_->RSSetScissorRects(0, NULL);
|
||||
}
|
||||
|
||||
if (SetupRasterizerState(command)) {
|
||||
XELOGE("Unable to setup rasterizer state");
|
||||
return 1;
|
||||
}
|
||||
if (SetupBlendState(command)) {
|
||||
XELOGE("Unable to setup blend state");
|
||||
return 1;
|
||||
}
|
||||
if (SetupDepthStencilState(command)) {
|
||||
XELOGE("Unable to setup depth/stencil state");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupRasterizerState(const DrawCommand& command) {
|
||||
uint32_t mode_control = register_file_[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32;
|
||||
|
||||
// Check cache.
|
||||
uint64_t key = hash_combine(mode_control);
|
||||
ID3D11RasterizerState* rasterizer_state = nullptr;
|
||||
auto it = rasterizer_state_cache_.find(key);
|
||||
if (it == rasterizer_state_cache_.end()) {
|
||||
D3D11_RASTERIZER_DESC rasterizer_desc;
|
||||
xe_zero_struct(&rasterizer_desc, sizeof(rasterizer_desc));
|
||||
rasterizer_desc.FillMode = D3D11_FILL_SOLID; // D3D11_FILL_WIREFRAME;
|
||||
switch (mode_control & 0x3) {
|
||||
case 0:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_NONE;
|
||||
break;
|
||||
case 1:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_FRONT;
|
||||
break;
|
||||
case 2:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_BACK;
|
||||
break;
|
||||
}
|
||||
if (command.prim_type == XE_GPU_PRIMITIVE_TYPE_RECTANGLE_LIST) {
|
||||
// Rect lists aren't culled. There may be other things they skip too.
|
||||
rasterizer_desc.CullMode = D3D11_CULL_NONE;
|
||||
}
|
||||
rasterizer_desc.FrontCounterClockwise = (mode_control & 0x4) == 0;
|
||||
rasterizer_desc.DepthBias = 0;
|
||||
rasterizer_desc.DepthBiasClamp = 0;
|
||||
rasterizer_desc.SlopeScaledDepthBias = 0;
|
||||
rasterizer_desc.DepthClipEnable = false; // ?
|
||||
rasterizer_desc.ScissorEnable = false;
|
||||
rasterizer_desc.MultisampleEnable = false;
|
||||
rasterizer_desc.AntialiasedLineEnable = false;
|
||||
device_->CreateRasterizerState(&rasterizer_desc, &rasterizer_state);
|
||||
rasterizer_state_cache_.insert({ key, rasterizer_state });
|
||||
} else {
|
||||
rasterizer_state = it->second;
|
||||
}
|
||||
|
||||
context_->RSSetState(rasterizer_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupBlendState(const DrawCommand& command) {
|
||||
static const D3D11_BLEND blend_map[] = {
|
||||
/* 0 */ D3D11_BLEND_ZERO,
|
||||
/* 1 */ D3D11_BLEND_ONE,
|
||||
/* 2 */ D3D11_BLEND_ZERO, // ?
|
||||
/* 3 */ D3D11_BLEND_ZERO, // ?
|
||||
/* 4 */ D3D11_BLEND_SRC_COLOR,
|
||||
/* 5 */ D3D11_BLEND_INV_SRC_COLOR,
|
||||
/* 6 */ D3D11_BLEND_SRC_ALPHA,
|
||||
/* 7 */ D3D11_BLEND_INV_SRC_ALPHA,
|
||||
/* 8 */ D3D11_BLEND_DEST_COLOR,
|
||||
/* 9 */ D3D11_BLEND_INV_DEST_COLOR,
|
||||
/* 10 */ D3D11_BLEND_DEST_ALPHA,
|
||||
/* 11 */ D3D11_BLEND_INV_DEST_ALPHA,
|
||||
/* 12 */ D3D11_BLEND_BLEND_FACTOR,
|
||||
/* 13 */ D3D11_BLEND_INV_BLEND_FACTOR,
|
||||
/* 14 */ D3D11_BLEND_SRC1_ALPHA, // ?
|
||||
/* 15 */ D3D11_BLEND_INV_SRC1_ALPHA, // ?
|
||||
/* 16 */ D3D11_BLEND_SRC_ALPHA_SAT,
|
||||
};
|
||||
static const D3D11_BLEND_OP blend_op_map[] = {
|
||||
/* 0 */ D3D11_BLEND_OP_ADD,
|
||||
/* 1 */ D3D11_BLEND_OP_SUBTRACT,
|
||||
/* 2 */ D3D11_BLEND_OP_MIN,
|
||||
/* 3 */ D3D11_BLEND_OP_MAX,
|
||||
/* 4 */ D3D11_BLEND_OP_REV_SUBTRACT,
|
||||
};
|
||||
|
||||
// alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE
|
||||
// Not in D3D11!
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb205120(v=vs.85).aspx
|
||||
uint32_t color_control = register_file_[XE_GPU_REG_RB_COLORCONTROL].u32;
|
||||
|
||||
uint32_t color_mask = register_file_[XE_GPU_REG_RB_COLOR_MASK].u32;
|
||||
uint32_t blend_control[4] = {
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_0].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_1].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_2].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_3].u32,
|
||||
};
|
||||
|
||||
// Check cache.
|
||||
uint64_t key = hash_combine(color_mask,
|
||||
blend_control[0], blend_control[1],
|
||||
blend_control[2], blend_control[3]);
|
||||
ID3D11BlendState* blend_state = nullptr;
|
||||
auto it = blend_state_cache_.find(key);
|
||||
if (it == blend_state_cache_.end()) {
|
||||
D3D11_BLEND_DESC blend_desc;
|
||||
xe_zero_struct(&blend_desc, sizeof(blend_desc));
|
||||
//blend_desc.AlphaToCoverageEnable = false;
|
||||
// ?
|
||||
blend_desc.IndependentBlendEnable = true;
|
||||
for (int n = 0; n < XECOUNT(blend_control); n++) {
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND
|
||||
blend_desc.RenderTarget[n].SrcBlend = blend_map[(blend_control[n] & 0x0000001F) >> 0];
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND
|
||||
blend_desc.RenderTarget[n].DestBlend = blend_map[(blend_control[n] & 0x00001F00) >> 8];
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN
|
||||
blend_desc.RenderTarget[n].BlendOp = blend_op_map[(blend_control[n] & 0x000000E0) >> 5];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND
|
||||
blend_desc.RenderTarget[n].SrcBlendAlpha = blend_map[(blend_control[n] & 0x001F0000) >> 16];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND
|
||||
blend_desc.RenderTarget[n].DestBlendAlpha = blend_map[(blend_control[n] & 0x1F000000) >> 24];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN
|
||||
blend_desc.RenderTarget[n].BlendOpAlpha = blend_op_map[(blend_control[n] & 0x00E00000) >> 21];
|
||||
// A2XX_RB_COLOR_MASK_WRITE_*
|
||||
blend_desc.RenderTarget[n].RenderTargetWriteMask = (color_mask >> (n * 4)) & 0xF;
|
||||
// A2XX_RB_COLORCONTROL_BLEND_DISABLE ?? Can't find this!
|
||||
// Just guess based on actions.
|
||||
blend_desc.RenderTarget[n].BlendEnable = !(
|
||||
(blend_desc.RenderTarget[n].SrcBlend == D3D11_BLEND_ONE) &&
|
||||
(blend_desc.RenderTarget[n].DestBlend == D3D11_BLEND_ZERO) &&
|
||||
(blend_desc.RenderTarget[n].BlendOp == D3D11_BLEND_OP_ADD) &&
|
||||
(blend_desc.RenderTarget[n].SrcBlendAlpha == D3D11_BLEND_ONE) &&
|
||||
(blend_desc.RenderTarget[n].DestBlendAlpha == D3D11_BLEND_ZERO) &&
|
||||
(blend_desc.RenderTarget[n].BlendOpAlpha == D3D11_BLEND_OP_ADD));
|
||||
}
|
||||
device_->CreateBlendState(&blend_desc, &blend_state);
|
||||
blend_state_cache_.insert({ key, blend_state });
|
||||
} else {
|
||||
blend_state = it->second;
|
||||
}
|
||||
|
||||
float blend_factor[4] = {
|
||||
register_file_[XE_GPU_REG_RB_BLEND_RED].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_GREEN].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_BLUE].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_ALPHA].f32,
|
||||
};
|
||||
uint32_t sample_mask = 0xFFFFFFFF; // ?
|
||||
context_->OMSetBlendState(blend_state, blend_factor, sample_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupDepthStencilState(const DrawCommand& command) {
|
||||
static const D3D11_COMPARISON_FUNC compare_func_map[] = {
|
||||
/* 0 */ D3D11_COMPARISON_NEVER,
|
||||
/* 1 */ D3D11_COMPARISON_LESS,
|
||||
|
@ -412,9 +547,14 @@ int D3D11GraphicsDriver::UpdateState(const DrawCommand& command) {
|
|||
/* 7 */ D3D11_STENCIL_OP_DECR,
|
||||
};
|
||||
|
||||
// Depth-stencil state.
|
||||
uint32_t depth_control = register_file_[XE_GPU_REG_RB_DEPTHCONTROL].u32;
|
||||
uint32_t stencil_ref_mask = register_file_[XE_GPU_REG_RB_STENCILREFMASK].u32;
|
||||
|
||||
// Check cache.
|
||||
uint64_t key = (uint64_t(depth_control) << 32) | stencil_ref_mask;
|
||||
ID3D11DepthStencilState* depth_stencil_state = nullptr;
|
||||
auto it = depth_stencil_state_cache_.find(key);
|
||||
if (it == depth_stencil_state_cache_.end()) {
|
||||
D3D11_DEPTH_STENCIL_DESC depth_stencil_desc;
|
||||
xe_zero_struct(&depth_stencil_desc, sizeof(depth_stencil_desc));
|
||||
// A2XX_RB_DEPTHCONTROL_BACKFACE_ENABLE
|
||||
|
@ -449,95 +589,15 @@ int D3D11GraphicsDriver::UpdateState(const DrawCommand& command) {
|
|||
depth_stencil_desc.BackFace.StencilPassOp = stencil_op_map[(depth_control & 0x1C000000) >> 26];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF
|
||||
depth_stencil_desc.BackFace.StencilDepthFailOp = stencil_op_map[(depth_control & 0xE0000000) >> 29];
|
||||
device_->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil_state);
|
||||
depth_stencil_state_cache_.insert({ key, depth_stencil_state });
|
||||
} else {
|
||||
depth_stencil_state = it->second;
|
||||
}
|
||||
|
||||
// RB_STENCILREFMASK_STENCILREF
|
||||
uint32_t stencil_ref = (stencil_ref_mask & 0x000000FF);
|
||||
ID3D11DepthStencilState* depth_stencil_state = 0;
|
||||
device_->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil_state);
|
||||
context_->OMSetDepthStencilState(depth_stencil_state, stencil_ref);
|
||||
XESAFERELEASE(depth_stencil_state);
|
||||
|
||||
static const D3D11_BLEND blend_map[] = {
|
||||
/* 0 */ D3D11_BLEND_ZERO,
|
||||
/* 1 */ D3D11_BLEND_ONE,
|
||||
/* 2 */ D3D11_BLEND_ZERO, // ?
|
||||
/* 3 */ D3D11_BLEND_ZERO, // ?
|
||||
/* 4 */ D3D11_BLEND_SRC_COLOR,
|
||||
/* 5 */ D3D11_BLEND_INV_SRC_COLOR,
|
||||
/* 6 */ D3D11_BLEND_SRC_ALPHA,
|
||||
/* 7 */ D3D11_BLEND_INV_SRC_ALPHA,
|
||||
/* 8 */ D3D11_BLEND_DEST_COLOR,
|
||||
/* 9 */ D3D11_BLEND_INV_DEST_COLOR,
|
||||
/* 10 */ D3D11_BLEND_DEST_ALPHA,
|
||||
/* 11 */ D3D11_BLEND_INV_DEST_ALPHA,
|
||||
/* 12 */ D3D11_BLEND_BLEND_FACTOR,
|
||||
/* 13 */ D3D11_BLEND_INV_BLEND_FACTOR,
|
||||
/* 14 */ D3D11_BLEND_SRC1_ALPHA, // ?
|
||||
/* 15 */ D3D11_BLEND_INV_SRC1_ALPHA, // ?
|
||||
/* 16 */ D3D11_BLEND_SRC_ALPHA_SAT,
|
||||
};
|
||||
static const D3D11_BLEND_OP blend_op_map[] = {
|
||||
/* 0 */ D3D11_BLEND_OP_ADD,
|
||||
/* 1 */ D3D11_BLEND_OP_SUBTRACT,
|
||||
/* 2 */ D3D11_BLEND_OP_MIN,
|
||||
/* 3 */ D3D11_BLEND_OP_MAX,
|
||||
/* 4 */ D3D11_BLEND_OP_REV_SUBTRACT,
|
||||
};
|
||||
|
||||
// alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE
|
||||
// Not in D3D11!
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb205120(v=vs.85).aspx
|
||||
uint32_t color_control = register_file_[XE_GPU_REG_RB_COLORCONTROL].u32;
|
||||
|
||||
// Blend state.
|
||||
uint32_t color_mask = register_file_[XE_GPU_REG_RB_COLOR_MASK].u32;
|
||||
uint32_t sample_mask = 0xFFFFFFFF; // ?
|
||||
float blend_factor[4] = {
|
||||
register_file_[XE_GPU_REG_RB_BLEND_RED].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_GREEN].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_BLUE].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_ALPHA].f32,
|
||||
};
|
||||
uint32_t blend_control[4] = {
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_0].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_1].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_2].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_3].u32,
|
||||
};
|
||||
D3D11_BLEND_DESC blend_desc;
|
||||
xe_zero_struct(&blend_desc, sizeof(blend_desc));
|
||||
//blend_desc.AlphaToCoverageEnable = false;
|
||||
// ?
|
||||
blend_desc.IndependentBlendEnable = true;
|
||||
for (int n = 0; n < XECOUNT(blend_control); n++) {
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND
|
||||
blend_desc.RenderTarget[n].SrcBlend = blend_map[(blend_control[n] & 0x0000001F) >> 0];
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND
|
||||
blend_desc.RenderTarget[n].DestBlend = blend_map[(blend_control[n] & 0x00001F00) >> 8];
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN
|
||||
blend_desc.RenderTarget[n].BlendOp = blend_op_map[(blend_control[n] & 0x000000E0) >> 5];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND
|
||||
blend_desc.RenderTarget[n].SrcBlendAlpha = blend_map[(blend_control[n] & 0x001F0000) >> 16];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND
|
||||
blend_desc.RenderTarget[n].DestBlendAlpha = blend_map[(blend_control[n] & 0x1F000000) >> 24];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN
|
||||
blend_desc.RenderTarget[n].BlendOpAlpha = blend_op_map[(blend_control[n] & 0x00E00000) >> 21];
|
||||
// A2XX_RB_COLOR_MASK_WRITE_*
|
||||
blend_desc.RenderTarget[n].RenderTargetWriteMask = (color_mask >> (n * 4)) & 0xF;
|
||||
// A2XX_RB_COLORCONTROL_BLEND_DISABLE ?? Can't find this!
|
||||
// Just guess based on actions.
|
||||
blend_desc.RenderTarget[n].BlendEnable = !(
|
||||
(blend_desc.RenderTarget[n].SrcBlend == D3D11_BLEND_ONE) &&
|
||||
(blend_desc.RenderTarget[n].DestBlend == D3D11_BLEND_ZERO) &&
|
||||
(blend_desc.RenderTarget[n].BlendOp == D3D11_BLEND_OP_ADD) &&
|
||||
(blend_desc.RenderTarget[n].SrcBlendAlpha == D3D11_BLEND_ONE) &&
|
||||
(blend_desc.RenderTarget[n].DestBlendAlpha == D3D11_BLEND_ZERO) &&
|
||||
(blend_desc.RenderTarget[n].BlendOpAlpha == D3D11_BLEND_OP_ADD));
|
||||
}
|
||||
ID3D11BlendState* blend_state = 0;
|
||||
device_->CreateBlendState(&blend_desc, &blend_state);
|
||||
context_->OMSetBlendState(blend_state, blend_factor, sample_mask);
|
||||
XESAFERELEASE(blend_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@ private:
|
|||
void InitializeInvalidTexture();
|
||||
|
||||
int UpdateState(const DrawCommand& command);
|
||||
int SetupRasterizerState(const DrawCommand& command);
|
||||
int SetupBlendState(const DrawCommand& command);
|
||||
int SetupDepthStencilState(const DrawCommand& command);
|
||||
int SetupConstantBuffers(const DrawCommand& command);
|
||||
int SetupShaders(const DrawCommand& command);
|
||||
int SetupInputAssembly(const DrawCommand& command);
|
||||
|
@ -61,6 +64,10 @@ private:
|
|||
ID3D11ShaderResourceView* invalid_texture_view_;
|
||||
ID3D11SamplerState* invalid_texture_sampler_state_;
|
||||
|
||||
std::unordered_map<uint64_t, ID3D11RasterizerState*> rasterizer_state_cache_;
|
||||
std::unordered_map<uint64_t, ID3D11BlendState*> blend_state_cache_;
|
||||
std::unordered_map<uint64_t, ID3D11DepthStencilState*> depth_stencil_state_cache_;
|
||||
|
||||
struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
|
Loading…
Reference in New Issue