#include <string>
#include "Common/Log.h"
#include "Common/GraphicsContext.h"
#include "Common/Profiler/Profiler.h"
#include "GPU/GPUState.h"
#include "GPU/Common/FramebufferManagerCommon.h"
#include "GPU/D3D11/ShaderManagerD3D11.h"
#include "GPU/D3D11/GPU_D3D11.h"
#include "GPU/D3D11/FramebufferManagerD3D11.h"
#include "GPU/D3D11/DrawEngineD3D11.h"
#include "GPU/D3D11/TextureCacheD3D11.h"
#include "GPU/D3D11/D3D11Util.h"
GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
: GPUCommonHW(gfxCtx, draw), drawEngine_(draw,
(ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE),
(ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT)) {
device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE);
context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
D3D_FEATURE_LEVEL featureLevel = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL);
shaderManagerD3D11_ = new ShaderManagerD3D11(draw, device_, context_, featureLevel);
framebufferManagerD3D11_ = new FramebufferManagerD3D11(draw);
framebufferManager_ = framebufferManagerD3D11_;
textureCacheD3D11_ = new TextureCacheD3D11(draw, framebufferManager_->GetDraw2D());
textureCache_ = textureCacheD3D11_;
drawEngineCommon_ = &drawEngine_;
shaderManager_ = shaderManagerD3D11_;
drawEngine_.SetGPUCommon(this);
drawEngine_.SetShaderManager(shaderManagerD3D11_);
drawEngine_.SetTextureCache(textureCacheD3D11_);
drawEngine_.SetFramebufferManager(framebufferManagerD3D11_);
drawEngine_.Init();
framebufferManagerD3D11_->SetTextureCache(textureCacheD3D11_);
framebufferManagerD3D11_->SetShaderManager(shaderManagerD3D11_);
framebufferManagerD3D11_->SetDrawEngine(&drawEngine_);
framebufferManagerD3D11_->Init(msaaLevel_);
textureCacheD3D11_->SetFramebufferManager(framebufferManagerD3D11_);
textureCacheD3D11_->SetShaderManager(shaderManagerD3D11_);
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
ERROR_LOG(Log::G3D, "gstate has drifted out of sync!");
}
UpdateCmdInfo();
gstate_c.SetUseFlags(CheckGPUFeatures());
BuildReportingInfo();
textureCache_->NotifyConfigChanged();
}
GPU_D3D11::~GPU_D3D11() {
}
u32 GPU_D3D11::CheckGPUFeatures() const {
u32 features = GPUCommonHW::CheckGPUFeatures();
features |= GPU_USE_ACCURATE_DEPTH;
features |= GPU_USE_TEXTURE_FLOAT;
features |= GPU_USE_INSTANCE_RENDERING;
features |= GPU_USE_TEXTURE_LOD_CONTROL;
uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::A4R4G4B4_UNORM_PACK16);
uint32_t fmt1555 = draw_->GetDataFormatSupport(Draw::DataFormat::A1R5G5B5_UNORM_PACK16);
uint32_t fmt565 = draw_->GetDataFormatSupport(Draw::DataFormat::R5G6B5_UNORM_PACK16);
if ((fmt4444 & Draw::FMT_TEXTURE) && (fmt565 & Draw::FMT_TEXTURE) && (fmt1555 & Draw::FMT_TEXTURE)) {
features |= GPU_USE_16BIT_FORMATS;
}
return CheckGPUFeaturesLate(features);
}
void GPU_D3D11::DeviceLost() {
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
shaderManager_->ClearShaders();
drawEngine_.ClearInputLayoutMap();
GPUCommonHW::DeviceLost();
}
void GPU_D3D11::DeviceRestore(Draw::DrawContext *draw) {
GPUCommonHW::DeviceRestore(draw);
}
void GPU_D3D11::BeginHostFrame() {
GPUCommonHW::BeginHostFrame();
textureCache_->StartFrame();
drawEngine_.BeginFrame();
shaderManager_->DirtyLastShader();
framebufferManager_->BeginFrame();
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
if (gstate_c.useFlagsChanged) {
WARN_LOG(Log::G3D, "Shader use flags changed, clearing all shaders and depth buffers");
shaderManager_->ClearShaders();
framebufferManager_->ClearAllDepthBuffers();
drawEngine_.ClearInputLayoutMap();
gstate_c.useFlagsChanged = false;
}
}
void GPU_D3D11::FinishDeferred() {
drawEngine_.FinishDeferred();
}
void GPU_D3D11::GetStats(char *buffer, size_t bufsize) {
size_t offset = FormatGPUStatsCommon(buffer, bufsize);
buffer += offset;
bufsize -= offset;
if ((int)bufsize < 0)
return;
snprintf(buffer, bufsize,
"Vertex, Fragment shaders loaded: %d, %d\n",
shaderManagerD3D11_->GetNumVertexShaders(),
shaderManagerD3D11_->GetNumFragmentShaders()
);
}