Work on D3D11 for various state settings. This code sucks. Needs a rewrite.

This commit is contained in:
Ben Vanik 2014-01-18 01:50:31 -08:00
parent a7db0f0410
commit c257ad0122
9 changed files with 435 additions and 65 deletions

View File

@ -21,8 +21,10 @@ using namespace xe::gpu::xenos;
D3D11GraphicsDriver::D3D11GraphicsDriver( D3D11GraphicsDriver::D3D11GraphicsDriver(
Memory* memory, ID3D11Device* device) : Memory* memory, IDXGISwapChain* swap_chain, ID3D11Device* device) :
GraphicsDriver(memory) { GraphicsDriver(memory) {
swap_chain_ = swap_chain;
swap_chain_->AddRef();
device_ = device; device_ = device;
device_->AddRef(); device_->AddRef();
device_->GetImmediateContext(&context_); device_->GetImmediateContext(&context_);
@ -30,6 +32,8 @@ D3D11GraphicsDriver::D3D11GraphicsDriver(
xe_zero_struct(&state_, sizeof(state_)); xe_zero_struct(&state_, sizeof(state_));
xe_zero_struct(&render_targets_, sizeof(render_targets_));
HRESULT hr; HRESULT hr;
D3D11_BUFFER_DESC buffer_desc; D3D11_BUFFER_DESC buffer_desc;
xe_zero_struct(&buffer_desc, sizeof(buffer_desc)); xe_zero_struct(&buffer_desc, sizeof(buffer_desc));
@ -45,15 +49,51 @@ D3D11GraphicsDriver::D3D11GraphicsDriver(
buffer_desc.ByteWidth = (32) * sizeof(int); buffer_desc.ByteWidth = (32) * sizeof(int);
hr = device_->CreateBuffer( hr = device_->CreateBuffer(
&buffer_desc, NULL, &state_.constant_buffers.loop_constants); &buffer_desc, NULL, &state_.constant_buffers.loop_constants);
//const char* shader_source =
// ""
// "[maxvertexcount(4)]\n"
// "void main(triange RectVert input[3], inout TriangleStream<RectVert> output) {"
// " output.Append(input[0]);"
// " output.Append(input[1]);"
// " output.Append(input[2]);"
// " /* compute 3 */"
// " output.RestartStrip();"
// "}";
//ID3D10Blob* shader_blob = 0;
//ID3D10Blob* error_blob = 0;
//HRESULT hr = D3DCompile(
// shader_source, strlen(shader_source),
// "d3d11_rect_shader.gs",
// NULL, NULL,
// "main",
// "gs_5_0",
// D3D10_SHADER_DEBUG | D3D10_SHADER_ENABLE_STRICTNESS, 0,
// &shader_blob, &error_blob);
//if (error_blob) {
// char* msg = (char*)error_blob->GetBufferPointer();
// XELOGE("D3D11: rect shader compile failed with %s", msg);
//}
//XESAFERELEASE(error_blob);
//byte* rect_shader_bytes = 0;
//size_t rect_shader_length = 0;
//ID3D11GeometryShader* rect_shader;
//hr = device_->CreateGeometryShader(
// shader_blob->GetBufferPointer(),
// shader_blob->GetBufferSize(),
// NULL, &rect_shader);
} }
D3D11GraphicsDriver::~D3D11GraphicsDriver() { D3D11GraphicsDriver::~D3D11GraphicsDriver() {
RebuildRenderTargets(0, 0);
XESAFERELEASE(state_.constant_buffers.float_constants); XESAFERELEASE(state_.constant_buffers.float_constants);
XESAFERELEASE(state_.constant_buffers.bool_constants); XESAFERELEASE(state_.constant_buffers.bool_constants);
XESAFERELEASE(state_.constant_buffers.loop_constants); XESAFERELEASE(state_.constant_buffers.loop_constants);
delete shader_cache_; delete shader_cache_;
XESAFERELEASE(context_); XESAFERELEASE(context_);
XESAFERELEASE(device_); XESAFERELEASE(device_);
XESAFERELEASE(swap_chain_);
} }
void D3D11GraphicsDriver::Initialize() { void D3D11GraphicsDriver::Initialize() {
@ -209,16 +249,168 @@ void D3D11GraphicsDriver::DrawIndexAuto(
context_->Draw(index_count, 0); context_->Draw(index_count, 0);
} }
int D3D11GraphicsDriver::RebuildRenderTargets(
uint32_t width, uint32_t height) {
if (width == render_targets_.width &&
height == render_targets_.height) {
// Cached copies are good.
return 0;
}
// Remove old versions.
for (int n = 0; n < XECOUNT(render_targets_.color_buffers); n++) {
auto& cb = render_targets_.color_buffers[n];
XESAFERELEASE(cb.buffer);
XESAFERELEASE(cb.color_view_8888);
}
XESAFERELEASE(render_targets_.depth_buffer);
XESAFERELEASE(render_targets_.depth_view_d28s8);
XESAFERELEASE(render_targets_.depth_view_d28fs8);
render_targets_.width = width;
render_targets_.height = height;
if (!width || !height) {
// This should only happen when cleaning up.
return 0;
}
for (int n = 0; n < XECOUNT(render_targets_.color_buffers); n++) {
auto& cb = render_targets_.color_buffers[n];
D3D11_TEXTURE2D_DESC color_buffer_desc;
xe_zero_struct(&color_buffer_desc, sizeof(color_buffer_desc));
color_buffer_desc.Width = width;
color_buffer_desc.Height = height;
color_buffer_desc.MipLevels = 1;
color_buffer_desc.ArraySize = 1;
color_buffer_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
color_buffer_desc.SampleDesc.Count = 1;
color_buffer_desc.SampleDesc.Quality = 0;
color_buffer_desc.Usage = D3D11_USAGE_DEFAULT;
color_buffer_desc.BindFlags =
D3D11_BIND_SHADER_RESOURCE |
D3D11_BIND_RENDER_TARGET;
color_buffer_desc.CPUAccessFlags = 0;
color_buffer_desc.MiscFlags = 0;
device_->CreateTexture2D(
&color_buffer_desc, NULL, &cb.buffer);
D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc;
xe_zero_struct(&render_target_view_desc, sizeof(render_target_view_desc));
render_target_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
// render_target_view_desc.Buffer ?
device_->CreateRenderTargetView(
cb.buffer,
&render_target_view_desc,
&cb.color_view_8888);
}
D3D11_TEXTURE2D_DESC depth_stencil_desc;
xe_zero_struct(&depth_stencil_desc, sizeof(depth_stencil_desc));
depth_stencil_desc.Width = width;
depth_stencil_desc.Height = height;
depth_stencil_desc.MipLevels = 1;
depth_stencil_desc.ArraySize = 1;
depth_stencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depth_stencil_desc.SampleDesc.Count = 1;
depth_stencil_desc.SampleDesc.Quality = 0;
depth_stencil_desc.Usage = D3D11_USAGE_DEFAULT;
depth_stencil_desc.BindFlags =
D3D11_BIND_DEPTH_STENCIL;
depth_stencil_desc.CPUAccessFlags = 0;
depth_stencil_desc.MiscFlags = 0;
device_->CreateTexture2D(
&depth_stencil_desc, NULL, &render_targets_.depth_buffer);
D3D11_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc;
xe_zero_struct(&depth_stencil_view_desc, sizeof(depth_stencil_view_desc));
depth_stencil_view_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depth_stencil_view_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depth_stencil_view_desc.Flags = 0;
device_->CreateDepthStencilView(
render_targets_.depth_buffer,
&depth_stencil_view_desc,
&render_targets_.depth_view_d28s8);
return 0;
}
int D3D11GraphicsDriver::UpdateState() { int D3D11GraphicsDriver::UpdateState() {
// Most information comes from here:
// https://chromium.googlesource.com/chromiumos/third_party/mesa/+/6173cc19c45d92ef0b7bc6aa008aa89bb29abbda/src/gallium/drivers/freedreno/freedreno_zsa.c // https://chromium.googlesource.com/chromiumos/third_party/mesa/+/6173cc19c45d92ef0b7bc6aa008aa89bb29abbda/src/gallium/drivers/freedreno/freedreno_zsa.c
// http://cgit.freedesktop.org/mesa/mesa/diff/?id=aac7f06ad843eaa696363e8e9c7781ca30cb4914 // http://cgit.freedesktop.org/mesa/mesa/diff/?id=aac7f06ad843eaa696363e8e9c7781ca30cb4914
// The only differences so far are extra packets for multiple render targets
// and a few modes being switched around.
RegisterFile& rf = register_file_; RegisterFile& rf = register_file_;
// RB_SURFACE_INFO uint32_t window_scissor_tl = rf.values[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL].u32;
// RB_DEPTH_INFO uint32_t window_scissor_br = rf.values[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR].u32;
//uint32_t window_width =
// (window_scissor_br & 0xFFFF) - (window_scissor_tl & 0xFFFF);
//uint32_t window_height =
// (window_scissor_br >> 16) - (window_scissor_tl >> 16);
uint32_t window_width = 1280;
uint32_t window_height = 720;
if (RebuildRenderTargets(window_width, window_height)) {
XELOGE("Unable to rebuild render targets to %d x %d",
window_width, window_height);
return 1;
}
// RB_SURFACE_INFO ?
// Enable buffers.
uint32_t enable_mode = rf.values[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7;
// 4 = color + depth
// 6 = copy ?
// color_info[0-3] has format 8888
uint32_t color_info[4] = {
rf.values[XE_GPU_REG_RB_COLOR_INFO].u32,
rf.values[XE_GPU_REG_RB_COLOR1_INFO].u32,
rf.values[XE_GPU_REG_RB_COLOR2_INFO].u32,
rf.values[XE_GPU_REG_RB_COLOR3_INFO].u32,
};
ID3D11RenderTargetView* render_target_views[4] = { 0 };
for (int n = 0; n < XECOUNT(color_info); n++) {
auto cb = render_targets_.color_buffers[n];
uint32_t color_format = (color_info[n] >> 16) & 0xF;
switch (color_format) {
case 0: // D3DFMT_A8R8G8B8 (or ABGR?)
case 1:
render_target_views[n] = cb.color_view_8888;
break;
default:
// Unknown.
XELOGGPU("Unsupported render target format %d", color_format);
break;
}
}
// depth_info has format 24_8
uint32_t depth_info = rf.values[XE_GPU_REG_RB_DEPTH_INFO].u32;
uint32_t depth_format = (depth_info >> 16) & 0x1;
ID3D11DepthStencilView* depth_stencil_view = 0;
switch (depth_format) {
case 0: // D3DFMT_D24S8
depth_stencil_view = render_targets_.depth_view_d28s8;
break;
default:
case 1: // D3DFMT_D24FS8
//depth_stencil_view = render_targets_.depth_view_d28fs8;
XELOGGPU("Unsupported depth/stencil format %d", depth_format);
break;
}
// TODO(benvanik): when a game switches does it expect to keep the same
// depth buffer contents?
// TODO(benvanik): only enable the number of valid render targets.
context_->OMSetRenderTargets(4, render_target_views, depth_stencil_view);
// General rasterizer state. // General rasterizer state.
uint32_t mode_control = rf.values[XE_GPU_REG_RB_MODECONTROL].u32; uint32_t mode_control = rf.values[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32;
D3D11_RASTERIZER_DESC rasterizer_desc; D3D11_RASTERIZER_DESC rasterizer_desc;
xe_zero_struct(&rasterizer_desc, sizeof(rasterizer_desc)); xe_zero_struct(&rasterizer_desc, sizeof(rasterizer_desc));
rasterizer_desc.FillMode = D3D11_FILL_SOLID; // D3D11_FILL_WIREFRAME; rasterizer_desc.FillMode = D3D11_FILL_SOLID; // D3D11_FILL_WIREFRAME;
@ -246,8 +438,69 @@ int D3D11GraphicsDriver::UpdateState() {
context_->RSSetState(rasterizer_state); context_->RSSetState(rasterizer_state);
XESAFERELEASE(rasterizer_state); XESAFERELEASE(rasterizer_state);
// Viewport.
// If we have resized the window we will want to change this.
uint32_t window_offset = rf.values[XE_GPU_REG_PA_SC_WINDOW_OFFSET].u32;
// ?
D3D11_VIEWPORT viewport;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = 1280;
viewport.Height = 720;
context_->RSSetViewports(1, &viewport);
// ?
// TODO(benvanik): figure out how to emulate viewports in D3D11. Could use
// viewport above to scale, though that doesn't support negatives/etc.
float vport_xoffset = rf.values[XE_GPU_REG_PA_CL_VPORT_XOFFSET].f32; // 640
float vport_xscale = rf.values[XE_GPU_REG_PA_CL_VPORT_XSCALE].f32; // 640
float vport_yoffset = rf.values[XE_GPU_REG_PA_CL_VPORT_YOFFSET].f32; // 360
float vport_yscale = rf.values[XE_GPU_REG_PA_CL_VPORT_YSCALE].f32; // -360
float vport_zoffset = rf.values[XE_GPU_REG_PA_CL_VPORT_ZOFFSET].f32; // 0
float vport_zscale = rf.values[XE_GPU_REG_PA_CL_VPORT_ZSCALE].f32; // 1
// Scissoring.
// TODO(benvanik): pull from scissor registers.
// ScissorEnable must be set in raster state above.
uint32_t screen_scissor_tl = rf.values[XE_GPU_REG_PA_SC_SCREEN_SCISSOR_TL].u32;
uint32_t screen_scissor_br = rf.values[XE_GPU_REG_PA_SC_SCREEN_SCISSOR_BR].u32;
if (screen_scissor_tl != 0 && screen_scissor_br != 0x20002000) {
D3D11_RECT scissor_rect;
scissor_rect.top = screen_scissor_tl >> 16;
scissor_rect.left = screen_scissor_tl & 0xFFFF;
scissor_rect.bottom = screen_scissor_br >> 16;
scissor_rect.right = screen_scissor_br & 0xFFFF;
context_->RSSetScissorRects(1, &scissor_rect);
} else {
context_->RSSetScissorRects(0, NULL);
}
static const D3D11_COMPARISON_FUNC compare_func_map[] = {
/* 0 */ D3D11_COMPARISON_NEVER,
/* 1 */ D3D11_COMPARISON_LESS,
/* 2 */ D3D11_COMPARISON_EQUAL,
/* 3 */ D3D11_COMPARISON_LESS_EQUAL,
/* 4 */ D3D11_COMPARISON_GREATER,
/* 5 */ D3D11_COMPARISON_NOT_EQUAL,
/* 6 */ D3D11_COMPARISON_GREATER_EQUAL,
/* 7 */ D3D11_COMPARISON_ALWAYS,
};
static const D3D11_STENCIL_OP stencil_op_map[] = {
/* 0 */ D3D11_STENCIL_OP_KEEP,
/* 1 */ D3D11_STENCIL_OP_ZERO,
/* 2 */ D3D11_STENCIL_OP_REPLACE,
/* 3 */ D3D11_STENCIL_OP_INCR_SAT,
/* 4 */ D3D11_STENCIL_OP_DECR_SAT,
/* 5 */ D3D11_STENCIL_OP_INVERT,
/* 6 */ D3D11_STENCIL_OP_INCR,
/* 7 */ D3D11_STENCIL_OP_DECR,
};
// Depth-stencil state. // Depth-stencil state.
uint32_t depth_control = rf.values[XE_GPU_REG_RB_DEPTHCONTROL].u32; uint32_t depth_control = rf.values[XE_GPU_REG_RB_DEPTHCONTROL].u32;
uint32_t stencil_ref_mask = rf.values[XE_GPU_REG_RB_STENCILREFMASK].u32;
D3D11_DEPTH_STENCIL_DESC depth_stencil_desc; D3D11_DEPTH_STENCIL_DESC depth_stencil_desc;
xe_zero_struct(&depth_stencil_desc, sizeof(depth_stencil_desc)); xe_zero_struct(&depth_stencil_desc, sizeof(depth_stencil_desc));
// A2XX_RB_DEPTHCONTROL_BACKFACE_ENABLE // A2XX_RB_DEPTHCONTROL_BACKFACE_ENABLE
@ -259,59 +512,117 @@ int D3D11GraphicsDriver::UpdateState() {
// A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE // A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE
// ? // ?
// A2XX_RB_DEPTHCONTROL_ZFUNC // A2XX_RB_DEPTHCONTROL_ZFUNC
// 0 = never, 7 = always -- almost lines up depth_stencil_desc.DepthFunc = compare_func_map[(depth_control & 0x00000070) >> 4];
depth_stencil_desc.DepthFunc = (D3D11_COMPARISON_FUNC)(((depth_control & 0x00000070) >> 4) + 1);
// A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE // A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE
depth_stencil_desc.StencilEnable = (depth_control & 0x00000001) != 0; depth_stencil_desc.StencilEnable = (depth_control & 0x00000001) != 0;
depth_stencil_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; // RB_STENCILREFMASK_STENCILMASK
depth_stencil_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; depth_stencil_desc.StencilReadMask = (stencil_ref_mask & 0x0000FF00) >> 8;
// RB_STENCILREFMASK_STENCILWRITEMASK
depth_stencil_desc.StencilWriteMask = (stencil_ref_mask & 0x00FF0000) >> 16;
// A2XX_RB_DEPTHCONTROL_STENCILFUNC // A2XX_RB_DEPTHCONTROL_STENCILFUNC
depth_stencil_desc.FrontFace.StencilFunc = depth_stencil_desc.FrontFace.StencilFunc = compare_func_map[(depth_control & 0x00000700) >> 8];
(D3D11_COMPARISON_FUNC)(((depth_control & 0x00000700) >> 8) + 1);
// A2XX_RB_DEPTHCONTROL_STENCILFAIL // A2XX_RB_DEPTHCONTROL_STENCILFAIL
// 0 = keep, 7 = decr -- almost lines up depth_stencil_desc.FrontFace.StencilFailOp = stencil_op_map[(depth_control & 0x00003800) >> 11];
depth_stencil_desc.FrontFace.StencilFailOp =
(D3D11_STENCIL_OP)(((depth_control & 0x00003800) >> 11) + 1);
// A2XX_RB_DEPTHCONTROL_STENCILZPASS // A2XX_RB_DEPTHCONTROL_STENCILZPASS
depth_stencil_desc.FrontFace.StencilPassOp = depth_stencil_desc.FrontFace.StencilPassOp = stencil_op_map[(depth_control & 0x0001C000) >> 14];
(D3D11_STENCIL_OP)(((depth_control & 0x0001C000) >> 14) + 1);
// A2XX_RB_DEPTHCONTROL_STENCILZFAIL // A2XX_RB_DEPTHCONTROL_STENCILZFAIL
depth_stencil_desc.FrontFace.StencilDepthFailOp = depth_stencil_desc.FrontFace.StencilDepthFailOp = stencil_op_map[(depth_control & 0x000E0000) >> 17];
(D3D11_STENCIL_OP)(((depth_control & 0x000E0000) >> 17) + 1);
// A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF // A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF
depth_stencil_desc.BackFace.StencilFunc = depth_stencil_desc.BackFace.StencilFunc = compare_func_map[(depth_control & 0x00700000) >> 20];
(D3D11_COMPARISON_FUNC)(((depth_control & 0x00700000) >> 20) + 1);
// A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF // A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF
depth_stencil_desc.BackFace.StencilFailOp = depth_stencil_desc.BackFace.StencilFailOp = stencil_op_map[(depth_control & 0x03800000) >> 23];
(D3D11_STENCIL_OP)(((depth_control & 0x03800000) >> 23) + 1);
// A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF // A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF
depth_stencil_desc.BackFace.StencilPassOp = depth_stencil_desc.BackFace.StencilPassOp = stencil_op_map[(depth_control & 0x1C000000) >> 26];
(D3D11_STENCIL_OP)(((depth_control & 0x1C000000) >> 26) + 1);
// A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF // A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF
depth_stencil_desc.BackFace.StencilDepthFailOp = depth_stencil_desc.BackFace.StencilDepthFailOp = stencil_op_map[(depth_control & 0xE0000000) >> 29];
(D3D11_STENCIL_OP)(((depth_control & 0xE0000000) >> 29) + 1); // RB_STENCILREFMASK_STENCILREF
uint32_t stencil_ref = (stencil_ref_mask & 0x000000FF);
ID3D11DepthStencilState* depth_stencil_state = 0; ID3D11DepthStencilState* depth_stencil_state = 0;
device_->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil_state); device_->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil_state);
context_->OMSetDepthStencilState(depth_stencil_state, 0 /* stencil ref */); context_->OMSetDepthStencilState(depth_stencil_state, stencil_ref);
XESAFERELEASE(depth_stencil_state); 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 = rf.values[XE_GPU_REG_RB_COLORCONTROL].u32;
// Blend state. // Blend state.
//context_->OMSetBlendState(blend_state, blend_factor, sample_mask); uint32_t color_mask = rf.values[XE_GPU_REG_RB_COLOR_MASK].u32;
uint32_t sample_mask = 0xFFFFFFFF; // ?
// Scissoring. float blend_factor[4] = {
// TODO(benvanik): pull from scissor registers. rf.values[XE_GPU_REG_RB_BLEND_RED].f32,
context_->RSSetScissorRects(0, NULL); rf.values[XE_GPU_REG_RB_BLEND_GREEN].f32,
rf.values[XE_GPU_REG_RB_BLEND_BLUE].f32,
// Viewport. rf.values[XE_GPU_REG_RB_BLEND_ALPHA].f32,
// If we have resized the window we will want to change this. };
D3D11_VIEWPORT viewport; uint32_t blend_control[4] = {
viewport.MinDepth = 0.0f; rf.values[XE_GPU_REG_RB_BLENDCONTROL_0].u32,
viewport.MaxDepth = 1.0f; rf.values[XE_GPU_REG_RB_BLENDCONTROL_1].u32,
viewport.TopLeftX = 0; rf.values[XE_GPU_REG_RB_BLENDCONTROL_2].u32,
viewport.TopLeftY = 0; rf.values[XE_GPU_REG_RB_BLENDCONTROL_3].u32,
viewport.Width = 1280; };
viewport.Height = 720; D3D11_BLEND_DESC blend_desc;
context_->RSSetViewports(1, &viewport); 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; return 0;
} }
@ -590,3 +901,30 @@ int D3D11GraphicsDriver::PrepareIndexBuffer(
return 0; return 0;
} }
int D3D11GraphicsDriver::Resolve() {
// No clue how this is supposed to work yet.
ID3D11Texture2D* back_buffer = 0;
swap_chain_->GetBuffer(0, __uuidof(ID3D11Texture2D),
(LPVOID*)&back_buffer);
D3D11_TEXTURE2D_DESC desc;
back_buffer->GetDesc(&desc);
if (desc.Width == render_targets_.width &&
desc.Height == render_targets_.height) {
// Same size/format, so copy quickly.
context_->CopyResource(back_buffer, render_targets_.color_buffers[0].buffer);
} else {
// TODO(benvanik): scale size using a quad draw.
}
XESAFERELEASE(back_buffer);
// TODO(benvanik): remove!
float color[4] = { 0.5f, 0.5f, 0.0f, 1.0f };
context_->ClearRenderTargetView(
render_targets_.color_buffers[0].color_view_8888, color);
// TODO(benvanik): take clear values from register
context_->ClearDepthStencilView(
render_targets_.depth_view_d28s8, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
return 0;
}

View File

@ -31,7 +31,8 @@ class D3D11VertexShader;
class D3D11GraphicsDriver : public GraphicsDriver { class D3D11GraphicsDriver : public GraphicsDriver {
public: public:
D3D11GraphicsDriver(Memory* memory, ID3D11Device* device); D3D11GraphicsDriver(
Memory* memory, IDXGISwapChain* swap_chain, ID3D11Device* device);
virtual ~D3D11GraphicsDriver(); virtual ~D3D11GraphicsDriver();
virtual void Initialize(); virtual void Initialize();
@ -51,8 +52,12 @@ public:
xenos::XE_GPU_PRIMITIVE_TYPE prim_type, xenos::XE_GPU_PRIMITIVE_TYPE prim_type,
uint32_t index_count); uint32_t index_count);
// TODO(benvanik): figure this out.
virtual int Resolve();
private: private:
int SetupDraw(xenos::XE_GPU_PRIMITIVE_TYPE prim_type); int SetupDraw(xenos::XE_GPU_PRIMITIVE_TYPE prim_type);
int RebuildRenderTargets(uint32_t width, uint32_t height);
int UpdateState(); int UpdateState();
int UpdateConstantBuffers(); int UpdateConstantBuffers();
int BindShaders(); int BindShaders();
@ -65,10 +70,23 @@ private:
uint32_t index_base, uint32_t index_size, uint32_t endianness); uint32_t index_base, uint32_t index_size, uint32_t endianness);
private: private:
IDXGISwapChain* swap_chain_;
ID3D11Device* device_; ID3D11Device* device_;
ID3D11DeviceContext* context_; ID3D11DeviceContext* context_;
D3D11ShaderCache* shader_cache_; D3D11ShaderCache* shader_cache_;
struct {
uint32_t width;
uint32_t height;
struct {
ID3D11Texture2D* buffer;
ID3D11RenderTargetView* color_view_8888;
} color_buffers[4];
ID3D11Texture2D* depth_buffer;
ID3D11DepthStencilView* depth_view_d28s8;
ID3D11DepthStencilView* depth_view_d28fs8;
} render_targets_;
struct { struct {
D3D11VertexShader* vertex_shader; D3D11VertexShader* vertex_shader;
D3D11PixelShader* pixel_shader; D3D11PixelShader* pixel_shader;

View File

@ -137,7 +137,8 @@ void D3D11GraphicsSystem::Initialize() {
// This runs in the worker thread and builds command lines to present // This runs in the worker thread and builds command lines to present
// in the window. // in the window.
XEASSERTNULL(driver_); XEASSERTNULL(driver_);
driver_ = new D3D11GraphicsDriver(memory_, device_); driver_ = new D3D11GraphicsDriver(
memory_, window_->swap_chain(), device_);
// Initial vsync kick. // Initial vsync kick.
DispatchInterruptCallback(0); DispatchInterruptCallback(0);
@ -147,6 +148,9 @@ void D3D11GraphicsSystem::Pump() {
if (swap_pending_) { if (swap_pending_) {
swap_pending_ = false; swap_pending_ = false;
// TODO(benvanik): remove this when commands are understood.
driver_->Resolve();
// Swap window. // Swap window.
// If we are set to vsync this will block. // If we are set to vsync this will block.
window_->Swap(); window_->Swap();

View File

@ -57,11 +57,11 @@ int D3D11Window::Initialize(const char* title, uint32_t width, uint32_t height)
xe_zero_struct(&desc, sizeof(desc)); xe_zero_struct(&desc, sizeof(desc));
desc.OutputWindow = handle(); desc.OutputWindow = handle();
desc.Windowed = TRUE; desc.Windowed = TRUE;
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
// Setup buffers. // Setup buffers.
desc.BufferCount = 1; desc.BufferCount = 2;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferDesc.Width = width; desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height; desc.BufferDesc.Height = height;

View File

@ -29,6 +29,8 @@ public:
IDXGIFactory1* dxgi_factory, ID3D11Device* device); IDXGIFactory1* dxgi_factory, ID3D11Device* device);
virtual ~D3D11Window(); virtual ~D3D11Window();
IDXGISwapChain* swap_chain() const { return swap_chain_; }
virtual int Initialize(const char* title, uint32_t width, uint32_t height); virtual int Initialize(const char* title, uint32_t width, uint32_t height);
void Swap(); void Swap();

View File

@ -47,6 +47,8 @@ public:
xenos::XE_GPU_PRIMITIVE_TYPE prim_type, xenos::XE_GPU_PRIMITIVE_TYPE prim_type,
uint32_t index_count) = 0; uint32_t index_count) = 0;
virtual int Resolve() = 0;
protected: protected:
GraphicsDriver(Memory* memory); GraphicsDriver(Memory* memory);

View File

@ -83,3 +83,7 @@ void NopGraphicsDriver::DrawIndexAuto(
// shader constants / bools / integers // shader constants / bools / integers
// fetch constants // fetch constants
} }
int NopGraphicsDriver::Resolve() {
return 0;
}

View File

@ -47,6 +47,8 @@ public:
xenos::XE_GPU_PRIMITIVE_TYPE prim_type, xenos::XE_GPU_PRIMITIVE_TYPE prim_type,
uint32_t index_count); uint32_t index_count);
virtual int Resolve();
protected: protected:
ShaderCache* shader_cache_; ShaderCache* shader_cache_;
}; };

View File

@ -203,7 +203,7 @@ SHIM_CALL DbgPrint_shim(
uint32_t value = arg_index < 7 uint32_t value = arg_index < 7
? SHIM_GET_ARG_32(1 + arg_index) ? SHIM_GET_ARG_32(1 + arg_index)
: (uint32_t)SHIM_MEM_64(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8)); : (uint32_t)SHIM_MEM_64(SHIM_GPR_32(1) + 16 + ((1 + arg_index) * 8));
SHIM_SET_MEM_32(value, (b - buffer) / sizeof(char)); SHIM_SET_MEM_32(value, (uint32_t)((b - buffer) / sizeof(char)));
arg_index++; arg_index++;
} }
else { else {