Large diffs are not rendered by default.

@@ -9,11 +9,10 @@
#include "VideoBackends/D3D/D3DState.h"
#include "VideoCommon/RenderBase.h"

enum class EFBAccessType;

namespace DX11
{
class D3DTexture2D;
class DXTexture;
class DXFramebuffer;

class Renderer : public ::Renderer
{
@@ -32,69 +31,53 @@ class Renderer : public ::Renderer
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment) override;
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

void SetPipeline(const AbstractPipeline* pipeline) override;
void SetFramebuffer(const AbstractFramebuffer* framebuffer) override;
void SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) override;
void SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
const ClearColor& color_value = {},
void SetFramebuffer(AbstractFramebuffer* framebuffer) override;
void SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) override;
void SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearColor& color_value = {},
float depth_value = 0.0f) override;
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
void SetTexture(u32 index, const AbstractTexture* texture) override;
void SetSamplerState(u32 index, const SamplerState& state) override;
void SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) override;
void UnbindTexture(const AbstractTexture* texture) override;
void SetInterlacingMode() override;
void SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) override;
void Draw(u32 base_vertex, u32 num_vertices) override;
void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) override;
void DispatchComputeShader(const AbstractShader* shader, u32 groups_x, u32 groups_y,
u32 groups_z) override;
void BindBackbuffer(const ClearColor& clear_color = {}) override;
void PresentBackbuffer() override;
void SetFullscreen(bool enable_fullscreen) override;
bool IsFullscreen() const override;

u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override;

u16 BBoxRead(int index) override;
void BBoxWrite(int index, u16 value) override;

void ResetAPIState() override;
void RestoreAPIState() override;

TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
void Flush() override;
void WaitForGPUIdle() override;

void RenderXFBToScreen(const AbstractTexture* texture, const EFBRectangle& rc) override;
void OnConfigChanged(u32 bits) override;

void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override;

void ReinterpretPixelData(unsigned int convtype) override;

private:
void SetupDeviceObjects();
void TeardownDeviceObjects();
void Create3DVisionTexture(int width, int height);
void CheckForSurfaceChange();
void CheckForSurfaceResize();
void UpdateBackbufferSize();

StateCache m_state_cache;

std::array<ID3D11BlendState*, 4> m_clear_blend_states{};
std::array<ID3D11DepthStencilState*, 3> m_clear_depth_states{};
ID3D11BlendState* m_reset_blend_state = nullptr;
ID3D11DepthStencilState* m_reset_depth_state = nullptr;
ID3D11RasterizerState* m_reset_rast_state = nullptr;

ID3D11Texture2D* m_screenshot_texture = nullptr;
D3DTexture2D* m_3d_vision_texture = nullptr;
std::unique_ptr<DXTexture> m_3d_vision_texture;
std::unique_ptr<DXFramebuffer> m_3d_vision_framebuffer;

bool m_last_fullscreen_state = false;
};
}
} // namespace DX11

This file was deleted.

This file was deleted.

@@ -7,36 +7,26 @@
#include <d3d11.h>

#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/CommonTypes.h"

#include "VideoBackends/D3D/BoundingBox.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/FramebufferManager.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
#include "VideoBackends/D3D/Render.h"
#include "VideoBackends/D3D/VertexShaderCache.h"

#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/Debugger.h"
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoConfig.h"

namespace DX11
{
// TODO: Find sensible values for these two
const u32 MAX_IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
const u32 MAX_VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
const u32 MAX_BUFFER_SIZE = MAX_IBUFFER_SIZE + MAX_VBUFFER_SIZE;

static ID3D11Buffer* AllocateConstantBuffer(u32 size)
{
const u32 cbsize = Common::AlignUp(size, 16u); // must be a multiple of 16
@@ -59,71 +49,172 @@ static void UpdateConstantBuffer(ID3D11Buffer* const buffer, const void* data, u
ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
}

void VertexManager::CreateDeviceObjects()
static ID3D11ShaderResourceView*
CreateTexelBufferView(ID3D11Buffer* buffer, TexelBufferFormat format, DXGI_FORMAT srv_format)
{
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);
ID3D11ShaderResourceView* srv;
CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(buffer, srv_format, 0,
VertexManager::TEXEL_STREAM_BUFFER_SIZE /
VertexManager::GetTexelBufferElementSize(format));
CHECK(SUCCEEDED(D3D::device->CreateShaderResourceView(buffer, &srv_desc, &srv)),
"Create SRV for texel buffer");
return srv;
}

VertexManager::VertexManager() = default;

VertexManager::~VertexManager()
{
for (auto& srv_ptr : m_texel_buffer_views)
SAFE_RELEASE(srv_ptr);
SAFE_RELEASE(m_texel_buffer);
SAFE_RELEASE(m_pixel_constant_buffer);
SAFE_RELEASE(m_geometry_constant_buffer);
SAFE_RELEASE(m_vertex_constant_buffer);
for (auto& buffer : m_buffers)
SAFE_RELEASE(buffer);
}

bool VertexManager::Initialize()
{
if (!VertexManagerBase::Initialize())
return false;

CD3D11_BUFFER_DESC bufdesc((VERTEX_STREAM_BUFFER_SIZE + INDEX_STREAM_BUFFER_SIZE) / BUFFER_COUNT,
D3D11_BIND_INDEX_BUFFER | D3D11_BIND_VERTEX_BUFFER,
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);

for (int i = 0; i < MAX_BUFFER_COUNT; i++)
for (int i = 0; i < BUFFER_COUNT; i++)
{
m_buffers[i] = nullptr;
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, nullptr, &m_buffers[i])),
"Failed to create buffer.");
D3D::SetDebugObjectName(m_buffers[i], "Buffer of VertexManager");
}

m_buffer_cursor = MAX_BUFFER_SIZE;

m_vertex_constant_buffer = AllocateConstantBuffer(sizeof(VertexShaderConstants));
m_geometry_constant_buffer = AllocateConstantBuffer(sizeof(GeometryShaderConstants));
m_pixel_constant_buffer = AllocateConstantBuffer(sizeof(PixelShaderConstants));
if (!m_vertex_constant_buffer || !m_geometry_constant_buffer || !m_pixel_constant_buffer)
return false;

CD3D11_BUFFER_DESC texel_buf_desc(TEXEL_STREAM_BUFFER_SIZE, D3D11_BIND_SHADER_RESOURCE,
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&texel_buf_desc, nullptr, &m_texel_buffer)),
"Creating texel buffer failed");
if (!m_texel_buffer)
return false;

static constexpr std::array<std::pair<TexelBufferFormat, DXGI_FORMAT>, NUM_TEXEL_BUFFER_FORMATS>
format_mapping = {{
{TEXEL_BUFFER_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT},
{TEXEL_BUFFER_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT},
{TEXEL_BUFFER_FORMAT_RGBA8_UINT, DXGI_FORMAT_R8G8B8A8_UNORM},
{TEXEL_BUFFER_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT},
}};
for (const auto& it : format_mapping)
{
m_texel_buffer_views[it.first] = CreateTexelBufferView(m_texel_buffer, it.first, it.second);
if (!m_texel_buffer_views[it.first])
return false;
}

return true;
}

void VertexManager::DestroyDeviceObjects()
void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
{
SAFE_RELEASE(m_pixel_constant_buffer);
SAFE_RELEASE(m_geometry_constant_buffer);
SAFE_RELEASE(m_vertex_constant_buffer);
for (int i = 0; i < MAX_BUFFER_COUNT; i++)
// Just use the one buffer for all three.
InvalidateConstants();
UpdateConstantBuffer(m_vertex_constant_buffer, uniforms, uniforms_size);
D3D::stateman->SetVertexConstants(m_vertex_constant_buffer);
D3D::stateman->SetGeometryConstants(m_vertex_constant_buffer);
D3D::stateman->SetPixelConstants(m_vertex_constant_buffer);
}

bool VertexManager::MapTexelBuffer(u32 required_size, D3D11_MAPPED_SUBRESOURCE& sr)
{
if ((m_texel_buffer_offset + required_size) > TEXEL_STREAM_BUFFER_SIZE)
{
// Restart buffer.
HRESULT hr = D3D::context->Map(m_texel_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
CHECK(SUCCEEDED(hr), "Map texel buffer");
if (FAILED(hr))
return false;

m_texel_buffer_offset = 0;
}
else
{
SAFE_RELEASE(m_buffers[i]);
// Don't overwrite the earlier-used space.
HRESULT hr = D3D::context->Map(m_texel_buffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &sr);
CHECK(SUCCEEDED(hr), "Map texel buffer");
if (FAILED(hr))
return false;
}

return true;
}

VertexManager::VertexManager()
bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
u32* out_offset)
{
m_staging_vertex_buffer.resize(MAXVBUFFERSIZE);
if (data_size > TEXEL_STREAM_BUFFER_SIZE)
return false;

m_cur_buffer_pointer = m_base_buffer_pointer = &m_staging_vertex_buffer[0];
m_end_buffer_pointer = m_base_buffer_pointer + m_staging_vertex_buffer.size();
const u32 elem_size = GetTexelBufferElementSize(format);
m_texel_buffer_offset = Common::AlignUp(m_texel_buffer_offset, elem_size);

m_staging_index_buffer.resize(MAXIBUFFERSIZE);
D3D11_MAPPED_SUBRESOURCE sr;
if (!MapTexelBuffer(data_size, sr))
return false;

CreateDeviceObjects();
}
*out_offset = m_texel_buffer_offset / elem_size;
std::memcpy(static_cast<u8*>(sr.pData) + m_texel_buffer_offset, data, data_size);
ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
m_texel_buffer_offset += data_size;

VertexManager::~VertexManager()
{
DestroyDeviceObjects();
D3D::context->Unmap(m_texel_buffer, 0);
D3D::stateman->SetTexture(0, m_texel_buffer_views[static_cast<size_t>(format)]);
return true;
}

void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
u32* out_offset, const void* palette_data, u32 palette_size,
TexelBufferFormat palette_format, u32* out_palette_offset)
{
// Just use the one buffer for all three.
UpdateConstantBuffer(m_vertex_constant_buffer, uniforms, uniforms_size);
D3D::stateman->SetVertexConstants(m_vertex_constant_buffer);
D3D::stateman->SetGeometryConstants(m_vertex_constant_buffer);
D3D::stateman->SetPixelConstants(m_vertex_constant_buffer);
VertexShaderManager::dirty = true;
GeometryShaderManager::dirty = true;
PixelShaderManager::dirty = true;
const u32 elem_size = GetTexelBufferElementSize(format);
const u32 palette_elem_size = GetTexelBufferElementSize(palette_format);
const u32 reserve_size = data_size + palette_size + palette_elem_size;
if (reserve_size > TEXEL_STREAM_BUFFER_SIZE)
return false;

m_texel_buffer_offset = Common::AlignUp(m_texel_buffer_offset, elem_size);

D3D11_MAPPED_SUBRESOURCE sr;
if (!MapTexelBuffer(reserve_size, sr))
return false;

const u32 palette_byte_offset = Common::AlignUp(data_size, palette_elem_size);
std::memcpy(static_cast<u8*>(sr.pData) + m_texel_buffer_offset, data, data_size);
std::memcpy(static_cast<u8*>(sr.pData) + m_texel_buffer_offset + palette_byte_offset,
palette_data, palette_size);
ADDSTAT(stats.thisFrame.bytesUniformStreamed, palette_byte_offset + palette_size);
*out_offset = m_texel_buffer_offset / elem_size;
*out_palette_offset = (m_texel_buffer_offset + palette_byte_offset) / palette_elem_size;
m_texel_buffer_offset += palette_byte_offset + palette_size;

D3D::context->Unmap(m_texel_buffer, 0);
D3D::stateman->SetTexture(0, m_texel_buffer_views[static_cast<size_t>(format)]);
D3D::stateman->SetTexture(1, m_texel_buffer_views[static_cast<size_t>(palette_format)]);
return true;
}

void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
void VertexManager::ResetBuffer(u32 vertex_stride)
{
m_base_buffer_pointer = m_cpu_vertex_buffer.data();
m_cur_buffer_pointer = m_base_buffer_pointer;
IndexGenerator::Start(m_staging_index_buffer.data());
m_end_buffer_pointer = m_base_buffer_pointer + m_cpu_vertex_buffer.size();
IndexGenerator::Start(m_cpu_index_buffer.data());
}

void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
@@ -143,10 +234,10 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
}

D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
if (cursor + totalBufferSize >= MAX_BUFFER_SIZE)
if (cursor + totalBufferSize >= BUFFER_SIZE)
{
// Wrap around
m_current_buffer = (m_current_buffer + 1) % MAX_BUFFER_COUNT;
m_current_buffer = (m_current_buffer + 1) % BUFFER_COUNT;
cursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
@@ -159,8 +250,7 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
if (vertexBufferSize > 0)
std::memcpy(mappedData + cursor, m_base_buffer_pointer, vertexBufferSize);
if (indexBufferSize > 0)
std::memcpy(mappedData + cursor + vertexBufferSize, m_staging_index_buffer.data(),
indexBufferSize);
std::memcpy(mappedData + cursor + vertexBufferSize, m_cpu_index_buffer.data(), indexBufferSize);
D3D::context->Unmap(m_buffers[m_current_buffer], 0);

m_buffer_cursor = cursor + totalBufferSize;
@@ -172,7 +262,7 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
D3D::stateman->SetIndexBuffer(m_buffers[m_current_buffer]);
}

void VertexManager::UploadConstants()
void VertexManager::UploadUniforms()
{
if (VertexShaderManager::dirty)
{
@@ -199,20 +289,4 @@ void VertexManager::UploadConstants()
D3D::stateman->SetVertexConstants(m_vertex_constant_buffer);
D3D::stateman->SetGeometryConstants(m_geometry_constant_buffer);
}

void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
{
FramebufferManager::SetIntegerEFBRenderTarget(
m_current_pipeline_config.blending_state.logicopenable);

if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active)
{
D3D::context->OMSetRenderTargetsAndUnorderedAccessViews(
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, 2, 1, &BBox::GetUAV(),
nullptr);
}

D3D::stateman->Apply();
D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
}
} // namespace DX11
@@ -18,13 +18,12 @@ struct ID3D11Buffer;

namespace DX11
{
class D3DBlob;
class D3DVertexFormat : public NativeVertexFormat
{
public:
D3DVertexFormat(const PortableVertexDeclaration& vtx_decl);
~D3DVertexFormat();
ID3D11InputLayout* GetInputLayout(D3DBlob* vs_bytecode);
ID3D11InputLayout* GetInputLayout(const void* vs_bytecode, size_t vs_bytecode_size);

private:
std::array<D3D11_INPUT_ELEMENT_DESC, 32> m_elems{};
@@ -39,35 +38,39 @@ class VertexManager : public VertexManagerBase
VertexManager();
~VertexManager();

std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
bool Initialize();

void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;
bool UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
u32* out_offset) override;
bool UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format, u32* out_offset,
const void* palette_data, u32 palette_size,
TexelBufferFormat palette_format, u32* out_palette_offset) override;

protected:
void CreateDeviceObjects() override;
void DestroyDeviceObjects() override;
void ResetBuffer(u32 vertex_stride, bool cull_all) override;
void ResetBuffer(u32 vertex_stride) override;
void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
u32* out_base_index) override;
void UploadConstants() override;
void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;
void UploadUniforms() override;

private:
enum
{
MAX_BUFFER_COUNT = 2
};
ID3D11Buffer* m_buffers[MAX_BUFFER_COUNT] = {};
static constexpr u32 BUFFER_COUNT = 2;
static constexpr u32 BUFFER_SIZE =
(VERTEX_STREAM_BUFFER_SIZE + INDEX_STREAM_BUFFER_SIZE) / BUFFER_COUNT;

bool MapTexelBuffer(u32 required_size, D3D11_MAPPED_SUBRESOURCE& sr);

ID3D11Buffer* m_buffers[BUFFER_COUNT] = {};
u32 m_current_buffer = 0;
u32 m_buffer_cursor = 0;

std::vector<u8> m_staging_vertex_buffer;
std::vector<u16> m_staging_index_buffer;

ID3D11Buffer* m_vertex_constant_buffer = nullptr;
ID3D11Buffer* m_geometry_constant_buffer = nullptr;
ID3D11Buffer* m_pixel_constant_buffer = nullptr;

ID3D11Buffer* m_texel_buffer = nullptr;
std::array<ID3D11ShaderResourceView*, NUM_TEXEL_BUFFER_FORMATS> m_texel_buffer_views;
u32 m_texel_buffer_offset = 0;
};

} // namespace DX11

This file was deleted.

This file was deleted.

@@ -12,17 +12,14 @@

#include "VideoBackends/D3D/BoundingBox.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DUtil.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/PerfQuery.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
#include "VideoBackends/D3D/Render.h"
#include "VideoBackends/D3D/TextureCache.h"
#include "VideoBackends/D3D/VertexManager.h"
#include "VideoBackends/D3D/VertexShaderCache.h"
#include "VideoBackends/D3D/VideoBackend.h"

#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/ShaderCache.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"

@@ -51,23 +48,25 @@ void VideoBackend::InitBackendInfo()

g_Config.backend_info.api_type = APIType::D3D;
g_Config.backend_info.MaxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
g_Config.backend_info.bUsesLowerLeftOrigin = false;
g_Config.backend_info.bSupportsExclusiveFullscreen = true;
g_Config.backend_info.bSupportsDualSourceBlend = true;
g_Config.backend_info.bSupportsPrimitiveRestart = true;
g_Config.backend_info.bSupportsOversizedViewports = false;
g_Config.backend_info.bSupportsGeometryShaders = true;
g_Config.backend_info.bSupportsComputeShaders = false;
g_Config.backend_info.bSupports3DVision = true;
g_Config.backend_info.bSupportsPostProcessing = false;
g_Config.backend_info.bSupportsPostProcessing = true;
g_Config.backend_info.bSupportsPaletteConversion = true;
g_Config.backend_info.bSupportsClipControl = true;
g_Config.backend_info.bSupportsDepthClamp = true;
g_Config.backend_info.bSupportsReversedDepthRange = false;
g_Config.backend_info.bSupportsLogicOp = true;
g_Config.backend_info.bSupportsMultithreading = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = true;
g_Config.backend_info.bSupportsST3CTextures = false;
g_Config.backend_info.bSupportsCopyToVram = true;
g_Config.backend_info.bSupportsLargePoints = false;
g_Config.backend_info.bSupportsBitfield = false;
g_Config.backend_info.bSupportsDynamicSamplerIndexing = false;
g_Config.backend_info.bSupportsBPTCTextures = false;
@@ -149,21 +148,20 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
// internal interfaces
g_renderer =
std::make_unique<Renderer>(backbuffer_width, backbuffer_height, wsi.render_surface_scale);
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
g_texture_cache = std::make_unique<TextureCache>();
g_vertex_manager = std::make_unique<VertexManager>();
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_texture_cache = std::make_unique<TextureCacheBase>();
g_perf_query = std::make_unique<PerfQuery>();

VertexShaderCache::Init();
PixelShaderCache::Init();
GeometryShaderCache::Init();

if (!g_renderer->Initialize() || !g_shader_cache->Initialize())
if (!g_renderer->Initialize() || !g_vertex_manager->Initialize() ||
!g_shader_cache->Initialize() || !g_framebuffer_manager->Initialize() ||
!g_texture_cache->Initialize())
{
return false;
}

D3D::InitUtils();
BBox::Init();

g_shader_cache->InitializeShaderCache();
return true;
}

@@ -172,16 +170,13 @@ void VideoBackend::Shutdown()
g_shader_cache->Shutdown();
g_renderer->Shutdown();

D3D::ShutdownUtils();
PixelShaderCache::Shutdown();
VertexShaderCache::Shutdown();
GeometryShaderCache::Shutdown();
BBox::Shutdown();

g_perf_query.reset();
g_vertex_manager.reset();
g_texture_cache.reset();
g_framebuffer_manager.reset();
g_shader_cache.reset();
g_vertex_manager.reset();
g_renderer.reset();

ShutdownShared();
@@ -13,7 +13,9 @@
#include "VideoBackends/Null/VertexManager.h"
#include "VideoBackends/Null/VideoBackend.h"

#include "VideoCommon/FramebufferManagerBase.h"
#include "Common/MsgHandler.h"

#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
@@ -61,10 +63,21 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
g_renderer = std::make_unique<Renderer>();
g_vertex_manager = std::make_unique<VertexManager>();
g_perf_query = std::make_unique<PerfQuery>();
g_framebuffer_manager = std::make_unique<FramebufferManagerBase>();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_texture_cache = std::make_unique<TextureCache>();
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
return g_renderer->Initialize() && g_shader_cache->Initialize();

if (!g_vertex_manager->Initialize() || !g_shader_cache->Initialize() ||
!g_renderer->Initialize() || !g_framebuffer_manager->Initialize() ||
!g_texture_cache->Initialize())
{
PanicAlert("Failed to initialize renderer classes");
Shutdown();
return false;
}

g_shader_cache->InitializeShaderCache();
return true;
}

void VideoBackend::Shutdown()
@@ -16,11 +16,6 @@ void NullTexture::CopyRectangleFromTexture(const AbstractTexture* src,
u32 dst_layer, u32 dst_level)
{
}
void NullTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect)
{
}
void NullTexture::ResolveFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& rect, u32 layer, u32 level)
{
@@ -70,15 +65,18 @@ void NullStagingTexture::Flush()
m_needs_flush = false;
}

NullFramebuffer::NullFramebuffer(AbstractTextureFormat color_format,
NullFramebuffer::NullFramebuffer(AbstractTexture* color_attachment,
AbstractTexture* depth_attachment,
AbstractTextureFormat color_format,
AbstractTextureFormat depth_format, u32 width, u32 height,
u32 layers, u32 samples)
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples)
: AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width,
height, layers, samples)
{
}

std::unique_ptr<NullFramebuffer> NullFramebuffer::Create(const NullTexture* color_attachment,
const NullTexture* depth_attachment)
std::unique_ptr<NullFramebuffer> NullFramebuffer::Create(NullTexture* color_attachment,
NullTexture* depth_attachment)
{
if (!ValidateConfig(color_attachment, depth_attachment))
return nullptr;
@@ -93,8 +91,8 @@ std::unique_ptr<NullFramebuffer> NullFramebuffer::Create(const NullTexture* colo
const u32 layers = either_attachment->GetLayers();
const u32 samples = either_attachment->GetSamples();

return std::make_unique<NullFramebuffer>(color_format, depth_format, width, height, layers,
samples);
return std::make_unique<NullFramebuffer>(color_attachment, depth_attachment, color_format,
depth_format, width, height, layers, samples);
}

} // namespace Null
@@ -25,9 +25,6 @@ class NullTexture final : public AbstractTexture
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
u32 dst_layer, u32 dst_level) override;
void ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
u32 layer, u32 level) override;
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
@@ -58,12 +55,13 @@ class NullStagingTexture final : public AbstractStagingTexture
class NullFramebuffer final : public AbstractFramebuffer
{
public:
explicit NullFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
explicit NullFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
u32 width, u32 height, u32 layers, u32 samples);
~NullFramebuffer() override = default;

static std::unique_ptr<NullFramebuffer> Create(const NullTexture* color_attachment,
const NullTexture* depth_attachment);
static std::unique_ptr<NullFramebuffer> Create(NullTexture* color_attachment,
NullTexture* depth_attachment);
};

} // namespace Null
@@ -9,6 +9,7 @@

#include "VideoCommon/AbstractPipeline.h"
#include "VideoCommon/AbstractShader.h"
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/VideoConfig.h"

namespace Null
@@ -74,22 +75,16 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
return std::make_unique<NullPipeline>();
}

std::unique_ptr<AbstractFramebuffer>
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment)
std::unique_ptr<AbstractFramebuffer> Renderer::CreateFramebuffer(AbstractTexture* color_attachment,
AbstractTexture* depth_attachment)
{
return NullFramebuffer::Create(static_cast<const NullTexture*>(color_attachment),
static_cast<const NullTexture*>(depth_attachment));
return NullFramebuffer::Create(static_cast<NullTexture*>(color_attachment),
static_cast<NullTexture*>(depth_attachment));
}

TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
std::unique_ptr<NativeVertexFormat>
Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
{
TargetRectangle result;
result.left = rc.left;
result.top = rc.top;
result.right = rc.right;
result.bottom = rc.bottom;
return result;
return std::make_unique<NativeVertexFormat>(vtx_decl);
}

} // namespace Null
@@ -20,26 +20,26 @@ class Renderer : public ::Renderer
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(const AbstractTexture* color_attachment,
const AbstractTexture* depth_attachment) override;
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;

u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override { return 0; }
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
u16 BBoxRead(int index) override { return 0; }
void BBoxWrite(int index, u16 value) override {}
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;

void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override
{
}

void ReinterpretPixelData(unsigned int convtype) override {}
void ReinterpretPixelData(EFBReinterpretType convtype) override {}
};
}
} // namespace Null
@@ -18,26 +18,21 @@ class TextureCache : public TextureCacheBase
public:
TextureCache() {}
~TextureCache() {}
bool CompileShaders() override { return true; }
void DeleteShaders() override {}
void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette,
TLUTFormat format) override
{
}

protected:
void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients) override
const EFBCopyFilterCoefficients& filter_coefficients) override
{
}

void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half, EFBCopyFormat dst_format, bool is_intensity,
float gamma, bool clamp_top, bool clamp_bottom,
const CopyFilterCoefficientArray& filter_coefficients) override
const EFBCopyFilterCoefficients& filter_coefficients) override
{
}
};

} // Null name space
} // namespace Null
@@ -3,52 +3,16 @@
// Refer to the license.txt file included.

#include "VideoBackends/Null/VertexManager.h"
#include "VideoBackends/Null/Render.h"

#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/VertexLoaderManager.h"

namespace Null
{
class NullNativeVertexFormat : public NativeVertexFormat
{
public:
NullNativeVertexFormat(const PortableVertexDeclaration& vtx_decl_) { vtx_decl = vtx_decl_; }
};

std::unique_ptr<NativeVertexFormat>
VertexManager::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
{
return std::make_unique<NullNativeVertexFormat>(vtx_decl);
}
VertexManager::VertexManager() = default;

void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
{
}

VertexManager::VertexManager() : m_local_v_buffer(MAXVBUFFERSIZE), m_local_i_buffer(MAXIBUFFERSIZE)
{
}

VertexManager::~VertexManager()
{
}

void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
{
m_cur_buffer_pointer = m_base_buffer_pointer = m_local_v_buffer.data();
m_end_buffer_pointer = m_cur_buffer_pointer + m_local_v_buffer.size();
IndexGenerator::Start(&m_local_i_buffer[0]);
}

void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
u32* out_base_vertex, u32* out_base_index)
{
}

void VertexManager::UploadConstants()
{
}
VertexManager::~VertexManager() = default;

void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
{
@@ -17,20 +17,7 @@ class VertexManager : public VertexManagerBase
VertexManager();
~VertexManager();

std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;

void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;

protected:
void ResetBuffer(u32 vertex_stride, bool cull_all) override;
void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
u32* out_base_index) override;
void UploadConstants() override;
void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;

private:
std::vector<u8> m_local_v_buffer;
std::vector<u16> m_local_i_buffer;
};
}
} // namespace Null
@@ -2,175 +2,77 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <algorithm>
#include <array>
#include <cstring>

#include "Common/GL/GLUtil.h"

#include "VideoBackends/OGL/BoundingBox.h"
#include "VideoBackends/OGL/FramebufferManager.h"
#include "VideoBackends/OGL/Render.h"

#include "VideoCommon/DriverDetails.h"
#include "VideoCommon/VideoConfig.h"

static GLuint s_bbox_buffer_id;
static GLuint s_pbo;

static std::array<int, 4> s_stencil_bounds;
static bool s_stencil_updated;
static bool s_stencil_cleared;

static int s_target_width;
static int s_target_height;

namespace OGL
{
void BoundingBox::SetTargetSizeChanged(int target_width, int target_height)
void BoundingBox::Init()
{
if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
if (!g_ActiveConfig.backend_info.bSupportsBBox)
return;

s_target_width = target_width;
s_target_height = target_height;
s_stencil_updated = false;

glBindBuffer(GL_PIXEL_PACK_BUFFER, s_pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, s_target_width * s_target_height, nullptr, GL_STREAM_READ);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

void BoundingBox::Init(int target_width, int target_height)
{
if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
{
int initial_values[4] = {0, 0, 0, 0};
glGenBuffers(1, &s_bbox_buffer_id);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(s32), initial_values, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, s_bbox_buffer_id);
}
else
{
s_stencil_bounds = {{0, 0, 0, 0}};
glGenBuffers(1, &s_pbo);
SetTargetSizeChanged(target_width, target_height);
}
int initial_values[4] = {0, 0, 0, 0};
glGenBuffers(1, &s_bbox_buffer_id);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(s32), initial_values, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, s_bbox_buffer_id);
}

void BoundingBox::Shutdown()
{
if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
{
glDeleteBuffers(1, &s_bbox_buffer_id);
}
else
{
glDeleteBuffers(1, &s_pbo);
}
if (!g_ActiveConfig.backend_info.bSupportsBBox)
return;

glDeleteBuffers(1, &s_bbox_buffer_id);
}

void BoundingBox::Set(int index, int value)
{
if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
{
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &value);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
else
{
s_stencil_bounds[index] = value;
if (!g_ActiveConfig.backend_info.bSupportsBBox)
return;

if (!s_stencil_cleared)
{
// Assumes that the EFB framebuffer is currently bound
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
s_stencil_updated = false;
s_stencil_cleared = true;
}
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &value);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}

int BoundingBox::Get(int index)
{
if (g_ActiveConfig.BBoxUseFragmentShaderImplementation())
if (!g_ActiveConfig.backend_info.bSupportsBBox)
return 0;

int data = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
if (!DriverDetails::HasBug(DriverDetails::BUG_SLOW_GETBUFFERSUBDATA) &&
!static_cast<Renderer*>(g_renderer.get())->IsGLES())
{
int data = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_bbox_buffer_id);
if (!DriverDetails::HasBug(DriverDetails::BUG_SLOW_GETBUFFERSUBDATA) &&
!static_cast<Renderer*>(g_renderer.get())->IsGLES())
{
// Using glMapBufferRange to read back the contents of the SSBO is extremely slow
// on nVidia drivers. This is more noticeable at higher internal resolutions.
// Using glGetBufferSubData instead does not seem to exhibit this slowdown.
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &data);
}
else
{
// Using glMapBufferRange is faster on AMD cards by a measurable margin.
void* ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int),
GL_MAP_READ_BIT);
if (ptr)
{
memcpy(&data, ptr, sizeof(int));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
}
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
return data;
// Using glMapBufferRange to read back the contents of the SSBO is extremely slow
// on nVidia drivers. This is more noticeable at higher internal resolutions.
// Using glGetBufferSubData instead does not seem to exhibit this slowdown.
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int), &data);
}
else
{
if (s_stencil_updated)
// Using glMapBufferRange is faster on AMD cards by a measurable margin.
void* ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, index * sizeof(int), sizeof(int),
GL_MAP_READ_BIT);
if (ptr)
{
s_stencil_updated = false;

FramebufferManager::ResolveEFBStencilTexture();
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer());
glBindBuffer(GL_PIXEL_PACK_BUFFER, s_pbo);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, s_target_width, s_target_height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer());

// Eke every bit of performance out of the compiler that we can
std::array<int, 4> bounds = s_stencil_bounds;

u8* data = static_cast<u8*>(glMapBufferRange(
GL_PIXEL_PACK_BUFFER, 0, s_target_height * s_target_width, GL_MAP_READ_BIT));

for (int row = 0; row < s_target_height; row++)
{
for (int col = 0; col < s_target_width; col++)
{
if (data[row * s_target_width + col] == 0)
continue;
bounds[0] = std::min(bounds[0], col);
bounds[1] = std::max(bounds[1], col);
bounds[2] = std::min(bounds[2], row);
bounds[3] = std::max(bounds[3], row);
}
}

s_stencil_bounds = bounds;

glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
memcpy(&data, ptr, sizeof(int));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
}

return s_stencil_bounds[index];
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
return data;
}

void BoundingBox::StencilWasUpdated()
{
s_stencil_updated = true;
s_stencil_cleared = false;
}

bool BoundingBox::NeedsStencilBuffer()
{
return g_ActiveConfig.bBBoxEnable && !g_ActiveConfig.BBoxUseFragmentShaderImplementation();
}
};
}; // namespace OGL
@@ -9,19 +9,10 @@ namespace OGL
class BoundingBox
{
public:
static void Init(int target_width, int target_height);
static void Init();
static void Shutdown();

static void SetTargetSizeChanged(int target_width, int target_height);

// When SSBO isn't available, the bounding box is calculated directly from the
// stencil buffer.
static bool NeedsStencilBuffer();
// When the stencil buffer is changed, this function needs to be called to
// invalidate the cached bounding box data.
static void StencilWasUpdated();

static void Set(int index, int value);
static int Get(int index);
};
};
}; // namespace OGL
@@ -1,19 +1,15 @@
add_library(videoogl
BoundingBox.cpp
FramebufferManager.cpp
main.cpp
NativeVertexFormat.cpp
OGLPipeline.cpp
OGLShader.cpp
OGLTexture.cpp
PerfQuery.cpp
PostProcessing.cpp
ProgramShaderCache.cpp
Render.cpp
SamplerCache.cpp
StreamBuffer.cpp
TextureCache.cpp
TextureConverter.cpp
VertexManager.cpp
)

This file was deleted.

This file was deleted.

@@ -7,6 +7,7 @@
#include "Common/MsgHandler.h"

#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/Render.h"
#include "VideoBackends/OGL/VertexManager.h"

#include "VideoCommon/NativeVertexFormat.h"
@@ -18,7 +19,7 @@
namespace OGL
{
std::unique_ptr<NativeVertexFormat>
VertexManager::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
{
return std::make_unique<GLVertexFormat>(vtx_decl);
}
@@ -44,10 +45,10 @@ static void SetPointer(u32 attrib, u32 stride, const AttributeFormat& format)
(u8*)nullptr + format.offset);
}

GLVertexFormat::GLVertexFormat(const PortableVertexDeclaration& _vtx_decl)
GLVertexFormat::GLVertexFormat(const PortableVertexDeclaration& vtx_decl)
: NativeVertexFormat(vtx_decl)
{
this->vtx_decl = _vtx_decl;
u32 vertex_stride = _vtx_decl.stride;
u32 vertex_stride = vtx_decl.stride;

// We will not allow vertex components causing uneven strides.
if (vertex_stride & 3)
@@ -63,22 +64,22 @@ GLVertexFormat::GLVertexFormat(const PortableVertexDeclaration& _vtx_decl)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vm->GetIndexBufferHandle());
glBindBuffer(GL_ARRAY_BUFFER, vm->GetVertexBufferHandle());

SetPointer(SHADER_POSITION_ATTRIB, vertex_stride, _vtx_decl.position);
SetPointer(SHADER_POSITION_ATTRIB, vertex_stride, vtx_decl.position);

for (int i = 0; i < 3; i++)
SetPointer(SHADER_NORM0_ATTRIB + i, vertex_stride, _vtx_decl.normals[i]);
SetPointer(SHADER_NORM0_ATTRIB + i, vertex_stride, vtx_decl.normals[i]);

for (int i = 0; i < 2; i++)
SetPointer(SHADER_COLOR0_ATTRIB + i, vertex_stride, _vtx_decl.colors[i]);
SetPointer(SHADER_COLOR0_ATTRIB + i, vertex_stride, vtx_decl.colors[i]);

for (int i = 0; i < 8; i++)
SetPointer(SHADER_TEXTURE0_ATTRIB + i, vertex_stride, _vtx_decl.texcoords[i]);
SetPointer(SHADER_TEXTURE0_ATTRIB + i, vertex_stride, vtx_decl.texcoords[i]);

SetPointer(SHADER_POSMTX_ATTRIB, vertex_stride, _vtx_decl.posmtx);
SetPointer(SHADER_POSMTX_ATTRIB, vertex_stride, vtx_decl.posmtx);
}

GLVertexFormat::~GLVertexFormat()
{
glDeleteVertexArrays(1, &VAO);
}
}
} // namespace OGL
@@ -40,34 +40,26 @@
<ClCompile Include="OGLShader.cpp" />
<ClCompile Include="OGLTexture.cpp" />
<ClCompile Include="BoundingBox.cpp" />
<ClCompile Include="FramebufferManager.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="NativeVertexFormat.cpp" />
<ClCompile Include="PerfQuery.cpp" />
<ClCompile Include="PostProcessing.cpp" />
<ClCompile Include="ProgramShaderCache.cpp" />
<ClCompile Include="Render.cpp" />
<ClCompile Include="SamplerCache.cpp" />
<ClCompile Include="StreamBuffer.cpp" />
<ClCompile Include="TextureCache.cpp" />
<ClCompile Include="TextureConverter.cpp" />
<ClCompile Include="VertexManager.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="OGLPipeline.h" />
<ClInclude Include="OGLShader.h" />
<ClInclude Include="OGLTexture.h" />
<ClInclude Include="BoundingBox.h" />
<ClInclude Include="FramebufferManager.h" />
<ClInclude Include="GPUTimer.h" />
<ClInclude Include="PerfQuery.h" />
<ClInclude Include="PostProcessing.h" />
<ClInclude Include="ProgramShaderCache.h" />
<ClInclude Include="Render.h" />
<ClInclude Include="SamplerCache.h" />
<ClInclude Include="StreamBuffer.h" />
<ClInclude Include="TextureCache.h" />
<ClInclude Include="TextureConverter.h" />
<ClInclude Include="VertexManager.h" />
<ClInclude Include="VideoBackend.h" />
</ItemGroup>
@@ -18,21 +18,12 @@
<ClCompile Include="VertexManager.cpp">
<Filter>Decoder</Filter>
</ClCompile>
<ClCompile Include="TextureConverter.cpp">
<Filter>GLUtil</Filter>
</ClCompile>
<ClCompile Include="BoundingBox.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="FramebufferManager.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="PerfQuery.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="PostProcessing.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="ProgramShaderCache.cpp">
<Filter>Render</Filter>
</ClCompile>
@@ -42,9 +33,6 @@
<ClCompile Include="StreamBuffer.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="TextureCache.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="main.cpp" />
<ClCompile Include="SamplerCache.cpp" />
<ClCompile Include="OGLTexture.cpp">
@@ -61,21 +49,12 @@
<ClInclude Include="VertexManager.h">
<Filter>Decoder</Filter>
</ClInclude>
<ClInclude Include="TextureConverter.h">
<Filter>GLUtil</Filter>
</ClInclude>
<ClInclude Include="BoundingBox.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="FramebufferManager.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="PerfQuery.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="PostProcessing.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="ProgramShaderCache.h">
<Filter>Render</Filter>
</ClInclude>
@@ -85,9 +64,6 @@
<ClInclude Include="StreamBuffer.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="TextureCache.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="SamplerCache.h" />
<ClInclude Include="VideoBackend.h" />
<ClInclude Include="GPUTimer.h">
@@ -24,23 +24,24 @@ static GLenum GetGLShaderTypeForStage(ShaderStage stage)
}
}

OGLShader::OGLShader(ShaderStage stage, GLenum gl_type, GLuint shader_id)
: AbstractShader(stage), m_type(gl_type), m_id(shader_id)
OGLShader::OGLShader(ShaderStage stage, GLenum gl_type, GLuint gl_id)
: AbstractShader(stage), m_id(ProgramShaderCache::GenerateShaderID()), m_type(gl_type),
m_gl_id(gl_id)
{
}

OGLShader::OGLShader(GLuint compute_program_id)
: AbstractShader(ShaderStage::Compute), m_type(GL_COMPUTE_SHADER),
m_compute_program_id(compute_program_id)
OGLShader::OGLShader(GLuint gl_compute_program_id)
: AbstractShader(ShaderStage::Compute), m_id(ProgramShaderCache::GenerateShaderID()),
m_type(GL_COMPUTE_SHADER), m_gl_compute_program_id(gl_compute_program_id)
{
}

OGLShader::~OGLShader()
{
if (m_stage != ShaderStage::Compute)
glDeleteShader(m_id);
glDeleteShader(m_gl_id);
else
glDeleteProgram(m_compute_program_id);
glDeleteProgram(m_gl_compute_program_id);
}

bool OGLShader::HasBinary() const
@@ -16,23 +16,25 @@ namespace OGL
class OGLShader final : public AbstractShader
{
public:
explicit OGLShader(ShaderStage stage, GLenum gl_type, GLuint shader_id);
explicit OGLShader(GLuint compute_program_id);
explicit OGLShader(ShaderStage stage, GLenum gl_type, GLuint gl_id);
explicit OGLShader(GLuint gl_compute_program_id);
~OGLShader() override;

u64 GetID() const { return m_id; }
GLenum GetGLShaderType() const { return m_type; }
GLuint GetGLShaderID() const { return m_id; }
GLuint GetGLComputeProgramID() const { return m_compute_program_id; }
GLuint GetGLShaderID() const { return m_gl_id; }
GLuint GetGLComputeProgramID() const { return m_gl_compute_program_id; }
bool HasBinary() const override;
BinaryData GetBinary() const override;

static std::unique_ptr<OGLShader> CreateFromSource(ShaderStage stage, const char* source,
size_t length);

private:
u64 m_id;
GLenum m_type;
GLuint m_id = 0;
GLuint m_compute_program_id = 0;
GLuint m_gl_id = 0;
GLuint m_gl_compute_program_id = 0;
};

} // namespace OGL

Large diffs are not rendered by default.

@@ -25,24 +25,24 @@ class OGLTexture final : public AbstractTexture
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
u32 dst_layer, u32 dst_level) override;
void ScaleRectangleFromTexture(const AbstractTexture* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
u32 layer, u32 level) override;
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
size_t buffer_size) override;

GLuint GetRawTexIdentifier() const;
GLuint GetFramebuffer() const;
GLuint GetGLTextureId() const { return m_texId; }
GLenum GetGLTarget() const
{
return IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY;
}
GLenum GetGLFormatForImageTexture() const;

private:
void BlitFramebuffer(OGLTexture* srcentry, const MathUtil::Rectangle<int>& src_rect,
u32 src_layer, u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
u32 dst_layer, u32 dst_level);

GLuint m_texId;
GLuint m_framebuffer = 0;
};

class OGLStagingTexture final : public AbstractStagingTexture
@@ -79,13 +79,18 @@ class OGLStagingTexture final : public AbstractStagingTexture
class OGLFramebuffer final : public AbstractFramebuffer
{
public:
OGLFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
OGLFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
u32 height, u32 layers, u32 samples, GLuint fbo);
~OGLFramebuffer() override;

static std::unique_ptr<OGLFramebuffer> Create(OGLTexture* color_attachment,
OGLTexture* depth_attachment);

GLuint GetFBO() const { return m_fbo; }
static std::unique_ptr<OGLFramebuffer> Create(const OGLTexture* color_attachment,
const OGLTexture* depth_attachment);

// Used for updating the dimensions of the system/window framebuffer.
void UpdateDimensions(u32 width, u32 height);

protected:
GLuint m_fbo;

This file was deleted.

This file was deleted.

@@ -4,6 +4,7 @@

#include "VideoBackends/OGL/ProgramShaderCache.h"

#include <atomic>
#include <limits>
#include <memory>
#include <string>
@@ -27,7 +28,6 @@
#include "VideoBackends/OGL/VertexManager.h"

#include "VideoCommon/AsyncShaderCompiler.h"
#include "VideoCommon/Debugger.h"
#include "VideoCommon/DriverDetails.h"
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/ImageWrite.h"
@@ -54,6 +54,7 @@ static GLuint CurrentProgram = 0;
ProgramShaderCache::PipelineProgramMap ProgramShaderCache::s_pipeline_programs;
std::mutex ProgramShaderCache::s_pipeline_program_lock;
static std::string s_glsl_header = "";
static std::atomic<u64> s_shader_counter{0};
static thread_local bool s_is_shared_context = false;

static std::string GetGLSLVersionString()
@@ -109,13 +110,13 @@ void SHADER::SetProgramVariables()
glUniformBlockBinding(glprogid, UBERBlock_id, 4);

// Bind Texture Samplers
for (int a = 0; a < 10; ++a)
for (int a = 0; a < 8; ++a)
{
std::string name = StringFromFormat(a < 8 ? "samp[%d]" : "samp%d", a);

// Still need to get sampler locations since we aren't binding them statically in the shaders
int loc = glGetUniformLocation(glprogid, name.c_str());
if (loc != -1)
int loc = glGetUniformLocation(glprogid, StringFromFormat("samp[%d]", a).c_str());
if (loc < 0)
loc = glGetUniformLocation(glprogid, StringFromFormat("samp%d", a).c_str());
if (loc >= 0)
glUniform1i(loc, a);
}

@@ -191,21 +192,22 @@ bool PipelineProgramKey::operator!=(const PipelineProgramKey& rhs) const

bool PipelineProgramKey::operator==(const PipelineProgramKey& rhs) const
{
return std::tie(vertex_shader, geometry_shader, pixel_shader) ==
std::tie(rhs.vertex_shader, rhs.geometry_shader, rhs.pixel_shader);
return std::tie(vertex_shader_id, geometry_shader_id, pixel_shader_id) ==
std::tie(rhs.vertex_shader_id, rhs.geometry_shader_id, rhs.pixel_shader_id);
}

bool PipelineProgramKey::operator<(const PipelineProgramKey& rhs) const
{
return std::tie(vertex_shader, geometry_shader, pixel_shader) <
std::tie(rhs.vertex_shader, rhs.geometry_shader, rhs.pixel_shader);
return std::tie(vertex_shader_id, geometry_shader_id, pixel_shader_id) <
std::tie(rhs.vertex_shader_id, rhs.geometry_shader_id, rhs.pixel_shader_id);
}

std::size_t PipelineProgramKeyHash::operator()(const PipelineProgramKey& key) const
{
// We would really want std::hash_combine for this..
std::hash<const void*> hasher;
return hasher(key.vertex_shader) + hasher(key.geometry_shader) + hasher(key.pixel_shader);
std::hash<u64> hasher;
return hasher(key.vertex_shader_id) + hasher(key.geometry_shader_id) +
hasher(key.pixel_shader_id);
}

StreamBuffer* ProgramShaderCache::GetUniformBuffer()
@@ -218,13 +220,6 @@ u32 ProgramShaderCache::GetUniformBufferAlignment()
return s_ubo_align;
}

void ProgramShaderCache::InvalidateConstants()
{
VertexShaderManager::dirty = true;
GeometryShaderManager::dirty = true;
PixelShaderManager::dirty = true;
}

void ProgramShaderCache::UploadConstants()
{
if (PixelShaderManager::dirty || VertexShaderManager::dirty || GeometryShaderManager::dirty)
@@ -574,7 +569,9 @@ const PipelineProgram* ProgramShaderCache::GetPipelineProgram(const GLVertexForm
const OGLShader* geometry_shader,
const OGLShader* pixel_shader)
{
PipelineProgramKey key = {vertex_shader, geometry_shader, pixel_shader};
PipelineProgramKey key = {vertex_shader ? vertex_shader->GetID() : 0,
geometry_shader ? geometry_shader->GetID() : 0,
pixel_shader ? pixel_shader->GetID() : 0};
{
std::lock_guard<std::mutex> guard(s_pipeline_program_lock);
auto iter = s_pipeline_programs.find(key);
@@ -750,6 +747,7 @@ void ProgramShaderCache::CreateHeader()
"%s\n"

// Silly differences
"#define API_OPENGL 1\n"
"#define float2 vec2\n"
"#define float3 vec3\n"
"#define float4 vec4\n"
@@ -759,8 +757,6 @@ void ProgramShaderCache::CreateHeader()
"#define int2 ivec2\n"
"#define int3 ivec3\n"
"#define int4 ivec4\n"

// hlsl to glsl function translation
"#define frac fract\n"
"#define lerp mix\n"

@@ -782,12 +778,17 @@ void ProgramShaderCache::CreateHeader()
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n"
"#define UBO_BINDING(packing, x) layout(packing, binding = x)\n"
"#define SAMPLER_BINDING(x) layout(binding = x)\n"
"#define SSBO_BINDING(x) layout(binding = x)\n" :
"#define TEXEL_BUFFER_BINDING(x) layout(binding = x)\n"
"#define SSBO_BINDING(x) layout(binding = x)\n"
"#define IMAGE_BINDING(format, x) layout(format, binding = x)\n" :
"#define ATTRIBUTE_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n"
"#define UBO_BINDING(packing, x) layout(packing)\n"
"#define SAMPLER_BINDING(x)\n",
"#define SAMPLER_BINDING(x)\n"
"#define TEXEL_BUFFER_BINDING(x)\n"
"#define SSBO_BINDING(x)\n"
"#define IMAGE_BINDING(format, x) layout(format)\n",
// Input/output blocks are matched by name during program linking
"#define VARYING_LOCATION(x)\n",
!is_glsles && g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics ?
@@ -823,6 +824,11 @@ void ProgramShaderCache::CreateHeader()
v >= GlslEs310 ? "precision highp image2DArray;" : "");
}

u64 ProgramShaderCache::GenerateShaderID()
{
return s_shader_counter++;
}

bool SharedContextAsyncShaderCompiler::WorkerThreadInitMainThread(void** param)
{
std::unique_ptr<GLContext> context =
@@ -44,9 +44,9 @@ struct SHADER

struct PipelineProgramKey
{
const OGLShader* vertex_shader;
const OGLShader* geometry_shader;
const OGLShader* pixel_shader;
u64 vertex_shader_id;
u64 geometry_shader_id;
u64 pixel_shader_id;

bool operator==(const PipelineProgramKey& rhs) const;
bool operator!=(const PipelineProgramKey& rhs) const;
@@ -82,14 +82,21 @@ class ProgramShaderCache
const std::string& gcode);
static StreamBuffer* GetUniformBuffer();
static u32 GetUniformBufferAlignment();
static void InvalidateConstants();
static void UploadConstants();
static void UploadConstants(const void* data, u32 data_size);

static void Init();
static void Shutdown();
static void CreateHeader();

// This counter increments with each shader object allocated, in order to give it a unique ID.
// Since the shaders can be destroyed after a pipeline is created, we can't use the shader pointer
// as a key for GL programs. For the same reason, we can't use the GL objects either. This ID is
// guaranteed to be unique for the emulation session, even if the memory allocator or GL driver
// re-uses pointers, therefore we won't have any collisions where the shaders attached to a
// pipeline do not match the pipeline configuration.
static u64 GenerateShaderID();

static const PipelineProgram* GetPipelineProgram(const GLVertexFormat* vertex_format,
const OGLShader* vertex_shader,
const OGLShader* geometry_shader,