forked from suyu/suyu
gl_rasterizer: Generate shaders and upload uniforms.
This commit is contained in:
parent
85d77a3d24
commit
beddc8afd2
2 changed files with 77 additions and 32 deletions
|
@ -96,10 +96,14 @@ RasterizerOpenGL::RasterizerOpenGL() {
|
|||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer->GetHandle());
|
||||
|
||||
vs_uniform_buffer.Create();
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, vs_uniform_buffer.handle);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLShader::VSUniformData), nullptr, GL_STREAM_COPY);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, vs_uniform_buffer.handle);
|
||||
for (unsigned index = 0; index < uniform_buffers.size(); ++index) {
|
||||
auto& buffer = uniform_buffers[index];
|
||||
buffer.Create();
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, buffer.handle);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLShader::MaxwellUniformData), nullptr,
|
||||
GL_STREAM_COPY);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.handle);
|
||||
}
|
||||
|
||||
accelerate_draw = AccelDraw::Disabled;
|
||||
|
||||
|
@ -167,15 +171,69 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
|
|||
buffer_offset += data_size;
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SetupVertexShader(GLShader::VSUniformData* ub_ptr, GLintptr buffer_offset) {
|
||||
MICROPROFILE_SCOPE(OpenGL_VS);
|
||||
UNREACHABLE();
|
||||
}
|
||||
void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos) {
|
||||
// Helper function for uploading uniform data
|
||||
const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) {
|
||||
if (has_ARB_direct_state_access) {
|
||||
glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size);
|
||||
} else {
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, handle);
|
||||
glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size);
|
||||
}
|
||||
};
|
||||
|
||||
void RasterizerOpenGL::SetupFragmentShader(GLShader::FSUniformData* ub_ptr,
|
||||
GLintptr buffer_offset) {
|
||||
MICROPROFILE_SCOPE(OpenGL_FS);
|
||||
UNREACHABLE();
|
||||
auto& gpu = Core::System().GetInstance().GPU().Maxwell3D();
|
||||
ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!");
|
||||
|
||||
for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) {
|
||||
ptr_pos += sizeof(GLShader::MaxwellUniformData);
|
||||
|
||||
auto& shader_config = gpu.regs.shader_config[index];
|
||||
const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)};
|
||||
|
||||
// VertexB program is always enabled, despite bit setting
|
||||
const bool is_enabled{shader_config.enable || program == Maxwell::ShaderProgram::VertexB};
|
||||
|
||||
// Skip stages that are not enabled
|
||||
if (!is_enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Upload uniform data as one UBO per stage
|
||||
const auto& stage = index - 1; // Stage indices are 0 - 5
|
||||
const GLintptr ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos);
|
||||
copy_buffer(uniform_buffers[stage].handle, ubo_offset,
|
||||
sizeof(GLShader::MaxwellUniformData));
|
||||
GLShader::MaxwellUniformData* ub_ptr =
|
||||
reinterpret_cast<GLShader::MaxwellUniformData*>(&buffer_ptr[ptr_pos]);
|
||||
ub_ptr->SetFromRegs(gpu.state.shader_stages[stage]);
|
||||
|
||||
// Fetch program code from memory
|
||||
GLShader::ProgramCode program_code;
|
||||
const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset};
|
||||
const VAddr cpu_address{gpu.memory_manager.PhysicalToVirtualAddress(gpu_address)};
|
||||
Memory::ReadBlock(cpu_address, program_code.data(), program_code.size() * sizeof(u64));
|
||||
GLShader::ShaderSetup setup{std::move(program_code)};
|
||||
|
||||
switch (program) {
|
||||
case Maxwell::ShaderProgram::VertexB: {
|
||||
GLShader::MaxwellVSConfig vs_config{setup};
|
||||
shader_program_manager->UseProgrammableVertexShader(vs_config, setup);
|
||||
break;
|
||||
}
|
||||
case Maxwell::ShaderProgram::Fragment: {
|
||||
GLShader::MaxwellFSConfig fs_config{setup};
|
||||
shader_program_manager->UseProgrammableFragmentShader(fs_config, setup);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unimplemented shader index=%d, enable=%d, offset=0x%08X", index,
|
||||
shader_config.enable.Value(), shader_config.offset);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
shader_program_manager->UseTrivialGeometryShader();
|
||||
}
|
||||
|
||||
bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
|
||||
|
@ -260,7 +318,9 @@ void RasterizerOpenGL::DrawArrays() {
|
|||
if (is_indexed) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
buffer_size += sizeof(GLShader::VSUniformData);
|
||||
|
||||
// Uniform space for the 5 shader stages
|
||||
buffer_size += sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage;
|
||||
|
||||
size_t ptr_pos = 0;
|
||||
u8* buffer_ptr;
|
||||
|
@ -276,24 +336,10 @@ void RasterizerOpenGL::DrawArrays() {
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
SetupVertexShader(reinterpret_cast<GLShader::VSUniformData*>(&buffer_ptr[ptr_pos]),
|
||||
buffer_offset + static_cast<GLintptr>(ptr_pos));
|
||||
const GLintptr vs_ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos);
|
||||
ptr_pos += sizeof(GLShader::VSUniformData);
|
||||
SetupShaders(buffer_ptr, buffer_offset, ptr_pos);
|
||||
|
||||
stream_buffer->Unmap();
|
||||
|
||||
const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) {
|
||||
if (has_ARB_direct_state_access) {
|
||||
glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size);
|
||||
} else {
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, handle);
|
||||
glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size);
|
||||
}
|
||||
};
|
||||
|
||||
copy_buffer(vs_uniform_buffer.handle, vs_ubo_offset, sizeof(GLShader::VSUniformData));
|
||||
|
||||
shader_program_manager->ApplyTo(state);
|
||||
state.Apply();
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "common/common_types.h"
|
||||
#include "common/hash.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
|
@ -141,11 +142,9 @@ private:
|
|||
void AnalyzeVertexArray(bool is_indexed);
|
||||
void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset);
|
||||
|
||||
OGLBuffer vs_uniform_buffer;
|
||||
std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers;
|
||||
|
||||
void SetupVertexShader(GLShader::VSUniformData* ub_ptr, GLintptr buffer_offset);
|
||||
|
||||
void SetupFragmentShader(GLShader::FSUniformData* ub_ptr, GLintptr buffer_offset);
|
||||
void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos);
|
||||
|
||||
enum class AccelDraw { Disabled, Arrays, Indexed };
|
||||
AccelDraw accelerate_draw;
|
||||
|
|
Loading…
Reference in a new issue