kepler_compute: Implement texture queries

This commit is contained in:
ReinUsesLisp 2019-07-11 21:54:07 -03:00
parent 2e5b5c2358
commit 3a450c1395
5 changed files with 99 additions and 5 deletions

View file

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <bitset>
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core.h" #include "core/core.h"
@ -49,6 +50,33 @@ void KeplerCompute::CallMethod(const GPU::MethodCall& method_call) {
} }
} }
Tegra::Texture::FullTextureInfo KeplerCompute::GetTexture(std::size_t offset) const {
const std::bitset<8> cbuf_mask = launch_description.const_buffer_enable_mask.Value();
ASSERT(cbuf_mask[regs.tex_cb_index]);
const auto& texinfo = launch_description.const_buffer_config[regs.tex_cb_index];
ASSERT(texinfo.Address() != 0);
const GPUVAddr address = texinfo.Address() + offset * sizeof(Texture::TextureHandle);
ASSERT(address < texinfo.Address() + texinfo.size);
const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(address)};
return GetTextureInfo(tex_handle, offset);
}
Texture::FullTextureInfo KeplerCompute::GetTextureInfo(const Texture::TextureHandle tex_handle,
std::size_t offset) const {
return Texture::FullTextureInfo{static_cast<u32>(offset), GetTICEntry(tex_handle.tic_id),
GetTSCEntry(tex_handle.tsc_id)};
}
u32 KeplerCompute::AccessConstBuffer32(u64 const_buffer, u64 offset) const {
const auto& buffer = launch_description.const_buffer_config[const_buffer];
u32 result;
std::memcpy(&result, memory_manager.GetPointer(buffer.Address() + offset), sizeof(u32));
return result;
}
void KeplerCompute::ProcessLaunch() { void KeplerCompute::ProcessLaunch() {
const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address(); const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address();
memory_manager.ReadBlockUnsafe(launch_desc_loc, &launch_description, memory_manager.ReadBlockUnsafe(launch_desc_loc, &launch_description,
@ -60,4 +88,29 @@ void KeplerCompute::ProcessLaunch() {
rasterizer.DispatchCompute(code_addr); rasterizer.DispatchCompute(code_addr);
} }
Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
const GPUVAddr tic_address_gpu{regs.tic.Address() + tic_index * sizeof(Texture::TICEntry)};
Texture::TICEntry tic_entry;
memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
const auto r_type{tic_entry.r_type.Value()};
const auto g_type{tic_entry.g_type.Value()};
const auto b_type{tic_entry.b_type.Value()};
const auto a_type{tic_entry.a_type.Value()};
// TODO(Subv): Different data types for separate components are not supported
DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
return tic_entry;
}
Texture::TSCEntry KeplerCompute::GetTSCEntry(u32 tsc_index) const {
const GPUVAddr tsc_address_gpu{regs.tsc.Address() + tsc_index * sizeof(Texture::TSCEntry)};
Texture::TSCEntry tsc_entry;
memory_manager.ReadBlockUnsafe(tsc_address_gpu, &tsc_entry, sizeof(Texture::TSCEntry));
return tsc_entry;
}
} // namespace Tegra::Engines } // namespace Tegra::Engines

View file

@ -12,6 +12,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/engines/engine_upload.h" #include "video_core/engines/engine_upload.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
#include "video_core/textures/texture.h"
namespace Core { namespace Core {
class System; class System;
@ -111,7 +112,7 @@ public:
INSERT_PADDING_WORDS(0x3FE); INSERT_PADDING_WORDS(0x3FE);
u32 texture_const_buffer_index; u32 tex_cb_index;
INSERT_PADDING_WORDS(0x374); INSERT_PADDING_WORDS(0x374);
}; };
@ -149,7 +150,7 @@ public:
union { union {
BitField<0, 8, u32> const_buffer_enable_mask; BitField<0, 8, u32> const_buffer_enable_mask;
BitField<29, 2, u32> cache_layout; BitField<29, 2, u32> cache_layout;
} memory_config; };
INSERT_PADDING_WORDS(0x8); INSERT_PADDING_WORDS(0x8);
@ -194,6 +195,14 @@ public:
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(const GPU::MethodCall& method_call); void CallMethod(const GPU::MethodCall& method_call);
Tegra::Texture::FullTextureInfo GetTexture(std::size_t offset) const;
/// Given a Texture Handle, returns the TSC and TIC entries.
Texture::FullTextureInfo GetTextureInfo(const Texture::TextureHandle tex_handle,
std::size_t offset) const;
u32 AccessConstBuffer32(u64 const_buffer, u64 offset) const;
private: private:
Core::System& system; Core::System& system;
VideoCore::RasterizerInterface& rasterizer; VideoCore::RasterizerInterface& rasterizer;
@ -201,6 +210,12 @@ private:
Upload::State upload_state; Upload::State upload_state;
void ProcessLaunch(); void ProcessLaunch();
/// Retrieves information about a specific TIC entry from the TIC buffer.
Texture::TICEntry GetTICEntry(u32 tic_index) const;
/// Retrieves information about a specific TSC entry from the TSC buffer.
Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
}; };
#define ASSERT_REG_POSITION(field_name, position) \ #define ASSERT_REG_POSITION(field_name, position) \
@ -218,12 +233,12 @@ ASSERT_REG_POSITION(launch, 0xAF);
ASSERT_REG_POSITION(tsc, 0x557); ASSERT_REG_POSITION(tsc, 0x557);
ASSERT_REG_POSITION(tic, 0x55D); ASSERT_REG_POSITION(tic, 0x55D);
ASSERT_REG_POSITION(code_loc, 0x582); ASSERT_REG_POSITION(code_loc, 0x582);
ASSERT_REG_POSITION(texture_const_buffer_index, 0x982); ASSERT_REG_POSITION(tex_cb_index, 0x982);
ASSERT_LAUNCH_PARAM_POSITION(program_start, 0x8); ASSERT_LAUNCH_PARAM_POSITION(program_start, 0x8);
ASSERT_LAUNCH_PARAM_POSITION(grid_dim_x, 0xC); ASSERT_LAUNCH_PARAM_POSITION(grid_dim_x, 0xC);
ASSERT_LAUNCH_PARAM_POSITION(shared_alloc, 0x11); ASSERT_LAUNCH_PARAM_POSITION(shared_alloc, 0x11);
ASSERT_LAUNCH_PARAM_POSITION(block_dim_x, 0x12); ASSERT_LAUNCH_PARAM_POSITION(block_dim_x, 0x12);
ASSERT_LAUNCH_PARAM_POSITION(memory_config, 0x14); ASSERT_LAUNCH_PARAM_POSITION(const_buffer_enable_mask, 0x14);
ASSERT_LAUNCH_PARAM_POSITION(const_buffer_config, 0x1D); ASSERT_LAUNCH_PARAM_POSITION(const_buffer_config, 0x1D);
#undef ASSERT_REG_POSITION #undef ASSERT_REG_POSITION

View file

@ -801,6 +801,8 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
} }
auto kernel = shader_cache.GetComputeKernel(code_addr); auto kernel = shader_cache.GetComputeKernel(code_addr);
SetupComputeImages(kernel);
const auto [program, next_bindings] = kernel->GetProgramHandle({}); const auto [program, next_bindings] = kernel->GetProgramHandle({});
state.draw.shader_program = program; state.draw.shader_program = program;
state.draw.program_pipeline = 0; state.draw.program_pipeline = 0;
@ -922,7 +924,7 @@ void RasterizerOpenGL::SetupComputeConstBuffers(const Shader& kernel) {
const auto& launch_desc = system.GPU().KeplerCompute().launch_description; const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
for (const auto& entry : kernel->GetShaderEntries().const_buffers) { for (const auto& entry : kernel->GetShaderEntries().const_buffers) {
const auto& config = launch_desc.const_buffer_config[entry.GetIndex()]; const auto& config = launch_desc.const_buffer_config[entry.GetIndex()];
const std::bitset<8> mask = launch_desc.memory_config.const_buffer_enable_mask.Value(); const std::bitset<8> mask = launch_desc.const_buffer_enable_mask.Value();
Tegra::Engines::ConstBufferInfo buffer; Tegra::Engines::ConstBufferInfo buffer;
buffer.address = config.Address(); buffer.address = config.Address();
buffer.size = config.size; buffer.size = config.size;
@ -1038,6 +1040,24 @@ bool RasterizerOpenGL::SetupTexture(const Shader& shader, u32 binding,
return false; return false;
} }
void RasterizerOpenGL::SetupComputeImages(const Shader& shader) {
const auto& compute = system.GPU().KeplerCompute();
const auto& entries = shader->GetShaderEntries().images;
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& entry = entries[bindpoint];
const auto texture = [&]() {
if (!entry.IsBindless()) {
return compute.GetTexture(entry.GetOffset());
}
const auto cbuf = entry.GetBindlessCBuf();
Tegra::Texture::TextureHandle tex_handle;
tex_handle.raw = compute.AccessConstBuffer32(cbuf.first, cbuf.second);
return compute.GetTextureInfo(tex_handle, entry.GetOffset());
}();
UNIMPLEMENTED();
}
}
void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
const auto& regs = system.GPU().Maxwell3D().regs; const auto& regs = system.GPU().Maxwell3D().regs;
const bool geometry_shaders_enabled = const bool geometry_shaders_enabled =

View file

@ -146,6 +146,8 @@ private:
const Tegra::Texture::FullTextureInfo& texture, const Tegra::Texture::FullTextureInfo& texture,
const GLShader::SamplerEntry& entry); const GLShader::SamplerEntry& entry);
void SetupComputeImages(const Shader& shader);
/// Syncs the viewport and depth range to match the guest state /// Syncs the viewport and depth range to match the guest state
void SyncViewport(OpenGLState& current_state); void SyncViewport(OpenGLState& current_state);

View file

@ -303,6 +303,10 @@ public:
return is_bindless; return is_bindless;
} }
std::pair<u32, u32> GetBindlessCBuf() const {
return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)};
}
bool operator<(const Image& rhs) const { bool operator<(const Image& rhs) const {
return std::tie(offset, index, type, is_bindless) < return std::tie(offset, index, type, is_bindless) <
std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless); std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless);