Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VideoBackends: Share GX vertex/index/uniform buffers with utility draws #7592

Merged
merged 7 commits into from Dec 4, 2018
33 changes: 0 additions & 33 deletions Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
Expand Up @@ -4,7 +4,6 @@

#include <string>

#include "Common/Align.h"
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"

Expand All @@ -18,8 +17,6 @@

#include "VideoCommon/Debugger.h"
#include "VideoCommon/GeometryShaderGen.h"
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VideoConfig.h"

namespace DX11
Expand All @@ -36,25 +33,6 @@ ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader()
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? CopyGeometryShader : nullptr;
}

ID3D11Buffer* gscbuf = nullptr;

ID3D11Buffer*& GeometryShaderCache::GetConstantBuffer()
{
// TODO: divide the global variables of the generated shaders into about 5 constant buffers to
// speed this up
if (GeometryShaderManager::dirty)
{
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(gscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, &GeometryShaderManager::constants, sizeof(GeometryShaderConstants));
D3D::context->Unmap(gscbuf, 0);
GeometryShaderManager::dirty = false;

ADDSTAT(stats.thisFrame.bytesUniformStreamed, sizeof(GeometryShaderConstants));
}
return gscbuf;
}

const char clear_shader_code[] = {
"struct VSOUTPUT\n"
"{\n"
Expand Down Expand Up @@ -116,15 +94,6 @@ const char copy_shader_code[] = {

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(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");
Expand All @@ -138,8 +107,6 @@ void GeometryShaderCache::Init()

void GeometryShaderCache::Shutdown()
{
SAFE_RELEASE(gscbuf);

SAFE_RELEASE(ClearGeometryShader);
SAFE_RELEASE(CopyGeometryShader);
}
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/VideoBackends/D3D/GeometryShaderCache.h
Expand Up @@ -20,7 +20,8 @@ class GeometryShaderCache
static ID3D11GeometryShader* GetClearGeometryShader();
static ID3D11GeometryShader* GetCopyGeometryShader();

static ID3D11Buffer*& GetConstantBuffer();
static ID3D11Buffer* GetConstantBuffer();
static void UpdateConstantBuffer(const void* data, u32 data_size);
};

} // namespace DX11
34 changes: 0 additions & 34 deletions Source/Core/VideoBackends/D3D/PixelShaderCache.cpp
Expand Up @@ -4,7 +4,6 @@

#include <string>

#include "Common/Align.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
Expand All @@ -20,8 +19,6 @@

#include "VideoCommon/Debugger.h"
#include "VideoCommon/PixelShaderGen.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VideoConfig.h"

namespace DX11
Expand All @@ -32,7 +29,6 @@ ID3D11PixelShader* s_AnaglyphProgram = nullptr;
ID3D11PixelShader* s_DepthResolveProgram = nullptr;
ID3D11PixelShader* s_rgba6_to_rgb8[2] = {nullptr};
ID3D11PixelShader* s_rgb8_to_rgba6[2] = {nullptr};
ID3D11Buffer* pscbuf = nullptr;

const char clear_program_code[] = {"void main(\n"
"out float4 ocol0 : SV_Target,\n"
Expand Down Expand Up @@ -277,36 +273,8 @@ ID3D11PixelShader* PixelShaderCache::GetDepthResolveProgram()
return s_DepthResolveProgram;
}

static void UpdateConstantBuffers()
{
if (PixelShaderManager::dirty)
{
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, &PixelShaderManager::constants, sizeof(PixelShaderConstants));
D3D::context->Unmap(pscbuf, 0);
PixelShaderManager::dirty = false;

ADDSTAT(stats.thisFrame.bytesUniformStreamed, sizeof(PixelShaderConstants));
}
}

ID3D11Buffer* PixelShaderCache::GetConstantBuffer()
{
UpdateConstantBuffers();
return pscbuf;
}

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(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");
Expand Down Expand Up @@ -334,8 +302,6 @@ void PixelShaderCache::InvalidateMSAAShaders()

void PixelShaderCache::Shutdown()
{
SAFE_RELEASE(pscbuf);

SAFE_RELEASE(s_ClearProgram);
SAFE_RELEASE(s_AnaglyphProgram);
SAFE_RELEASE(s_DepthResolveProgram);
Expand Down
2 changes: 0 additions & 2 deletions Source/Core/VideoBackends/D3D/PixelShaderCache.h
Expand Up @@ -21,8 +21,6 @@ class PixelShaderCache
static void Init();
static void Shutdown();

static ID3D11Buffer* GetConstantBuffer();

static ID3D11PixelShader* GetColorCopyProgram(bool multisampled);
static ID3D11PixelShader* GetClearProgram();
static ID3D11PixelShader* GetAnaglyphProgram();
Expand Down
103 changes: 19 additions & 84 deletions Source/Core/VideoBackends/D3D/Render.cpp
Expand Up @@ -63,7 +63,7 @@ typedef struct _Nv_Stereo_Image_Header
#define NVSTEREO_IMAGE_SIGNATURE 0x4433564e

Renderer::Renderer(int backbuffer_width, int backbuffer_height)
: ::Renderer(backbuffer_width, backbuffer_height)
: ::Renderer(backbuffer_width, backbuffer_height, AbstractTextureFormat::RGBA8)
{
m_last_multisamples = g_ActiveConfig.iMultisamples;
m_last_stereo_mode = g_ActiveConfig.stereo_mode != StereoMode::Off;
Expand Down Expand Up @@ -167,16 +167,6 @@ void Renderer::SetupDeviceObjects()
D3D::SetDebugObjectName(m_reset_rast_state, "rasterizer state for Renderer::ResetAPIState");

m_screenshot_texture = nullptr;

CD3D11_BUFFER_DESC vbo_desc(UTILITY_VBO_SIZE, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC,
D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateBuffer(&vbo_desc, nullptr, &m_utility_vertex_buffer);
CHECK(SUCCEEDED(hr), "Create utility VBO");

CD3D11_BUFFER_DESC ubo_desc(UTILITY_UBO_SIZE, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC,
D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateBuffer(&ubo_desc, nullptr, &m_utility_uniform_buffer);
CHECK(SUCCEEDED(hr), "Create utility UBO");
}

// Kill off all device objects
Expand All @@ -196,8 +186,6 @@ void Renderer::TeardownDeviceObjects()
SAFE_RELEASE(m_reset_rast_state);
SAFE_RELEASE(m_screenshot_texture);
SAFE_RELEASE(m_3d_vision_texture);
SAFE_RELEASE(m_utility_vertex_buffer);
SAFE_RELEASE(m_utility_uniform_buffer);
}

void Renderer::Create3DVisionTexture(int width, int height)
Expand Down Expand Up @@ -273,25 +261,6 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
return DXPipeline::Create(config);
}

void Renderer::UpdateUtilityUniformBuffer(const void* uniforms, u32 uniforms_size)
{
DEBUG_ASSERT(uniforms_size > 0 && uniforms_size < UTILITY_UBO_SIZE);
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = D3D::context->Map(m_utility_uniform_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
CHECK(SUCCEEDED(hr), "Map utility UBO");
std::memcpy(mapped.pData, uniforms, uniforms_size);
D3D::context->Unmap(m_utility_uniform_buffer, 0);
}

void Renderer::UpdateUtilityVertexBuffer(const void* vertices, u32 vertex_stride, u32 num_vertices)
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = D3D::context->Map(m_utility_vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
CHECK(SUCCEEDED(hr), "Map utility VBO");
std::memcpy(mapped.pData, vertices, num_vertices * vertex_stride);
D3D::context->Unmap(m_utility_vertex_buffer, 0);
}

void Renderer::SetPipeline(const AbstractPipeline* pipeline)
{
const DXPipeline* dx_pipeline = static_cast<const DXPipeline*>(pipeline);
Expand All @@ -308,54 +277,6 @@ void Renderer::SetPipeline(const AbstractPipeline* pipeline)
D3D::stateman->SetPixelShader(dx_pipeline->GetPixelShader());
}

void Renderer::DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
u32 vertex_stride, u32 num_vertices)
{
// Copy in uniforms.
if (uniforms_size > 0)
{
UpdateUtilityUniformBuffer(uniforms, uniforms_size);
D3D::stateman->SetVertexConstants(m_utility_uniform_buffer);
D3D::stateman->SetPixelConstants(m_utility_uniform_buffer);
D3D::stateman->SetGeometryConstants(m_utility_uniform_buffer);
}

// If the vertices are larger than our buffer, we need to break it up into multiple draws.
const char* vertices_ptr = static_cast<const char*>(vertices);
while (num_vertices > 0)
{
u32 vertices_this_draw = num_vertices;
if (vertices_ptr)
{
vertices_this_draw = std::min(vertices_this_draw, UTILITY_VBO_SIZE / vertex_stride);
DEBUG_ASSERT(vertices_this_draw > 0);
UpdateUtilityVertexBuffer(vertices_ptr, vertex_stride, vertices_this_draw);
D3D::stateman->SetVertexBuffer(m_utility_vertex_buffer, vertex_stride, 0);
}

// Apply pending state and draw.
D3D::stateman->Apply();
D3D::context->Draw(vertices_this_draw, 0);
vertices_ptr += vertex_stride * vertices_this_draw;
num_vertices -= vertices_this_draw;
}
}

void Renderer::DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
{
D3D::stateman->SetComputeShader(static_cast<const DXShader*>(shader)->GetD3DComputeShader());

if (uniforms_size > 0)
{
UpdateUtilityUniformBuffer(uniforms, uniforms_size);
D3D::stateman->SetComputeConstants(m_utility_uniform_buffer);
}

D3D::stateman->Apply();
D3D::context->Dispatch(groups_x, groups_y, groups_z);
}

TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
{
TargetRectangle result;
Expand Down Expand Up @@ -549,15 +470,29 @@ void Renderer::SetViewport(float x, float y, float width, float height, float ne
{
// In D3D, the viewport rectangle must fit within the render target.
D3D11_VIEWPORT vp;
vp.TopLeftX = MathUtil::Clamp(x, 0.0f, static_cast<float>(m_target_width - 1));
vp.TopLeftY = MathUtil::Clamp(y, 0.0f, static_cast<float>(m_target_height - 1));
vp.Width = MathUtil::Clamp(width, 1.0f, static_cast<float>(m_target_width) - vp.TopLeftX);
vp.Height = MathUtil::Clamp(height, 1.0f, static_cast<float>(m_target_height) - vp.TopLeftY);
vp.TopLeftX = MathUtil::Clamp(x, 0.0f, static_cast<float>(m_current_framebuffer_width - 1));
vp.TopLeftY = MathUtil::Clamp(y, 0.0f, static_cast<float>(m_current_framebuffer_height - 1));
vp.Width =
MathUtil::Clamp(width, 1.0f, static_cast<float>(m_current_framebuffer_width) - vp.TopLeftX);
vp.Height =
MathUtil::Clamp(height, 1.0f, static_cast<float>(m_current_framebuffer_height) - vp.TopLeftY);
vp.MinDepth = near_depth;
vp.MaxDepth = far_depth;
D3D::context->RSSetViewports(1, &vp);
}

void Renderer::Draw(u32 base_vertex, u32 num_vertices)
{
D3D::stateman->Apply();
D3D::context->Draw(num_vertices, base_vertex);
}

void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
{
D3D::stateman->Apply();
D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
}

void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z)
{
Expand Down
13 changes: 2 additions & 11 deletions Source/Core/VideoBackends/D3D/Render.h
Expand Up @@ -50,6 +50,8 @@ class Renderer : public ::Renderer
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 SetFullscreen(bool enable_fullscreen) override;
bool IsFullscreen() const override;

Expand All @@ -73,11 +75,6 @@ class Renderer : public ::Renderer

void ReinterpretPixelData(unsigned int convtype) override;

void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
u32 vertex_stride, u32 num_vertices) override;
void DispatchComputeShader(const AbstractShader* shader, const void* uniforms, u32 uniforms_size,
u32 groups_x, u32 groups_y, u32 groups_z) override;

private:
void SetupDeviceObjects();
void TeardownDeviceObjects();
Expand All @@ -89,9 +86,6 @@ class Renderer : public ::Renderer
void BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D* src_texture,
u32 src_width, u32 src_height);

void UpdateUtilityUniformBuffer(const void* uniforms, u32 uniforms_size);
void UpdateUtilityVertexBuffer(const void* vertices, u32 vertex_stride, u32 num_vertices);

StateCache m_state_cache;

std::array<ID3D11BlendState*, 4> m_clear_blend_states{};
Expand All @@ -103,9 +97,6 @@ class Renderer : public ::Renderer
ID3D11Texture2D* m_screenshot_texture = nullptr;
D3DTexture2D* m_3d_vision_texture = nullptr;

ID3D11Buffer* m_utility_vertex_buffer = nullptr;
ID3D11Buffer* m_utility_uniform_buffer = nullptr;

u32 m_last_multisamples = 1;
bool m_last_stereo_mode = false;
bool m_last_fullscreen_state = false;
Expand Down