void VertexShaderCache::Init() { const D3D11_INPUT_ELEMENT_DESC simpleelems[2] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; const D3D11_INPUT_ELEMENT_DESC clearelems[2] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; unsigned int cbsize = ROUND_UP(sizeof(VertexShaderConstants), 16); // 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, nullptr, &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, &blob); D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout); SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (SimpleLayout == nullptr || SimpleVertexShader == nullptr) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout"); D3D::CompileVertexShader(clear_shader_code, &blob); D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout); ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (ClearLayout == nullptr || ClearVertexShader == nullptr) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); std::string cache_filename = StringFromFormat("%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = nullptr; }
void DX11::Shader::UpdateConstantBuffer(ID3D11DeviceContext * context, std::vector<float> & constants, ID3D11Buffer ** buffer) { while((constants.size() % 4) != 0) { constants.push_back(0.0f); } if(*buffer) { context->UpdateSubresource(*buffer, 0, 0, constants.data(), 0, 0); } else { ID3D11Device * device = 0; context->GetDevice(&device); if(device) { D3D11_SUBRESOURCE_DATA data = { 0 }; data.pSysMem = constants.data(); device->CreateBuffer( &CD3D11_BUFFER_DESC(sizeof(float) * constants.size(), D3D11_BIND_CONSTANT_BUFFER), &data, buffer); device->Release(); } } }
void GeometryShaderCache::Init() { unsigned int gbsize = Common::AlignUp(static_cast<unsigned int>(sizeof(GeometryShaderConstants)), 16); // must be a multiple of 16 D3D11_BUFFER_DESC gbdesc = CD3D11_BUFFER_DESC(gbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); HRESULT hr = D3D::device->CreateBuffer(&gbdesc, nullptr, &gscbuf); CHECK(hr == S_OK, "Create geometry shader constant buffer (size=%u)", gbsize); D3D::SetDebugObjectName((ID3D11DeviceChild*)gscbuf, "geometry shader constant buffer used to emulate the GX pipeline"); // used when drawing clear quads ClearGeometryShader = D3D::CompileAndCreateGeometryShader(clear_shader_code); CHECK(ClearGeometryShader != nullptr, "Create clear geometry shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearGeometryShader, "clear geometry shader"); // used for buffer copy CopyGeometryShader = D3D::CompileAndCreateGeometryShader(copy_shader_code); CHECK(CopyGeometryShader != nullptr, "Create copy geometry shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)CopyGeometryShader, "copy geometry shader"); Clear(); if (g_ActiveConfig.bShaderCache) LoadShaderCache(); }
void GeometryShaderCache::Init() { unsigned int gbsize = ROUND_UP(sizeof(GeometryShaderConstants), 16); // must be a multiple of 16 D3D11_BUFFER_DESC gbdesc = CD3D11_BUFFER_DESC(gbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); HRESULT hr = D3D::device->CreateBuffer(&gbdesc, nullptr, &gscbuf); CHECK(hr == S_OK, "Create geometry shader constant buffer (size=%u)", gbsize); D3D::SetDebugObjectName((ID3D11DeviceChild*)gscbuf, "geometry shader constant buffer used to emulate the GX pipeline"); // used when drawing clear quads ClearGeometryShader = D3D::CompileAndCreateGeometryShader(clear_shader_code); CHECK(ClearGeometryShader != nullptr, "Create clear geometry shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearGeometryShader, "clear geometry shader"); // used for buffer copy CopyGeometryShader = D3D::CompileAndCreateGeometryShader(copy_shader_code); CHECK(CopyGeometryShader != nullptr, "Create copy geometry shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)CopyGeometryShader, "copy geometry shader"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); std::string cache_filename = StringFromFormat("%sdx11-%s-gs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); GeometryShaderCacheInserter inserter; g_gs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = nullptr; }
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf, u32 cbufid, const float *colmat) { g_renderer->ResetAPIState(); // stretch picture with increased internal resolution const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)config.width, (float)config.height); D3D::context->RSSetViewports(1, &vp); // set transformation if (nullptr == efbcopycbuf[cbufid].get()) { const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); D3D11_SUBRESOURCE_DATA data; data.pSysMem = colmat; HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, D3D::ToAddr(efbcopycbuf[cbufid])); CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid); D3D::SetDebugObjectName(efbcopycbuf[cbufid].get(), "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); } D3D::stateman->SetPixelConstants(efbcopycbuf[cbufid].get()); const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); // TODO: try targetSource.asRECT(); const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom); // Use linear filtering if (bScaleByHalf), use point filtering otherwise if (scaleByHalf) D3D::SetLinearCopySampler(); else D3D::SetPointCopySampler(); // if texture is currently in use, it needs to be temporarily unset u32 textureSlotMask = D3D::stateman->UnsetTexture(texture->GetSRV()); D3D::stateman->Apply(); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr); // Create texture copy D3D::drawShadedTexQuad( ((srcFormat == PEControl::Z24) ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture())->GetSRV(), &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), (srcFormat == PEControl::Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), (g_Config.iStereoMode > 0) ? GeometryShaderCache::GetCopyGeometryShader() : nullptr); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); if (g_ActiveConfig.bSkipEFBCopyToRam) { this->Zero(dst); } else { s_encoder->Encode(dst, this, srcFormat, srcRect, isIntensity, scaleByHalf); } }
void VertexShaderCache::Init() { const D3D11_INPUT_ELEMENT_DESC simpleelems[2] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; const D3D11_INPUT_ELEMENT_DESC clearelems[2] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; unsigned int cbsize = Common::AlignUp(static_cast<unsigned int>(sizeof(VertexShaderConstants)), 16); // 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, nullptr, &vscbuf); CHECK(hr == S_OK, "Create vertex shader constant buffer (size=%u)", cbsize); D3D::SetDebugObjectName(vscbuf, "vertex shader constant buffer used to emulate the GX pipeline"); D3DBlob* blob; D3D::CompileVertexShader(simple_shader_code, &blob); D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout); SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (SimpleLayout == nullptr || SimpleVertexShader == nullptr) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName(SimpleVertexShader, "simple vertex shader"); D3D::SetDebugObjectName(SimpleLayout, "simple input layout"); D3D::CompileVertexShader(clear_shader_code, &blob); D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout); ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (ClearLayout == nullptr || ClearVertexShader == nullptr) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName(ClearVertexShader, "clear vertex shader"); D3D::SetDebugObjectName(ClearLayout, "clear input layout"); Clear(); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); if (g_ActiveConfig.bShaderCache) LoadShaderCache(); g_async_compiler = std::make_unique<VideoCommon::AsyncShaderCompiler>(); g_async_compiler->ResizeWorkerThreads(g_ActiveConfig.CanPrecompileUberShaders() ? g_ActiveConfig.GetShaderPrecompilerThreads() : g_ActiveConfig.GetShaderCompilerThreads()); if (g_ActiveConfig.CanPrecompileUberShaders()) QueueUberShaderCompiles(); }
void InitUtils() { util_vbuf = new UtilVertexBuffer(0x4000); float border[4] = { 0.f, 0.f, 0.f, 0.f }; D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f); HRESULT hr = D3D::device->CreateSamplerState(&samDesc, &point_copy_sampler); if (FAILED(hr)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__); else SetDebugObjectName((ID3D11DeviceChild*)point_copy_sampler, "point copy sampler state"); samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f); hr = D3D::device->CreateSamplerState(&samDesc, &linear_copy_sampler); if (FAILED(hr)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__); else SetDebugObjectName((ID3D11DeviceChild*)linear_copy_sampler, "linear copy sampler state"); // cached data used to avoid unnecessarily reloading the vertex buffers memset(&tex_quad_data, 0, sizeof(tex_quad_data)); memset(&tex_sub_quad_data, 0, sizeof(tex_sub_quad_data)); memset(&draw_quad_data, 0, sizeof(draw_quad_data)); memset(&clear_quad_data, 0, sizeof(clear_quad_data)); // make sure to properly load the vertex data whenever the corresponding functions get called the first time stq_observer = stsq_observer = cq_observer = clearq_observer = true; util_vbuf->AddWrapObserver(&stq_observer); util_vbuf->AddWrapObserver(&stsq_observer); util_vbuf->AddWrapObserver(&cq_observer); util_vbuf->AddWrapObserver(&clearq_observer); font.Init(); // Create resources for encoder quads // Create vertex quad D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(ENCODER_QUAD_VERTS), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE); D3D11_SUBRESOURCE_DATA srd = { ENCODER_QUAD_VERTS, 0, 0 }; hr = D3D::device->CreateBuffer(&bd, &srd, &s_encoderQuad); CHECK(SUCCEEDED(hr), "create encoder quad buffer"); // Create vertex shader D3DBlob* blob; D3D::CompileVertexShader(ENCODER_VS, sizeof(ENCODER_VS), &blob); s_encoderVShader = D3D::CreateVertexShaderFromByteCode(blob); CHECK(SUCCEEDED(hr), "create encoder vertex shader"); // Create input layout hr = D3D::device->CreateInputLayout(ENCODER_QUAD_LAYOUT_DESC, sizeof(ENCODER_QUAD_LAYOUT_DESC) / sizeof(D3D11_INPUT_ELEMENT_DESC), blob->Data(), blob->Size(), &s_encoderQuadLayout); CHECK(SUCCEEDED(hr), "create encoder input layout"); blob->Release(); // Create vertex shader for encoder quads with texture coords s_encoderTexVShader = D3D::CompileAndCreateVertexShader(ENCODER_TEX_VS, sizeof(ENCODER_TEX_VS)); }
ConstantBufferPtr ConstantBuffer::Create(ID3D11Device* pDevice, UINT size) { ConstantBufferPtr p(new ConstantBuffer); D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC((size+15)&~15, D3D11_BIND_CONSTANT_BUFFER); CHECK_HR(pDevice->CreateBuffer(&bd, NULL, &p->m_pBuffer)); return p; }
DX11::TextureShader::TextureShader(ID3D11Device * device) : DX11::Shader(device, Type::Texture), standardConstBuffer(0), pixelObject(0) { device->CreateBuffer( &CD3D11_BUFFER_DESC(sizeof(StandardConstants), D3D11_BIND_CONSTANT_BUFFER), 0, &standardConstBuffer); ZeroMemory(paramConstBuffers, NUM_PARAM_BUFFERS * sizeof(void*)); }
DX11::ModelShader::ModelShader(ID3D11Device * device) : DX11::Shader(device, Type::Model) , vertexConstBuffer(0) , pixelConstBuffer(0) , indirectArgsBuffer(0) , currentTechnique(0) , indirectPrimitive(PrimitiveUnknown) { device->CreateBuffer( &CD3D11_BUFFER_DESC(sizeof(VertexConstants), D3D11_BIND_CONSTANT_BUFFER), 0, &vertexConstBuffer); device->CreateBuffer( &CD3D11_BUFFER_DESC(sizeof(PixelConstants), D3D11_BIND_CONSTANT_BUFFER), 0, &pixelConstBuffer); device->CreateBuffer( &CD3D11_BUFFER_DESC(sizeof(LightConstants)* MAX_LIGHTS, D3D11_BIND_CONSTANT_BUFFER), 0, &lightParamsBuffer); }
void PixelShaderCache::Init() { unsigned int cbsize = Common::AlignUp(static_cast<unsigned int>(sizeof(PixelShaderConstants)), 16); // 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, nullptr, &pscbuf); CHECK(pscbuf != nullptr, "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); CHECK(s_ClearProgram != nullptr, "Create clear pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader"); // used for anaglyph stereoscopy s_AnaglyphProgram = D3D::CompileAndCreatePixelShader(anaglyph_program_code); CHECK(s_AnaglyphProgram != nullptr, "Create anaglyph pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_AnaglyphProgram, "anaglyph pixel shader"); // used when copying/resolving the color buffer s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(color_copy_program_code); CHECK(s_ColorCopyProgram[0] != nullptr, "Create color copy pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorCopyProgram[0], "color copy pixel shader"); // used for color conversion s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(color_matrix_program_code); CHECK(s_ColorMatrixProgram[0] != nullptr, "Create color matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorMatrixProgram[0], "color matrix pixel shader"); // used for depth copy s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(depth_matrix_program); CHECK(s_DepthMatrixProgram[0] != nullptr, "Create depth matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_DepthMatrixProgram[0], "depth matrix pixel shader"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); SETSTAT(stats.numPixelShadersCreated, 0); SETSTAT(stats.numPixelShadersAlive, 0); std::string cache_filename = StringFromFormat("%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strGameID.c_str()); PixelShaderCacheInserter inserter; g_ps_disk_cache.OpenAndRead(cache_filename, inserter); last_entry = nullptr; }
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool scaleByHalf, unsigned int cbufid, const float *colmat) { g_renderer->ResetAPIState(); // stretch picture with increased internal resolution const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)config.width, (float)config.height); D3D::context->RSSetViewports(1, &vp); // set transformation if (nullptr == efbcopycbuf[cbufid]) { const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); D3D11_SUBRESOURCE_DATA data; data.pSysMem = colmat; HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]); CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); } D3D::stateman->SetPixelConstants(efbcopycbuf[cbufid]); const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); // TODO: try targetSource.asRECT(); const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom); // Use linear filtering if (bScaleByHalf), use point filtering otherwise if (scaleByHalf) D3D::SetLinearCopySampler(); else D3D::SetPointCopySampler(); // Make sure we don't draw with the texture set as both a source and target. // (This can happen because we don't unbind textures when we free them.) D3D::stateman->UnsetTexture(texture->GetSRV()); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr); // Create texture copy D3D::drawShadedTexQuad( (srcFormat == PEControl::Z24 ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture())->GetSRV(), &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), srcFormat == PEControl::Z24 ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader()); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); }
void MeshRenderer::Init(int numVertices, const MeshVertex* vertices, const MeshColor* color, const MeshSkin* skin, int numIndices, const AFIndex* indices) { Destroy(); static InputElement layout[] = { CInputElement("COLOR", SF_R8G8B8A8_UNORM, 0), CInputElement("TEXCOORD", SF_R32G32_FLOAT, 4), }; shaderId = shaderMan.Create("skin", layout, dimof(layout), BM_NONE, DSM_DEPTH_ENABLE, CM_CW); deviceMan11.GetDevice()->CreateBuffer(&CD3D11_BUFFER_DESC(numVertices * sizeof(MeshVertex), D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS, D3D11_USAGE_DEFAULT, 0, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, sizeof(MeshVertex)), nullptr, &skinnedPosBuffer); D3D11_SUBRESOURCE_DATA subresData = { vertices, 0, 0 }; deviceMan11.GetDevice()->CreateBuffer(&CD3D11_BUFFER_DESC(numVertices * sizeof(MeshVertex), D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, sizeof(MeshVertex)), &subresData, &posBuffer); subresData.pSysMem = skin; HRESULT hr = deviceMan11.GetDevice()->CreateBuffer(&CD3D11_BUFFER_DESC(numVertices * sizeof(MeshSkin), D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, sizeof(MeshSkin)), &subresData, &skinBuffer); colorBuffer = afCreateVertexBuffer(numVertices * sizeof(MeshColor), color); iboId = afCreateIndexBuffer(indices, numIndices); uboId = afCreateUBO(sizeof(MeshConstantBuffer)); int strides[] = {sizeof(MeshColor)}; VBOID vbos[] = {colorBuffer}; vao = afCreateVAO(layout, dimof(layout), 1, vbos, strides, iboId); sampler = afCreateSampler(SF_MIPMAP, SW_REPEAT); }
void LineGeometryShader::Init() { m_ready = false; HRESULT hr; // Create constant buffer for uploading data to geometry shader D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams_Padded), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); hr = D3D::device->CreateBuffer(&bd, nullptr, &m_paramsBuffer); CHECK(SUCCEEDED(hr), "create line geometry shader params buffer"); D3D::SetDebugObjectName(m_paramsBuffer, "line geometry shader params buffer"); m_ready = true; }
void PSTextureEncoder::Init() { // TODO: Move this to a constant somewhere in common. TextureConfig encoding_texture_config(EFB_WIDTH * 4, 1024, 1, 1, AbstractTextureFormat::BGRA8, true); m_encoding_render_texture = g_renderer->CreateTexture(encoding_texture_config); m_encoding_readback_texture = g_renderer->CreateStagingTexture(StagingTextureType::Readback, encoding_texture_config); _assert_(m_encoding_render_texture && m_encoding_readback_texture); // Create constant buffer for uploading data to shaders D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(EFBEncodeParams), D3D11_BIND_CONSTANT_BUFFER); HRESULT hr = D3D::device->CreateBuffer(&bd, nullptr, &m_encode_params); CHECK(SUCCEEDED(hr), "create efb encode params buffer"); D3D::SetDebugObjectName(m_encode_params, "efb encoder params buffer"); }
void PixelShaderCache::Init() { unsigned int cbsize = ((sizeof(PixelShaderConstants))&(~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"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader"); // used when copying/resolving the color buffer s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code)); CHECK(s_ColorCopyProgram[0]!=NULL, "Create color copy pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorCopyProgram[0], "color copy pixel shader"); // used for color conversion s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code)); CHECK(s_ColorMatrixProgram[0]!=NULL, "Create color matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorMatrixProgram[0], "color matrix pixel shader"); // used for depth copy s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program)); CHECK(s_DepthMatrixProgram[0]!=NULL, "Create depth matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_DepthMatrixProgram[0], "depth matrix pixel shader"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); SETSTAT(stats.numPixelShadersCreated, 0); SETSTAT(stats.numPixelShadersAlive, 0); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); PixelShaderCacheInserter inserter; g_ps_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = NULL; }
void VertexManager::CreateDeviceObjects() { D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(MAX_BUFFER_SIZE, D3D11_BIND_INDEX_BUFFER | D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); m_vertexDrawOffset = 0; m_indexDrawOffset = 0; for (int i = 0; i < MAX_BUFFER_COUNT; i++) { m_buffers[i] = nullptr; CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, nullptr, D3D::ToAddr(m_buffers[i]))), "Failed to create buffer."); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_buffers[i].get(), "Buffer of VertexManager"); } m_currentBuffer = 0; m_bufferCursor = MAX_BUFFER_SIZE; }
void PSTextureEncoder::Init() { m_ready = false; HRESULT hr; // Create output texture RGBA format D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC( DXGI_FORMAT_B8G8R8A8_UNORM, EFB_WIDTH * 4, EFB_HEIGHT / 4, 1, 1, D3D11_BIND_RENDER_TARGET); hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_out); CHECK(SUCCEEDED(hr), "create efb encode output texture"); D3D::SetDebugObjectName(m_out, "efb encoder output texture"); // Create output render target view D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC(m_out, D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_B8G8R8A8_UNORM); hr = D3D::device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV); CHECK(SUCCEEDED(hr), "create efb encode output render target view"); D3D::SetDebugObjectName(m_outRTV, "efb encoder output rtv"); // Create output staging buffer t2dd.Usage = D3D11_USAGE_STAGING; t2dd.BindFlags = 0; t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ; hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_outStage); CHECK(SUCCEEDED(hr), "create efb encode output staging buffer"); D3D::SetDebugObjectName(m_outStage, "efb encoder output staging buffer"); // Create constant buffer for uploading data to shaders D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(EFBEncodeParams), D3D11_BIND_CONSTANT_BUFFER); hr = D3D::device->CreateBuffer(&bd, nullptr, &m_encodeParams); CHECK(SUCCEEDED(hr), "create efb encode params buffer"); D3D::SetDebugObjectName(m_encodeParams, "efb encoder params buffer"); m_ready = true; }
void BBox::Init() { if (g_ActiveConfig.backend_info.bSupportsBBox) { // Create 2 buffers here. // First on Default pool. auto desc = CD3D11_BUFFER_DESC(4 * sizeof(s32), D3D11_BIND_UNORDERED_ACCESS, D3D11_USAGE_DEFAULT, 0, 0, 4); s_values[0] = s_values[1] = s_values[2] = s_values[3] = 0; D3D11_SUBRESOURCE_DATA data; data.pSysMem = s_values; data.SysMemPitch = 4 * sizeof(s32); data.SysMemSlicePitch = 0; HRESULT hr; hr = D3D::device->CreateBuffer(&desc, &data, ToAddr(s_bbox_buffer)); CHECK(SUCCEEDED(hr), "Create BoundingBox buffer."); D3D::SetDebugObjectName(s_bbox_buffer.get(), "BoundingBox buffer"); // Second to use as a staging buffer. desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; hr = D3D::device->CreateBuffer(&desc, nullptr, ToAddr(s_bbox_staging_buffer)); CHECK(SUCCEEDED(hr), "Create BoundingBox staging buffer."); D3D::SetDebugObjectName(s_bbox_staging_buffer.get(), "BoundingBox staging buffer"); // UAV is required to allow concurrent access. D3D11_UNORDERED_ACCESS_VIEW_DESC UAVdesc = {}; UAVdesc.Format = DXGI_FORMAT_R32_SINT; UAVdesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; UAVdesc.Buffer.FirstElement = 0; UAVdesc.Buffer.Flags = 0; UAVdesc.Buffer.NumElements = 4; hr = D3D::device->CreateUnorderedAccessView(s_bbox_buffer.get(), &UAVdesc, ToAddr(s_bbox_uav)); CHECK(SUCCEEDED(hr), "Create BoundingBox UAV."); s_cpu_dirty = true; s_gpu_dirty = true; } }
////////////////////////////////////////////////////////////////////////// // d3d11 constant buffer cgl::CD3D11ConstantBuffer::CD3D11ConstantBuffer( UINT elementSize, D3D11_USAGE usage /*= D3D11_USAGE_DEFAULT*/, UINT cpuAccessFlags /*= 0*/, UINT miscFlags /*= 0*/ ) : CD3D11Buffer(elementSize, CD3D11_BUFFER_DESC(0, D3D11_BIND_CONSTANT_BUFFER, usage, cpuAccessFlags, miscFlags, elementSize )) { }
////////////////////////////////////////////////////////////////////////// // d3d11 index buffer cgl::CD3D11IndexBuffer::CD3D11IndexBuffer( UINT elementSize, D3D11_USAGE usage /*= D3D11_USAGE_DEFAULT*/, UINT cpuAccessFlags /*= 0*/, UINT miscFlags /*= 0*/ ) : CD3D11Buffer(elementSize, CD3D11_BUFFER_DESC(0, D3D11_BIND_INDEX_BUFFER, usage, cpuAccessFlags, miscFlags, elementSize )) { }
////////////////////////////////////////////////////////////////////////// // d3d11 vertex buffer cgl::CD3D11VertexBuffer::CD3D11VertexBuffer(UINT stride, D3D11_USAGE usage, UINT cpuAccessFlags, UINT miscFlags ) : CD3D11Buffer(stride, CD3D11_BUFFER_DESC(0, D3D11_BIND_VERTEX_BUFFER, usage, cpuAccessFlags, miscFlags )) { }
void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf, unsigned int cbufid, const float *colmat) { if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { g_renderer->ResetAPIState(); // stretch picture with increased internal resolution const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtual_width, (float)virtual_height); D3D::context->RSSetViewports(1, &vp); // set transformation if (nullptr == efbcopycbuf[cbufid]) { const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); D3D11_SUBRESOURCE_DATA data; data.pSysMem = colmat; HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]); CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); } D3D::stateman->SetPixelConstants(efbcopycbuf[cbufid]); const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); // TODO: try targetSource.asRECT(); const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom); // Use linear filtering if (bScaleByHalf), use point filtering otherwise if (scaleByHalf) D3D::SetLinearCopySampler(); else D3D::SetPointCopySampler(); // if texture is currently in use, it needs to be temporarily unset u32 textureSlotMask = D3D::stateman->UnsetTexture(texture->GetSRV()); D3D::stateman->Apply(); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr); // Create texture copy D3D::drawShadedTexQuad( (srcFormat == PEControl::Z24) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(), &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), (srcFormat == PEControl::Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader()); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); // Restore old texture in all previously used slots, if any D3D::stateman->SetTextureByMask(textureSlotMask, texture->GetSRV()); } if (!g_ActiveConfig.bCopyEFBToTexture) { u8* dst = Memory::GetPointer(dstAddr); size_t encoded_size = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf); u64 hash = GetHash64(dst, (int)encoded_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); // Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date if (!g_ActiveConfig.bEFBCopyCacheEnable) TextureCache::MakeRangeDynamic(addr, (u32)encoded_size); else if (!TextureCache::Find(addr, hash)) TextureCache::MakeRangeDynamic(addr, (u32)encoded_size); this->hash = hash; } }
////////////////////////////////////////////////////////////////////////// // d3d11 input buffer cgl::util::CGLInputBuffer::CGLInputBuffer(cgl::core::PD3D11InputLayout pLayout, ICGLInputBufferDataProvider* pDataProvider, D3D11_USAGE usage /*= D3D11_USAGE_DEFAULT*/, DWORD cpuAccessFlags /*= 0*/) : CGLBase("CD3D11InputBuffer"), CGLTypedBindable(this), m_pLayout(pLayout), m_pDataProvider(pDataProvider), m_desc(CD3D11_BUFFER_DESC(0, D3D11_BIND_VERTEX_BUFFER, usage, cpuAccessFlags)) { SetParam<UINT>(BIND_PARAM_STRIDE_UINT, 1); SetParam<UINT>(BIND_PARAM_OFFSET_UINT, 0); SetParam<UINT>(BIND_PARAM_SLOT_UINT, 0); }
void VertexShaderCache::Init() { const D3D11_INPUT_ELEMENT_DESC simpleelems[2] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; const D3D11_INPUT_ELEMENT_DESC clearelems[2] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "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); SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout"); D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code), &blob); D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout); ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout"); Clear(); // these values are hardcoded, they depend on internal D3DCompile behavior // TODO: Do this with D3DReflect or something instead unsigned int k; for (k = 0;k < 6;k++) vs_constant_offset_table[C_POSNORMALMATRIX+k] = 0+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_PROJECTION+k] = 24+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_MATERIALS+k] = 40+4*k; for (k = 0;k < 40;k++) vs_constant_offset_table[C_LIGHTS+k] = 56+4*k; for (k = 0;k < 24;k++) vs_constant_offset_table[C_TEXMATRICES+k] = 216+4*k; for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k; for (k = 0;k < 32;k++) vs_constant_offset_table[C_NORMALMATRICES+k] = 568+4*k; for (k = 0;k < 64;k++) vs_constant_offset_table[C_POSTTRANSFORMMATRICES+k] = 696+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_DEPTHPARAMS+k] = 952+4*k; if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = NULL; }
void init( HWND hWnd ) { HRESULT hr; DXGI_SWAP_CHAIN_DESC scDesc; memset( &scDesc, 0, sizeof scDesc ); scDesc.BufferDesc.Width = g_windowWidth; scDesc.BufferDesc.Height = g_windowHeight; scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scDesc.BufferDesc.RefreshRate.Denominator = 1; scDesc.BufferDesc.RefreshRate.Numerator = 60; scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scDesc.BufferCount = 1; scDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scDesc.SampleDesc.Count = 1; scDesc.Windowed = TRUE; scDesc.OutputWindow = hWnd; D3D_FEATURE_LEVEL features[] = { D3D_FEATURE_LEVEL_11_0 }; UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #ifndef NDEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif IDXGISwapChain* swapChain; ID3D11Device* device; ID3D11DeviceContext* context; hr = D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, features, ARRAYSIZE( features ), D3D11_SDK_VERSION, &scDesc, &swapChain, &device, &featureLevel_, &context ); Assert( hr ); swapChain_.reset( swapChain ); device_.reset( device ); context_.reset( context ); ID3D11Texture2D* backBuffer; ID3D11RenderTargetView* backBufferRTV; hr = swapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &backBuffer ) ); Assert( hr ); hr = device_->CreateRenderTargetView( backBuffer, nullptr, &backBufferRTV ); Assert( hr ); backBufferRTV_.reset( backBufferRTV ); backBuffer->Release(); // Common state ID3D11RasterizerState* rs; D3D11_RASTERIZER_DESC rsDesc; memset( &rsDesc, 0, sizeof rsDesc ); rsDesc.CullMode = D3D11_CULL_BACK; rsDesc.FillMode = D3D11_FILL_SOLID; rsDesc.DepthClipEnable = TRUE; hr = device_->CreateRasterizerState( &rsDesc, &rs ); Assert( hr ); rasterState_.reset( rs ); // Body std::string binData; std::string vsBinData; ID3D11VertexShader* vs; binData = fileGetContents( "def.vs.cso" ); hr = device_->CreateVertexShader( reinterpret_cast< const void* >( binData.c_str() ), binData.size(), nullptr, &vs ); Assert( hr ); modelVS_.reset( vs ); vsBinData = binData; ID3D11PixelShader* ps; binData = fileGetContents( "def.ps.cso" ); hr = device_->CreatePixelShader( reinterpret_cast< const void* >( binData.c_str() ), binData.size(), nullptr, &ps ); Assert( hr ); modelPS_.reset( ps ); D3D11_BUFFER_DESC bufDesc = CD3D11_BUFFER_DESC( 64, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT, 0 ); ID3D11Buffer* buf; hr = device_->CreateBuffer( &bufDesc, nullptr, &buf ); Assert( hr ); modelCB_.reset( buf ); // 四角錐ポリゴン static const MeshFormat pyramidVertex[] = { { -1.0f, 0.0f, -1.0f, 0xFF33AAAA }, { 1.0f, 0.0f, -1.0f, 0xFF33AAAA }, { -1.0f, 0.0f, 1.0f, 0xFF33AAAA }, { -1.0f, 0.0f, 1.0f, 0xFF33AAAA }, { 1.0f, 0.0f, -1.0f, 0xFF33AAAA }, { 1.0f, 0.0f, 1.0f, 0xFF33AAAA }, { 1.0f, 0.0f, -1.0f, 0xFFEE33BB }, { -1.0f, 0.0f, -1.0f, 0xFFEE33BB }, { 0.0f, 1.0f, 0.0f, 0xFFEE33BB }, { -1.0f, 0.0f, -1.0f, 0xFFCC33BB }, { -1.0f, 0.0f, 1.0f, 0xFFCC33BB }, { 0.0f, 1.0f, 0.0f, 0xFFCC33BB }, { -1.0f, 0.0f, 1.0f, 0xFFAA33BB }, { 1.0f, 0.0f, 1.0f, 0xFFAA33BB }, { 0.0f, 1.0f, 0.0f, 0xFFAA33BB }, { 1.0f, 0.0f, 1.0f, 0xFF8833BB }, { 1.0f, 0.0f, -1.0f, 0xFF8833BB }, { 0.0f, 1.0f, 0.0f, 0xFF8833BB }, }; bufDesc = CD3D11_BUFFER_DESC( sizeof pyramidVertex, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE, 0 ); D3D11_SUBRESOURCE_DATA subresData; subresData.pSysMem = pyramidVertex; subresData.SysMemPitch = subresData.SysMemSlicePitch = 0; hr = device_->CreateBuffer( &bufDesc, &subresData, &buf ); Assert( hr ); modelVB_.reset( buf ); D3D11_INPUT_ELEMENT_DESC ieDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; ID3D11InputLayout* il; hr = device_->CreateInputLayout( ieDesc, ARRAYSIZE( ieDesc ), vsBinData.data(), vsBinData.size(), &il ); Assert( hr ); modelIL_.reset( il ); }
void XFBEncoder::Init() { HRESULT hr; // Create output texture // The pixel shader can generate one YUYV entry per pixel. One YUYV entry // is created for every two EFB pixels. D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC( DXGI_FORMAT_R8G8B8A8_UNORM, MAX_XFB_WIDTH/2, MAX_XFB_HEIGHT, 1, 1, D3D11_BIND_RENDER_TARGET); hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_out); CHECK(SUCCEEDED(hr), "create xfb encoder output texture"); D3D::SetDebugObjectName(m_out, "xfb encoder output texture"); // Create output render target view D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC(m_out, D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_R8G8B8A8_UNORM); hr = D3D::device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV); CHECK(SUCCEEDED(hr), "create xfb encoder output texture rtv"); D3D::SetDebugObjectName(m_outRTV, "xfb encoder output rtv"); // Create output staging buffer t2dd.Usage = D3D11_USAGE_STAGING; t2dd.BindFlags = 0; t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ; hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_outStage); CHECK(SUCCEEDED(hr), "create xfb encoder output staging buffer"); D3D::SetDebugObjectName(m_outStage, "xfb encoder output staging buffer"); // Create constant buffer for uploading params to shaders D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(XFBEncodeParams), D3D11_BIND_CONSTANT_BUFFER); hr = D3D::device->CreateBuffer(&bd, nullptr, &m_encodeParams); CHECK(SUCCEEDED(hr), "create xfb encode params buffer"); D3D::SetDebugObjectName(m_encodeParams, "xfb encoder params buffer"); // Create vertex quad bd = CD3D11_BUFFER_DESC(sizeof(QUAD_VERTS), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE); D3D11_SUBRESOURCE_DATA srd = { QUAD_VERTS, 0, 0 }; hr = D3D::device->CreateBuffer(&bd, &srd, &m_quad); CHECK(SUCCEEDED(hr), "create xfb encode quad vertex buffer"); D3D::SetDebugObjectName(m_quad, "xfb encoder quad vertex buffer"); // Create vertex shader D3DBlob* bytecode = nullptr; if (!D3D::CompileVertexShader(XFB_ENCODE_VS, &bytecode)) { ERROR_LOG(VIDEO, "XFB encode vertex shader failed to compile"); return; } hr = D3D::device->CreateVertexShader(bytecode->Data(), bytecode->Size(), nullptr, &m_vShader); CHECK(SUCCEEDED(hr), "create xfb encode vertex shader"); D3D::SetDebugObjectName(m_vShader, "xfb encoder vertex shader"); // Create input layout for vertex quad using bytecode from vertex shader hr = D3D::device->CreateInputLayout(QUAD_LAYOUT_DESC, sizeof(QUAD_LAYOUT_DESC)/sizeof(D3D11_INPUT_ELEMENT_DESC), bytecode->Data(), bytecode->Size(), &m_quadLayout); CHECK(SUCCEEDED(hr), "create xfb encode quad vertex layout"); D3D::SetDebugObjectName(m_quadLayout, "xfb encoder quad layout"); bytecode->Release(); // Create pixel shader m_pShader = D3D::CompileAndCreatePixelShader(XFB_ENCODE_PS); if (!m_pShader) { ERROR_LOG(VIDEO, "XFB encode pixel shader failed to compile"); return; } D3D::SetDebugObjectName(m_pShader, "xfb encoder pixel shader"); // Create blend state D3D11_BLEND_DESC bld = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); hr = D3D::device->CreateBlendState(&bld, &m_xfbEncodeBlendState); CHECK(SUCCEEDED(hr), "create xfb encode blend state"); D3D::SetDebugObjectName(m_xfbEncodeBlendState, "xfb encoder blend state"); // Create depth state D3D11_DEPTH_STENCIL_DESC dsd = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT()); dsd.DepthEnable = FALSE; hr = D3D::device->CreateDepthStencilState(&dsd, &m_xfbEncodeDepthState); CHECK(SUCCEEDED(hr), "create xfb encode depth state"); D3D::SetDebugObjectName(m_xfbEncodeDepthState, "xfb encoder depth state"); // Create rasterizer state D3D11_RASTERIZER_DESC rd = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT()); rd.CullMode = D3D11_CULL_NONE; rd.DepthClipEnable = FALSE; hr = D3D::device->CreateRasterizerState(&rd, &m_xfbEncodeRastState); CHECK(SUCCEEDED(hr), "create xfb encode rasterizer state"); D3D::SetDebugObjectName(m_xfbEncodeRastState, "xfb encoder rast state"); // Create EFB texture sampler D3D11_SAMPLER_DESC sd = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT()); // FIXME: Should we really use point sampling here? sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; hr = D3D::device->CreateSamplerState(&sd, &m_efbSampler); CHECK(SUCCEEDED(hr), "create xfb encode texture sampler"); D3D::SetDebugObjectName(m_efbSampler, "xfb encoder texture sampler"); }
OpenGL::OpenGL(ID3D11Device* device, ID3D11DeviceContext* context) { s_instance = this; _orthoLeft = 0; _orthoRight = 0; _orthoBottom = 0; _orthoTop = 0; _device = device; _context = context; _vertexBuffer = NULL; _currentTextureId = 0; _enableTexture2D = false; _batchCurrentTextureId = 0; _batchEnableTexture2D = false; _loadingComplete = false; _vertexBuilder = new VertexBuilder(); _maxVertices = MaxBatchVertices; _firstDrawInFrame = false; _currentBatchVertex = 0; _enableScissoring = false; _scissorRect.left = 0; _scissorRect.right = 0; _scissorRect.top = 0; _scissorRect.bottom = 0; _vertexShader = NULL; _pixelShaderTexture = NULL; _pixelShaderColor = NULL; auto vsize = sizeof (this->_batchVertices); // Asynchronously load the vertex and pixel shaders auto loadVSTask = ReadDataAsync("OpenGLVS.cso"); auto loadPSColorTask = ReadDataAsync("OpenGLColorPS.cso"); auto loadPSTextureTask = ReadDataAsync("OpenGLTexturePS.cso"); auto createVSTask = loadVSTask.then([this](ByteArray ba) { auto bytecodeVS = ba.data; ThrowIfFailed( _device->CreateVertexShader( bytecodeVS->Data, bytecodeVS->Length, nullptr, &_vertexShader ) ); const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; ThrowIfFailed( _device->CreateInputLayout( vertexDesc, ARRAYSIZE(vertexDesc), bytecodeVS->Data, bytecodeVS->Length, &_inputLayout ) ); }); auto createPSColorTask = loadPSColorTask.then([this](ByteArray ba) { auto bytecodePS = ba.data; ThrowIfFailed( _device->CreatePixelShader( bytecodePS->Data, bytecodePS->Length, nullptr, &_pixelShaderColor ) ); }); auto createPSTextureTask = loadPSTextureTask.then([this](ByteArray ba) { auto bytecodePS = ba.data; ThrowIfFailed( _device->CreatePixelShader( bytecodePS->Data, bytecodePS->Length, nullptr, &_pixelShaderTexture ) ); ThrowIfFailed( _device->CreateBuffer( &CD3D11_BUFFER_DESC(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER), nullptr, &_constantBuffer )); }); createPSTextureTask.then([this] () { _loadingComplete = true; }); ZeroMemory(&_rasterizerDesc, sizeof(_rasterizerDesc)); _rasterizerDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID; _rasterizerDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_NONE; _rasterizerDesc.FrontCounterClockwise = true; _rasterizerDesc.DepthBias = 0; _rasterizerDesc.SlopeScaledDepthBias = 0.f; _rasterizerDesc.DepthBiasClamp = 0.f; _rasterizerDesc.DepthClipEnable = true; _rasterizerDesc.ScissorEnable = false; _rasterizerDesc.MultisampleEnable = false; _rasterizerDesc.AntialiasedLineEnable = false; ID3D11RasterizerState* rasterizerState; _device->CreateRasterizerState(&_rasterizerDesc, &rasterizerState); _context->RSSetState(rasterizerState); // Push an identity matrix on the stack to start with DirectX::XMFLOAT4X4* matrix = new DirectX::XMFLOAT4X4(); auto identity = DirectX::XMMatrixIdentity(); DirectX::XMStoreFloat4x4(matrix, identity); _matrices.push(matrix); }
namespace DX11 { static std::unique_ptr<TextureEncoder> g_encoder; const size_t MAX_COPY_BUFFERS = 32; ID3D11Buffer* efbcopycbuf[MAX_COPY_BUFFERS] = { 0 }; TextureCache::TCacheEntry::~TCacheEntry() { texture->Release(); } void TextureCache::TCacheEntry::Bind(unsigned int stage) { D3D::stateman->SetTexture(stage, texture->GetSRV()); } bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level) { // TODO: Somehow implement this (D3DX11 doesn't support dumping individual LODs) static bool warn_once = true; if (level && warn_once) { WARN_LOG(VIDEO, "Dumping individual LOD not supported by D3D11 backend!"); warn_once = false; return false; } ID3D11Texture2D* pNewTexture = nullptr; ID3D11Texture2D* pSurface = texture->GetTex(); D3D11_TEXTURE2D_DESC desc; pSurface->GetDesc(&desc); desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.Usage = D3D11_USAGE_STAGING; HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &pNewTexture); bool saved_png = false; if (SUCCEEDED(hr) && pNewTexture) { D3D::context->CopyResource(pNewTexture, pSurface); D3D11_MAPPED_SUBRESOURCE map; hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map); if (SUCCEEDED(hr)) { saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, desc.Width, desc.Height); D3D::context->Unmap(pNewTexture, 0); } SAFE_RELEASE(pNewTexture); } return saved_png; } void TextureCache::TCacheEntry::CopyRectangleFromTexture( const TCacheEntryBase* source, const MathUtil::Rectangle<int> &srcrect, const MathUtil::Rectangle<int> &dstrect) { TCacheEntry* srcentry = (TCacheEntry*)source; if (srcrect.GetWidth() == dstrect.GetWidth() && srcrect.GetHeight() == dstrect.GetHeight()) { const D3D11_BOX *psrcbox = nullptr; D3D11_BOX srcbox; if (srcrect.left != 0 || srcrect.top != 0) { srcbox.left = srcrect.left; srcbox.top = srcrect.top; srcbox.right = srcrect.right; srcbox.bottom = srcrect.bottom; psrcbox = &srcbox; } D3D::context->CopySubresourceRegion( texture->GetTex(), 0, dstrect.left, dstrect.top, 0, srcentry->texture->GetTex(), 0, psrcbox); return; } else if (!config.rendertarget) { return; } g_renderer->ResetAPIState(); // reset any game specific settings const D3D11_VIEWPORT vp = CD3D11_VIEWPORT( float(dstrect.left), float(dstrect.top), float(dstrect.GetWidth()), float(dstrect.GetHeight())); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr); D3D::context->RSSetViewports(1, &vp); D3D::SetLinearCopySampler(); D3D11_RECT srcRC; srcRC.left = srcrect.left; srcRC.right = srcrect.right; srcRC.top = srcrect.top; srcRC.bottom = srcrect.bottom; D3D::drawShadedTexQuad(srcentry->texture->GetSRV(), &srcRC, srcentry->config.width, srcentry->config.height, PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), nullptr, 1.0, 0); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) { unsigned int src_pitch = 4 * expanded_width; D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, src_pitch, level, usage); } TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config) { if (config.rendertarget) { return new TCacheEntry(config, D3DTexture2D::Create(config.width, config.height, (D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, config.layers)); } else { D3D11_USAGE usage = D3D11_USAGE_DEFAULT; D3D11_CPU_ACCESS_FLAG cpu_access = (D3D11_CPU_ACCESS_FLAG)0; if (config.levels == 1) { usage = D3D11_USAGE_DYNAMIC; cpu_access = D3D11_CPU_ACCESS_WRITE; } const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, config.width, config.height, 1, config.levels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access); ID3D11Texture2D *pTexture; const HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture); CHECK(SUCCEEDED(hr), "Create texture of the TextureCache"); TCacheEntry* const entry = new TCacheEntry(config, new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE)); entry->usage = usage; // TODO: better debug names D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetTex(), "a texture of the TextureCache"); D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache"); SAFE_RELEASE(pTexture); return entry; } } void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool scaleByHalf, unsigned int cbufid, const float *colmat) { g_renderer->ResetAPIState(); // stretch picture with increased internal resolution const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)config.width, (float)config.height); D3D::context->RSSetViewports(1, &vp); // set transformation if (nullptr == efbcopycbuf[cbufid]) { const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); D3D11_SUBRESOURCE_DATA data; data.pSysMem = colmat; HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]); CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); } D3D::stateman->SetPixelConstants(efbcopycbuf[cbufid]); const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); // TODO: try targetSource.asRECT(); const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom); // Use linear filtering if (bScaleByHalf), use point filtering otherwise if (scaleByHalf) D3D::SetLinearCopySampler(); else D3D::SetPointCopySampler(); // Make sure we don't draw with the texture set as both a source and target. // (This can happen because we don't unbind textures when we free them.) D3D::stateman->UnsetTexture(texture->GetSRV()); D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr); // Create texture copy D3D::drawShadedTexQuad( (srcFormat == PEControl::Z24 ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture())->GetSRV(), &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), srcFormat == PEControl::Z24 ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader()); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); } void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) { g_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, srcFormat, srcRect, isIntensity, scaleByHalf); } const char palette_shader[] = R"HLSL( sampler samp0 : register(s0); Texture2DArray Tex0 : register(t0); Buffer<uint> Tex1 : register(t1); uniform float Multiply; uint Convert3To8(uint v) { // Swizzle bits: 00000123 -> 12312312 return (v << 5) | (v << 2) | (v >> 1); } uint Convert4To8(uint v) { // Swizzle bits: 00001234 -> 12341234 return (v << 4) | v; } uint Convert5To8(uint v) { // Swizzle bits: 00012345 -> 12345123 return (v << 3) | (v >> 2); } uint Convert6To8(uint v) { // Swizzle bits: 00123456 -> 12345612 return (v << 2) | (v >> 4); } float4 DecodePixel_RGB5A3(uint val) { int r,g,b,a; if ((val&0x8000)) { r=Convert5To8((val>>10) & 0x1f); g=Convert5To8((val>>5 ) & 0x1f); b=Convert5To8((val ) & 0x1f); a=0xFF; } else { a=Convert3To8((val>>12) & 0x7); r=Convert4To8((val>>8 ) & 0xf); g=Convert4To8((val>>4 ) & 0xf); b=Convert4To8((val ) & 0xf); } return float4(r, g, b, a) / 255; } float4 DecodePixel_RGB565(uint val) { int r, g, b, a; r = Convert5To8((val >> 11) & 0x1f); g = Convert6To8((val >> 5) & 0x3f); b = Convert5To8((val) & 0x1f); a = 0xFF; return float4(r, g, b, a) / 255; } float4 DecodePixel_IA8(uint val) { int i = val & 0xFF; int a = val >> 8; return float4(i, i, i, a) / 255; } void main( out float4 ocol0 : SV_Target, in float4 pos : SV_Position, in float3 uv0 : TEXCOORD0) { uint src = round(Tex0.Sample(samp0,uv0) * Multiply).r; src = Tex1.Load(src); src = ((src << 8) & 0xFF00) | (src >> 8); ocol0 = DECODE(src); } )HLSL"; void TextureCache::ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) { g_renderer->ResetAPIState(); // stretch picture with increased internal resolution const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)unconverted->config.width, (float)unconverted->config.height); D3D::context->RSSetViewports(1, &vp); D3D11_BOX box{ 0, 0, 0, 512, 1, 1 }; D3D::context->UpdateSubresource(palette_buf, 0, &box, palette, 0, 0); D3D::stateman->SetTexture(1, palette_buf_srv); // TODO: Add support for C14X2 format. (Different multiplier, more palette entries.) float params[4] = { (unconverted->format & 0xf) == 0 ? 15.f : 255.f }; D3D::context->UpdateSubresource(palette_uniform, 0, nullptr, ¶ms, 0, 0); D3D::stateman->SetPixelConstants(palette_uniform); const D3D11_RECT sourcerect = CD3D11_RECT(0, 0, unconverted->config.width, unconverted->config.height); D3D::SetPointCopySampler(); // Make sure we don't draw with the texture set as both a source and target. // (This can happen because we don't unbind textures when we free them.) D3D::stateman->UnsetTexture(static_cast<TCacheEntry*>(entry)->texture->GetSRV()); D3D::context->OMSetRenderTargets(1, &static_cast<TCacheEntry*>(entry)->texture->GetRTV(), nullptr); // Create texture copy D3D::drawShadedTexQuad( static_cast<TCacheEntry*>(unconverted)->texture->GetSRV(), &sourcerect, unconverted->config.width, unconverted->config.height, palette_pixel_shader[format], VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader()); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); } ID3D11PixelShader *GetConvertShader(const char* Type) { std::string shader = "#define DECODE DecodePixel_"; shader.append(Type); shader.append("\n"); shader.append(palette_shader); return D3D::CompileAndCreatePixelShader(shader); } TextureCache::TextureCache() { // FIXME: Is it safe here? g_encoder = std::make_unique<PSTextureEncoder>(); g_encoder->Init(); palette_buf = nullptr; palette_buf_srv = nullptr; palette_uniform = nullptr; palette_pixel_shader[GX_TL_IA8] = GetConvertShader("IA8"); palette_pixel_shader[GX_TL_RGB565] = GetConvertShader("RGB565"); palette_pixel_shader[GX_TL_RGB5A3] = GetConvertShader("RGB5A3"); auto lutBd = CD3D11_BUFFER_DESC(sizeof(u16) * 256, D3D11_BIND_SHADER_RESOURCE); HRESULT hr = D3D::device->CreateBuffer(&lutBd, nullptr, &palette_buf); CHECK(SUCCEEDED(hr), "create palette decoder lut buffer"); D3D::SetDebugObjectName(palette_buf, "texture decoder lut buffer"); // TODO: C14X2 format. auto outlutUavDesc = CD3D11_SHADER_RESOURCE_VIEW_DESC(palette_buf, DXGI_FORMAT_R16_UINT, 0, 256, 0); hr = D3D::device->CreateShaderResourceView(palette_buf, &outlutUavDesc, &palette_buf_srv); CHECK(SUCCEEDED(hr), "create palette decoder lut srv"); D3D::SetDebugObjectName(palette_buf_srv, "texture decoder lut srv"); const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(16, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &palette_uniform); CHECK(SUCCEEDED(hr), "Create palette decoder constant buffer"); D3D::SetDebugObjectName((ID3D11DeviceChild*)palette_uniform, "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); }
ConstantStreamBuffer::ConstantStreamBuffer(int size) : m_max_size(ROUND_UP(size, 256)), m_need_init(true) { m_use_partial_buffer_update = D3D::SupportPartialContantBufferUpdate(); D3D11_BUFFER_DESC desc = CD3D11_BUFFER_DESC(m_max_size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); device->CreateBuffer(&desc, nullptr, &m_buf); }