forked from ShuriZma/suyu
gl_rasterizer: Enable clip distances when set in register and in shader
This commit is contained in:
parent
7befe0134d
commit
2908d30274
|
@ -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.
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue