kepler_compute: Implement texture queries
This commit is contained in:
parent
2e5b5c2358
commit
3a450c1395
5 changed files with 99 additions and 5 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue