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.pull/314/head
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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue