1
0
Fork 0
forked from suyu/suyu

gl_rasterizer: Enable clip distances when set in register and in shader

This commit is contained in:
ReinUsesLisp 2018-11-29 16:13:13 -03:00
parent 7befe0134d
commit 2908d30274
5 changed files with 37 additions and 13 deletions

View file

@ -42,6 +42,7 @@ public:
static constexpr std::size_t NumVertexArrays = 32; static constexpr std::size_t NumVertexArrays = 32;
static constexpr std::size_t NumVertexAttributes = 32; static constexpr std::size_t NumVertexAttributes = 32;
static constexpr std::size_t NumTextureSamplers = 32; static constexpr std::size_t NumTextureSamplers = 32;
static constexpr std::size_t NumClipDistances = 8;
static constexpr std::size_t MaxShaderProgram = 6; static constexpr std::size_t MaxShaderProgram = 6;
static constexpr std::size_t MaxShaderStage = 5; static constexpr std::size_t MaxShaderStage = 5;
// Maximum number of const buffers per shader stage. // Maximum number of const buffers per shader stage.

View file

@ -295,6 +295,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
// shaders. The constbuffer bindpoint starts after the shader stage configuration bind points. // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
u32 current_texture_bindpoint = 0; u32 current_texture_bindpoint = 0;
std::array<bool, Maxwell::NumClipDistances> clip_distances{};
for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
const auto& shader_config = gpu.regs.shader_config[index]; const auto& shader_config = gpu.regs.shader_config[index];
@ -355,12 +356,22 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader, current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
primitive_mode, current_texture_bindpoint); primitive_mode, current_texture_bindpoint);
// Workaround for Intel drivers.
// When a clip distance is enabled but not set in the shader it crops parts of the screen
// (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the
// clip distances only when it's written by a shader stage.
for (std::size_t i = 0; i < Maxwell::NumClipDistances; ++i) {
clip_distances[i] |= shader->GetShaderEntries().clip_distances[i];
}
// When VertexA is enabled, we have dual vertex shaders // When VertexA is enabled, we have dual vertex shaders
if (program == Maxwell::ShaderProgram::VertexA) { if (program == Maxwell::ShaderProgram::VertexA) {
// VertexB was combined with VertexA, so we skip the VertexB iteration // VertexB was combined with VertexA, so we skip the VertexB iteration
index++; index++;
} }
} }
SyncClipEnabled(clip_distances);
} }
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
@ -642,7 +653,6 @@ void RasterizerOpenGL::DrawArrays() {
SyncCullMode(); SyncCullMode();
SyncPrimitiveRestart(); SyncPrimitiveRestart();
SyncScissorTest(state); SyncScissorTest(state);
SyncClipEnabled();
// Alpha Testing is synced on shaders. // Alpha Testing is synced on shaders.
SyncTransformFeedback(); SyncTransformFeedback();
SyncPointState(); SyncPointState();
@ -1019,20 +1029,23 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0; state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0;
} }
void RasterizerOpenGL::SyncClipEnabled() { void RasterizerOpenGL::SyncClipEnabled(
const std::array<bool, Maxwell::Regs::NumClipDistances>& clip_mask) {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
state.clip_distance[0] = regs.clip_distance_enabled.c0 != 0; const std::array<bool, Maxwell::Regs::NumClipDistances> reg_state{
state.clip_distance[1] = regs.clip_distance_enabled.c1 != 0; regs.clip_distance_enabled.c0 != 0, regs.clip_distance_enabled.c1 != 0,
state.clip_distance[2] = regs.clip_distance_enabled.c2 != 0; regs.clip_distance_enabled.c2 != 0, regs.clip_distance_enabled.c3 != 0,
state.clip_distance[3] = regs.clip_distance_enabled.c3 != 0; regs.clip_distance_enabled.c4 != 0, regs.clip_distance_enabled.c5 != 0,
state.clip_distance[4] = regs.clip_distance_enabled.c4 != 0; regs.clip_distance_enabled.c6 != 0, regs.clip_distance_enabled.c7 != 0};
state.clip_distance[5] = regs.clip_distance_enabled.c5 != 0;
state.clip_distance[6] = regs.clip_distance_enabled.c6 != 0; for (std::size_t i = 0; i < Maxwell::Regs::NumClipDistances; ++i) {
state.clip_distance[7] = regs.clip_distance_enabled.c7 != 0; state.clip_distance[i] = reg_state[i] && clip_mask[i];
}
} }
void RasterizerOpenGL::SyncClipCoef() { void RasterizerOpenGL::SyncClipCoef() {
UNREACHABLE(); UNIMPLEMENTED();
} }
void RasterizerOpenGL::SyncCullMode() { void RasterizerOpenGL::SyncCullMode() {

View file

@ -142,7 +142,8 @@ private:
void SyncViewport(OpenGLState& current_state); void SyncViewport(OpenGLState& current_state);
/// Syncs the clip enabled status to match the guest state /// Syncs the clip enabled status to match the guest state
void SyncClipEnabled(); void SyncClipEnabled(
const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& clip_mask);
/// Syncs the clip coefficients to match the guest state /// Syncs the clip coefficients to match the guest state
void SyncClipCoef(); void SyncClipCoef();

View file

@ -525,6 +525,7 @@ public:
((header.vtg.clip_distances >> index) & 1) == 0, ((header.vtg.clip_distances >> index) & 1) == 0,
"Shader is setting gl_ClipDistance{} without enabling it in the header", index); "Shader is setting gl_ClipDistance{} without enabling it in the header", index);
clip_distances[index] = true;
fixed_pipeline_output_attributes_used.insert(attribute); fixed_pipeline_output_attributes_used.insert(attribute);
shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';'); shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';');
break; break;
@ -602,6 +603,11 @@ public:
return used_samplers; return used_samplers;
} }
/// Returns an array of the used clip distances.
const std::array<bool, Maxwell::NumClipDistances>& GetClipDistances() const {
return clip_distances;
}
/// Returns the GLSL sampler used for the input shader sampler, and creates a new one if /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if
/// necessary. /// necessary.
std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
@ -975,6 +981,7 @@ private:
const std::string& suffix; const std::string& suffix;
const Tegra::Shader::Header& header; const Tegra::Shader::Header& header;
std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used; std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used;
std::array<bool, Maxwell::NumClipDistances> clip_distances{};
u64 local_memory_size; u64 local_memory_size;
}; };
@ -997,7 +1004,8 @@ public:
/// Returns entries in the shader that are useful for external functions /// Returns entries in the shader that are useful for external functions
ShaderEntries GetEntries() const { ShaderEntries GetEntries() const {
return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), shader_length}; return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), regs.GetClipDistances(),
shader_length};
} }
private: private:

View file

@ -163,6 +163,7 @@ private:
struct ShaderEntries { struct ShaderEntries {
std::vector<ConstBufferEntry> const_buffer_entries; std::vector<ConstBufferEntry> const_buffer_entries;
std::vector<SamplerEntry> texture_samplers; std::vector<SamplerEntry> texture_samplers;
std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> clip_distances;
std::size_t shader_length; std::size_t shader_length;
}; };