Making texture swizzles dynamic. Seems to fix some color swap issues.

And probably exposes many more ;)
This commit is contained in:
Ben Vanik 2015-12-07 22:39:33 -08:00
parent 09022a6ad3
commit ec113275dc
10 changed files with 40 additions and 52 deletions

View File

@ -78,8 +78,9 @@ class DrawBatcher {
void set_ps_param_gen(int register_index) { void set_ps_param_gen(int register_index) {
active_draw_.header->ps_param_gen = register_index; active_draw_.header->ps_param_gen = register_index;
} }
void set_texture_sampler(int index, GLuint64 handle) { void set_texture_sampler(int index, GLuint64 handle, uint32_t swizzle) {
active_draw_.header->texture_samplers[index] = handle; active_draw_.header->texture_samplers[index] = handle;
active_draw_.header->texture_swizzles[index] = swizzle;
} }
void set_index_buffer(const CircularBuffer::Allocation& allocation) { void set_index_buffer(const CircularBuffer::Allocation& allocation) {
// Offset is used in glDrawElements. // Offset is used in glDrawElements.
@ -140,6 +141,7 @@ class DrawBatcher {
// TODO(benvanik): pack tightly // TODO(benvanik): pack tightly
GLuint64 texture_samplers[32]; GLuint64 texture_samplers[32];
GLuint texture_swizzles[32];
float4 float_consts[512]; float4 float_consts[512];
uint32_t bool_consts[8]; uint32_t bool_consts[8];

View File

@ -408,7 +408,7 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
->blitter() ->blitter()
->CopyColorTexture2D(framebuffer_texture, src_rect, ->CopyColorTexture2D(framebuffer_texture, src_rect,
static_cast<GLuint>(swap_state_.back_buffer_texture), static_cast<GLuint>(swap_state_.back_buffer_texture),
dest_rect, GL_LINEAR); dest_rect, GL_LINEAR, true);
if (FLAGS_draw_all_framebuffers) { if (FLAGS_draw_all_framebuffers) {
int32_t offsetx = (1280 - (1280 / 5)); int32_t offsetx = (1280 - (1280 / 5));
@ -431,7 +431,7 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
->CopyColorTexture2D( ->CopyColorTexture2D(
tex, src_rect, tex, src_rect,
static_cast<GLuint>(swap_state_.back_buffer_texture), dest_rect, static_cast<GLuint>(swap_state_.back_buffer_texture), dest_rect,
GL_LINEAR); GL_LINEAR, true);
offsety += 720 / 5; offsety += 720 / 5;
} }
@ -455,7 +455,7 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
->CopyColorTexture2D( ->CopyColorTexture2D(
tex, src_rect, tex, src_rect,
static_cast<GLuint>(swap_state_.back_buffer_texture), dest_rect, static_cast<GLuint>(swap_state_.back_buffer_texture), dest_rect,
GL_LINEAR); GL_LINEAR, false);
doffsetx += 1280 / 5; doffsetx += 1280 / 5;
} }
@ -1485,7 +1485,7 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::PopulateSampler(
// Reset slot. // Reset slot.
// If we fail, we still draw but with an invalid texture. // If we fail, we still draw but with an invalid texture.
draw_batcher_.set_texture_sampler(texture_binding.fetch_constant, 0); draw_batcher_.set_texture_sampler(texture_binding.fetch_constant, 0, 0);
if (FLAGS_disable_textures) { if (FLAGS_disable_textures) {
return UpdateStatus::kCompatible; return UpdateStatus::kCompatible;
@ -1521,7 +1521,8 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::PopulateSampler(
// Shaders will use bindless to fetch right from it. // Shaders will use bindless to fetch right from it.
draw_batcher_.set_texture_sampler(texture_binding.fetch_constant, draw_batcher_.set_texture_sampler(texture_binding.fetch_constant,
entry_view->texture_sampler_handle); entry_view->texture_sampler_handle,
fetch.swizzle);
return UpdateStatus::kCompatible; return UpdateStatus::kCompatible;
} }

View File

@ -78,7 +78,7 @@ void GL4GraphicsSystem::Swap(xe::ui::UIEvent* e) {
static_cast<GLuint>(swap_state.front_buffer_texture), static_cast<GLuint>(swap_state.front_buffer_texture),
Rect2D(0, 0, swap_state.width, swap_state.height), Rect2D(0, 0, swap_state.width, swap_state.height),
Rect2D(0, 0, target_window_->width(), target_window_->height()), Rect2D(0, 0, target_window_->width(), target_window_->height()),
GL_LINEAR); GL_LINEAR, false);
} }
} // namespace gl4 } // namespace gl4

View File

@ -473,25 +473,6 @@ TextureCache::TextureEntry* TextureCache::LookupOrInsertTexture(
glTextureParameteri(entry->handle, GL_TEXTURE_BASE_LEVEL, 0); glTextureParameteri(entry->handle, GL_TEXTURE_BASE_LEVEL, 0);
glTextureParameteri(entry->handle, GL_TEXTURE_MAX_LEVEL, 1); glTextureParameteri(entry->handle, GL_TEXTURE_MAX_LEVEL, 1);
// Pre-shader swizzle.
// TODO(benvanik): can this be dynamic? Maybe per view?
// We may have to emulate this in the shader.
uint32_t swizzle_r = texture_info.swizzle & 0x7;
uint32_t swizzle_g = (texture_info.swizzle >> 3) & 0x7;
uint32_t swizzle_b = (texture_info.swizzle >> 6) & 0x7;
uint32_t swizzle_a = (texture_info.swizzle >> 9) & 0x7;
static const GLenum swizzle_map[] = {
GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO, GL_ONE,
};
glTextureParameteri(entry->handle, GL_TEXTURE_SWIZZLE_R,
swizzle_map[swizzle_r]);
glTextureParameteri(entry->handle, GL_TEXTURE_SWIZZLE_G,
swizzle_map[swizzle_g]);
glTextureParameteri(entry->handle, GL_TEXTURE_SWIZZLE_B,
swizzle_map[swizzle_b]);
glTextureParameteri(entry->handle, GL_TEXTURE_SWIZZLE_A,
swizzle_map[swizzle_a]);
// Upload/convert. // Upload/convert.
bool uploaded = false; bool uploaded = false;
switch (texture_info.dimension) { switch (texture_info.dimension) {
@ -590,7 +571,7 @@ GLuint TextureCache::ConvertTexture(Blitter* blitter, uint32_t guest_address,
dest_rect); dest_rect);
} else { } else {
blitter->CopyColorTexture2D(src_texture, src_rect, texture_entry->handle, blitter->CopyColorTexture2D(src_texture, src_rect, texture_entry->handle,
dest_rect, GL_LINEAR); dest_rect, GL_LINEAR, swap_channels);
} }
// HACK: remove texture from write watch list so readback won't kill us. // HACK: remove texture from write watch list so readback won't kill us.
@ -615,7 +596,7 @@ GLuint TextureCache::ConvertTexture(Blitter* blitter, uint32_t guest_address,
dest_rect); dest_rect);
} else { } else {
blitter->CopyColorTexture2D(src_texture, src_rect, entry->handle, blitter->CopyColorTexture2D(src_texture, src_rect, entry->handle,
dest_rect, GL_LINEAR); dest_rect, GL_LINEAR, swap_channels);
} }
return entry->handle; return entry->handle;
} }
@ -642,7 +623,7 @@ GLuint TextureCache::ConvertTexture(Blitter* blitter, uint32_t guest_address,
blitter->CopyDepthTexture(src_texture, src_rect, entry->handle, dest_rect); blitter->CopyDepthTexture(src_texture, src_rect, entry->handle, dest_rect);
} else { } else {
blitter->CopyColorTexture2D(src_texture, src_rect, entry->handle, dest_rect, blitter->CopyColorTexture2D(src_texture, src_rect, entry->handle, dest_rect,
GL_LINEAR); GL_LINEAR, swap_channels);
} }
GLuint handle = entry->handle; GLuint handle = entry->handle;

View File

@ -115,6 +115,7 @@ struct StateData {
int padding[3]; int padding[3];
// TODO(benvanik): variable length. // TODO(benvanik): variable length.
uvec2 texture_samplers[32]; uvec2 texture_samplers[32];
uint texture_swizzles[32];
vec4 float_consts[512]; vec4 float_consts[512];
int bool_consts[8]; int bool_consts[8];
int loop_consts[32]; int loop_consts[32];
@ -625,6 +626,16 @@ void GlslShaderTranslator::ProcessTextureFetchInstruction(
EmitSourceDepth("}\n"); EmitSourceDepth("}\n");
break; break;
} }
EmitSourceDepth("{\n");
EmitSourceDepth(
" float swiz_source[6] = {pv.x, pv.y, pv.z, pv.w, 0.0, 1.0};\n");
EmitSourceDepth(" uint swiz = state.texture_swizzles[%d];\n",
instr.operands[1].storage_index);
EmitSourceDepth(" pv = vec4(swiz_source[swiz & 0x7],\n");
EmitSourceDepth(" swiz_source[(swiz >> 3) & 0x7],\n");
EmitSourceDepth(" swiz_source[(swiz >> 6) & 0x7],\n");
EmitSourceDepth(" swiz_source[(swiz >> 9) & 0x7]);\n");
EmitSourceDepth("}\n");
break; break;
case FetchOpcode::kGetTextureBorderColorFrac: case FetchOpcode::kGetTextureBorderColorFrac:
EmitUnimplementedTranslationError(); EmitUnimplementedTranslationError();

View File

@ -109,7 +109,6 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
// a2xx_sq_surfaceformat // a2xx_sq_surfaceformat
auto& info = *out_info; auto& info = *out_info;
info.guest_address = fetch.address << 12; info.guest_address = fetch.address << 12;
info.swizzle = fetch.swizzle;
info.dimension = static_cast<Dimension>(fetch.dimension); info.dimension = static_cast<Dimension>(fetch.dimension);
info.width = info.height = info.depth = 0; info.width = info.height = info.depth = 0;

View File

@ -155,7 +155,6 @@ struct FormatInfo {
struct TextureInfo { struct TextureInfo {
uint32_t guest_address; uint32_t guest_address;
uint32_t swizzle;
Dimension dimension; Dimension dimension;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;

View File

@ -621,13 +621,11 @@ void TraceViewer::DrawTextureInfo(
ImGui::Text("Cube: ?"); ImGui::Text("Cube: ?");
break; break;
} }
static const char* swizzle_map[] = {"Red", "Green", "Blue", "Alpha", static const char* kSwizzleMap[] = {"R", "G", "B", "A", "0", "1"};
"Zero", "One", "UNK6", "UNK7"}; ImGui::Text("Swizzle: %s%s%s%s", kSwizzleMap[(fetch.swizzle >> 0) & 0x7],
ImGui::Text("Swizzle: %s %s %s %s", kSwizzleMap[(fetch.swizzle >> 3) & 0x7],
swizzle_map[(texture_info.swizzle >> 0) & 0x7], kSwizzleMap[(fetch.swizzle >> 6) & 0x7],
swizzle_map[(texture_info.swizzle >> 3) & 0x7], kSwizzleMap[(fetch.swizzle >> 9) & 0x7]);
swizzle_map[(texture_info.swizzle >> 6) & 0x7],
swizzle_map[(texture_info.swizzle >> 9) & 0x7]);
ImGui::Columns(1); ImGui::Columns(1);
} }

View File

@ -62,10 +62,12 @@ void main() {
const std::string color_fs_source = header + const std::string color_fs_source = header +
R"( R"(
layout(location = 1) uniform sampler2D src_texture; layout(location = 1) uniform sampler2D src_texture;
layout(location = 2) uniform bool swap;
layout(location = 0) in vec2 vtx_uv; layout(location = 0) in vec2 vtx_uv;
layout(location = 0) out vec4 oC; layout(location = 0) out vec4 oC;
void main() { void main() {
oC = texture(src_texture, vtx_uv); oC = texture(src_texture, vtx_uv);
if (!swap) oC = oC.bgra;
})"; })";
const std::string depth_fs_source = header + const std::string depth_fs_source = header +
R"( R"(
@ -242,7 +244,8 @@ void Blitter::Draw(GLuint src_texture, Rect2D src_rect, Rect2D dest_rect,
} }
void Blitter::BlitTexture2D(GLuint src_texture, Rect2D src_rect, void Blitter::BlitTexture2D(GLuint src_texture, Rect2D src_rect,
Rect2D dest_rect, GLenum filter) { Rect2D dest_rect, GLenum filter,
bool swap_channels) {
SavedState state; SavedState state;
state.Save(); state.Save();
@ -252,6 +255,8 @@ void Blitter::BlitTexture2D(GLuint src_texture, Rect2D src_rect,
glStencilMask(0xFF); glStencilMask(0xFF);
glBindProgramPipeline(color_pipeline_); glBindProgramPipeline(color_pipeline_);
glProgramUniform1i(color_fragment_program_, 2, swap_channels ? 1 : 0);
Draw(src_texture, src_rect, dest_rect, filter); Draw(src_texture, src_rect, dest_rect, filter);
state.Restore(); state.Restore();
@ -259,7 +264,7 @@ void Blitter::BlitTexture2D(GLuint src_texture, Rect2D src_rect,
void Blitter::CopyColorTexture2D(GLuint src_texture, Rect2D src_rect, void Blitter::CopyColorTexture2D(GLuint src_texture, Rect2D src_rect,
GLuint dest_texture, Rect2D dest_rect, GLuint dest_texture, Rect2D dest_rect,
GLenum filter) { GLenum filter, bool swap_channels) {
SavedState state; SavedState state;
state.Save(); state.Save();
@ -268,14 +273,7 @@ void Blitter::CopyColorTexture2D(GLuint src_texture, Rect2D src_rect,
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
glBindProgramPipeline(color_pipeline_); glBindProgramPipeline(color_pipeline_);
// Make sure the texture swizzles match before performing a copy glProgramUniform1i(color_fragment_program_, 2, swap_channels ? 1 : 0);
// TODO: Is this a good place for this?
GLint swizzle_map[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}};
glGetTextureParameteriv(src_texture, GL_TEXTURE_SWIZZLE_RGBA, swizzle_map[0]);
glGetTextureParameteriv(dest_texture, GL_TEXTURE_SWIZZLE_RGBA,
swizzle_map[1]);
glTextureParameteriv(src_texture, GL_TEXTURE_SWIZZLE_RGBA, swizzle_map[1]);
glNamedFramebufferTexture(scratch_framebuffer_, GL_COLOR_ATTACHMENT0, glNamedFramebufferTexture(scratch_framebuffer_, GL_COLOR_ATTACHMENT0,
dest_texture, 0); dest_texture, 0);
@ -286,8 +284,6 @@ void Blitter::CopyColorTexture2D(GLuint src_texture, Rect2D src_rect,
glNamedFramebufferTexture(scratch_framebuffer_, GL_COLOR_ATTACHMENT0, GL_NONE, glNamedFramebufferTexture(scratch_framebuffer_, GL_COLOR_ATTACHMENT0, GL_NONE,
0); 0);
glTextureParameteriv(src_texture, GL_TEXTURE_SWIZZLE_RGBA, swizzle_map[0]);
state.Restore(); state.Restore();
} }

View File

@ -39,10 +39,11 @@ class Blitter {
void Shutdown(); void Shutdown();
void BlitTexture2D(GLuint src_texture, Rect2D src_rect, Rect2D dest_rect, void BlitTexture2D(GLuint src_texture, Rect2D src_rect, Rect2D dest_rect,
GLenum filter); GLenum filter, bool swap_channels);
void CopyColorTexture2D(GLuint src_texture, Rect2D src_rect, void CopyColorTexture2D(GLuint src_texture, Rect2D src_rect,
GLuint dest_texture, Rect2D dest_rect, GLenum filter); GLuint dest_texture, Rect2D dest_rect, GLenum filter,
bool swap_channels);
void CopyDepthTexture(GLuint src_texture, Rect2D src_rect, void CopyDepthTexture(GLuint src_texture, Rect2D src_rect,
GLuint dest_texture, Rect2D dest_rect); GLuint dest_texture, Rect2D dest_rect);