GL: Set up the textures used for each draw call.
Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a certain number in OpenGL. We try to only use the minimum amount of host textures by not keeping a 1:1 relation between guest texture ids and host texture ids, ie, guest texture id 8 can be host texture id 0 if it's the only texture used in the guest shader program. This mapping will have to be passed to the shader decompiler so it can rewrite the texture accesses.
This commit is contained in:
parent
cb3183212d
commit
b0ca330e14
|
@ -276,7 +276,9 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
|
|
||||||
// TODO(bunnei): Sync framebuffer_scale uniform here
|
// TODO(bunnei): Sync framebuffer_scale uniform here
|
||||||
// TODO(bunnei): Sync scissorbox uniform(s) here
|
// TODO(bunnei): Sync scissorbox uniform(s) here
|
||||||
// TODO(bunnei): Sync and bind the texture surfaces
|
|
||||||
|
// Sync and bind the texture surfaces
|
||||||
|
BindTextures();
|
||||||
|
|
||||||
// Sync and bind the shader
|
// Sync and bind the shader
|
||||||
if (shader_dirty) {
|
if (shader_dirty) {
|
||||||
|
@ -380,6 +382,39 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::BindTextures() {
|
||||||
|
using Regs = Tegra::Engines::Maxwell3D::Regs;
|
||||||
|
auto maxwell3d = Core::System::GetInstance().GPU().Get3DEngine();
|
||||||
|
|
||||||
|
// Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a
|
||||||
|
// certain number in OpenGL. We try to only use the minimum amount of host textures by not
|
||||||
|
// keeping a 1:1 relation between guest texture ids and host texture ids, ie, guest texture id 8
|
||||||
|
// can be host texture id 0 if it's the only texture used in the guest shader program.
|
||||||
|
u32 host_texture_index = 0;
|
||||||
|
for (u32 stage = 0; stage < Regs::MaxShaderStage; ++stage) {
|
||||||
|
ASSERT(host_texture_index < texture_samplers.size());
|
||||||
|
const auto textures = maxwell3d.GetStageTextures(static_cast<Regs::ShaderStage>(stage));
|
||||||
|
for (unsigned texture_index = 0; texture_index < textures.size(); ++texture_index) {
|
||||||
|
const auto& texture = textures[texture_index];
|
||||||
|
|
||||||
|
if (texture.enabled) {
|
||||||
|
texture_samplers[host_texture_index].SyncWithConfig(texture.tsc);
|
||||||
|
Surface surface = res_cache.GetTextureSurface(texture);
|
||||||
|
if (surface != nullptr) {
|
||||||
|
state.texture_units[host_texture_index].texture_2d = surface->texture.handle;
|
||||||
|
} else {
|
||||||
|
// Can occur when texture addr is null or its memory is unmapped/invalid
|
||||||
|
state.texture_units[texture_index].texture_2d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
++host_texture_index;
|
||||||
|
} else {
|
||||||
|
state.texture_units[texture_index].texture_2d = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {}
|
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {}
|
||||||
|
|
||||||
void RasterizerOpenGL::FlushAll() {
|
void RasterizerOpenGL::FlushAll() {
|
||||||
|
@ -470,7 +505,6 @@ void RasterizerOpenGL::SamplerInfo::Create() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) {
|
void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) {
|
||||||
|
|
||||||
GLuint s = sampler.handle;
|
GLuint s = sampler.handle;
|
||||||
|
|
||||||
if (mag_filter != config.mag_filter) {
|
if (mag_filter != config.mag_filter) {
|
||||||
|
|
|
@ -110,6 +110,9 @@ private:
|
||||||
void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
|
void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
|
||||||
bool has_stencil);
|
bool has_stencil);
|
||||||
|
|
||||||
|
/// Binds the required textures to OpenGL before drawing a batch.
|
||||||
|
void BindTextures();
|
||||||
|
|
||||||
/// Syncs the viewport to match the guest state
|
/// Syncs the viewport to match the guest state
|
||||||
void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale);
|
void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale);
|
||||||
|
|
||||||
|
|
Reference in New Issue